diff options
60 files changed, 782 insertions, 504 deletions
diff --git a/configure b/configure index 877a8213f3..3d83e168bc 100755 --- a/configure +++ b/configure @@ -155,7 +155,6 @@ curl="" curses="" docs="" fdt="" -nptl="" pixman="" sdl="" virtfs="" @@ -856,10 +855,6 @@ for opt do ;; --enable-fdt) fdt="yes" ;; - --disable-nptl) nptl="no" - ;; - --enable-nptl) nptl="yes" - ;; --enable-mixemu) mixemu="yes" ;; --disable-linux-aio) linux_aio="no" @@ -1103,8 +1098,6 @@ echo " --enable-kvm enable KVM acceleration support" echo " --disable-rdma disable RDMA-based migration support" echo " --enable-rdma enable RDMA-based migration support" echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)" -echo " --disable-nptl disable usermode NPTL support" -echo " --enable-nptl enable usermode NPTL support" echo " --enable-system enable all system emulation targets" echo " --disable-system disable all system emulation targets" echo " --enable-user enable supported user emulation targets" @@ -1439,7 +1432,7 @@ fi ########################################## # NPTL probe -if test "$nptl" != "no" ; then +if test "$linux_user" = "yes"; then cat > $TMPC <<EOF #include <sched.h> #include <linux/futex.h> @@ -1450,14 +1443,8 @@ int main(void) { return 0; } EOF - - if compile_object ; then - nptl=yes - else - if test "$nptl" = "yes" ; then - feature_not_found "nptl" - fi - nptl=no + if ! compile_object ; then + feature_not_found "nptl" fi fi @@ -3581,7 +3568,6 @@ echo "bluez support $bluez" echo "Documentation $docs" [ ! -z "$uname_release" ] && \ echo "uname -r $uname_release" -echo "NPTL support $nptl" echo "GUEST_BASE $guest_base" echo "PIE $pie" echo "vde support $vde" @@ -4216,7 +4202,6 @@ mkdir -p $target_dir echo "# Automatically generated by configure - do not modify" > $config_target_mak bflt="no" -target_nptl="no" interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"` gdb_xml_files="" @@ -4231,16 +4216,13 @@ case "$target_name" in TARGET_BASE_ARCH=i386 ;; alpha) - target_nptl="yes" ;; arm|armeb) TARGET_ARCH=arm bflt="yes" - target_nptl="yes" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" ;; cris) - target_nptl="yes" ;; lm32) ;; @@ -4251,12 +4233,10 @@ case "$target_name" in microblaze|microblazeel) TARGET_ARCH=microblaze bflt="yes" - target_nptl="yes" ;; mips|mipsel) TARGET_ARCH=mips echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak - target_nptl="yes" ;; mipsn32|mipsn32el) TARGET_ARCH=mips64 @@ -4277,13 +4257,11 @@ case "$target_name" in ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="yes" ;; ppcemb) TARGET_BASE_ARCH=ppc TARGET_ABI_DIR=ppc gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" - target_nptl="yes" ;; ppc64) TARGET_BASE_ARCH=ppc @@ -4300,7 +4278,6 @@ case "$target_name" in sh4|sh4eb) TARGET_ARCH=sh4 bflt="yes" - target_nptl="yes" ;; sparc) ;; @@ -4314,7 +4291,6 @@ case "$target_name" in echo "TARGET_ABI32=y" >> $config_target_mak ;; s390x) - target_nptl="yes" ;; unicore32) ;; @@ -4396,10 +4372,6 @@ fi if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then echo "TARGET_HAS_BFLT=y" >> $config_target_mak fi -if test "$target_user_only" = "yes" \ - -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then - echo "CONFIG_USE_NPTL=y" >> $config_target_mak -fi if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak fi diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak index 18e5337a77..bc07600f96 100644 --- a/default-configs/alpha-softmmu.mak +++ b/default-configs/alpha-softmmu.mak @@ -14,3 +14,4 @@ CONFIG_VMWARE_VGA=y CONFIG_IDE_CMD646=y CONFIG_I8259=y CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak index b443702b87..926709ae52 100644 --- a/default-configs/mips-softmmu.mak +++ b/default-configs/mips-softmmu.mak @@ -3,7 +3,6 @@ include pci.mak include sound.mak include usb.mak -CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA=y CONFIG_VGA_PCI=y @@ -34,3 +33,4 @@ CONFIG_I8259=y CONFIG_JAZZ_LED=y CONFIG_MC146818RTC=y CONFIG_VT82C686=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak index d63895792b..0ef3f09c77 100644 --- a/default-configs/mips64-softmmu.mak +++ b/default-configs/mips64-softmmu.mak @@ -3,7 +3,6 @@ include pci.mak include sound.mak include usb.mak -CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA=y CONFIG_VGA_PCI=y @@ -34,3 +33,4 @@ CONFIG_I8259=y CONFIG_JAZZ_LED=y CONFIG_MC146818RTC=y CONFIG_VT82C686=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak index c9be3f49ca..60893182b3 100644 --- a/default-configs/mips64el-softmmu.mak +++ b/default-configs/mips64el-softmmu.mak @@ -3,7 +3,6 @@ include pci.mak include sound.mak include usb.mak -CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA=y CONFIG_VGA_PCI=y @@ -36,3 +35,4 @@ CONFIG_I8259=y CONFIG_JAZZ_LED=y CONFIG_MC146818RTC=y CONFIG_VT82C686=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak index 4f4a449408..cd59e2479a 100644 --- a/default-configs/mipsel-softmmu.mak +++ b/default-configs/mipsel-softmmu.mak @@ -3,7 +3,6 @@ include pci.mak include sound.mak include usb.mak -CONFIG_ISA_MMIO=y CONFIG_ESP=y CONFIG_VGA=y CONFIG_VGA_PCI=y @@ -34,3 +33,4 @@ CONFIG_I8259=y CONFIG_JAZZ_LED=y CONFIG_MC146818RTC=y CONFIG_VT82C686=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 73e4cc5f63..eac0b28fb9 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -46,3 +46,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index 6d1933bbf9..7831c2bf57 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -48,4 +48,11 @@ CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For pSeries CONFIG_XICS=$(CONFIG_PSERIES) # For PReP +CONFIG_I82378=y +CONFIG_I8259=y +CONFIG_I8254=y +CONFIG_PCSPK=y +CONFIG_I82374=y +CONFIG_I8257=y CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak index e3b5e50360..86080a7574 100644 --- a/default-configs/ppcemb-softmmu.mak +++ b/default-configs/ppcemb-softmmu.mak @@ -41,3 +41,4 @@ CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For PReP CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak index f6bf62d1c2..8e00390d4f 100644 --- a/default-configs/sh4-softmmu.mak +++ b/default-configs/sh4-softmmu.mak @@ -5,7 +5,14 @@ include usb.mak CONFIG_SERIAL=y CONFIG_PTIMER=y CONFIG_PFLASH_CFI02=y -CONFIG_ISA_MMIO=y CONFIG_SH4=y CONFIG_IDE_MMIO=y CONFIG_SM501=y +CONFIG_ISA_TESTDEV=y +CONFIG_I82378=y +CONFIG_I8259=y +CONFIG_I8254=y +CONFIG_PCSPK=y +CONFIG_I82374=y +CONFIG_I8257=y +CONFIG_MC146818RTC=y diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak index c1d513d099..efdd05842f 100644 --- a/default-configs/sh4eb-softmmu.mak +++ b/default-configs/sh4eb-softmmu.mak @@ -5,7 +5,14 @@ include usb.mak CONFIG_SERIAL=y CONFIG_PTIMER=y CONFIG_PFLASH_CFI02=y -CONFIG_ISA_MMIO=y CONFIG_SH4=y CONFIG_IDE_MMIO=y CONFIG_SM501=y +CONFIG_ISA_TESTDEV=y +CONFIG_I82378=y +CONFIG_I8259=y +CONFIG_I8254=y +CONFIG_PCSPK=y +CONFIG_I82374=y +CONFIG_I8257=y +CONFIG_MC146818RTC=y diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak index 9b08ee8a20..299c97b715 100644 --- a/default-configs/sparc64-softmmu.mak +++ b/default-configs/sparc64-softmmu.mak @@ -15,3 +15,4 @@ CONFIG_IDE_ISA=y CONFIG_IDE_CMD646=y CONFIG_PCI_APB=y CONFIG_MC146818RTC=y +CONFIG_ISA_TESTDEV=y diff --git a/exec.c b/exec.c index 7997002f14..3ba9525bd3 100644 --- a/exec.c +++ b/exec.c @@ -646,6 +646,10 @@ CPUArchState *cpu_copy(CPUArchState *env) CPUWatchpoint *wp; #endif + /* Reset non arch specific state */ + cpu_reset(ENV_GET_CPU(new_env)); + + /* Copy arch specific state into the new CPU */ memcpy(new_env, env, sizeof(CPUArchState)); /* Clone all break/watchpoints. diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs index 193746a73e..9164556a4d 100644 --- a/hw/isa/Makefile.objs +++ b/hw/isa/Makefile.objs @@ -1,7 +1,6 @@ common-obj-y += isa-bus.o common-obj-$(CONFIG_APM) += apm.o common-obj-$(CONFIG_I82378) += i82378.o -common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o common-obj-$(CONFIG_PC87312) += pc87312.o common-obj-$(CONFIG_PIIX4) += piix4.o common-obj-$(CONFIG_VT82C686) += vt82c686.o diff --git a/hw/isa/isa_mmio.c b/hw/isa/isa_mmio.c deleted file mode 100644 index 00ae8ebc2e..0000000000 --- a/hw/isa/isa_mmio.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Memory mapped access to ISA IO space. - * - * 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 "hw/hw.h" -#include "hw/isa/isa.h" -#include "exec/address-spaces.h" - -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, hwaddr addr, - uint32_t val) -{ - cpu_outw(addr & IOPORTS_MASK, val); -} - -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, hwaddr addr) -{ - return cpu_inb(addr & IOPORTS_MASK); -} - -static uint32_t isa_mmio_readw(void *opaque, hwaddr addr) -{ - return cpu_inw(addr & IOPORTS_MASK); -} - -static uint32_t isa_mmio_readl(void *opaque, hwaddr addr) -{ - return cpu_inl(addr & IOPORTS_MASK); -} - -static const MemoryRegionOps isa_mmio_ops = { - .old_mmio = { - .write = { isa_mmio_writeb, isa_mmio_writew, isa_mmio_writel }, - .read = { isa_mmio_readb, isa_mmio_readw, isa_mmio_readl, }, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -void isa_mmio_setup(MemoryRegion *mr, hwaddr size) -{ - memory_region_init_io(mr, NULL, &isa_mmio_ops, NULL, "isa-mmio", size); -} - -void isa_mmio_init(hwaddr base, hwaddr size) -{ - MemoryRegion *mr = g_malloc(sizeof(*mr)); - - isa_mmio_setup(mr, size); - memory_region_add_subregion(get_system_memory(), base, mr); -} diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 5843417567..3da2e67098 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -304,7 +304,8 @@ static void gt64120_pci_mapping(GT64120State *s) s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21; isa_mem_base = s->PCI0IO_start; if (s->PCI0IO_length) { - isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length); + memory_region_init_alias(&s->PCI0IO_mem, OBJECT(s), "isa_mmio", + get_system_io(), 0, s->PCI0IO_length); memory_region_add_subregion(get_system_memory(), s->PCI0IO_start, &s->PCI0IO_mem); } diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 9e305d2878..a7e9dcf4bf 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -333,8 +333,7 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { - fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name); - exit(1); + fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); } } diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 31e138b056..d6e0860a83 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -119,6 +119,7 @@ static void mips_jazz_init(MemoryRegion *address_space, qemu_irq *rc4030, *i8259; rc4030_dma *dmas; void* rc4030_opaque; + MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *rtc = g_new(MemoryRegion, 1); MemoryRegion *i8042 = g_new(MemoryRegion, 1); MemoryRegion *dma_dummy = g_new(MemoryRegion, 1); @@ -176,9 +177,8 @@ static void mips_jazz_init(MemoryRegion *address_space, bios_size = -1; } if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) { - fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", + fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n", bios_name); - exit(1); } /* Init CPU internal devices */ @@ -201,7 +201,9 @@ static void mips_jazz_init(MemoryRegion *address_space, pcspk_init(isa_bus, pit); /* ISA IO space at 0x90000000 */ - isa_mmio_init(0x90000000, 0x01000000); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, 0x01000000); + memory_region_add_subregion(address_space, 0x90000000, isa); isa_mem_base = 0x11000000; /* Video card */ diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index de87241e9c..dad58c0ed2 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -908,9 +908,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) } if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { fprintf(stderr, - "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", + "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n", bios_name); - exit(1); } } /* In little endian mode the 32bit words in the bios are swapped, diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index a10cf13a92..e8802c128e 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -140,6 +140,7 @@ mips_mipssim_init(QEMUMachineInitArgs *args) const char *initrd_filename = args->initrd_filename; char *filename; MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MIPSCPU *cpu; @@ -191,9 +192,8 @@ mips_mipssim_init(QEMUMachineInitArgs *args) if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { /* Bail out if we have neither a kernel image nor boot vector code. */ fprintf(stderr, - "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", + "qemu: Warning, could not load MIPS bios '%s', and no -kernel argument was specified\n", filename); - exit(1); } else { /* We have a boot vector start address. */ env->active_tc.PC = (target_long)(int32_t)0xbfc00000; @@ -212,7 +212,9 @@ mips_mipssim_init(QEMUMachineInitArgs *args) cpu_mips_clock_init(env); /* Register 64 KB of ISA IO space at 0x1fd00000. */ - isa_mmio_init(0x1fd00000, 0x00010000); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, 0x00010000); + memory_region_add_subregion(get_system_memory(), 0x1fd00000, isa); /* A single 16450 sits at offset 0x3f8. It is attached to MIPS CPU INT2, which is interrupt 4. */ diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 22beb0a67c..4bc2e3fa7a 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -164,6 +164,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args) MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios; MemoryRegion *iomem = g_new(MemoryRegion, 1); + MemoryRegion *isa = g_new(MemoryRegion, 1); int bios_size; MIPSCPU *cpu; CPUMIPSState *env; @@ -273,7 +274,10 @@ void mips_r4k_init(QEMUMachineInitArgs *args) rtc_init(isa_bus, 2000, NULL); /* Register 64 KB of ISA IO space at 0x14000000 */ - isa_mmio_init(0x14000000, 0x00010000); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, 0x00010000); + memory_region_add_subregion(get_system_memory(), 0x14000000, isa); + isa_mem_base = 0x10000000; pit = pit_init(isa_bus, 0x40, 0, NULL); diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c index 699a16ffbe..5867c70069 100644 --- a/hw/misc/pc-testdev.c +++ b/hw/misc/pc-testdev.c @@ -49,6 +49,7 @@ typedef struct PCTestdev { ISADevice parent_obj; MemoryRegion ioport; + MemoryRegion ioport_byte; MemoryRegion flush; MemoryRegion irq; MemoryRegion iomem; @@ -80,13 +81,20 @@ static void test_ioport_write(void *opaque, hwaddr addr, uint64_t data, unsigned len) { PCTestdev *dev = opaque; - dev->ioport_data = data; + int bits = len * 8; + int start_bit = (addr & 3) * 8; + uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit; + dev->ioport_data &= ~mask; + dev->ioport_data |= data << start_bit; } static uint64_t test_ioport_read(void *opaque, hwaddr addr, unsigned len) { PCTestdev *dev = opaque; - return dev->ioport_data; + int bits = len * 8; + int start_bit = (addr & 3) * 8; + uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit; + return (dev->ioport_data & mask) >> start_bit; } static const MemoryRegionOps test_ioport_ops = { @@ -95,6 +103,16 @@ static const MemoryRegionOps test_ioport_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static const MemoryRegionOps test_ioport_byte_ops = { + .read = test_ioport_read, + .write = test_ioport_write, + .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 void test_flush_page(void *opaque, hwaddr addr, uint64_t data, unsigned len) { @@ -122,7 +140,6 @@ static uint64_t test_iomem_read(void *opaque, hwaddr addr, unsigned len) PCTestdev *dev = opaque; uint64_t ret = 0; memcpy(&ret, &dev->iomem_buf[addr], len); - ret = le64_to_cpu(ret); return ret; } @@ -131,7 +148,6 @@ static void test_iomem_write(void *opaque, hwaddr addr, uint64_t val, unsigned len) { PCTestdev *dev = opaque; - val = cpu_to_le64(val); memcpy(&dev->iomem_buf[addr], &val, len); dev->iomem_buf[addr] = val; } @@ -151,6 +167,9 @@ static void testdev_realizefn(DeviceState *d, Error **errp) memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev, "pc-testdev-ioport", 4); + memory_region_init_io(&dev->ioport_byte, OBJECT(dev), + &test_ioport_byte_ops, dev, + "pc-testdev-ioport-byte", 4); memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev, "pc-testdev-flush-page", 4); memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev, @@ -160,6 +179,7 @@ static void testdev_realizefn(DeviceState *d, Error **errp) memory_region_add_subregion(io, 0xe0, &dev->ioport); memory_region_add_subregion(io, 0xe4, &dev->flush); + memory_region_add_subregion(io, 0xe8, &dev->ioport_byte); memory_region_add_subregion(io, 0x2000, &dev->irq); memory_region_add_subregion(mem, 0xff000000, &dev->iomem); } diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 06ace085b5..3756ce9a4b 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -70,9 +70,14 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) #define MAX_IVEC 0x40 #define NO_IRQ_REQUEST (MAX_IVEC + 1) +#define TYPE_APB "pbm" + +#define APB_DEVICE(obj) \ + OBJECT_CHECK(APBState, (obj), TYPE_APB) + typedef struct APBState { - SysBusDevice busdev; - PCIBus *bus; + PCIHostState parent_obj; + MemoryRegion apb_config; MemoryRegion pci_config; MemoryRegion pci_mmio; @@ -284,10 +289,11 @@ static void apb_pci_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { APBState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); val = qemu_bswap_len(val, size); APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val); - pci_data_write(s->bus, addr, val, size); + pci_data_write(phb->bus, addr, val, size); } static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, @@ -295,63 +301,14 @@ static uint64_t apb_pci_config_read(void *opaque, hwaddr addr, { uint32_t ret; APBState *s = opaque; + PCIHostState *phb = PCI_HOST_BRIDGE(s); - ret = pci_data_read(s->bus, addr, size); + ret = pci_data_read(phb->bus, addr, size); ret = qemu_bswap_len(ret, size); APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret); return ret; } -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, hwaddr addr, - uint32_t val) -{ - cpu_outw(addr & IOPORTS_MASK, bswap16(val)); -} - -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, hwaddr addr) -{ - uint32_t val; - - val = cpu_inb(addr & IOPORTS_MASK); - return val; -} - -static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr) -{ - uint32_t val; - - val = bswap16(cpu_inw(addr & IOPORTS_MASK)); - return val; -} - -static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr) -{ - uint32_t val; - - val = bswap32(cpu_inl(addr & IOPORTS_MASK)); - return val; -} - -static const MemoryRegionOps pci_ioport_ops = { - .old_mmio = { - .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl }, - .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - /* The APB host has an IRQ line for each IRQ line of each slot. */ static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num) { @@ -431,12 +388,13 @@ PCIBus *pci_apb_init(hwaddr special_base, { DeviceState *dev; SysBusDevice *s; + PCIHostState *phb; APBState *d; PCIDevice *pci_dev; PCIBridge *br; /* Ultrasparc PBM main bus */ - dev = qdev_create(NULL, "pbm"); + dev = qdev_create(NULL, TYPE_APB); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); /* apb_config */ @@ -445,24 +403,25 @@ PCIBus *pci_apb_init(hwaddr special_base, sysbus_mmio_map(s, 1, special_base + 0x1000000ULL); /* pci_ioport */ sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); - d = FROM_SYSBUS(APBState, s); + d = APB_DEVICE(dev); memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); - d->bus = pci_register_bus(&d->busdev.qdev, "pci", - pci_apb_set_irq, pci_pbm_map_irq, d, - &d->pci_mmio, - get_system_io(), - 0, 32, TYPE_PCI_BUS); + phb = PCI_HOST_BRIDGE(dev); + phb->bus = pci_register_bus(DEVICE(phb), "pci", + pci_apb_set_irq, pci_pbm_map_irq, d, + &d->pci_mmio, + get_system_io(), + 0, 32, TYPE_PCI_BUS); *pbm_irqs = d->pbm_irqs; d->ivec_irqs = ivec_irqs; - pci_create_simple(d->bus, 0, "pbm-pci"); + pci_create_simple(phb->bus, 0, "pbm-pci"); /* APB secondary busses */ - pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true, + pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true, "pbm-bridge"); br = DO_UPCAST(PCIBridge, dev, pci_dev); pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1", @@ -470,7 +429,7 @@ PCIBus *pci_apb_init(hwaddr special_base, qdev_init_nofail(&pci_dev->qdev); *bus2 = pci_bridge_get_sec_bus(br); - pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true, + pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true, "pbm-bridge"); br = DO_UPCAST(PCIBridge, dev, pci_dev); pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2", @@ -478,13 +437,13 @@ PCIBus *pci_apb_init(hwaddr special_base, qdev_init_nofail(&pci_dev->qdev); *bus3 = pci_bridge_get_sec_bus(br); - return d->bus; + return phb->bus; } static void pci_pbm_reset(DeviceState *d) { unsigned int i; - APBState *s = container_of(d, APBState, busdev.qdev); + APBState *s = APB_DEVICE(d); for (i = 0; i < 8; i++) { s->pci_irq_map[i] &= PBM_PCI_IMR_MASK; @@ -513,7 +472,7 @@ static int pci_pbm_init_device(SysBusDevice *dev) APBState *s; unsigned int i; - s = FROM_SYSBUS(APBState, dev); + s = APB_DEVICE(dev); for (i = 0; i < 8; i++) { s->pci_irq_map[i] = (0x1f << 6) | (i << 2); } @@ -536,8 +495,8 @@ static int pci_pbm_init_device(SysBusDevice *dev) sysbus_init_mmio(dev, &s->pci_config); /* pci_ioport */ - memory_region_init_io(&s->pci_ioport, OBJECT(s), &pci_ioport_ops, s, - "apb-pci-ioport", 0x10000); + memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", + get_system_io(), 0, 0x10000); /* at region 2 */ sysbus_init_mmio(dev, &s->pci_ioport); @@ -581,8 +540,8 @@ static void pbm_host_class_init(ObjectClass *klass, void *data) } static const TypeInfo pbm_host_info = { - .name = "pbm", - .parent = TYPE_SYS_BUS_DEVICE, + .name = TYPE_APB, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(APBState), .class_init = pbm_host_class_init, }; diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 592d6666bc..5086d42c13 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -210,14 +210,8 @@ typedef struct PCIBonitoState MemoryRegion iomem; MemoryRegion iomem_ldma; MemoryRegion iomem_cop; - - hwaddr bonito_pciio_start; - hwaddr bonito_pciio_length; - int bonito_pciio_handle; - - hwaddr bonito_localio_start; - hwaddr bonito_localio_length; - int bonito_localio_handle; + MemoryRegion bonito_pciio; + MemoryRegion bonito_localio; } PCIBonitoState; @@ -750,15 +744,16 @@ static int bonito_initfn(PCIDevice *dev) sysbus_mmio_map(sysbus, 4, 0xbfe00300); /* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */ - s->bonito_pciio_start = BONITO_PCIIO_BASE; - s->bonito_pciio_length = BONITO_PCIIO_SIZE; - isa_mem_base = s->bonito_pciio_start; - isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length); + memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio", + get_system_io(), 0, BONITO_PCIIO_SIZE); + sysbus_init_mmio(sysbus, &s->bonito_pciio); + sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE); /* add pci local io mapping */ - s->bonito_localio_start = BONITO_DEV_BASE; - s->bonito_localio_length = BONITO_DEV_SIZE; - isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length); + memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio", + get_system_io(), 0, BONITO_DEV_SIZE); + sysbus_init_mmio(sysbus, &s->bonito_localio); + sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE); /* set the default value of north bridge pci config */ pci_set_word(dev->config + PCI_COMMAND, 0x0000); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index fe803480a7..7ef806ef7f 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -152,6 +152,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; + MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *unin_memory = g_new(MemoryRegion, 1); MemoryRegion *unin2_memory = g_new(MemoryRegion, 1); int linux_boot, i, j, k; @@ -288,7 +289,9 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) } /* Register 8 MB of ISA IO space */ - isa_mmio_init(0xf2000000, 0x00800000); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, 0x00800000); + memory_region_add_subregion(get_system_memory(), 0xf2000000, isa); /* UniN init: XXX should be a real device */ memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 8b8c6b93a5..42bb9d55c8 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -87,6 +87,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) int linux_boot, i; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); + MemoryRegion *isa = g_new(MemoryRegion, 1); uint32_t kernel_base, initrd_base, cmdline_base = 0; int32_t kernel_size, initrd_size; PCIBus *pci_bus; @@ -225,7 +226,9 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) } /* Register 2 MB of ISA IO space */ - isa_mmio_init(0xfe000000, 0x00200000); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, 0x00200000); + memory_region_add_subregion(sysmem, 0xfe000000, isa); /* XXX: we register only 1 output pin for heathrow PIC */ heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 5b039abb38..369ab9e26e 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -164,6 +164,7 @@ static void bamboo_init(QEMUMachineInitArgs *args) 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 *isa = g_new(MemoryRegion, 1); MemoryRegion *ram_memories = g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories)); hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS]; @@ -225,7 +226,9 @@ static void bamboo_init(QEMUMachineInitArgs *args) exit(1); } - isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN); + memory_region_init_alias(isa, NULL, "isa_mmio", + get_system_io(), 0, PPC440EP_PCI_IOLEN); + memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa); if (serial_hds[0] != NULL) { serial_mm_init(address_space_mem, 0xef600300, 0, pic[0], diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 19f2442482..7e04b1ac84 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -410,7 +410,7 @@ static const MemoryRegionOps PPC_prep_io_ops = { .read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl }, .write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel }, }, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_NATIVE_ENDIAN, }; #define NVRAM_SIZE 0x2000 diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 318bc9d6ef..c880a757c8 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -440,43 +440,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); - } - g_assert_not_reached(); -} - -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; - } - g_assert_not_reached(); -} - -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. @@ -605,8 +568,8 @@ static int spapr_phb_init(SysBusDevice *s) memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); sprintf(namebuf, "%s.io-alias", sphb->dtbusname); - memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb, - namebuf, SPAPR_PCI_IO_WIN_SIZE); + memory_region_init_alias(&sphb->iowindow, OBJECT(sphb), namebuf, + get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index c33a72f80f..e81176a11e 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -28,9 +28,14 @@ #include "qemu/bswap.h" #include "exec/address-spaces.h" +#define TYPE_SH_PCI_HOST_BRIDGE "sh_pci" + +#define SH_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE) + typedef struct SHPCIState { - SysBusDevice busdev; - PCIBus *bus; + PCIHostState parent_obj; + PCIDevice *dev; qemu_irq irq[4]; MemoryRegion memconfig_p4; @@ -45,6 +50,8 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val, unsigned size) { SHPCIState *pcic = p; + PCIHostState *phb = PCI_HOST_BRIDGE(pcic); + switch(addr) { case 0 ... 0xfc: cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val); @@ -64,7 +71,7 @@ static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val, } break; case 0x220: - pci_data_write(pcic->bus, pcic->par, val, 4); + pci_data_write(phb->bus, pcic->par, val, 4); break; } } @@ -73,6 +80,8 @@ static uint64_t sh_pci_reg_read (void *p, hwaddr addr, unsigned size) { SHPCIState *pcic = p; + PCIHostState *phb = PCI_HOST_BRIDGE(pcic); + switch(addr) { case 0 ... 0xfc: return le32_to_cpup((uint32_t*)(pcic->dev->config + addr)); @@ -83,7 +92,7 @@ static uint64_t sh_pci_reg_read (void *p, hwaddr addr, case 0x1c8: return pcic->iobr; case 0x220: - return pci_data_read(pcic->bus, pcic->par, 4); + return pci_data_read(phb->bus, pcic->par, 4); } return 0; } @@ -112,30 +121,33 @@ static void sh_pci_set_irq(void *opaque, int irq_num, int level) static int sh_pci_device_init(SysBusDevice *dev) { + PCIHostState *phb; SHPCIState *s; int i; - s = FROM_SYSBUS(SHPCIState, dev); + s = SH_PCI_HOST_BRIDGE(dev); + phb = PCI_HOST_BRIDGE(s); for (i = 0; i < 4; i++) { sysbus_init_irq(dev, &s->irq[i]); } - s->bus = pci_register_bus(&s->busdev.qdev, "pci", - sh_pci_set_irq, sh_pci_map_irq, - s->irq, - get_system_memory(), - get_system_io(), - PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS); + phb->bus = pci_register_bus(DEVICE(dev), "pci", + sh_pci_set_irq, sh_pci_map_irq, + s->irq, + get_system_memory(), + get_system_io(), + PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS); memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s, "sh_pci", 0x224); memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2", &s->memconfig_p4, 0, 0x224); - isa_mmio_setup(&s->isa, 0x40000); + memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa", + get_system_io(), 0, 0x40000); sysbus_init_mmio(dev, &s->memconfig_p4); sysbus_init_mmio(dev, &s->memconfig_a7); s->iobr = 0xfe240000; memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa); - s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host"); + s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host"); return 0; } @@ -171,8 +183,8 @@ static void sh_pci_device_class_init(ObjectClass *klass, void *data) } static const TypeInfo sh_pci_device_info = { - .name = "sh_pci", - .parent = TYPE_SYS_BUS_DEVICE, + .name = TYPE_SH_PCI_HOST_BRIDGE, + .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(SHPCIState), .class_init = sh_pci_device_class_init, }; diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 564c1959ee..34a5e7331c 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -605,9 +605,11 @@ pci_ebus_init1(PCIDevice *pci_dev) pci_dev->config[0x09] = 0x00; // programming i/f pci_dev->config[0x0D] = 0x0a; // latency_timer - isa_mmio_setup(&s->bar0, 0x1000000); + memory_region_init_alias(&s->bar0, OBJECT(s), "bar0", get_system_io(), + 0, 0x1000000); pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0); - isa_mmio_setup(&s->bar1, 0x800000); + memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(), + 0, 0x800000); pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1); return 0; } diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index f2800ec682..a407b50f4a 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -210,11 +210,15 @@ extern unsigned long reserved_va; }) #endif -#define h2g(x) ({ \ +#define h2g_nocheck(x) ({ \ unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \ + (abi_ulong)__ret; \ +}) + +#define h2g(x) ({ \ /* Check if given address fits target address space */ \ assert(h2g_valid(x)); \ - (abi_ulong)__ret; \ + h2g_nocheck(x); \ }) #define saddr(x) g2h(x) diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 1bd00aea23..7ea1ad7f9c 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -32,7 +32,7 @@ void gdb_register_coprocessor(CPUState *cpu, static inline int cpu_index(CPUState *cpu) { -#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL) +#if defined(CONFIG_USER_ONLY) return cpu->host_tid; #else return cpu->cpu_index + 1; diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index e1bf96ca69..495bcf3a08 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -92,9 +92,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d) extern hwaddr isa_mem_base; -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); int DMA_read_memory (int nchan, void *buf, int pos, int size); diff --git a/ioport.c b/ioport.c index 89b17d69f4..79b7f1ae38 100644 --- a/ioport.c +++ b/ioport.c @@ -183,6 +183,7 @@ static void portio_write(void *opaque, hwaddr addr, uint64_t data, static const MemoryRegionOps portio_ops = { .read = portio_read, .write = portio_write, + .endianness = DEVICE_LITTLE_ENDIAN, .valid.unaligned = true, .impl.unaligned = true, }; diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 003d424701..73f29314f6 100644 --- a/linux-user/arm/syscall.h +++ b/linux-user/arm/syscall.h @@ -40,3 +40,5 @@ struct target_pt_regs { #else #define UNAME_MACHINE "armv5tel" #endif + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h index 50e50b4f3f..832ee64bd8 100644 --- a/linux-user/cris/syscall.h +++ b/linux-user/cris/syscall.h @@ -38,4 +38,6 @@ struct target_pt_regs { unsigned long eda; }; +#define TARGET_CLONE_BACKWARDS2 + #endif diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h index 266e2c4c83..12b8c3b672 100644 --- a/linux-user/i386/syscall.h +++ b/linux-user/i386/syscall.h @@ -144,3 +144,5 @@ struct target_vm86plus_struct { }; #define UNAME_MACHINE "i686" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h index abcac79d25..58f86454d6 100644 --- a/linux-user/i386/target_cpu.h +++ b/linux-user/i386/target_cpu.h @@ -28,6 +28,21 @@ static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) env->regs[R_EAX] = 0; } -/* TODO: need to implement cpu_set_tls() */ +#if defined(TARGET_ABI32) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr); -#endif +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ + do_set_thread_area(env, newtls); + cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); +} +#else +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr); + +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ + do_arch_prctl(env, TARGET_ARCH_SET_FS, newtls); +} +#endif /* defined(TARGET_ABI32) */ + +#endif /* !defined(TARGET_CPU_H) */ diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h index 8a2a305a0b..cad9c90dd0 100644 --- a/linux-user/m68k/target_cpu.h +++ b/linux-user/m68k/target_cpu.h @@ -29,6 +29,10 @@ static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) env->dregs[0] = 0; } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls) +{ + TaskState *ts = env->opaque; + ts->tp_value = newtls; +} #endif diff --git a/linux-user/main.c b/linux-user/main.c index f6a3aad9e5..5dc09471e4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -92,7 +92,6 @@ int cpu_get_pic_interrupt(CPUX86State *env) } #endif -#if defined(CONFIG_USE_NPTL) /***********************************************************/ /* Helper routines for implementing atomic operations. */ @@ -207,43 +206,6 @@ void cpu_list_unlock(void) { pthread_mutex_unlock(&cpu_list_mutex); } -#else /* if !CONFIG_USE_NPTL */ -/* These are no-ops because we are not threadsafe. */ -static inline void cpu_exec_start(CPUState *cpu) -{ -} - -static inline void cpu_exec_end(CPUState *cpu) -{ -} - -static inline void start_exclusive(void) -{ -} - -static inline void end_exclusive(void) -{ -} - -void fork_start(void) -{ -} - -void fork_end(int child) -{ - if (child) { - gdbserver_fork((CPUArchState *)thread_cpu->env_ptr); - } -} - -void cpu_list_lock(void) -{ -} - -void cpu_list_unlock(void) -{ -} -#endif #ifdef TARGET_I386 @@ -2349,7 +2311,31 @@ done_syscall: abi_ulong trap_instr; unsigned int code; - ret = get_user_ual(trap_instr, env->active_tc.PC); + if (env->hflags & MIPS_HFLAG_M16) { + if (env->insn_flags & ASE_MICROMIPS) { + /* microMIPS mode */ + abi_ulong instr[2]; + + ret = get_user_u16(instr[0], env->active_tc.PC) || + get_user_u16(instr[1], env->active_tc.PC + 2); + + trap_instr = (instr[0] << 16) | instr[1]; + } else { + /* MIPS16e mode */ + ret = get_user_u16(trap_instr, env->active_tc.PC); + if (ret != 0) { + goto error; + } + code = (trap_instr >> 6) & 0x3f; + if (do_break(env, &info, code) != 0) { + goto error; + } + break; + } + } else { + ret = get_user_ual(trap_instr, env->active_tc.PC); + } + if (ret != 0) { goto error; } @@ -2373,14 +2359,30 @@ done_syscall: abi_ulong trap_instr; unsigned int code = 0; - ret = get_user_ual(trap_instr, env->active_tc.PC); + if (env->hflags & MIPS_HFLAG_M16) { + /* microMIPS mode */ + abi_ulong instr[2]; + + ret = get_user_u16(instr[0], env->active_tc.PC) || + get_user_u16(instr[1], env->active_tc.PC + 2); + + trap_instr = (instr[0] << 16) | instr[1]; + } else { + ret = get_user_ual(trap_instr, env->active_tc.PC); + } + if (ret != 0) { goto error; } /* The immediate versions don't provide a code. */ if (!(trap_instr & 0xFC000000)) { - code = ((trap_instr >> 6) & ((1 << 10) - 1)); + if (env->hflags & MIPS_HFLAG_M16) { + /* microMIPS mode */ + code = ((trap_instr >> 12) & ((1 << 4) - 1)); + } else { + code = ((trap_instr >> 6) & ((1 << 10) - 1)); + } } if (do_break(env, &info, code) != 0) { @@ -3157,12 +3159,7 @@ THREAD CPUState *thread_cpu; void task_settid(TaskState *ts) { if (ts->ts_tid == 0) { -#ifdef CONFIG_USE_NPTL ts->ts_tid = (pid_t)syscall(SYS_gettid); -#else - /* when no threads are used, tid becomes pid */ - ts->ts_tid = getpid(); -#endif } } @@ -3640,9 +3637,7 @@ int main(int argc, char **argv, char **envp) exit(1); } cpu = ENV_GET_CPU(env); -#if defined(TARGET_SPARC) || defined(TARGET_PPC) - cpu_reset(cpu); -#endif + cpu_reset(ENV_GET_CPU(env)); thread_cpu = cpu; diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h index c3e5c55b3d..d550989d5e 100644 --- a/linux-user/microblaze/syscall.h +++ b/linux-user/microblaze/syscall.h @@ -48,4 +48,6 @@ struct target_pt_regs { uint32_t kernel_mode; }; +#define TARGET_CLONE_BACKWARDS + #endif diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h index 3deb862cc4..9d437d918b 100644 --- a/linux-user/mips/syscall.h +++ b/linux-user/mips/syscall.h @@ -225,3 +225,5 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h index cd707df32f..1710f766e2 100644 --- a/linux-user/mips64/syscall.h +++ b/linux-user/mips64/syscall.h @@ -222,3 +222,5 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips64" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/mmap.c b/linux-user/mmap.c index de2219768d..a249f0ceb6 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -33,7 +33,6 @@ //#define DEBUG_MMAP -#if defined(CONFIG_USE_NPTL) static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static __thread int mmap_lock_count; @@ -66,16 +65,6 @@ void mmap_fork_end(int child) else pthread_mutex_unlock(&mmap_mutex); } -#else -/* We aren't threadsafe to start with, so no need to worry about locking. */ -void mmap_lock(void) -{ -} - -void mmap_unlock(void) -{ -} -#endif /* NOTE: all the constants are the HOST ones, but addresses are target. */ int target_mprotect(abi_ulong start, abi_ulong len, int prot) diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h index 501fb81162..32a46ac840 100644 --- a/linux-user/openrisc/target_cpu.h +++ b/linux-user/openrisc/target_cpu.h @@ -25,9 +25,14 @@ static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) if (newsp) { env->gpr[1] = newsp; } - env->gpr[2] = 0; + env->gpr[11] = 0; } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls) +{ + /* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS + * in copy_thread(), so QEMU need not do so either. + */ +} #endif diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h index 481047b2dd..ba36acbc33 100644 --- a/linux-user/ppc/syscall.h +++ b/linux-user/ppc/syscall.h @@ -62,3 +62,5 @@ struct target_revectored_struct { #else #define UNAME_MACHINE "ppc" #endif + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 6569608b64..4a16e8fe1d 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -16,16 +16,10 @@ #include "exec/user/thunk.h" #include "syscall_defs.h" #include "syscall.h" -#include "target_cpu.h" -#include "target_signal.h" #include "exec/gdbstub.h" #include "qemu/queue.h" -#if defined(CONFIG_USE_NPTL) #define THREAD __thread -#else -#define THREAD -#endif /* This struct is used to hold certain information about the image. * Basically, it replicates in user space what would be certain @@ -118,11 +112,10 @@ typedef struct TaskState { uint32_t v86flags; uint32_t v86mask; #endif -#ifdef CONFIG_USE_NPTL abi_ulong child_tidptr; -#endif #ifdef TARGET_M68K int sim_syscalls; + abi_ulong tp_value; #endif #if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) /* Extra fields for semihosted binaries. */ @@ -269,10 +262,8 @@ void mmap_unlock(void); abi_ulong mmap_find_vma(abi_ulong, abi_ulong); void cpu_list_lock(void); void cpu_list_unlock(void); -#if defined(CONFIG_USE_NPTL) void mmap_fork_start(void); void mmap_fork_end(int child); -#endif /* main.c */ extern unsigned long guest_stack_size; @@ -450,8 +441,13 @@ static inline void *lock_user_string(abi_ulong guest_addr) #define unlock_user_struct(host_ptr, guest_addr, copy) \ unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) -#if defined(CONFIG_USE_NPTL) #include <pthread.h> -#endif + +/* Include target-specific struct and function definitions; + * they may need access to the target-independent structures + * above, so include them last. + */ +#include "target_cpu.h" +#include "target_signal.h" #endif /* QEMU_H */ diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h index e4603b79c3..ea8c304840 100644 --- a/linux-user/s390x/syscall.h +++ b/linux-user/s390x/syscall.h @@ -21,3 +21,5 @@ struct target_pt_regs { }; #define UNAME_MACHINE "s390x" + +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h index 5a9bb7e546..4cd64bf41d 100644 --- a/linux-user/sparc/syscall.h +++ b/linux-user/sparc/syscall.h @@ -7,3 +7,10 @@ struct target_pt_regs { }; #define UNAME_MACHINE "sun4" + +/* SPARC kernels don't define this in their Kconfig, but they have the + * same ABI as if they did, implemented by sparc-specific code which fishes + * directly in the u_regs() struct for half the parameters in sparc_do_fork() + * and copy_thread(). + */ +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h index 5a620a2bb7..4944d465a2 100644 --- a/linux-user/sparc/target_cpu.h +++ b/linux-user/sparc/target_cpu.h @@ -25,12 +25,20 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) if (newsp) { env->regwptr[22] = newsp; } + /* syscall return for clone child: 0, and clear CF since + * this counts as a success return value. + */ env->regwptr[0] = 0; - /* FIXME: Do we also need to clear CF? */ - /* XXXXX */ - printf("HELPME: %s:%d\n", __FILE__, __LINE__); +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) + env->xcc &= ~PSR_CARRY; +#else + env->psr &= ~PSR_CARRY; +#endif } -/* TODO: need to implement cpu_set_tls() */ +static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) +{ + env->gregs[7] = newtls; +} #endif diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h index 81a816de94..e60bf311c0 100644 --- a/linux-user/sparc64/syscall.h +++ b/linux-user/sparc64/syscall.h @@ -8,3 +8,10 @@ struct target_pt_regs { }; #define UNAME_MACHINE "sun4u" + +/* SPARC kernels don't define this in their Kconfig, but they have the + * same ABI as if they did, implemented by sparc-specific code which fishes + * directly in the u_regs() struct for half the parameters in sparc_do_fork() + * and copy_thread(). + */ +#define TARGET_CLONE_BACKWARDS diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 00a0390ea9..3f6db4b0d1 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -111,13 +111,8 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include "qemu.h" -#if defined(CONFIG_USE_NPTL) #define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) -#else -/* XXX: Hardcode the above values. */ -#define CLONE_NPTL_FLAGS2 0 -#endif //#define DEBUG @@ -234,12 +229,10 @@ _syscall1(int,exit_group,int,error_code) #if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) _syscall1(int,set_tid_address,int *,tidptr) #endif -#if defined(CONFIG_USE_NPTL) #if defined(TARGET_NR_futex) && defined(__NR_futex) _syscall6(int,sys_futex,int *,uaddr,int,op,int,val, const struct timespec *,timeout,int *,uaddr2,int,val3) #endif -#endif #define __NR_sys_sched_getaffinity __NR_sched_getaffinity _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); @@ -1039,6 +1032,9 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, #elif defined(TARGET_SH4) ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; return host_pipe[0]; +#elif defined(TARGET_SPARC) + ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1]; + return host_pipe[0]; #endif } @@ -4055,7 +4051,7 @@ static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, } #if defined(TARGET_I386) && defined(TARGET_ABI32) -static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) { uint64_t *gdt_table = g2h(env->gdt.base); struct target_modify_ldt_ldt_s ldt_info; @@ -4189,7 +4185,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) #endif /* TARGET_I386 && TARGET_ABI32 */ #ifndef TARGET_ABI32 -static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) { abi_long ret = 0; abi_ulong val; @@ -4227,7 +4223,6 @@ static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) #define NEW_STACK_SIZE 0x40000 -#if defined(CONFIG_USE_NPTL) static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; typedef struct { @@ -4272,16 +4267,6 @@ static void *clone_func(void *arg) /* never exits */ return NULL; } -#else - -static int clone_func(void *arg) -{ - CPUArchState *env = arg; - cpu_loop(env); - /* never exits */ - return 0; -} -#endif /* do_fork() Must return host values and target errnos (unlike most do_*() functions). */ @@ -4292,12 +4277,8 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, int ret; TaskState *ts; CPUArchState *new_env; -#if defined(CONFIG_USE_NPTL) unsigned int nptl_flags; sigset_t sigmask; -#else - uint8_t *new_stack; -#endif /* Emulate vfork() with fork() */ if (flags & CLONE_VFORK) @@ -4305,23 +4286,18 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, if (flags & CLONE_VM) { TaskState *parent_ts = (TaskState *)env->opaque; -#if defined(CONFIG_USE_NPTL) new_thread_info info; pthread_attr_t attr; -#endif + ts = g_malloc0(sizeof(TaskState)); init_task_state(ts); /* we create a new CPU instance. */ new_env = cpu_copy(env); -#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC) - cpu_reset(ENV_GET_CPU(new_env)); -#endif /* Init regs that differ from the parent. */ cpu_clone_regs(new_env, newsp); new_env->opaque = ts; ts->bprm = parent_ts->bprm; ts->info = parent_ts->info; -#if defined(CONFIG_USE_NPTL) nptl_flags = flags; flags &= ~CLONE_NPTL_FLAGS2; @@ -4371,17 +4347,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, pthread_cond_destroy(&info.cond); pthread_mutex_destroy(&info.mutex); pthread_mutex_unlock(&clone_lock); -#else - if (flags & CLONE_NPTL_FLAGS2) - return -EINVAL; - /* This is probably going to die very quickly, but do it anyway. */ - new_stack = g_malloc0 (NEW_STACK_SIZE); -#ifdef __ia64__ - ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env); -#else - ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); -#endif -#endif } else { /* if no CLONE_VM, we consider it is a fork */ if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) @@ -4392,7 +4357,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, /* Child Process. */ cpu_clone_regs(env, newsp); fork_end(1); -#if defined(CONFIG_USE_NPTL) /* There is a race condition here. The parent process could theoretically read the TID in the child process before the child tid is set. This would require using either ptrace @@ -4408,7 +4372,6 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, cpu_set_tls (env, newtls); if (flags & CLONE_CHILD_CLEARTID) ts->child_tidptr = child_tidptr; -#endif } else { fork_end(0); } @@ -4834,7 +4797,6 @@ static inline abi_long host_to_target_stat64(void *cpu_env, } #endif -#if defined(CONFIG_USE_NPTL) /* ??? Using host futex calls even when target atomic operations are not really atomic probably breaks things. However implementing futexes locally would make futexes shared between multiple processes @@ -4886,7 +4848,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, return -TARGET_ENOSYS; } } -#endif /* Map host to target signal numbers for the wait family of syscalls. Assume all other status bits are the same. */ @@ -5132,9 +5093,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { -#ifdef CONFIG_USE_NPTL CPUState *cpu = ENV_GET_CPU(cpu_env); -#endif abi_long ret; struct stat st; struct statfs stfs; @@ -5148,7 +5107,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, switch(num) { case TARGET_NR_exit: -#ifdef CONFIG_USE_NPTL /* In old applications this may be used to implement _exit(2). However in threaded applictions it is used for thread termination, and _exit_group is used for application termination. @@ -5186,7 +5144,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, g_free(ts); pthread_exit(NULL); } -#endif #ifdef TARGET_GPROF _mcleanup(); #endif @@ -6956,16 +6913,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(fsync(arg1)); break; case TARGET_NR_clone: -#if defined(TARGET_SH4) || defined(TARGET_ALPHA) - 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) + /* Linux manages to have three different orderings for its + * arguments to clone(); the BACKWARDS and BACKWARDS2 defines + * match the kernel's CONFIG_CLONE_* settings. + * Microblaze is further special in that it uses a sixth + * implicit argument to clone for the TLS pointer. + */ +#if defined(TARGET_MICROBLAZE) ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); -#elif defined(TARGET_S390X) +#elif defined(TARGET_CLONE_BACKWARDS) + ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); +#elif defined(TARGET_CLONE_BACKWARDS2) ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); #else - ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); + ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); #endif break; #ifdef __NR_exit_group @@ -8558,6 +8519,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #elif defined(TARGET_I386) && defined(TARGET_ABI32) ret = do_set_thread_area(cpu_env, arg1); break; +#elif defined(TARGET_M68K) + { + TaskState *ts = ((CPUArchState *)cpu_env)->opaque; + ts->tp_value = arg1; + break; + } #else goto unimplemented_nowarn; #endif @@ -8566,6 +8533,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_get_thread_area: #if defined(TARGET_I386) && defined(TARGET_ABI32) ret = do_get_thread_area(cpu_env, arg1); + break; +#elif defined(TARGET_M68K) + { + TaskState *ts = ((CPUArchState *)cpu_env)->opaque; + ret = ts->tp_value; + break; + } #else goto unimplemented_nowarn; #endif @@ -8670,11 +8644,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; #endif -#if defined(CONFIG_USE_NPTL) case TARGET_NR_futex: ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6); break; -#endif #if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) case TARGET_NR_inotify_init: ret = get_errno(sys_inotify_init()); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 92c01a9603..086fbfffe7 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1138,8 +1138,7 @@ struct target_winsize { #endif #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \ - || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \ - || defined(TARGET_OPENRISC) + || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) struct target_stat { unsigned short st_dev; unsigned short __pad1; @@ -1837,29 +1836,55 @@ struct target_stat { abi_ulong __unused[3]; }; #elif defined(TARGET_OPENRISC) + +/* These are the asm-generic versions of the stat and stat64 structures */ + struct target_stat { abi_ulong st_dev; abi_ulong st_ino; - abi_ulong st_nlink; - unsigned int st_mode; + unsigned int st_nlink; unsigned int st_uid; unsigned int st_gid; - unsigned int __pad0; abi_ulong st_rdev; + abi_ulong __pad1; abi_long st_size; - abi_long st_blksize; - abi_long st_blocks; /* Number 512-byte blocks allocated. */ - - abi_ulong target_st_atime; + int st_blksize; + int __pad2; + abi_long st_blocks; + abi_long target_st_atime; abi_ulong target_st_atime_nsec; - abi_ulong target_st_mtime; + abi_long target_st_mtime; abi_ulong target_st_mtime_nsec; - abi_ulong target_st_ctime; + abi_long target_st_ctime; abi_ulong target_st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; - abi_long __unused[3]; +struct target_stat64 { + uint64_t st_dev; + uint64_t st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + uint64_t st_rdev; + uint64_t __pad1; + int64_t st_size; + int st_blksize; + int __pad2; + int64_t st_blocks; + int target_st_atime; + unsigned int target_st_atime_nsec; + int target_st_mtime; + unsigned int target_st_mtime_nsec; + int target_st_ctime; + unsigned int target_st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; }; + #else #error unsupported CPU #endif @@ -2434,8 +2459,11 @@ typedef union target_epoll_data { struct target_epoll_event { uint32_t events; +#ifdef TARGET_ARM + uint32_t __pad; +#endif target_epoll_data_t data; -}; +} QEMU_PACKED; #endif struct target_rlimit64 { uint64_t rlim_cur; diff --git a/memory.c b/memory.c index 01846c9768..1494e955d4 100644 --- a/memory.c +++ b/memory.c @@ -339,28 +339,65 @@ static void flatview_simplify(FlatView *view) } } -static void memory_region_oldmmio_read_accessor(void *opaque, +static bool memory_region_big_endian(MemoryRegion *mr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return mr->ops->endianness != DEVICE_LITTLE_ENDIAN; +#else + return mr->ops->endianness == DEVICE_BIG_ENDIAN; +#endif +} + +static bool memory_region_wrong_endianness(MemoryRegion *mr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return mr->ops->endianness == DEVICE_LITTLE_ENDIAN; +#else + return mr->ops->endianness == DEVICE_BIG_ENDIAN; +#endif +} + +static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) +{ + if (memory_region_wrong_endianness(mr)) { + switch (size) { + case 1: + break; + case 2: + *data = bswap16(*data); + break; + case 4: + *data = bswap32(*data); + break; + case 8: + *data = bswap64(*data); + break; + default: + abort(); + } + } +} + +static void memory_region_oldmmio_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); *value |= (tmp & mask) << shift; } -static void memory_region_read_accessor(void *opaque, +static void memory_region_read_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; if (mr->flush_coalesced_mmio) { @@ -370,28 +407,26 @@ static void memory_region_read_accessor(void *opaque, *value |= (tmp & mask) << shift; } -static void memory_region_oldmmio_write_accessor(void *opaque, +static void memory_region_oldmmio_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; tmp = (*value >> shift) & mask; mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); } -static void memory_region_write_accessor(void *opaque, +static void memory_region_write_accessor(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask) { - MemoryRegion *mr = opaque; uint64_t tmp; if (mr->flush_coalesced_mmio) { @@ -406,13 +441,13 @@ static void access_with_adjusted_size(hwaddr addr, unsigned size, unsigned access_size_min, unsigned access_size_max, - void (*access)(void *opaque, + void (*access)(MemoryRegion *mr, hwaddr addr, uint64_t *value, unsigned size, unsigned shift, uint64_t mask), - void *opaque) + MemoryRegion *mr) { uint64_t access_mask; unsigned access_size; @@ -428,13 +463,15 @@ static void access_with_adjusted_size(hwaddr addr, /* FIXME: support unaligned access? */ access_size = MAX(MIN(size, access_size_max), access_size_min); access_mask = -1ULL >> (64 - access_size * 8); - for (i = 0; i < size; i += access_size) { -#ifdef TARGET_WORDS_BIGENDIAN - access(opaque, addr + i, value, access_size, - (size - access_size - i) * 8, access_mask); -#else - access(opaque, addr + i, value, access_size, i * 8, access_mask); -#endif + if (memory_region_big_endian(mr)) { + for (i = 0; i < size; i += access_size) { + access(mr, addr + i, value, access_size, + (size - access_size - i) * 8, access_mask); + } + } else { + for (i = 0; i < size; i += access_size) { + access(mr, addr + i, value, access_size, i * 8, access_mask); + } } } @@ -786,15 +823,6 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr) qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); } -static bool memory_region_wrong_endianness(MemoryRegion *mr) -{ -#ifdef TARGET_WORDS_BIGENDIAN - return mr->ops->endianness == DEVICE_LITTLE_ENDIAN; -#else - return mr->ops->endianness == DEVICE_BIG_ENDIAN; -#endif -} - void memory_region_init(MemoryRegion *mr, Object *owner, const char *name, @@ -921,27 +949,6 @@ static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, return data; } -static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size) -{ - if (memory_region_wrong_endianness(mr)) { - switch (size) { - case 1: - break; - case 2: - *data = bswap16(*data); - break; - case 4: - *data = bswap32(*data); - break; - case 8: - *data = bswap64(*data); - break; - default: - abort(); - } - } -} - static bool memory_region_dispatch_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, diff --git a/po/Makefile b/po/Makefile index 60ccd7d3bb..705166e2d3 100644 --- a/po/Makefile +++ b/po/Makefile @@ -1,20 +1,23 @@ # This makefile is very special as it's meant to build as part of the build # process and also within the source tree to update the translation files. -VERSION=$(shell cat ../VERSION) -SRCS=$(filter-out messages.po,$(wildcard *.po)) -OBJS=$(patsubst %.po,%.mo,$(SRCS)) - +# Set SRC_PATH for in-tree builds without configuration. SRC_PATH=.. -include ../config-host.mak +include $(SRC_PATH)/rules.mak + +PO_PATH=$(SRC_PATH)/po + +VERSION=$(shell cat $(SRC_PATH)/VERSION) +SRCS=$(filter-out $(PO_PATH)/messages.po,$(wildcard $(PO_PATH)/*.po)) +OBJS=$(patsubst $(PO_PATH)/%.po,%.mo,$(SRCS)) -vpath %.po $(SRC_PATH)/po +vpath %.po $(PO_PATH) all: - @echo Use 'make update' to update translation files - @echo or us 'make build' or 'make install' to build and install - @echo the translation files + @echo "Use 'make update' to update translation files or use 'make build'" + @echo "or 'make install' to build and install the translation files." update: $(SRCS) @@ -31,12 +34,16 @@ install: $(OBJS) done %.mo: %.po - @msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po + $(call quiet-command, msgfmt -o $@ $<, " GEN $@") -messages.po: $(SRC_PATH)/ui/gtk.c - @xgettext -o $@ --foreign-user --package-name=QEMU --package-version=$(VERSION) --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C $< +$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c + $(call quiet-command, cd $(SRC_PATH) && \ + (xgettext -o - --from-code=UTF-8 --foreign-user \ + --package-name=QEMU --package-version=$(VERSION) \ + --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \ + sed -e s/CHARSET/UTF-8/) >$@, " GEN $@") -%.po: messages.po - @msgmerge $@ $< > $@.bak && mv $@.bak $@ +$(PO_PATH)/%.po: $(PO_PATH)/messages.po + $(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@, " GEN $@") .PHONY: clean all diff --git a/tests/Makefile b/tests/Makefile index 6c34eec1d2..cdbb79e111 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -53,7 +53,8 @@ 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) +check-qtest-i386-y = tests/endianness-test$(EXESUF) +check-qtest-i386-y += tests/fdc-test$(EXESUF) gcov-files-i386-y = hw/fdc.c check-qtest-i386-y += tests/ide-test$(EXESUF) check-qtest-i386-y += tests/hd-geo-test$(EXESUF) @@ -65,8 +66,16 @@ check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) check-qtest-x86_64-y = $(check-qtest-i386-y) gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y)) +check-qtest-mips-y = tests/endianness-test$(EXESUF) +check-qtest-mips64-y = tests/endianness-test$(EXESUF) +check-qtest-mips64el-y = tests/endianness-test$(EXESUF) +check-qtest-ppc-y = tests/endianness-test$(EXESUF) +check-qtest-ppc64-y = tests/endianness-test$(EXESUF) +check-qtest-sh4-y = tests/endianness-test$(EXESUF) +check-qtest-sh4eb-y = tests/endianness-test$(EXESUF) +check-qtest-sparc64-y = tests/endianness-test$(EXESUF) #check-qtest-sparc-y = tests/m48t59-test$(EXESUF) -#check-qtest-sparc64-y = tests/m48t59-test$(EXESUF) +#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF) gcov-files-sparc-y += hw/m48t59.c gcov-files-sparc64-y += hw/m48t59.c check-qtest-arm-y = tests/tmp105-test$(EXESUF) @@ -136,6 +145,7 @@ libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o +tests/endianness-test$(EXESUF): tests/endianness-test.o tests/fdc-test$(EXESUF): tests/fdc-test.o tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y) tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o diff --git a/tests/endianness-test.c b/tests/endianness-test.c new file mode 100644 index 0000000000..feb32a8503 --- /dev/null +++ b/tests/endianness-test.c @@ -0,0 +1,316 @@ +/* + * QTest testcase for ISA endianness + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Paolo Bonzini <pbonzini@redhat.com> + * + * 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 "libqtest.h" + +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "qemu/bswap.h" + +typedef struct TestCase TestCase; +struct TestCase { + const char *arch; + const char *machine; + uint64_t isa_base; + bool bswap; + const char *superio; +}; + +static const TestCase test_cases[] = { + { "i386", "pc", -1 }, + { "mips", "magnum", 0x90000000, .bswap = true }, + { "mips", "pica61", 0x90000000, .bswap = true }, + { "mips", "mips", 0x14000000, .bswap = true }, + { "mips", "malta", 0x10000000, .bswap = true }, + { "mips64", "magnum", 0x90000000, .bswap = true }, + { "mips64", "pica61", 0x90000000, .bswap = true }, + { "mips64", "mips", 0x14000000, .bswap = true }, + { "mips64", "malta", 0x10000000, .bswap = true }, + { "mips64el", "fulong2e", 0x1fd00000 }, + { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" }, + { "ppc", "prep", 0x80000000, .bswap = true }, + { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" }, + { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" }, + { "ppc64", "pseries", 0x10080000000, .bswap = true, .superio = "i82378" }, + { "sh4", "r2d", 0xfe240000, .superio = "i82378" }, + { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" }, + { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true }, + { "x86_64", "pc", -1 }, + {} +}; + +static uint8_t isa_inb(const TestCase *test, uint16_t addr) +{ + uint8_t value; + if (test->isa_base == -1) { + value = inb(addr); + } else { + value = readb(test->isa_base + addr); + } + return value; +} + +static uint16_t isa_inw(const TestCase *test, uint16_t addr) +{ + uint16_t value; + if (test->isa_base == -1) { + value = inw(addr); + } else { + value = readw(test->isa_base + addr); + } + return test->bswap ? bswap16(value) : value; +} + +static uint32_t isa_inl(const TestCase *test, uint16_t addr) +{ + uint32_t value; + if (test->isa_base == -1) { + value = inl(addr); + } else { + value = readl(test->isa_base + addr); + } + return test->bswap ? bswap32(value) : value; +} + +static void isa_outb(const TestCase *test, uint16_t addr, uint8_t value) +{ + if (test->isa_base == -1) { + outb(addr, value); + } else { + writeb(test->isa_base + addr, value); + } +} + +static void isa_outw(const TestCase *test, uint16_t addr, uint16_t value) +{ + value = test->bswap ? bswap16(value) : value; + if (test->isa_base == -1) { + outw(addr, value); + } else { + writew(test->isa_base + addr, value); + } +} + +static void isa_outl(const TestCase *test, uint16_t addr, uint32_t value) +{ + value = test->bswap ? bswap32(value) : value; + if (test->isa_base == -1) { + outl(addr, value); + } else { + writel(test->isa_base + addr, value); + } +} + + +static void test_endianness(gconstpointer data) +{ + const TestCase *test = data; + char *args; + + args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev", + test->machine, + test->superio ? " -device " : "", + test->superio ?: ""); + qtest_start(args); + isa_outl(test, 0xe0, 0x87654321); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21); + + isa_outw(test, 0xe2, 0x8866); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21); + + isa_outw(test, 0xe0, 0x4422); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22); + + isa_outb(test, 0xe3, 0x87); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22); + + isa_outb(test, 0xe2, 0x65); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22); + + isa_outb(test, 0xe1, 0x43); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22); + + isa_outb(test, 0xe0, 0x21); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87); + g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65); + g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43); + g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21); + qtest_quit(global_qtest); + g_free(args); +} + +static void test_endianness_split(gconstpointer data) +{ + const TestCase *test = data; + char *args; + + args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev", + test->machine, + test->superio ? " -device " : "", + test->superio ?: ""); + qtest_start(args); + isa_outl(test, 0xe8, 0x87654321); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + + isa_outw(test, 0xea, 0x8866); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + + isa_outw(test, 0xe8, 0x4422); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422); + + isa_outb(test, 0xeb, 0x87); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766); + + isa_outb(test, 0xea, 0x65); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422); + + isa_outb(test, 0xe9, 0x43); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322); + + isa_outb(test, 0xe8, 0x21); + g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321); + qtest_quit(global_qtest); + g_free(args); +} + +static void test_endianness_combine(gconstpointer data) +{ + const TestCase *test = data; + char *args; + + args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev", + test->machine, + test->superio ? " -device " : "", + test->superio ?: ""); + qtest_start(args); + isa_outl(test, 0xe0, 0x87654321); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321); + + isa_outw(test, 0xe2, 0x8866); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664321); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321); + + isa_outw(test, 0xe0, 0x4422); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664422); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422); + + isa_outb(test, 0xe3, 0x87); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87664422); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8766); + + isa_outb(test, 0xe2, 0x65); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654422); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422); + + isa_outb(test, 0xe1, 0x43); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654322); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4322); + + isa_outb(test, 0xe0, 0x21); + g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321); + g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765); + g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321); + qtest_quit(global_qtest); + g_free(args); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + int ret; + int i; + + g_test_init(&argc, &argv, NULL); + + for (i = 0; test_cases[i].arch; i++) { + gchar *path; + if (strcmp(test_cases[i].arch, arch) != 0) { + continue; + } + path = g_strdup_printf("/%s/endianness/%s", + arch, test_cases[i].machine); + g_test_add_data_func(path, &test_cases[i], test_endianness); + + path = g_strdup_printf("/%s/endianness/split/%s", + arch, test_cases[i].machine); + g_test_add_data_func(path, &test_cases[i], test_endianness_split); + + path = g_strdup_printf("/%s/endianness/combine/%s", + arch, test_cases[i].machine); + g_test_add_data_func(path, &test_cases[i], test_endianness_combine); + } + + ret = g_test_run(); + + return ret; +} diff --git a/translate-all.c b/translate-all.c index e8683d2c66..3b5fc7c901 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1148,7 +1148,8 @@ void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len) #if !defined(CONFIG_SOFTMMU) static void tb_invalidate_phys_page(tb_page_addr_t addr, - uintptr_t pc, void *puc) + uintptr_t pc, void *puc, + bool locked) { TranslationBlock *tb; PageDesc *p; @@ -1206,6 +1207,9 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, itself */ cpu->current_tb = NULL; tb_gen_code(env, current_pc, current_cs_base, current_flags, 1); + if (locked) { + mmap_unlock(); + } cpu_resume_from_signal(env, puc); } #endif @@ -1723,7 +1727,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) if (!(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE) && p->first_tb) { - tb_invalidate_phys_page(addr, 0, NULL); + tb_invalidate_phys_page(addr, 0, NULL, false); } p->flags = flags; } @@ -1818,7 +1822,7 @@ int page_unprotect(target_ulong address, uintptr_t pc, void *puc) /* and since the content will be modified, we must invalidate the corresponding translated code. */ - tb_invalidate_phys_page(addr, pc, puc); + tb_invalidate_phys_page(addr, pc, puc, true); #ifdef DEBUG_TB_CHECK tb_invalidate_check(addr); #endif diff --git a/user-exec.c b/user-exec.c index d45ca8e877..82bfa66ce3 100644 --- a/user-exec.c +++ b/user-exec.c @@ -95,6 +95,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, return 1; } + /* Convert forcefully to guest address space, invalid addresses + are still valid segv ones */ + address = h2g_nocheck(address); + env = current_cpu->env_ptr; /* see if it is an MMU fault */ ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX); |