aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/usb2.txt4
-rw-r--r--hw/display/Makefile.objs4
-rw-r--r--hw/display/qxl.c1
-rw-r--r--hw/display/qxl.h1
-rw-r--r--hw/display/vga-isa-mm.c60
-rw-r--r--hw/pci-host/bonito.c145
-rw-r--r--hw/ppc/Makefile.objs2
-rw-r--r--hw/ppc/mac_newworld.c12
-rw-r--r--hw/ppc/mac_oldworld.c12
-rw-r--r--hw/ppc/ppc405_boards.c60
-rw-r--r--hw/ppc/ppc405_uc.c173
-rw-r--r--hw/ppc/prep.c111
-rw-r--r--hw/ppc/spapr.c225
-rw-r--r--hw/ppc/spapr_cpu_core.c63
-rw-r--r--hw/ppc/spapr_events.c12
-rw-r--r--hw/ppc/spapr_irq.c286
-rw-r--r--hw/ppc/spapr_pci.c32
-rw-r--r--hw/ppc/spapr_vio.c66
-rw-r--r--hw/usb/dev-mtp.c93
-rw-r--r--hw/usb/hcd-ohci.c3
-rw-r--r--hw/vfio/common.c3
-rw-r--r--hw/vfio/spapr.c21
-rw-r--r--include/hw/ppc/spapr.h16
-rw-r--r--include/hw/ppc/spapr_irq.h54
-rw-r--r--include/hw/ppc/xics.h1
-rw-r--r--include/hw/vfio/vfio-common.h1
-rw-r--r--job.c2
-rw-r--r--linux-user/syscall.c1609
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/slof.binbin924840 -> 974544 bytes
-rw-r--r--qemu-deprecated.texi6
m---------roms/SLOF0
-rw-r--r--target/ppc/cpu.h5
-rw-r--r--target/ppc/excp_helper.c11
-rw-r--r--target/ppc/fpu_helper.c292
-rw-r--r--target/ppc/helper.h14
-rw-r--r--target/ppc/int_helper.c46
-rw-r--r--target/ppc/translate.c107
-rw-r--r--target/ppc/translate/fp-impl.inc.c26
-rw-r--r--target/ppc/translate_init.inc.c19
-rw-r--r--tests/boot-serial-test.c2
-rwxr-xr-xtests/qemu-iotests/22995
-rw-r--r--tests/qemu-iotests/229.out23
-rw-r--r--tests/qemu-iotests/group1
44 files changed, 1816 insertions, 1905 deletions
diff --git a/docs/usb2.txt b/docs/usb2.txt
index f63c8d9465..172614d3a7 100644
--- a/docs/usb2.txt
+++ b/docs/usb2.txt
@@ -94,8 +94,8 @@ physical port addressing
First you can (for all USB devices) specify the physical port where
the device will show up in the guest. This can be done using the
-"port" property. UHCI has two root ports (1,2). EHCI has four root
-ports (1-4), the emulated (1.1) USB hub has eight ports.
+"port" property. UHCI has two root ports (1,2). EHCI has six root
+ports (1-6), the emulated (1.1) USB hub has eight ports.
Plugging a tablet into UHCI port 1 works like this:
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index fb8408c6d0..a606fb7404 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -1,5 +1,5 @@
-common-obj-y += ramfb.o
-common-obj-y += ramfb-standalone.o
+common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o
+common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o
common-obj-$(CONFIG_ADS7846) += ads7846.o
common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 830c392c53..8e9135d9c6 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2057,7 +2057,6 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
qemu_spice_display_init_common(&qxl->ssd);
qxl->mode = QXL_MODE_UNDEFINED;
- qxl->generation = 1;
qxl->num_memslots = NUM_MEMSLOTS;
qemu_mutex_init(&qxl->track_lock);
qemu_mutex_init(&qxl->async_lock);
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index 089696ef62..6eacba080d 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -43,7 +43,6 @@ typedef struct PCIQXLDevice {
enum qxl_mode mode;
uint32_t cmdflags;
- int generation;
uint32_t revision;
int32_t num_memslots;
diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c
index 232216cad0..215e649719 100644
--- a/hw/display/vga-isa-mm.c
+++ b/hw/display/vga-isa-mm.c
@@ -36,64 +36,30 @@ typedef struct ISAVGAMMState {
} ISAVGAMMState;
/* Memory mapped interface */
-static uint32_t vga_mm_readb (void *opaque, hwaddr addr)
+static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size)
{
ISAVGAMMState *s = opaque;
- return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xff;
+ return vga_ioport_read(&s->vga, addr >> s->it_shift) &
+ MAKE_64BIT_MASK(0, size * 8);
}
-static void vga_mm_writeb (void *opaque,
- hwaddr addr, uint32_t value)
+static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
{
ISAVGAMMState *s = opaque;
- vga_ioport_write(&s->vga, addr >> s->it_shift, value & 0xff);
-}
-
-static uint32_t vga_mm_readw (void *opaque, hwaddr addr)
-{
- ISAVGAMMState *s = opaque;
-
- return vga_ioport_read(&s->vga, addr >> s->it_shift) & 0xffff;
-}
-
-static void vga_mm_writew (void *opaque,
- 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, hwaddr addr)
-{
- ISAVGAMMState *s = opaque;
-
- return vga_ioport_read(&s->vga, addr >> s->it_shift);
-}
-
-static void vga_mm_writel (void *opaque,
- hwaddr addr, uint32_t value)
-{
- ISAVGAMMState *s = opaque;
-
- vga_ioport_write(&s->vga, addr >> s->it_shift, value);
+ vga_ioport_write(&s->vga, addr >> s->it_shift,
+ value & MAKE_64BIT_MASK(0, size * 8));
}
static const MemoryRegionOps vga_mm_ctrl_ops = {
- .old_mmio = {
- .read = {
- vga_mm_readb,
- vga_mm_readw,
- vga_mm_readl,
- },
- .write = {
- vga_mm_writeb,
- vga_mm_writew,
- vga_mm_writel,
- },
- },
+ .read = vga_mm_read,
+ .write = vga_mm_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 2d25e9bf7c..9868e2eccc 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -460,34 +460,8 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr)
return pciaddr;
}
-static void bonito_spciconf_writeb(void *opaque, hwaddr addr,
- uint32_t val)
-{
- PCIBonitoState *s = opaque;
- PCIDevice *d = PCI_DEVICE(s);
- PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
- uint32_t pciaddr;
- uint16_t status;
-
- DPRINTF("bonito_spciconf_writeb "TARGET_FMT_plx" val %x\n", addr, val);
- pciaddr = bonito_sbridge_pciaddr(s, addr);
-
- if (pciaddr == 0xffffffff) {
- return;
- }
-
- /* set the pci address in s->config_reg */
- 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(d->config + PCI_STATUS);
- status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
- pci_set_word(d->config + PCI_STATUS, status);
-}
-
-static void bonito_spciconf_writew(void *opaque, hwaddr addr,
- uint32_t val)
+static void bonito_spciconf_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
PCIBonitoState *s = opaque;
PCIDevice *d = PCI_DEVICE(s);
@@ -495,8 +469,8 @@ static void bonito_spciconf_writew(void *opaque, hwaddr addr,
uint32_t pciaddr;
uint16_t status;
- DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);
- assert((addr & 0x1) == 0);
+ DPRINTF("bonito_spciconf_write "TARGET_FMT_plx" size %d val %x\n",
+ addr, size, val);
pciaddr = bonito_sbridge_pciaddr(s, addr);
@@ -506,7 +480,7 @@ static void bonito_spciconf_writew(void *opaque, hwaddr addr,
/* set the pci address in s->config_reg */
phb->config_reg = (pciaddr) | (1u << 31);
- pci_data_write(phb->bus, phb->config_reg, val, 2);
+ pci_data_write(phb->bus, phb->config_reg, val, size);
/* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
status = pci_get_word(d->config + PCI_STATUS);
@@ -514,8 +488,7 @@ static void bonito_spciconf_writew(void *opaque, hwaddr addr,
pci_set_word(d->config + PCI_STATUS, status);
}
-static void bonito_spciconf_writel(void *opaque, hwaddr addr,
- uint32_t val)
+static uint64_t bonito_spciconf_read(void *opaque, hwaddr addr, unsigned size)
{
PCIBonitoState *s = opaque;
PCIDevice *d = PCI_DEVICE(s);
@@ -523,121 +496,33 @@ static void bonito_spciconf_writel(void *opaque, hwaddr addr,
uint32_t pciaddr;
uint16_t status;
- DPRINTF("bonito_spciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
- assert((addr & 0x3) == 0);
+ DPRINTF("bonito_spciconf_read "TARGET_FMT_plx" size %d\n", addr, size);
pciaddr = bonito_sbridge_pciaddr(s, addr);
if (pciaddr == 0xffffffff) {
- return;
+ return MAKE_64BIT_MASK(0, size * 8);
}
/* set the pci address in s->config_reg */
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(d->config + PCI_STATUS);
status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
pci_set_word(d->config + PCI_STATUS, status);
-}
-
-static uint32_t bonito_spciconf_readb(void *opaque, hwaddr addr)
-{
- PCIBonitoState *s = opaque;
- PCIDevice *d = PCI_DEVICE(s);
- PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
- uint32_t pciaddr;
- uint16_t status;
-
- DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"\n", addr);
- pciaddr = bonito_sbridge_pciaddr(s, addr);
- if (pciaddr == 0xffffffff) {
- return 0xff;
- }
-
- /* set the pci address in s->config_reg */
- phb->config_reg = (pciaddr) | (1u << 31);
-
- /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
- status = pci_get_word(d->config + PCI_STATUS);
- status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
- pci_set_word(d->config + PCI_STATUS, status);
-
- return pci_data_read(phb->bus, phb->config_reg, 1);
-}
-
-static uint32_t bonito_spciconf_readw(void *opaque, hwaddr addr)
-{
- PCIBonitoState *s = opaque;
- PCIDevice *d = PCI_DEVICE(s);
- PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
- uint32_t pciaddr;
- uint16_t status;
-
- DPRINTF("bonito_spciconf_readw "TARGET_FMT_plx"\n", addr);
- assert((addr & 0x1) == 0);
-
- pciaddr = bonito_sbridge_pciaddr(s, addr);
-
- if (pciaddr == 0xffffffff) {
- return 0xffff;
- }
-
- /* set the pci address in s->config_reg */
- phb->config_reg = (pciaddr) | (1u << 31);
-
- /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
- status = pci_get_word(d->config + PCI_STATUS);
- status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
- pci_set_word(d->config + PCI_STATUS, status);
-
- return pci_data_read(phb->bus, phb->config_reg, 2);
-}
-
-static uint32_t bonito_spciconf_readl(void *opaque, hwaddr addr)
-{
- PCIBonitoState *s = opaque;
- PCIDevice *d = PCI_DEVICE(s);
- PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
- uint32_t pciaddr;
- uint16_t status;
-
- DPRINTF("bonito_spciconf_readl "TARGET_FMT_plx"\n", addr);
- assert((addr & 0x3) == 0);
-
- pciaddr = bonito_sbridge_pciaddr(s, addr);
-
- if (pciaddr == 0xffffffff) {
- return 0xffffffff;
- }
-
- /* set the pci address in s->config_reg */
- phb->config_reg = (pciaddr) | (1u << 31);
-
- /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */
- status = pci_get_word(d->config + PCI_STATUS);
- status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);
- pci_set_word(d->config + PCI_STATUS, status);
-
- return pci_data_read(phb->bus, phb->config_reg, 4);
+ return pci_data_read(phb->bus, phb->config_reg, size);
}
/* south bridge PCI configure space. 0x1fe8 0000 - 0x1fef ffff */
static const MemoryRegionOps bonito_spciconf_ops = {
- .old_mmio = {
- .read = {
- bonito_spciconf_readb,
- bonito_spciconf_readw,
- bonito_spciconf_readl,
- },
- .write = {
- bonito_spciconf_writeb,
- bonito_spciconf_writew,
- bonito_spciconf_writel,
- },
- },
+ .read = bonito_spciconf_read,
+ .write = bonito_spciconf_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index bcab6323b7..4ab5564672 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -4,7 +4,7 @@ obj-y += ppc.o ppc_booke.o fdt.o
obj-$(CONFIG_PSERIES) += spapr.o spapr_caps.o spapr_vio.o spapr_events.o
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
-obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o
+obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o spapr_irq.o
# IBM PowerNV
obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 2ca294664b..a6b95f024c 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -454,7 +454,17 @@ static void ppc_core99_init(MachineState *machine)
pmac_format_nvram_partition(nvr, 0x2000);
/* No PCI init: the BIOS will do it */
- fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
+ dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
+ fw_cfg = FW_CFG(dev);
+ qdev_prop_set_uint32(dev, "data_width", 1);
+ qdev_prop_set_bit(dev, "dma_enabled", false);
+ object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
+ OBJECT(fw_cfg), NULL);
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(s, 0, CFG_ADDR);
+ sysbus_mmio_map(s, 1, CFG_ADDR + 2);
+
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 064d7eb30a..80b5525775 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -309,7 +309,17 @@ static void ppc_heathrow_init(MachineState *machine)
/* No PCI init: the BIOS will do it */
- fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
+ dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
+ fw_cfg = FW_CFG(dev);
+ qdev_prop_set_uint32(dev, "data_width", 1);
+ qdev_prop_set_bit(dev, "dma_enabled", false);
+ object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
+ OBJECT(fw_cfg), NULL);
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(s, 0, CFG_ADDR);
+ sysbus_mmio_map(s, 1, CFG_ADDR + 2);
+
fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 70111075b3..f5a9c24b6c 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -66,7 +66,7 @@ struct ref405ep_fpga_t {
uint8_t reg1;
};
-static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
+static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size)
{
ref405ep_fpga_t *fpga;
uint32_t ret;
@@ -87,8 +87,8 @@ static uint32_t ref405ep_fpga_readb (void *opaque, hwaddr addr)
return ret;
}
-static void ref405ep_fpga_writeb (void *opaque,
- hwaddr addr, uint32_t value)
+static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
{
ref405ep_fpga_t *fpga;
@@ -105,54 +105,14 @@ static void ref405ep_fpga_writeb (void *opaque,
}
}
-static uint32_t ref405ep_fpga_readw (void *opaque, hwaddr addr)
-{
- uint32_t ret;
-
- ret = ref405ep_fpga_readb(opaque, addr) << 8;
- ret |= ref405ep_fpga_readb(opaque, addr + 1);
-
- return ret;
-}
-
-static void ref405ep_fpga_writew (void *opaque,
- 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, hwaddr addr)
-{
- uint32_t ret;
-
- ret = ref405ep_fpga_readb(opaque, addr) << 24;
- ret |= ref405ep_fpga_readb(opaque, addr + 1) << 16;
- ret |= ref405ep_fpga_readb(opaque, addr + 2) << 8;
- ret |= ref405ep_fpga_readb(opaque, addr + 3);
-
- return ret;
-}
-
-static void ref405ep_fpga_writel (void *opaque,
- hwaddr addr, uint32_t value)
-{
- ref405ep_fpga_writeb(opaque, addr, (value >> 24) & 0xFF);
- ref405ep_fpga_writeb(opaque, addr + 1, (value >> 16) & 0xFF);
- ref405ep_fpga_writeb(opaque, addr + 2, (value >> 8) & 0xFF);
- ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF);
-}
-
static const MemoryRegionOps ref405ep_fpga_ops = {
- .old_mmio = {
- .read = {
- ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl,
- },
- .write = {
- ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel,
- },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .read = ref405ep_fpga_readb,
+ .write = ref405ep_fpga_writeb,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void ref405ep_fpga_reset (void *opaque)
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 4bd9fbcc1e..5c58415cf1 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -283,7 +283,7 @@ struct ppc4xx_opba_t {
uint8_t pr;
};
-static uint32_t opba_readb (void *opaque, hwaddr addr)
+static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size)
{
ppc4xx_opba_t *opba;
uint32_t ret;
@@ -307,8 +307,8 @@ static uint32_t opba_readb (void *opaque, hwaddr addr)
return ret;
}
-static void opba_writeb (void *opaque,
- hwaddr addr, uint32_t value)
+static void opba_writeb(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
{
ppc4xx_opba_t *opba;
@@ -328,61 +328,14 @@ static void opba_writeb (void *opaque,
break;
}
}
-
-static uint32_t opba_readw (void *opaque, hwaddr addr)
-{
- uint32_t ret;
-
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- ret = opba_readb(opaque, addr) << 8;
- ret |= opba_readb(opaque, addr + 1);
-
- return ret;
-}
-
-static void opba_writew (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- opba_writeb(opaque, addr, value >> 8);
- opba_writeb(opaque, addr + 1, value);
-}
-
-static uint32_t opba_readl (void *opaque, hwaddr addr)
-{
- uint32_t ret;
-
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- ret = opba_readb(opaque, addr) << 24;
- ret |= opba_readb(opaque, addr + 1) << 16;
-
- return ret;
-}
-
-static void opba_writel (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_OPBA
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- opba_writeb(opaque, addr, value >> 24);
- opba_writeb(opaque, addr + 1, value >> 16);
-}
-
static const MemoryRegionOps opba_ops = {
- .old_mmio = {
- .read = { opba_readb, opba_readw, opba_readl, },
- .write = { opba_writeb, opba_writew, opba_writel, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .read = opba_readb,
+ .write = opba_writeb,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void ppc4xx_opba_reset (void *opaque)
@@ -750,65 +703,27 @@ struct ppc405_gpio_t {
uint32_t isr1l;
};
-static uint32_t ppc405_gpio_readb (void *opaque, hwaddr addr)
+static uint64_t ppc405_gpio_read(void *opaque, hwaddr addr, unsigned size)
{
#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+ printf("%s: addr " TARGET_FMT_plx " size %d\n", __func__, addr, size);
#endif
return 0;
}
-static void ppc405_gpio_writeb (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readw (void *opaque, hwaddr addr)
+static void ppc405_gpio_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
{
#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
- return 0;
-}
-
-static void ppc405_gpio_writew (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
-}
-
-static uint32_t ppc405_gpio_readl (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
-
- return 0;
-}
-
-static void ppc405_gpio_writel (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_GPIO
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
+ printf("%s: addr " TARGET_FMT_plx " size %d val %08" PRIx32 "\n",
+ __func__, addr, size, value);
#endif
}
static const MemoryRegionOps ppc405_gpio_ops = {
- .old_mmio = {
- .read = { ppc405_gpio_readb, ppc405_gpio_readw, ppc405_gpio_readl, },
- .write = { ppc405_gpio_writeb, ppc405_gpio_writew, ppc405_gpio_writel, },
- },
+ .read = ppc405_gpio_read,
+ .write = ppc405_gpio_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
@@ -1017,44 +932,6 @@ struct ppc4xx_gpt_t {
uint32_t mask[5];
};
-static uint32_t ppc4xx_gpt_readb (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- /* XXX: generate a bus fault */
- return -1;
-}
-
-static void ppc4xx_gpt_writeb (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- /* XXX: generate a bus fault */
-}
-
-static uint32_t ppc4xx_gpt_readw (void *opaque, hwaddr addr)
-{
-#ifdef DEBUG_GPT
- printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
-#endif
- /* XXX: generate a bus fault */
- return -1;
-}
-
-static void ppc4xx_gpt_writew (void *opaque,
- hwaddr addr, uint32_t value)
-{
-#ifdef DEBUG_I2C
- printf("%s: addr " TARGET_FMT_plx " val %08" PRIx32 "\n", __func__, addr,
- value);
-#endif
- /* XXX: generate a bus fault */
-}
-
static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n)
{
/* XXX: TODO */
@@ -1107,7 +984,7 @@ static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt)
/* XXX: TODO */
}
-static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
+static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size)
{
ppc4xx_gpt_t *gpt;
uint32_t ret;
@@ -1162,8 +1039,8 @@ static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr)
return ret;
}
-static void ppc4xx_gpt_writel (void *opaque,
- hwaddr addr, uint32_t value)
+static void ppc4xx_gpt_write(void *opaque, hwaddr addr, uint64_t value,
+ unsigned size)
{
ppc4xx_gpt_t *gpt;
int idx;
@@ -1225,10 +1102,10 @@ static void ppc4xx_gpt_writel (void *opaque,
}
static const MemoryRegionOps gpt_ops = {
- .old_mmio = {
- .read = { ppc4xx_gpt_readb, ppc4xx_gpt_readw, ppc4xx_gpt_readl, },
- .write = { ppc4xx_gpt_writeb, ppc4xx_gpt_writew, ppc4xx_gpt_writel, },
- },
+ .read = ppc4xx_gpt_read,
+ .write = ppc4xx_gpt_write,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 91a8f42834..162b27a3b8 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -78,94 +78,6 @@ static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
/* ISA IO ports bridge */
#define PPC_IO_BASE 0x80000000
-/* PowerPC control and status registers */
-#if 0 // Not used
-static struct {
- /* IDs */
- uint32_t veni_devi;
- uint32_t revi;
- /* Control and status */
- uint32_t gcsr;
- uint32_t xcfr;
- uint32_t ct32;
- uint32_t mcsr;
- /* General purpose registers */
- uint32_t gprg[6];
- /* Exceptions */
- uint32_t feen;
- uint32_t fest;
- uint32_t fema;
- uint32_t fecl;
- uint32_t eeen;
- uint32_t eest;
- uint32_t eecl;
- uint32_t eeint;
- uint32_t eemck0;
- uint32_t eemck1;
- /* Error diagnostic */
-} XCSR;
-
-static void PPC_XCSR_writeb (void *opaque,
- 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,
- 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,
- 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, hwaddr addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
- retval);
-
- return retval;
-}
-
-static uint32_t PPC_XCSR_readw (void *opaque, hwaddr addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
- retval);
-
- return retval;
-}
-
-static uint32_t PPC_XCSR_readl (void *opaque, hwaddr addr)
-{
- uint32_t retval = 0;
-
- printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr,
- retval);
-
- return retval;
-}
-
-static const MemoryRegionOps PPC_XCSR_ops = {
- .old_mmio = {
- .read = { PPC_XCSR_readb, PPC_XCSR_readw, PPC_XCSR_readl, },
- .write = { PPC_XCSR_writeb, PPC_XCSR_writew, PPC_XCSR_writel, },
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-#endif
-
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
qemu_irq reset_irq;
@@ -648,11 +560,10 @@ static void ppc_prep_init(MachineState *machine)
portio_list_init(&prep_port_list, NULL, prep_portio_list, sysctrl, "prep");
portio_list_add(&prep_port_list, isa_address_space_io(isa), 0x0);
- /* PowerPC control and status register group */
-#if 0
- memory_region_init_io(xcsr, NULL, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000);
- memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr);
-#endif
+ /*
+ * PowerPC control and status register group: unimplemented,
+ * would be at address 0xFEFF0000.
+ */
if (machine_usb(machine)) {
pci_create_simple(pci_bus, -1, "pci-ohci");
@@ -676,6 +587,7 @@ static void ppc_prep_init(MachineState *machine)
static void prep_machine_init(MachineClass *mc)
{
+ mc->deprecation_reason = "use 40p machine type instead";
mc->desc = "PowerPC PREP platform";
mc->init = ppc_prep_init;
mc->block_default_type = IF_IDE;
@@ -709,7 +621,7 @@ static void ibm_40p_init(MachineState *machine)
uint16_t cmos_checksum;
PowerPCCPU *cpu;
DeviceState *dev;
- SysBusDevice *pcihost;
+ SysBusDevice *pcihost, *s;
Nvram *m48t59 = NULL;
PCIBus *pci_bus;
ISABus *isa_bus;
@@ -802,7 +714,16 @@ static void ibm_40p_init(MachineState *machine)
}
/* Prepare firmware configuration for OpenBIOS */
- fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2);
+ dev = qdev_create(NULL, TYPE_FW_CFG_MEM);
+ fw_cfg = FW_CFG(dev);
+ qdev_prop_set_uint32(dev, "data_width", 1);
+ qdev_prop_set_bit(dev, "dma_enabled", false);
+ object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
+ OBJECT(fw_cfg), NULL);
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(s, 0, CFG_ADDR);
+ sysbus_mmio_map(s, 1, CFG_ADDR + 2);
if (machine->kernel_filename) {
/* load kernel */
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a70704a8b2..4edb6c7d16 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -54,7 +54,6 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "hw/pci-host/spapr.h"
-#include "hw/ppc/xics.h"
#include "hw/pci/msi.h"
#include "hw/pci/pci.h"
@@ -117,33 +116,6 @@ static bool spapr_is_thread0_in_vcore(sPAPRMachineState *spapr,
return spapr_get_vcpu_id(cpu) % spapr->vsmt == 0;
}
-static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
- const char *type_ics,
- int nr_irqs, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
-
- obj = object_new(type_ics);
- object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
- object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
- &error_abort);
- object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err);
- if (local_err) {
- goto error;
- }
- object_property_set_bool(obj, true, "realized", &local_err);
- if (local_err) {
- goto error;
- }
-
- return ICS_BASE(obj);
-
-error:
- error_propagate(errp, local_err);
- return NULL;
-}
-
static bool pre_2_10_vmstate_dummy_icp_needed(void *opaque)
{
/* Dummy entries correspond to unused ICPState objects in older QEMUs,
@@ -184,38 +156,6 @@ static int xics_max_server_number(sPAPRMachineState *spapr)
return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
}
-static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp)
-{
- sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
- Error *local_err = NULL;
-
- if (kvm_enabled()) {
- if (machine_kernel_irqchip_allowed(machine) &&
- !xics_kvm_init(spapr, &local_err)) {
- spapr->icp_type = TYPE_KVM_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs,
- &local_err);
- }
- if (machine_kernel_irqchip_required(machine) && !spapr->ics) {
- error_prepend(&local_err,
- "kernel_irqchip requested but unavailable: ");
- goto error;
- }
- error_free(local_err);
- local_err = NULL;
- }
-
- if (!spapr->ics) {
- xics_spapr_init(spapr);
- spapr->icp_type = TYPE_ICP;
- spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs,
- &local_err);
- }
-
-error:
- error_propagate(errp, local_err);
-}
-
static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
int smt_threads)
{
@@ -1650,6 +1590,10 @@ static void spapr_machine_reset(void)
ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal);
}
+ if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ spapr_irq_msi_reset(spapr);
+ }
+
qemu_devices_reset();
/* DRC reset may cause a device to be unplugged. This will cause troubles
@@ -1924,6 +1868,24 @@ static const VMStateDescription vmstate_spapr_patb_entry = {
},
};
+static bool spapr_irq_map_needed(void *opaque)
+{
+ sPAPRMachineState *spapr = opaque;
+
+ return spapr->irq_map && !bitmap_empty(spapr->irq_map, spapr->irq_map_nr);
+}
+
+static const VMStateDescription vmstate_spapr_irq_map = {
+ .name = "spapr_irq_map",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = spapr_irq_map_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_BITMAP(irq_map, sPAPRMachineState, 0, irq_map_nr),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static const VMStateDescription vmstate_spapr = {
.name = "spapr",
.version_id = 3,
@@ -1951,6 +1913,7 @@ static const VMStateDescription vmstate_spapr = {
&vmstate_spapr_cap_cfpc,
&vmstate_spapr_cap_sbbc,
&vmstate_spapr_cap_ibs,
+ &vmstate_spapr_irq_map,
NULL
}
};
@@ -2604,7 +2567,7 @@ static void spapr_machine_init(MachineState *machine)
load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
/* Set up Interrupt Controller before we create the VCPUs */
- xics_system_init(machine, XICS_IRQS_SPAPR, &error_fatal);
+ smc->irq->init(spapr, &error_fatal);
/* Set up containers for ibm,client-architecture-support negotiated options
*/
@@ -3802,121 +3765,13 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
return cpu ? ICP(cpu->intc) : NULL;
}
-#define ICS_IRQ_FREE(ics, srcno) \
- (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
-
-static int ics_find_free_block(ICSState *ics, int num, int alignnum)
-{
- int first, i;
-
- for (first = 0; first < ics->nr_irqs; first += alignnum) {
- if (num > (ics->nr_irqs - first)) {
- return -1;
- }
- for (i = first; i < first + num; ++i) {
- if (!ICS_IRQ_FREE(ics, i)) {
- break;
- }
- }
- if (i == (first + num)) {
- return first;
- }
- }
-
- return -1;
-}
-
-int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
-{
- ICSState *ics = spapr->ics;
- int first = -1;
-
- assert(ics);
-
- /*
- * MSIMesage::data is used for storing VIRQ so
- * it has to be aligned to num to support multiple
- * MSI vectors. MSI-X is not affected by this.
- * The hint is used for the first IRQ, the rest should
- * be allocated continuously.
- */
- if (align) {
- assert((num == 1) || (num == 2) || (num == 4) ||
- (num == 8) || (num == 16) || (num == 32));
- first = ics_find_free_block(ics, num, num);
- } else {
- first = ics_find_free_block(ics, num, 1);
- }
-
- if (first < 0) {
- error_setg(errp, "can't find a free %d-IRQ block", num);
- return -1;
- }
-
- return first + ics->offset;
-}
-
-int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
-{
- ICSState *ics = spapr->ics;
-
- assert(ics);
-
- if (!ics_valid_irq(ics, irq)) {
- error_setg(errp, "IRQ %d is invalid", irq);
- return -1;
- }
-
- if (!ICS_IRQ_FREE(ics, irq - ics->offset)) {
- error_setg(errp, "IRQ %d is not free", irq);
- return -1;
- }
-
- ics_set_irq_type(ics, irq - ics->offset, lsi);
- return 0;
-}
-
-void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
-{
- ICSState *ics = spapr->ics;
- int srcno = irq - ics->offset;
- int i;
-
- if (ics_valid_irq(ics, irq)) {
- trace_spapr_irq_free(0, irq, num);
- for (i = srcno; i < srcno + num; ++i) {
- if (ICS_IRQ_FREE(ics, i)) {
- trace_spapr_irq_free_warn(0, i + ics->offset);
- }
- memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
- }
- }
-}
-
-qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
-{
- ICSState *ics = spapr->ics;
-
- if (ics_valid_irq(ics, irq)) {
- return ics->qirqs[irq - ics->offset];
- }
-
- return NULL;
-}
-
static void spapr_pic_print_info(InterruptStatsProvider *obj,
Monitor *mon)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- icp_pic_print_info(ICP(cpu->intc), mon);
- }
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
- ics_pic_print_info(spapr->ics, mon);
+ smc->irq->print_info(spapr, mon);
}
int spapr_get_vcpu_id(PowerPCCPU *cpu)
@@ -4029,6 +3884,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
spapr_caps_add_properties(smc, &error_abort);
+ smc->irq = &spapr_irq_xics;
}
static const TypeInfo spapr_machine_info = {
@@ -4079,19 +3935,42 @@ static const TypeInfo spapr_machine_info = {
} \
type_init(spapr_machine_register_##suffix)
+ /*
+ * pseries-3.1
+ */
+static void spapr_machine_3_1_instance_options(MachineState *machine)
+{
+}
+
+static void spapr_machine_3_1_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(3_1, "3.1", true);
+
/*
* pseries-3.0
*/
+#define SPAPR_COMPAT_3_0 \
+ HW_COMPAT_3_0
+
static void spapr_machine_3_0_instance_options(MachineState *machine)
{
+ spapr_machine_3_1_instance_options(machine);
}
static void spapr_machine_3_0_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
+
+ spapr_machine_3_1_class_options(mc);
+ SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_3_0);
+
+ smc->legacy_irq_allocation = true;
}
-DEFINE_SPAPR_MACHINE(3_0, "3.0", true);
+DEFINE_SPAPR_MACHINE(3_0, "3.0", false);
/*
* pseries-2.12
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 993759db47..876f0b3d9d 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -11,6 +11,7 @@
#include "hw/ppc/spapr_cpu_core.h"
#include "target/ppc/cpu.h"
#include "hw/ppc/spapr.h"
+#include "hw/ppc/xics.h" /* for icp_create() - to be removed */
#include "hw/boards.h"
#include "qapi/error.h"
#include "sysemu/cpus.h"
@@ -113,26 +114,6 @@ const char *spapr_get_cpu_core_type(const char *cpu_type)
return object_class_get_name(oc);
}
-static void spapr_unrealize_vcpu(PowerPCCPU *cpu)
-{
- qemu_unregister_reset(spapr_cpu_reset, cpu);
- object_unparent(cpu->intc);
- cpu_remove_sync(CPU(cpu));
- object_unparent(OBJECT(cpu));
-}
-
-static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
-{
- sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
- CPUCore *cc = CPU_CORE(dev);
- int i;
-
- for (i = 0; i < cc->nr_threads; i++) {
- spapr_unrealize_vcpu(sc->threads[i]);
- }
- g_free(sc->threads);
-}
-
static bool slb_shadow_needed(void *opaque)
{
sPAPRCPUState *spapr_cpu = opaque;
@@ -207,10 +188,34 @@ static const VMStateDescription vmstate_spapr_cpu_state = {
}
};
+static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
+{
+ if (!sc->pre_3_0_migration) {
+ vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
+ }
+ qemu_unregister_reset(spapr_cpu_reset, cpu);
+ object_unparent(cpu->intc);
+ cpu_remove_sync(CPU(cpu));
+ object_unparent(OBJECT(cpu));
+}
+
+static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
+{
+ sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
+ CPUCore *cc = CPU_CORE(dev);
+ int i;
+
+ for (i = 0; i < cc->nr_threads; i++) {
+ spapr_unrealize_vcpu(sc->threads[i], sc);
+ }
+ g_free(sc->threads);
+}
+
static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
- Error **errp)
+ sPAPRCPUCore *sc, Error **errp)
{
CPUPPCState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
Error *local_err = NULL;
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
@@ -233,6 +238,11 @@ static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
goto error_unregister;
}
+ if (!sc->pre_3_0_migration) {
+ vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
+ cpu->machine_data);
+ }
+
return;
error_unregister:
@@ -272,10 +282,6 @@ static PowerPCCPU *spapr_create_vcpu(sPAPRCPUCore *sc, int i, Error **errp)
}
cpu->machine_data = g_new0(sPAPRCPUState, 1);
- if (!sc->pre_3_0_migration) {
- vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
- cpu->machine_data);
- }
object_unref(obj);
return cpu;
@@ -290,9 +296,6 @@ static void spapr_delete_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
{
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
- if (!sc->pre_3_0_migration) {
- vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
- }
cpu->machine_data = NULL;
g_free(spapr_cpu);
object_unparent(OBJECT(cpu));
@@ -325,7 +328,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
}
for (j = 0; j < cc->nr_threads; j++) {
- spapr_realize_vcpu(sc->threads[j], spapr, &local_err);
+ spapr_realize_vcpu(sc->threads[j], spapr, sc, &local_err);
if (local_err) {
goto err_unrealize;
}
@@ -334,7 +337,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
err_unrealize:
while (--j >= 0) {
- spapr_unrealize_vcpu(sc->threads[j]);
+ spapr_unrealize_vcpu(sc->threads[j], sc);
}
err:
while (--i >= 0) {
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index e4f5946a21..32719a1b72 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -707,9 +707,11 @@ void spapr_clear_pending_events(sPAPRMachineState *spapr)
void spapr_events_init(sPAPRMachineState *spapr)
{
- int epow_irq;
+ int epow_irq = SPAPR_IRQ_EPOW;
- epow_irq = spapr_irq_findone(spapr, &error_fatal);
+ if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ epow_irq = spapr_irq_findone(spapr, &error_fatal);
+ }
spapr_irq_claim(spapr, epow_irq, false, &error_fatal);
@@ -729,9 +731,11 @@ void spapr_events_init(sPAPRMachineState *spapr)
* checking that it's enabled.
*/
if (spapr->use_hotplug_event_source) {
- int hp_irq;
+ int hp_irq = SPAPR_IRQ_HOTPLUG;
- hp_irq = spapr_irq_findone(spapr, &error_fatal);
+ if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ hp_irq = spapr_irq_findone(spapr, &error_fatal);
+ }
spapr_irq_claim(spapr, hp_irq, false, &error_fatal);
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
new file mode 100644
index 0000000000..0cbb5dd393
--- /dev/null
+++ b/hw/ppc/spapr_irq.c
@@ -0,0 +1,286 @@
+/*
+ * QEMU PowerPC sPAPR IRQ interface
+ *
+ * Copyright (c) 2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/xics.h"
+#include "sysemu/kvm.h"
+
+#include "trace.h"
+
+void spapr_irq_msi_init(sPAPRMachineState *spapr, uint32_t nr_msis)
+{
+ spapr->irq_map_nr = nr_msis;
+ spapr->irq_map = bitmap_new(spapr->irq_map_nr);
+}
+
+int spapr_irq_msi_alloc(sPAPRMachineState *spapr, uint32_t num, bool align,
+ Error **errp)
+{
+ int irq;
+
+ /*
+ * The 'align_mask' parameter of bitmap_find_next_zero_area()
+ * should be one less than a power of 2; 0 means no
+ * alignment. Adapt the 'align' value of the former allocator
+ * to fit the requirements of bitmap_find_next_zero_area()
+ */
+ align -= 1;
+
+ irq = bitmap_find_next_zero_area(spapr->irq_map, spapr->irq_map_nr, 0, num,
+ align);
+ if (irq == spapr->irq_map_nr) {
+ error_setg(errp, "can't find a free %d-IRQ block", num);
+ return -1;
+ }
+
+ bitmap_set(spapr->irq_map, irq, num);
+
+ return irq + SPAPR_IRQ_MSI;
+}
+
+void spapr_irq_msi_free(sPAPRMachineState *spapr, int irq, uint32_t num)
+{
+ bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
+}
+
+void spapr_irq_msi_reset(sPAPRMachineState *spapr)
+{
+ bitmap_clear(spapr->irq_map, 0, spapr->irq_map_nr);
+}
+
+
+/*
+ * XICS IRQ backend.
+ */
+
+static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
+ const char *type_ics,
+ int nr_irqs, Error **errp)
+{
+ Error *local_err = NULL;
+ Object *obj;
+
+ obj = object_new(type_ics);
+ object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
+ object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
+ &error_abort);
+ object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err);
+ if (local_err) {
+ goto error;
+ }
+ object_property_set_bool(obj, true, "realized", &local_err);
+ if (local_err) {
+ goto error;
+ }
+
+ return ICS_BASE(obj);
+
+error:
+ error_propagate(errp, local_err);
+ return NULL;
+}
+
+static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
+{
+ MachineState *machine = MACHINE(spapr);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ int nr_irqs = smc->irq->nr_irqs;
+ Error *local_err = NULL;
+
+ /* Initialize the MSI IRQ allocator. */
+ if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ spapr_irq_msi_init(spapr, XICS_IRQ_BASE + nr_irqs - SPAPR_IRQ_MSI);
+ }
+
+ if (kvm_enabled()) {
+ if (machine_kernel_irqchip_allowed(machine) &&
+ !xics_kvm_init(spapr, &local_err)) {
+ spapr->icp_type = TYPE_KVM_ICP;
+ spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs,
+ &local_err);
+ }
+ if (machine_kernel_irqchip_required(machine) && !spapr->ics) {
+ error_prepend(&local_err,
+ "kernel_irqchip requested but unavailable: ");
+ goto error;
+ }
+ error_free(local_err);
+ local_err = NULL;
+ }
+
+ if (!spapr->ics) {
+ xics_spapr_init(spapr);
+ spapr->icp_type = TYPE_ICP;
+ spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs,
+ &local_err);
+ }
+
+error:
+ error_propagate(errp, local_err);
+}
+
+#define ICS_IRQ_FREE(ics, srcno) \
+ (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
+
+static int spapr_irq_claim_xics(sPAPRMachineState *spapr, int irq, bool lsi,
+ Error **errp)
+{
+ ICSState *ics = spapr->ics;
+
+ assert(ics);
+
+ if (!ics_valid_irq(ics, irq)) {
+ error_setg(errp, "IRQ %d is invalid", irq);
+ return -1;
+ }
+
+ if (!ICS_IRQ_FREE(ics, irq - ics->offset)) {
+ error_setg(errp, "IRQ %d is not free", irq);
+ return -1;
+ }
+
+ ics_set_irq_type(ics, irq - ics->offset, lsi);
+ return 0;
+}
+
+static void spapr_irq_free_xics(sPAPRMachineState *spapr, int irq, int num)
+{
+ ICSState *ics = spapr->ics;
+ uint32_t srcno = irq - ics->offset;
+ int i;
+
+ if (ics_valid_irq(ics, irq)) {
+ trace_spapr_irq_free(0, irq, num);
+ for (i = srcno; i < srcno + num; ++i) {
+ if (ICS_IRQ_FREE(ics, i)) {
+ trace_spapr_irq_free_warn(0, i);
+ }
+ memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
+ }
+ }
+}
+
+static qemu_irq spapr_qirq_xics(sPAPRMachineState *spapr, int irq)
+{
+ ICSState *ics = spapr->ics;
+ uint32_t srcno = irq - ics->offset;
+
+ if (ics_valid_irq(ics, irq)) {
+ return ics->qirqs[srcno];
+ }
+
+ return NULL;
+}
+
+static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
+{
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ icp_pic_print_info(ICP(cpu->intc), mon);
+ }
+
+ ics_pic_print_info(spapr->ics, mon);
+}
+
+sPAPRIrq spapr_irq_xics = {
+ .nr_irqs = XICS_IRQS_SPAPR,
+
+ .init = spapr_irq_init_xics,
+ .claim = spapr_irq_claim_xics,
+ .free = spapr_irq_free_xics,
+ .qirq = spapr_qirq_xics,
+ .print_info = spapr_irq_print_info_xics,
+};
+
+/*
+ * sPAPR IRQ frontend routines for devices
+ */
+
+int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
+{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ return smc->irq->claim(spapr, irq, lsi, errp);
+}
+
+void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
+{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ smc->irq->free(spapr, irq, num);
+}
+
+qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
+{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ return smc->irq->qirq(spapr, irq);
+}
+
+/*
+ * XICS legacy routines - to deprecate one day
+ */
+
+static int ics_find_free_block(ICSState *ics, int num, int alignnum)
+{
+ int first, i;
+
+ for (first = 0; first < ics->nr_irqs; first += alignnum) {
+ if (num > (ics->nr_irqs - first)) {
+ return -1;
+ }
+ for (i = first; i < first + num; ++i) {
+ if (!ICS_IRQ_FREE(ics, i)) {
+ break;
+ }
+ }
+ if (i == (first + num)) {
+ return first;
+ }
+ }
+
+ return -1;
+}
+
+int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
+{
+ ICSState *ics = spapr->ics;
+ int first = -1;
+
+ assert(ics);
+
+ /*
+ * MSIMesage::data is used for storing VIRQ so
+ * it has to be aligned to num to support multiple
+ * MSI vectors. MSI-X is not affected by this.
+ * The hint is used for the first IRQ, the rest should
+ * be allocated continuously.
+ */
+ if (align) {
+ assert((num == 1) || (num == 2) || (num == 4) ||
+ (num == 8) || (num == 16) || (num == 32));
+ first = ics_find_free_block(ics, num, num);
+ } else {
+ first = ics_find_free_block(ics, num, 1);
+ }
+
+ if (first < 0) {
+ error_setg(errp, "can't find a free %d-IRQ block", num);
+ return -1;
+ }
+
+ return first + ics->offset;
+}
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 497b896c7d..5cd676e443 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -267,6 +267,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong args, uint32_t nret,
target_ulong rets)
{
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
uint32_t config_addr = rtas_ld(args, 0);
uint64_t buid = rtas_ldq(args, 1);
unsigned int func = rtas_ld(args, 3);
@@ -334,6 +335,9 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return;
}
+ if (!smc->legacy_irq_allocation) {
+ spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
+ }
spapr_irq_free(spapr, msi->first_irq, msi->num);
if (msi_present(pdev)) {
spapr_msi_setmsg(pdev, 0, false, 0, 0);
@@ -372,7 +376,13 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
/* Allocate MSIs */
- irq = spapr_irq_find(spapr, req_num, ret_intr_type == RTAS_TYPE_MSI, &err);
+ if (smc->legacy_irq_allocation) {
+ irq = spapr_irq_find(spapr, req_num, ret_intr_type == RTAS_TYPE_MSI,
+ &err);
+ } else {
+ irq = spapr_irq_msi_alloc(spapr, req_num,
+ ret_intr_type == RTAS_TYPE_MSI, &err);
+ }
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
@@ -392,6 +402,9 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
/* Release previous MSIs */
if (msi) {
+ if (!smc->legacy_irq_allocation) {
+ spapr_irq_msi_free(spapr, msi->first_irq, msi->num);
+ }
spapr_irq_free(spapr, msi->first_irq, msi->num);
g_hash_table_remove(phb->msi, &config_addr);
}
@@ -1546,6 +1559,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
sPAPRMachineState *spapr =
(sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
TYPE_SPAPR_MACHINE);
+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
SysBusDevice *s = SYS_BUS_DEVICE(dev);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = PCI_HOST_BRIDGE(s);
@@ -1563,7 +1577,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
}
if (sphb->index != (uint32_t)-1) {
- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
Error *local_err = NULL;
smc->phb_placement(spapr, sphb->index,
@@ -1705,14 +1718,16 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
/* Initialize the LSI table */
for (i = 0; i < PCI_NUM_PINS; i++) {
- uint32_t irq;
+ uint32_t irq = SPAPR_IRQ_PCI_LSI + sphb->index * PCI_NUM_PINS + i;
Error *local_err = NULL;
- irq = spapr_irq_findone(spapr, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "can't allocate LSIs: ");
- return;
+ if (smc->legacy_irq_allocation) {
+ irq = spapr_irq_findone(spapr, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_prepend(errp, "can't allocate LSIs: ");
+ return;
+ }
}
spapr_irq_claim(spapr, irq, true, &local_err);
@@ -2123,6 +2138,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "ranges", &ranges, sizeof_ranges));
_FDT(fdt_setprop(fdt, bus_off, "reg", &bus_reg, sizeof(bus_reg)));
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pci-config-space-type", 0x1));
+ /* TODO: fine tune the total count of allocatable MSIs per PHB */
_FDT(fdt_setprop_cell(fdt, bus_off, "ibm,pe-total-#msi", XICS_IRQS_SPAPR));
/* Dynamic DMA window */
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index be9af71437..840d4a3c45 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -37,12 +37,13 @@
#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
-#include "hw/ppc/xics.h"
#include "hw/ppc/fdt.h"
#include "trace.h"
#include <libfdt.h>
+#define SPAPR_VIO_REG_BASE 0x71000000
+
static void spapr_vio_get_irq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -445,6 +446,55 @@ static void spapr_vio_busdev_reset(DeviceState *qdev)
}
}
+/*
+ * The register property of a VIO device is defined in livirt using
+ * 0x1000 as a base register number plus a 0x1000 increment. For the
+ * VIO tty device, the base number is changed to 0x30000000. QEMU uses
+ * a base register number of 0x71000000 and then a simple increment.
+ *
+ * The formula below tries to compute a unique index number from the
+ * register value that will be used to define the IRQ number of the
+ * VIO device.
+ *
+ * A maximum of 256 VIO devices is covered. Collisions are possible
+ * but they will be detected when the IRQ is claimed.
+ */
+static inline uint32_t spapr_vio_reg_to_irq(uint32_t reg)
+{
+ uint32_t irq;
+
+ if (reg >= SPAPR_VIO_REG_BASE) {
+ /*
+ * VIO device register values when allocated by QEMU. For
+ * these, we simply mask the high bits to fit the overall
+ * range: [0x00 - 0xff].
+ *
+ * The nvram VIO device (reg=0x71000000) is a static device of
+ * the pseries machine and so is always allocated by QEMU. Its
+ * IRQ number is 0x0.
+ */
+ irq = reg & 0xff;
+
+ } else if (reg >= 0x30000000) {
+ /*
+ * VIO tty devices register values, when allocated by livirt,
+ * are mapped in range [0xf0 - 0xff], gives us a maximum of 16
+ * vtys.
+ */
+ irq = 0xf0 | ((reg >> 12) & 0xf);
+
+ } else {
+ /*
+ * Other VIO devices register values, when allocated by
+ * livirt, should be mapped in range [0x00 - 0xef]. Conflicts
+ * will be detected when IRQ is claimed.
+ */
+ irq = (reg >> 12) & 0xff;
+ }
+
+ return SPAPR_IRQ_VIO | irq;
+}
+
static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
@@ -485,10 +535,14 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
}
if (!dev->irq) {
- dev->irq = spapr_irq_findone(spapr, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ dev->irq = spapr_vio_reg_to_irq(dev->reg);
+
+ if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ dev->irq = spapr_irq_findone(spapr, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
}
@@ -557,7 +611,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
/* Create bus on bridge device */
qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
bus = SPAPR_VIO_BUS(qbus);
- bus->next_reg = 0x71000000;
+ bus->next_reg = SPAPR_VIO_REG_BASE;
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 1ded7ac9a3..3fdc4b0da1 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -82,6 +82,7 @@ enum mtp_code {
FMT_ASSOCIATION = 0x3001,
/* event codes */
+ EVT_CANCEL_TRANSACTION = 0x4001,
EVT_OBJ_ADDED = 0x4002,
EVT_OBJ_REMOVED = 0x4003,
EVT_OBJ_INFO_CHANGED = 0x4007,
@@ -146,9 +147,12 @@ struct MTPData {
uint32_t trans;
uint64_t offset;
uint64_t length;
- uint32_t alloc;
+ uint64_t alloc;
uint8_t *data;
bool first;
+ /* Used for >4G file sizes */
+ bool pending;
+ uint64_t cached_length;
int fd;
};
@@ -1551,14 +1555,35 @@ static void usb_mtp_handle_control(USBDevice *dev, USBPacket *p,
int length, uint8_t *data)
{
int ret;
+ MTPState *s = USB_MTP(dev);
+ uint16_t *event = (uint16_t *)data;
- ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
- if (ret >= 0) {
- return;
+ switch (request) {
+ case ClassInterfaceOutRequest | 0x64:
+ if (*event == EVT_CANCEL_TRANSACTION) {
+ g_free(s->result);
+ s->result = NULL;
+ usb_mtp_data_free(s->data_in);
+ s->data_in = NULL;
+ if (s->write_pending) {
+ g_free(s->dataset.filename);
+ s->write_pending = false;
+ }
+ usb_mtp_data_free(s->data_out);
+ s->data_out = NULL;
+ } else {
+ p->status = USB_RET_STALL;
+ }
+ break;
+ default:
+ ret = usb_desc_handle_control(dev, p, request,
+ value, index, length, data);
+ if (ret >= 0) {
+ return;
+ }
}
trace_usb_mtp_stall(dev->addr, "unknown control request");
- p->status = USB_RET_STALL;
}
static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p)
@@ -1580,13 +1605,31 @@ static void utf16_to_str(uint8_t len, uint16_t *arr, char *name)
g_free(wstr);
}
+/* Wrapper around write, returns 0 on failure */
+static uint64_t write_retry(int fd, void *buf, uint64_t size)
+{
+ uint64_t bytes_left = size, ret;
+
+ while (bytes_left > 0) {
+ ret = write(fd, buf, bytes_left);
+ if ((ret == -1) && (errno != EINTR || errno != EAGAIN ||
+ errno != EWOULDBLOCK)) {
+ break;
+ }
+ bytes_left -= ret;
+ buf += ret;
+ }
+
+ return size - bytes_left;
+}
+
static void usb_mtp_write_data(MTPState *s)
{
MTPData *d = s->data_out;
MTPObject *parent =
usb_mtp_object_lookup(s, s->dataset.parent_handle);
char *path = NULL;
- int rc = -1;
+ uint64_t rc;
mode_t mask = 0644;
assert(d != NULL);
@@ -1603,7 +1646,7 @@ static void usb_mtp_write_data(MTPState *s)
d->fd = mkdir(path, mask);
goto free;
}
- if (s->dataset.size < d->length) {
+ if ((s->dataset.size != 0xFFFFFFFF) && (s->dataset.size < d->length)) {
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
0, 0, 0, 0);
goto done;
@@ -1622,8 +1665,8 @@ static void usb_mtp_write_data(MTPState *s)
goto success;
}
- rc = write(d->fd, d->data, s->dataset.size);
- if (rc == -1) {
+ rc = write_retry(d->fd, d->data, s->dataset.size);
+ if (!rc) {
usb_mtp_queue_result(s, RES_STORE_FULL, d->trans,
0, 0, 0, 0);
goto done;
@@ -1699,6 +1742,7 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
MTPData *d = s->data_out;
uint64_t dlen;
uint32_t data_len = p->iov.size;
+ uint64_t total_len;
if (!d) {
usb_mtp_queue_result(s, RES_INVALID_OBJECTINFO, 0,
@@ -1707,18 +1751,33 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
}
if (d->first) {
/* Total length of incoming data */
- d->length = cpu_to_le32(container->length) - sizeof(mtp_container);
+ total_len = cpu_to_le32(container->length) - sizeof(mtp_container);
/* Length of data in this packet */
data_len -= sizeof(mtp_container);
- usb_mtp_realloc(d, d->length);
+ usb_mtp_realloc(d, total_len);
+ d->length += total_len;
d->offset = 0;
+ d->cached_length = total_len;
d->first = false;
+ d->pending = false;
+ }
+
+ if (d->pending) {
+ usb_mtp_realloc(d, d->cached_length);
+ d->length += d->cached_length;
+ d->pending = false;
}
if (d->length - d->offset > data_len) {
dlen = data_len;
} else {
dlen = d->length - d->offset;
+ /* Check for cached data for large files */
+ if ((s->dataset.size == 0xFFFFFFFF) && (dlen < p->iov.size)) {
+ usb_mtp_realloc(d, p->iov.size - dlen);
+ d->length += p->iov.size - dlen;
+ dlen = p->iov.size;
+ }
}
switch (d->code) {
@@ -1738,12 +1797,18 @@ static void usb_mtp_get_data(MTPState *s, mtp_container *container,
case CMD_SEND_OBJECT:
usb_packet_copy(p, d->data + d->offset, dlen);
d->offset += dlen;
- if (d->offset == d->length) {
+ if ((p->iov.size % 64) || !p->iov.size) {
+ assert((s->dataset.size == 0xFFFFFFFF) ||
+ (s->dataset.size == d->length));
+
usb_mtp_write_data(s);
usb_mtp_data_free(s->data_out);
s->data_out = NULL;
return;
}
+ if (d->offset == d->length) {
+ d->pending = true;
+ }
break;
default:
p->status = USB_RET_STALL;
@@ -1953,7 +2018,7 @@ static void usb_mtp_realize(USBDevice *dev, Error **errp)
QTAILQ_INIT(&s->objects);
if (s->desc == NULL) {
if (s->root == NULL) {
- error_setg(errp, "usb-mtp: x-root property must be configured");
+ error_setg(errp, "usb-mtp: rootdir property must be configured");
return;
}
s->desc = strrchr(s->root, '/');
@@ -1982,7 +2047,7 @@ static const VMStateDescription vmstate_usb_mtp = {
};
static Property mtp_properties[] = {
- DEFINE_PROP_STRING("x-root", MTPState, root),
+ DEFINE_PROP_STRING("rootdir", MTPState, root),
DEFINE_PROP_STRING("desc", MTPState, desc),
DEFINE_PROP_BOOL("readonly", MTPState, readonly, true),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index d4c0293db5..98da5f0f04 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1156,6 +1156,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
OHCI_SET_BM(td.flags, TD_EC, 3);
break;
}
+ /* An error occured so we have to clear the interrupt counter. See
+ * spec at 6.4.4 on page 104 */
+ ohci->done_count = 0;
}
ed->head |= OHCI_ED_H;
}
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index cd1f4af18a..3f31f80b12 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1136,6 +1136,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
info.iova_pgsizes = 4096;
}
vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes);
+ container->pgsizes = info.iova_pgsizes;
} else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU) ||
ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_v2_IOMMU)) {
struct vfio_iommu_spapr_tce_info info;
@@ -1200,6 +1201,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
}
if (v2) {
+ container->pgsizes = info.ddw.pgsizes;
/*
* There is a default window in just created container.
* To make region_add/del simpler, we better remove this
@@ -1214,6 +1216,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
}
} else {
/* The default table uses 4K pages */
+ container->pgsizes = 0x1000;
vfio_host_win_add(container, info.dma32_window_start,
info.dma32_window_start +
info.dma32_window_size - 1,
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 259397c002..becf71a3fc 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -15,6 +15,7 @@
#include "hw/vfio/vfio-common.h"
#include "hw/hw.h"
+#include "exec/ram_addr.h"
#include "qemu/error-report.h"
#include "trace.h"
@@ -144,9 +145,27 @@ int vfio_spapr_create_window(VFIOContainer *container,
{
int ret;
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
- unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
+ uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, pages;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
+ long systempagesize = qemu_getrampagesize();
+
+ /*
+ * The host might not support the guest supported IOMMU page size,
+ * so we will use smaller physical IOMMU pages to back them.
+ */
+ if (pagesize > systempagesize) {
+ pagesize = systempagesize;
+ }
+ pagesize = 1ULL << (63 - clz64(container->pgsizes &
+ (pagesize | (pagesize - 1))));
+ if (!pagesize) {
+ error_report("Host doesn't support page size 0x%"PRIx64
+ ", the supported mask is 0x%lx",
+ memory_region_iommu_get_min_page_size(iommu_mr),
+ container->pgsizes);
+ return -EINVAL;
+ }
/*
* FIXME: For VFIO iommu types which have KVM acceleration to
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 7e5de1a6fd..ad4d7cfd97 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -4,10 +4,10 @@
#include "qemu/units.h"
#include "sysemu/dma.h"
#include "hw/boards.h"
-#include "hw/ppc/xics.h"
#include "hw/ppc/spapr_drc.h"
#include "hw/mem/pc-dimm.h"
#include "hw/ppc/spapr_ovec.h"
+#include "hw/ppc/spapr_irq.h"
struct VIOsPAPRBus;
struct sPAPRPHBState;
@@ -15,6 +15,7 @@ struct sPAPRNVRAM;
typedef struct sPAPREventLogEntry sPAPREventLogEntry;
typedef struct sPAPREventSource sPAPREventSource;
typedef struct sPAPRPendingHPT sPAPRPendingHPT;
+typedef struct ICSState ICSState;
#define HPTE64_V_HPTE_DIRTY 0x0000000000000040ULL
#define SPAPR_ENTRY_POINT 0x100
@@ -101,12 +102,15 @@ struct sPAPRMachineClass {
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
bool use_ohci_by_default; /* use USB-OHCI instead of XHCI */
bool pre_2_10_has_unused_icps;
+ bool legacy_irq_allocation;
+
void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
hwaddr *mmio32, hwaddr *mmio64,
unsigned n_dma, uint32_t *liobns, Error **errp);
sPAPRResizeHPT resize_hpt_default;
sPAPRCapabilities default_caps;
+ sPAPRIrq *irq;
};
/**
@@ -167,6 +171,8 @@ struct sPAPRMachineState {
char *kvm_type;
const char *icp_type;
+ int32_t irq_map_nr;
+ unsigned long *irq_map;
bool cmd_line_caps[SPAPR_CAP_NUM];
sPAPRCapabilities def, eff, mig;
@@ -775,14 +781,6 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu);
void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp);
PowerPCCPU *spapr_find_cpu(int vcpu_id);
-int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align,
- Error **errp);
-#define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp)
-int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
-void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num);
-qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
-
-
int spapr_caps_pre_load(void *opaque);
int spapr_caps_pre_save(void *opaque);
diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h
new file mode 100644
index 0000000000..0e98c4474b
--- /dev/null
+++ b/include/hw/ppc/spapr_irq.h
@@ -0,0 +1,54 @@
+/*
+ * QEMU PowerPC sPAPR IRQ backend definitions
+ *
+ * Copyright (c) 2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef HW_SPAPR_IRQ_H
+#define HW_SPAPR_IRQ_H
+
+/*
+ * IRQ range offsets per device type
+ */
+#define SPAPR_IRQ_EPOW 0x1000 /* XICS_IRQ_BASE offset */
+#define SPAPR_IRQ_HOTPLUG 0x1001
+#define SPAPR_IRQ_VIO 0x1100 /* 256 VIO devices */
+#define SPAPR_IRQ_PCI_LSI 0x1200 /* 32+ PHBs devices */
+
+#define SPAPR_IRQ_MSI 0x1300 /* Offset of the dynamic range covered
+ * by the bitmap allocator */
+
+typedef struct sPAPRMachineState sPAPRMachineState;
+
+void spapr_irq_msi_init(sPAPRMachineState *spapr, uint32_t nr_msis);
+int spapr_irq_msi_alloc(sPAPRMachineState *spapr, uint32_t num, bool align,
+ Error **errp);
+void spapr_irq_msi_free(sPAPRMachineState *spapr, int irq, uint32_t num);
+void spapr_irq_msi_reset(sPAPRMachineState *spapr);
+
+typedef struct sPAPRIrq {
+ uint32_t nr_irqs;
+
+ void (*init)(sPAPRMachineState *spapr, Error **errp);
+ int (*claim)(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
+ void (*free)(sPAPRMachineState *spapr, int irq, int num);
+ qemu_irq (*qirq)(sPAPRMachineState *spapr, int irq);
+ void (*print_info)(sPAPRMachineState *spapr, Monitor *mon);
+} sPAPRIrq;
+
+extern sPAPRIrq spapr_irq_xics;
+
+int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
+void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num);
+qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
+
+/*
+ * XICS legacy routines
+ */
+int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp);
+#define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp)
+
+#endif
diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
index 6ac8a9392d..9c2916c9b2 100644
--- a/include/hw/ppc/xics.h
+++ b/include/hw/ppc/xics.h
@@ -29,7 +29,6 @@
#define XICS_H
#include "hw/qdev.h"
-#include "target/ppc/cpu-qom.h"
#define XICS_IPI 0x2
#define XICS_BUID 0x1
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 15ea6c26fd..821def0565 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -73,6 +73,7 @@ typedef struct VFIOContainer {
unsigned iommu_type;
int error;
bool initialized;
+ unsigned long pgsizes;
/*
* This assumes the host IOMMU can support only a single
* contiguous IOVA window. We may need to generalize that in
diff --git a/job.c b/job.c
index fa671b431a..e36ebaafd8 100644
--- a/job.c
+++ b/job.c
@@ -732,10 +732,10 @@ static void job_cancel_async(Job *job, bool force)
{
if (job->user_paused) {
/* Do not call job_enter here, the caller will handle it. */
- job->user_paused = false;
if (job->driver->user_resume) {
job->driver->user_resume(job);
}
+ job->user_paused = false;
assert(job->pause_count > 0);
job->pause_count--;
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 3c3c1aec48..850b72a0c7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -163,7 +163,6 @@
* (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
*/
-//#define DEBUG
/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
* once. This exercises the codepaths for restart.
*/
@@ -5884,9 +5883,6 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg)
ie++;
}
arg_type = ie->arg_type;
-#if defined(DEBUG)
- gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
-#endif
if (ie->do_ioctl) {
return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
} else if (!ie->host_cmd) {
@@ -8096,13 +8092,15 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask,
return 0;
}
-/* do_syscall() should always have a single exit point at the end so
- that actions, such as logging of syscall results, can be performed.
- All errnos that do_syscall() returns must be -TARGET_<errcode>. */
-abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
- abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6, abi_long arg7,
- abi_long arg8)
+/* This is an internal helper for do_syscall so that it is easier
+ * to have a single return point, so that actions, such as logging
+ * of syscall results, can be performed.
+ * All errnos that do_syscall() returns must be -TARGET_<errcode>.
+ */
+static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4,
+ abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8)
{
CPUState *cpu = ENV_GET_CPU(cpu_env);
abi_long ret;
@@ -8117,28 +8115,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
void *p;
-#if defined(DEBUG_ERESTARTSYS)
- /* Debug-only code for exercising the syscall-restart code paths
- * in the per-architecture cpu main loops: restart every syscall
- * the guest makes once before letting it through.
- */
- {
- static int flag;
-
- flag = !flag;
- if (flag) {
- return -TARGET_ERESTARTSYS;
- }
- }
-#endif
-
-#ifdef DEBUG
- gemu_log("syscall %d", num);
-#endif
- trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
- if(do_strace)
- print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
-
switch(num) {
case TARGET_NR_exit:
/* In old applications this may be used to implement _exit(2).
@@ -8147,8 +8123,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
Do thread termination if we have more then one thread. */
if (block_signals()) {
- ret = -TARGET_ERESTARTSYS;
- break;
+ return -TARGET_ERESTARTSYS;
}
cpu_list_lock();
@@ -8177,14 +8152,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
cpu_list_unlock();
preexit_cleanup(cpu_env, arg1);
_exit(arg1);
- ret = 0; /* avoid warning */
- break;
+ return 0; /* avoid warning */
case TARGET_NR_read:
- if (arg3 == 0)
- ret = 0;
- else {
+ if (arg3 == 0) {
+ return 0;
+ } else {
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(safe_read(arg1, p, arg3));
if (ret >= 0 &&
fd_trans_host_to_target_data(arg1)) {
@@ -8192,10 +8166,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(p, arg2, ret);
}
- break;
+ return ret;
case TARGET_NR_write:
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
+ return -TARGET_EFAULT;
if (fd_trans_target_to_host_data(arg1)) {
void *copy = g_malloc(arg3);
memcpy(copy, p, arg3);
@@ -8208,49 +8182,48 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(safe_write(arg1, p, arg3));
}
unlock_user(p, arg2, 0);
- break;
+ return ret;
+
#ifdef TARGET_NR_open
case TARGET_NR_open:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
target_to_host_bitmask(arg2, fcntl_flags_tbl),
arg3));
fd_trans_unregister(ret);
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
case TARGET_NR_openat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(do_openat(cpu_env, arg1, p,
target_to_host_bitmask(arg3, fcntl_flags_tbl),
arg4));
fd_trans_unregister(ret);
unlock_user(p, arg2, 0);
- break;
+ return ret;
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
case TARGET_NR_name_to_handle_at:
ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
case TARGET_NR_open_by_handle_at:
ret = do_open_by_handle_at(arg1, arg2, arg3);
fd_trans_unregister(ret);
- break;
+ return ret;
#endif
case TARGET_NR_close:
fd_trans_unregister(arg1);
- ret = get_errno(close(arg1));
- break;
+ return get_errno(close(arg1));
+
case TARGET_NR_brk:
- ret = do_brk(arg1);
- break;
+ return do_brk(arg1);
#ifdef TARGET_NR_fork
case TARGET_NR_fork:
- ret = get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
- break;
+ return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
#endif
#ifdef TARGET_NR_waitpid
case TARGET_NR_waitpid:
@@ -8259,9 +8232,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
if (!is_error(ret) && arg2 && ret
&& put_user_s32(host_to_target_waitstatus(status), arg2))
- goto efault;
+ return -TARGET_EFAULT;
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_waitid
case TARGET_NR_waitid:
@@ -8271,21 +8244,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
if (!is_error(ret) && arg3 && info.si_pid != 0) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
- goto efault;
+ return -TARGET_EFAULT;
host_to_target_siginfo(p, &info);
unlock_user(p, arg3, sizeof(target_siginfo_t));
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_creat /* not on alpha */
case TARGET_NR_creat:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(creat(p, arg2));
fd_trans_unregister(ret);
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_link
case TARGET_NR_link:
@@ -8300,14 +8273,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg2, 0);
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_linkat)
case TARGET_NR_linkat:
{
void * p2 = NULL;
if (!arg2 || !arg4)
- goto efault;
+ return -TARGET_EFAULT;
p = lock_user_string(arg2);
p2 = lock_user_string(arg4);
if (!p || !p2)
@@ -8317,23 +8290,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg2, 0);
unlock_user(p2, arg4, 0);
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_unlink
case TARGET_NR_unlink:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(unlink(p));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_unlinkat)
case TARGET_NR_unlinkat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(unlinkat(arg1, p, arg3));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
case TARGET_NR_execve:
{
@@ -8350,7 +8323,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
guest_argp = arg2;
for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
if (get_user_ual(addr, gp))
- goto efault;
+ return -TARGET_EFAULT;
if (!addr)
break;
argc++;
@@ -8359,7 +8332,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
guest_envp = arg3;
for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
if (get_user_ual(addr, gp))
- goto efault;
+ return -TARGET_EFAULT;
if (!addr)
break;
envc++;
@@ -8431,13 +8404,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
g_free(argp);
g_free(envp);
}
- break;
+ return ret;
case TARGET_NR_chdir:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(chdir(p));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#ifdef TARGET_NR_time
case TARGET_NR_time:
{
@@ -8446,58 +8419,47 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)
&& arg1
&& put_user_sal(host_time, arg1))
- goto efault;
+ return -TARGET_EFAULT;
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_mknod
case TARGET_NR_mknod:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(mknod(p, arg2, arg3));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_mknodat)
case TARGET_NR_mknodat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(mknodat(arg1, p, arg3, arg4));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_chmod
case TARGET_NR_chmod:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(chmod(p, arg2));
unlock_user(p, arg1, 0);
- break;
-#endif
-#ifdef TARGET_NR_break
- case TARGET_NR_break:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_oldstat
- case TARGET_NR_oldstat:
- goto unimplemented;
+ return ret;
#endif
#ifdef TARGET_NR_lseek
case TARGET_NR_lseek:
- ret = get_errno(lseek(arg1, arg2, arg3));
- break;
+ return get_errno(lseek(arg1, arg2, arg3));
#endif
#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
/* Alpha specific */
case TARGET_NR_getxpid:
((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
- ret = get_errno(getpid());
- break;
+ return get_errno(getpid());
#endif
#ifdef TARGET_NR_getpid
case TARGET_NR_getpid:
- ret = get_errno(getpid());
- break;
+ return get_errno(getpid());
#endif
case TARGET_NR_mount:
{
@@ -8507,7 +8469,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg1) {
p = lock_user_string(arg1);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
} else {
p = NULL;
@@ -8518,7 +8480,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg1) {
unlock_user(p, arg1, 0);
}
- goto efault;
+ return -TARGET_EFAULT;
}
if (arg3) {
@@ -8528,7 +8490,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
}
unlock_user(p2, arg2, 0);
- goto efault;
+ return -TARGET_EFAULT;
}
} else {
p3 = NULL;
@@ -8553,43 +8515,34 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p3, arg3, 0);
}
}
- break;
+ return ret;
#ifdef TARGET_NR_umount
case TARGET_NR_umount:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(umount(p));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_stime /* not on alpha */
case TARGET_NR_stime:
{
time_t host_time;
if (get_user_sal(host_time, arg1))
- goto efault;
- ret = get_errno(stime(&host_time));
+ return -TARGET_EFAULT;
+ return get_errno(stime(&host_time));
}
- break;
#endif
- case TARGET_NR_ptrace:
- goto unimplemented;
#ifdef TARGET_NR_alarm /* not on alpha */
case TARGET_NR_alarm:
- ret = alarm(arg1);
- break;
-#endif
-#ifdef TARGET_NR_oldfstat
- case TARGET_NR_oldfstat:
- goto unimplemented;
+ return alarm(arg1);
#endif
#ifdef TARGET_NR_pause /* not on alpha */
case TARGET_NR_pause:
if (!block_signals()) {
sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
}
- ret = -TARGET_EINTR;
- break;
+ return -TARGET_EINTR;
#endif
#ifdef TARGET_NR_utime
case TARGET_NR_utime:
@@ -8598,7 +8551,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_utimbuf *target_tbuf;
if (arg2) {
if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
tbuf.actime = tswapal(target_tbuf->actime);
tbuf.modtime = tswapal(target_tbuf->modtime);
unlock_user_struct(target_tbuf, arg2, 0);
@@ -8607,11 +8560,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
host_tbuf = NULL;
}
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(utime(p, host_tbuf));
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_utimes
case TARGET_NR_utimes:
@@ -8621,17 +8574,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (copy_from_user_timeval(&tv[0], arg2)
|| copy_from_user_timeval(&tv[1],
arg2 + sizeof(struct target_timeval)))
- goto efault;
+ return -TARGET_EFAULT;
tvp = tv;
} else {
tvp = NULL;
}
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(utimes(p, tvp));
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_futimesat)
case TARGET_NR_futimesat:
@@ -8641,63 +8594,50 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (copy_from_user_timeval(&tv[0], arg3)
|| copy_from_user_timeval(&tv[1],
arg3 + sizeof(struct target_timeval)))
- goto efault;
+ return -TARGET_EFAULT;
tvp = tv;
} else {
tvp = NULL;
}
- if (!(p = lock_user_string(arg2)))
- goto efault;
+ if (!(p = lock_user_string(arg2))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(futimesat(arg1, path(p), tvp));
unlock_user(p, arg2, 0);
}
- break;
-#endif
-#ifdef TARGET_NR_stty
- case TARGET_NR_stty:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_gtty
- case TARGET_NR_gtty:
- goto unimplemented;
+ return ret;
#endif
#ifdef TARGET_NR_access
case TARGET_NR_access:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(access(path(p), arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
case TARGET_NR_faccessat:
- if (!(p = lock_user_string(arg2)))
- goto efault;
+ if (!(p = lock_user_string(arg2))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(faccessat(arg1, p, arg3, 0));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_nice /* not on alpha */
case TARGET_NR_nice:
- ret = get_errno(nice(arg1));
- break;
-#endif
-#ifdef TARGET_NR_ftime
- case TARGET_NR_ftime:
- goto unimplemented;
+ return get_errno(nice(arg1));
#endif
case TARGET_NR_sync:
sync();
- ret = 0;
- break;
+ return 0;
#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
case TARGET_NR_syncfs:
- ret = get_errno(syncfs(arg1));
- break;
+ return get_errno(syncfs(arg1));
#endif
case TARGET_NR_kill:
- ret = get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
- break;
+ return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
#ifdef TARGET_NR_rename
case TARGET_NR_rename:
{
@@ -8711,7 +8651,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg2, 0);
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_renameat)
case TARGET_NR_renameat:
@@ -8726,7 +8666,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg4, 0);
unlock_user(p, arg2, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_renameat2)
case TARGET_NR_renameat2:
@@ -8742,48 +8682,46 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg4, 0);
unlock_user(p, arg2, 0);
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_mkdir
case TARGET_NR_mkdir:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(mkdir(p, arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_mkdirat)
case TARGET_NR_mkdirat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(mkdirat(arg1, p, arg3));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_rmdir
case TARGET_NR_rmdir:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(rmdir(p));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
case TARGET_NR_dup:
ret = get_errno(dup(arg1));
if (ret >= 0) {
fd_trans_dup(arg1, ret);
}
- break;
+ return ret;
#ifdef TARGET_NR_pipe
case TARGET_NR_pipe:
- ret = do_pipe(cpu_env, arg1, 0, 0);
- break;
+ return do_pipe(cpu_env, arg1, 0, 0);
#endif
#ifdef TARGET_NR_pipe2
case TARGET_NR_pipe2:
- ret = do_pipe(cpu_env, arg1,
- target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
- break;
+ return do_pipe(cpu_env, arg1,
+ target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
#endif
case TARGET_NR_times:
{
@@ -8793,7 +8731,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg1) {
tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
if (!tmsp)
- goto efault;
+ return -TARGET_EFAULT;
tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
@@ -8802,80 +8740,49 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret))
ret = host_to_target_clock_t(ret);
}
- break;
-#ifdef TARGET_NR_prof
- case TARGET_NR_prof:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_signal
- case TARGET_NR_signal:
- goto unimplemented;
-#endif
+ return ret;
case TARGET_NR_acct:
if (arg1 == 0) {
ret = get_errno(acct(NULL));
} else {
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(acct(path(p)));
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#ifdef TARGET_NR_umount2
case TARGET_NR_umount2:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(umount2(p, arg2));
unlock_user(p, arg1, 0);
- break;
-#endif
-#ifdef TARGET_NR_lock
- case TARGET_NR_lock:
- goto unimplemented;
+ return ret;
#endif
case TARGET_NR_ioctl:
- ret = do_ioctl(arg1, arg2, arg3);
- break;
+ return do_ioctl(arg1, arg2, arg3);
#ifdef TARGET_NR_fcntl
case TARGET_NR_fcntl:
- ret = do_fcntl(arg1, arg2, arg3);
- break;
-#endif
-#ifdef TARGET_NR_mpx
- case TARGET_NR_mpx:
- goto unimplemented;
+ return do_fcntl(arg1, arg2, arg3);
#endif
case TARGET_NR_setpgid:
- ret = get_errno(setpgid(arg1, arg2));
- break;
-#ifdef TARGET_NR_ulimit
- case TARGET_NR_ulimit:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_oldolduname
- case TARGET_NR_oldolduname:
- goto unimplemented;
-#endif
+ return get_errno(setpgid(arg1, arg2));
case TARGET_NR_umask:
- ret = get_errno(umask(arg1));
- break;
+ return get_errno(umask(arg1));
case TARGET_NR_chroot:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(chroot(p));
unlock_user(p, arg1, 0);
- break;
-#ifdef TARGET_NR_ustat
- case TARGET_NR_ustat:
- goto unimplemented;
-#endif
+ return ret;
#ifdef TARGET_NR_dup2
case TARGET_NR_dup2:
ret = get_errno(dup2(arg1, arg2));
if (ret >= 0) {
fd_trans_dup(arg1, arg2);
}
- break;
+ return ret;
#endif
#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
case TARGET_NR_dup3:
@@ -8890,22 +8797,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (ret >= 0) {
fd_trans_dup(arg1, arg2);
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_getppid /* not on alpha */
case TARGET_NR_getppid:
- ret = get_errno(getppid());
- break;
+ return get_errno(getppid());
#endif
#ifdef TARGET_NR_getpgrp
case TARGET_NR_getpgrp:
- ret = get_errno(getpgrp());
- break;
+ return get_errno(getpgrp());
#endif
case TARGET_NR_setsid:
- ret = get_errno(setsid());
- break;
+ return get_errno(setsid());
#ifdef TARGET_NR_sigaction
case TARGET_NR_sigaction:
{
@@ -8914,7 +8818,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_old_sigaction *old_act;
if (arg2) {
if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask);
act.sa_flags = old_act->sa_flags;
@@ -8925,7 +8829,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
- goto efault;
+ return -TARGET_EFAULT;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_mask = oact.sa_mask.sig[0];
old_act->sa_flags = oact.sa_flags;
@@ -8936,7 +8840,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg2) {
if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
act.sa_flags = old_act->sa_flags;
@@ -8950,7 +8854,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
- goto efault;
+ return -TARGET_EFAULT;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_flags = oact.sa_flags;
old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
@@ -8964,7 +8868,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_sigaction act, oact, *pact;
if (arg2) {
if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
act._sa_handler = old_act->_sa_handler;
target_siginitset(&act.sa_mask, old_act->sa_mask);
act.sa_flags = old_act->sa_flags;
@@ -8980,7 +8884,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
- goto efault;
+ return -TARGET_EFAULT;
old_act->_sa_handler = oact._sa_handler;
old_act->sa_mask = oact.sa_mask.sig[0];
old_act->sa_flags = oact.sa_flags;
@@ -8989,7 +8893,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
#endif
}
- break;
+ return ret;
#endif
case TARGET_NR_rt_sigaction:
{
@@ -9006,12 +8910,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_sigaction act, oact, *pact = 0;
if (arg4 != sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
if (arg2) {
if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
act._sa_handler = rt_act->_sa_handler;
act.sa_mask = rt_act->sa_mask;
act.sa_flags = rt_act->sa_flags;
@@ -9022,7 +8925,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(do_sigaction(arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
- goto efault;
+ return -TARGET_EFAULT;
rt_act->_sa_handler = oact._sa_handler;
rt_act->sa_mask = oact.sa_mask;
rt_act->sa_flags = oact.sa_flags;
@@ -9039,12 +8942,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_sigaction *oact;
if (sigsetsize != sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
if (arg2) {
if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
#ifdef TARGET_ARCH_HAS_KA_RESTORER
act->ka_restorer = restorer;
@@ -9067,7 +8969,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(oact, arg3, 1);
#endif
}
- break;
+ return ret;
#ifdef TARGET_NR_sgetmask /* not on alpha */
case TARGET_NR_sgetmask:
{
@@ -9079,7 +8981,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = target_set;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_ssetmask /* not on alpha */
case TARGET_NR_ssetmask:
@@ -9093,7 +8995,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = target_set;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_sigprocmask
case TARGET_NR_sigprocmask:
@@ -9114,8 +9016,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK;
break;
default:
- ret = -TARGET_EINVAL;
- goto fail;
+ return -TARGET_EINVAL;
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
@@ -9142,11 +9043,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK;
break;
default:
- ret = -TARGET_EINVAL;
- goto fail;
+ return -TARGET_EINVAL;
}
if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
- goto efault;
+ return -TARGET_EFAULT;
target_to_host_old_sigset(&set, p);
unlock_user(p, arg2, 0);
set_ptr = &set;
@@ -9157,13 +9057,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_sigprocmask(how, set_ptr, &oldset);
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
- goto efault;
+ return -TARGET_EFAULT;
host_to_target_old_sigset(p, &oldset);
unlock_user(p, arg3, sizeof(target_sigset_t));
}
#endif
}
- break;
+ return ret;
#endif
case TARGET_NR_rt_sigprocmask:
{
@@ -9171,8 +9071,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
sigset_t set, oldset, *set_ptr;
if (arg4 != sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
if (arg2) {
@@ -9187,11 +9086,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK;
break;
default:
- ret = -TARGET_EINVAL;
- goto fail;
+ return -TARGET_EINVAL;
}
if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
- goto efault;
+ return -TARGET_EFAULT;
target_to_host_sigset(&set, p);
unlock_user(p, arg2, 0);
set_ptr = &set;
@@ -9202,12 +9100,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_sigprocmask(how, set_ptr, &oldset);
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
- goto efault;
+ return -TARGET_EFAULT;
host_to_target_sigset(p, &oldset);
unlock_user(p, arg3, sizeof(target_sigset_t));
}
}
- break;
+ return ret;
#ifdef TARGET_NR_sigpending
case TARGET_NR_sigpending:
{
@@ -9215,12 +9113,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sigpending(&set));
if (!is_error(ret)) {
if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
- goto efault;
+ return -TARGET_EFAULT;
host_to_target_old_sigset(p, &set);
unlock_user(p, arg1, sizeof(target_sigset_t));
}
}
- break;
+ return ret;
#endif
case TARGET_NR_rt_sigpending:
{
@@ -9232,19 +9130,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* the old_sigset_t is smaller in size.
*/
if (arg2 > sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
ret = get_errno(sigpending(&set));
if (!is_error(ret)) {
if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
- goto efault;
+ return -TARGET_EFAULT;
host_to_target_sigset(p, &set);
unlock_user(p, arg1, sizeof(target_sigset_t));
}
}
- break;
+ return ret;
#ifdef TARGET_NR_sigsuspend
case TARGET_NR_sigsuspend:
{
@@ -9254,7 +9151,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
#else
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
- goto efault;
+ return -TARGET_EFAULT;
target_to_host_old_sigset(&ts->sigsuspend_mask, p);
unlock_user(p, arg1, 0);
#endif
@@ -9264,18 +9161,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ts->in_sigsuspend = 1;
}
}
- break;
+ return ret;
#endif
case TARGET_NR_rt_sigsuspend:
{
TaskState *ts = cpu->opaque;
if (arg2 != sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
- goto efault;
+ return -TARGET_EFAULT;
target_to_host_sigset(&ts->sigsuspend_mask, p);
unlock_user(p, arg1, 0);
ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
@@ -9284,7 +9180,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ts->in_sigsuspend = 1;
}
}
- break;
+ return ret;
case TARGET_NR_rt_sigtimedwait:
{
sigset_t set;
@@ -9292,12 +9188,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
siginfo_t uinfo;
if (arg4 != sizeof(target_sigset_t)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
- goto efault;
+ return -TARGET_EFAULT;
target_to_host_sigset(&set, p);
unlock_user(p, arg1, 0);
if (arg3) {
@@ -9313,7 +9208,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
0);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
host_to_target_siginfo(p, &uinfo);
unlock_user(p, arg2, sizeof(target_siginfo_t));
@@ -9321,55 +9216,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_signal(ret);
}
}
- break;
+ return ret;
case TARGET_NR_rt_sigqueueinfo:
{
siginfo_t uinfo;
p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg3, 0);
ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
}
- break;
+ return ret;
case TARGET_NR_rt_tgsigqueueinfo:
{
siginfo_t uinfo;
p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg4, 0);
ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
}
- break;
+ return ret;
#ifdef TARGET_NR_sigreturn
case TARGET_NR_sigreturn:
if (block_signals()) {
- ret = -TARGET_ERESTARTSYS;
- } else {
- ret = do_sigreturn(cpu_env);
+ return -TARGET_ERESTARTSYS;
}
- break;
+ return do_sigreturn(cpu_env);
#endif
case TARGET_NR_rt_sigreturn:
if (block_signals()) {
- ret = -TARGET_ERESTARTSYS;
- } else {
- ret = do_rt_sigreturn(cpu_env);
+ return -TARGET_ERESTARTSYS;
}
- break;
+ return do_rt_sigreturn(cpu_env);
case TARGET_NR_sethostname:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(sethostname(p, arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#ifdef TARGET_NR_setrlimit
case TARGET_NR_setrlimit:
{
@@ -9377,13 +9268,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_rlimit *target_rlim;
struct rlimit rlim;
if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
unlock_user_struct(target_rlim, arg2, 0);
- ret = get_errno(setrlimit(resource, &rlim));
+ return get_errno(setrlimit(resource, &rlim));
}
- break;
#endif
#ifdef TARGET_NR_getrlimit
case TARGET_NR_getrlimit:
@@ -9395,13 +9285,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(getrlimit(resource, &rlim));
if (!is_error(ret)) {
if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
- goto efault;
+ return -TARGET_EFAULT;
target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
unlock_user_struct(target_rlim, arg2, 1);
}
}
- break;
+ return ret;
#endif
case TARGET_NR_getrusage:
{
@@ -9411,17 +9301,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_rusage(arg2, &rusage);
}
}
- break;
+ return ret;
case TARGET_NR_gettimeofday:
{
struct timeval tv;
ret = get_errno(gettimeofday(&tv, NULL));
if (!is_error(ret)) {
if (copy_to_user_timeval(arg1, &tv))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
case TARGET_NR_settimeofday:
{
struct timeval tv, *ptv = NULL;
@@ -9429,21 +9319,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg1) {
if (copy_from_user_timeval(&tv, arg1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ptv = &tv;
}
if (arg2) {
if (copy_from_user_timezone(&tz, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ptz = &tz;
}
- ret = get_errno(settimeofday(ptv, ptz));
+ return get_errno(settimeofday(ptv, ptz));
}
- break;
#if defined(TARGET_NR_select)
case TARGET_NR_select:
#if defined(TARGET_WANT_NI_OLD_SELECT)
@@ -9456,7 +9345,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = do_select(arg1, arg2, arg3, arg4, arg5);
#endif
- break;
+ return ret;
#endif
#ifdef TARGET_NR_pselect6
case TARGET_NR_pselect6:
@@ -9487,15 +9376,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
if (ret) {
- goto fail;
+ return ret;
}
ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
if (ret) {
- goto fail;
+ return ret;
}
ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
if (ret) {
- goto fail;
+ return ret;
}
/*
@@ -9504,7 +9393,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
*/
if (ts_addr) {
if (target_to_host_timespec(&ts, ts_addr)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ts_ptr = &ts;
} else {
@@ -9518,7 +9407,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
if (!arg7) {
- goto efault;
+ return -TARGET_EFAULT;
}
arg_sigset = tswapal(arg7[0]);
arg_sigsize = tswapal(arg7[1]);
@@ -9528,13 +9417,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
sig.set = &set;
if (arg_sigsize != sizeof(*target_sigset)) {
/* Like the kernel, we enforce correct size sigsets */
- ret = -TARGET_EINVAL;
- goto fail;
+ return -TARGET_EINVAL;
}
target_sigset = lock_user(VERIFY_READ, arg_sigset,
sizeof(*target_sigset), 1);
if (!target_sigset) {
- goto efault;
+ return -TARGET_EFAULT;
}
target_to_host_sigset(&set, target_sigset);
unlock_user(target_sigset, arg_sigset, 0);
@@ -9550,17 +9438,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
- goto efault;
+ return -TARGET_EFAULT;
if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
- goto efault;
+ return -TARGET_EFAULT;
if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
- goto efault;
+ return -TARGET_EFAULT;
if (ts_addr && host_to_target_timespec(ts_addr, &ts))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_symlink
case TARGET_NR_symlink:
@@ -9575,7 +9463,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg2, 0);
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_symlinkat)
case TARGET_NR_symlinkat:
@@ -9590,11 +9478,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg3, 0);
unlock_user(p, arg1, 0);
}
- break;
-#endif
-#ifdef TARGET_NR_oldlstat
- case TARGET_NR_oldlstat:
- goto unimplemented;
+ return ret;
#endif
#ifdef TARGET_NR_readlink
case TARGET_NR_readlink:
@@ -9626,7 +9510,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg2, ret);
unlock_user(p, arg1, 0);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_readlinkat)
case TARGET_NR_readlinkat:
@@ -9647,37 +9531,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p2, arg3, ret);
unlock_user(p, arg2, 0);
}
- break;
-#endif
-#ifdef TARGET_NR_uselib
- case TARGET_NR_uselib:
- goto unimplemented;
+ return ret;
#endif
#ifdef TARGET_NR_swapon
case TARGET_NR_swapon:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(swapon(p, arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
case TARGET_NR_reboot:
if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
/* arg4 must be ignored in all other cases */
p = lock_user_string(arg4);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(reboot(arg1, arg2, arg3, p));
unlock_user(p, arg4, 0);
} else {
ret = get_errno(reboot(arg1, arg2, arg3, NULL));
}
- break;
-#ifdef TARGET_NR_readdir
- case TARGET_NR_readdir:
- goto unimplemented;
-#endif
+ return ret;
#ifdef TARGET_NR_mmap
case TARGET_NR_mmap:
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
@@ -9688,7 +9564,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_ulong *v;
abi_ulong v1, v2, v3, v4, v5, v6;
if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
- goto efault;
+ return -TARGET_EFAULT;
v1 = tswapal(v[0]);
v2 = tswapal(v[1]);
v3 = tswapal(v[2]);
@@ -9706,22 +9582,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg5,
arg6));
#endif
- break;
+ return ret;
#endif
#ifdef TARGET_NR_mmap2
case TARGET_NR_mmap2:
#ifndef MMAP_SHIFT
#define MMAP_SHIFT 12
#endif
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6 << MMAP_SHIFT));
- break;
+ ret = target_mmap(arg1, arg2, arg3,
+ target_to_host_bitmask(arg4, mmap_flags_tbl),
+ arg5, arg6 << MMAP_SHIFT);
+ return get_errno(ret);
#endif
case TARGET_NR_munmap:
- ret = get_errno(target_munmap(arg1, arg2));
- break;
+ return get_errno(target_munmap(arg1, arg2));
case TARGET_NR_mprotect:
{
TaskState *ts = cpu->opaque;
@@ -9734,62 +9608,53 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg1 = ts->info->stack_limit;
}
}
- ret = get_errno(target_mprotect(arg1, arg2, arg3));
- break;
+ return get_errno(target_mprotect(arg1, arg2, arg3));
#ifdef TARGET_NR_mremap
case TARGET_NR_mremap:
- ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
- break;
+ return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
#endif
/* ??? msync/mlock/munlock are broken for softmmu. */
#ifdef TARGET_NR_msync
case TARGET_NR_msync:
- ret = get_errno(msync(g2h(arg1), arg2, arg3));
- break;
+ return get_errno(msync(g2h(arg1), arg2, arg3));
#endif
#ifdef TARGET_NR_mlock
case TARGET_NR_mlock:
- ret = get_errno(mlock(g2h(arg1), arg2));
- break;
+ return get_errno(mlock(g2h(arg1), arg2));
#endif
#ifdef TARGET_NR_munlock
case TARGET_NR_munlock:
- ret = get_errno(munlock(g2h(arg1), arg2));
- break;
+ return get_errno(munlock(g2h(arg1), arg2));
#endif
#ifdef TARGET_NR_mlockall
case TARGET_NR_mlockall:
- ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
- break;
+ return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
#endif
#ifdef TARGET_NR_munlockall
case TARGET_NR_munlockall:
- ret = get_errno(munlockall());
- break;
+ return get_errno(munlockall());
#endif
#ifdef TARGET_NR_truncate
case TARGET_NR_truncate:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(truncate(p, arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_ftruncate
case TARGET_NR_ftruncate:
- ret = get_errno(ftruncate(arg1, arg2));
- break;
+ return get_errno(ftruncate(arg1, arg2));
#endif
case TARGET_NR_fchmod:
- ret = get_errno(fchmod(arg1, arg2));
- break;
+ return get_errno(fchmod(arg1, arg2));
#if defined(TARGET_NR_fchmodat)
case TARGET_NR_fchmodat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(fchmodat(arg1, p, arg3, 0));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
case TARGET_NR_getpriority:
/* Note that negative values are valid for getpriority, so we must
@@ -9797,8 +9662,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
errno = 0;
ret = getpriority(arg1, arg2);
if (ret == -1 && errno != 0) {
- ret = -host_to_target_errno(errno);
- break;
+ return -host_to_target_errno(errno);
}
#ifdef TARGET_ALPHA
/* Return value is the unbiased priority. Signal no error. */
@@ -9807,18 +9671,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
/* Return value is a biased priority to avoid negative numbers. */
ret = 20 - ret;
#endif
- break;
+ return ret;
case TARGET_NR_setpriority:
- ret = get_errno(setpriority(arg1, arg2, arg3));
- break;
-#ifdef TARGET_NR_profil
- case TARGET_NR_profil:
- goto unimplemented;
-#endif
+ return get_errno(setpriority(arg1, arg2, arg3));
#ifdef TARGET_NR_statfs
case TARGET_NR_statfs:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(statfs(path(p), &stfs));
unlock_user(p, arg1, 0);
convert_statfs:
@@ -9826,7 +9686,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_statfs *target_stfs;
if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
- goto efault;
+ return -TARGET_EFAULT;
__put_user(stfs.f_type, &target_stfs->f_type);
__put_user(stfs.f_bsize, &target_stfs->f_bsize);
__put_user(stfs.f_blocks, &target_stfs->f_blocks);
@@ -9846,7 +9706,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg2, 1);
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_fstatfs
case TARGET_NR_fstatfs:
@@ -9855,8 +9715,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_statfs64
case TARGET_NR_statfs64:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(statfs(path(p), &stfs));
unlock_user(p, arg1, 0);
convert_statfs64:
@@ -9864,7 +9725,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_statfs64 *target_stfs;
if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
- goto efault;
+ return -TARGET_EFAULT;
__put_user(stfs.f_type, &target_stfs->f_type);
__put_user(stfs.f_bsize, &target_stfs->f_bsize);
__put_user(stfs.f_blocks, &target_stfs->f_blocks);
@@ -9879,127 +9740,102 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
unlock_user_struct(target_stfs, arg3, 1);
}
- break;
+ return ret;
case TARGET_NR_fstatfs64:
ret = get_errno(fstatfs(arg1, &stfs));
goto convert_statfs64;
#endif
-#ifdef TARGET_NR_ioperm
- case TARGET_NR_ioperm:
- goto unimplemented;
-#endif
#ifdef TARGET_NR_socketcall
case TARGET_NR_socketcall:
- ret = do_socketcall(arg1, arg2);
- break;
+ return do_socketcall(arg1, arg2);
#endif
#ifdef TARGET_NR_accept
case TARGET_NR_accept:
- ret = do_accept4(arg1, arg2, arg3, 0);
- break;
+ return do_accept4(arg1, arg2, arg3, 0);
#endif
#ifdef TARGET_NR_accept4
case TARGET_NR_accept4:
- ret = do_accept4(arg1, arg2, arg3, arg4);
- break;
+ return do_accept4(arg1, arg2, arg3, arg4);
#endif
#ifdef TARGET_NR_bind
case TARGET_NR_bind:
- ret = do_bind(arg1, arg2, arg3);
- break;
+ return do_bind(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_connect
case TARGET_NR_connect:
- ret = do_connect(arg1, arg2, arg3);
- break;
+ return do_connect(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_getpeername
case TARGET_NR_getpeername:
- ret = do_getpeername(arg1, arg2, arg3);
- break;
+ return do_getpeername(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_getsockname
case TARGET_NR_getsockname:
- ret = do_getsockname(arg1, arg2, arg3);
- break;
+ return do_getsockname(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_getsockopt
case TARGET_NR_getsockopt:
- ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
- break;
+ return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
#endif
#ifdef TARGET_NR_listen
case TARGET_NR_listen:
- ret = get_errno(listen(arg1, arg2));
- break;
+ return get_errno(listen(arg1, arg2));
#endif
#ifdef TARGET_NR_recv
case TARGET_NR_recv:
- ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
- break;
+ return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
#endif
#ifdef TARGET_NR_recvfrom
case TARGET_NR_recvfrom:
- ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
- break;
+ return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
#endif
#ifdef TARGET_NR_recvmsg
case TARGET_NR_recvmsg:
- ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
- break;
+ return do_sendrecvmsg(arg1, arg2, arg3, 0);
#endif
#ifdef TARGET_NR_send
case TARGET_NR_send:
- ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
- break;
+ return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
#endif
#ifdef TARGET_NR_sendmsg
case TARGET_NR_sendmsg:
- ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
- break;
+ return do_sendrecvmsg(arg1, arg2, arg3, 1);
#endif
#ifdef TARGET_NR_sendmmsg
case TARGET_NR_sendmmsg:
- ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
- break;
+ return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
case TARGET_NR_recvmmsg:
- ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
- break;
+ return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
#endif
#ifdef TARGET_NR_sendto
case TARGET_NR_sendto:
- ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
- break;
+ return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
#endif
#ifdef TARGET_NR_shutdown
case TARGET_NR_shutdown:
- ret = get_errno(shutdown(arg1, arg2));
- break;
+ return get_errno(shutdown(arg1, arg2));
#endif
#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
case TARGET_NR_getrandom:
p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(getrandom(p, arg2, arg3));
unlock_user(p, arg1, ret);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_socket
case TARGET_NR_socket:
- ret = do_socket(arg1, arg2, arg3);
- break;
+ return do_socket(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_socketpair
case TARGET_NR_socketpair:
- ret = do_socketpair(arg1, arg2, arg3, arg4);
- break;
+ return do_socketpair(arg1, arg2, arg3, arg4);
#endif
#ifdef TARGET_NR_setsockopt
case TARGET_NR_setsockopt:
- ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
- break;
+ return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
#endif
#if defined(TARGET_NR_syslog)
case TARGET_NR_syslog:
@@ -10015,34 +9851,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
- {
- ret = get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
- }
- break;
+ return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
case TARGET_SYSLOG_ACTION_READ: /* Read from log */
case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
{
- ret = -TARGET_EINVAL;
if (len < 0) {
- goto fail;
+ return -TARGET_EINVAL;
}
- ret = 0;
if (len == 0) {
- break;
+ return 0;
}
p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
if (!p) {
- ret = -TARGET_EFAULT;
- goto fail;
+ return -TARGET_EFAULT;
}
ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
unlock_user(p, arg2, arg3);
}
- break;
+ return ret;
default:
- ret = -EINVAL;
- break;
+ return -TARGET_EINVAL;
}
}
break;
@@ -10056,7 +9885,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (copy_from_user_timeval(&pvalue->it_interval, arg2)
|| copy_from_user_timeval(&pvalue->it_value,
arg2 + sizeof(struct target_timeval)))
- goto efault;
+ return -TARGET_EFAULT;
} else {
pvalue = NULL;
}
@@ -10066,10 +9895,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
&ovalue.it_interval)
|| copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
&ovalue.it_value))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
case TARGET_NR_getitimer:
{
struct itimerval value;
@@ -10080,22 +9909,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
&value.it_interval)
|| copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
&value.it_value))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#ifdef TARGET_NR_stat
case TARGET_NR_stat:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(stat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat;
#endif
#ifdef TARGET_NR_lstat
case TARGET_NR_lstat:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(lstat(path(p), &st));
unlock_user(p, arg1, 0);
goto do_stat;
@@ -10111,7 +9942,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct target_stat *target_st;
if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
- goto efault;
+ return -TARGET_EFAULT;
memset(target_st, 0, sizeof(*target_st));
__put_user(st.st_dev, &target_st->st_dev);
__put_user(st.st_ino, &target_st->st_ino);
@@ -10129,28 +9960,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(target_st, arg2, 1);
}
}
- break;
-#endif
-#ifdef TARGET_NR_olduname
- case TARGET_NR_olduname:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_iopl
- case TARGET_NR_iopl:
- goto unimplemented;
+ return ret;
#endif
case TARGET_NR_vhangup:
- ret = get_errno(vhangup());
- break;
-#ifdef TARGET_NR_idle
- case TARGET_NR_idle:
- goto unimplemented;
-#endif
+ return get_errno(vhangup());
#ifdef TARGET_NR_syscall
case TARGET_NR_syscall:
- ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
- arg6, arg7, arg8, 0);
- break;
+ return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
+ arg6, arg7, arg8, 0);
#endif
case TARGET_NR_wait4:
{
@@ -10168,7 +9985,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (status_ptr && ret) {
status = host_to_target_waitstatus(status);
if (put_user_s32(status, status_ptr))
- goto efault;
+ return -TARGET_EFAULT;
}
if (target_rusage) {
rusage_err = host_to_target_rusage(target_rusage, &rusage);
@@ -10178,14 +9995,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
}
- break;
+ return ret;
#ifdef TARGET_NR_swapoff
case TARGET_NR_swapoff:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(swapoff(p));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
case TARGET_NR_sysinfo:
{
@@ -10195,7 +10012,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret) && arg1)
{
if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
- goto efault;
+ return -TARGET_EFAULT;
__put_user(value.uptime, &target_value->uptime);
__put_user(value.loads[0], &target_value->loads[0]);
__put_user(value.loads[1], &target_value->loads[1]);
@@ -10213,70 +10030,57 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(target_value, arg1, 1);
}
}
- break;
+ return ret;
#ifdef TARGET_NR_ipc
case TARGET_NR_ipc:
- ret = do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
- break;
+ return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
#endif
#ifdef TARGET_NR_semget
case TARGET_NR_semget:
- ret = get_errno(semget(arg1, arg2, arg3));
- break;
+ return get_errno(semget(arg1, arg2, arg3));
#endif
#ifdef TARGET_NR_semop
case TARGET_NR_semop:
- ret = do_semop(arg1, arg2, arg3);
- break;
+ return do_semop(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_semctl
case TARGET_NR_semctl:
- ret = do_semctl(arg1, arg2, arg3, arg4);
- break;
+ return do_semctl(arg1, arg2, arg3, arg4);
#endif
#ifdef TARGET_NR_msgctl
case TARGET_NR_msgctl:
- ret = do_msgctl(arg1, arg2, arg3);
- break;
+ return do_msgctl(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_msgget
case TARGET_NR_msgget:
- ret = get_errno(msgget(arg1, arg2));
- break;
+ return get_errno(msgget(arg1, arg2));
#endif
#ifdef TARGET_NR_msgrcv
case TARGET_NR_msgrcv:
- ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
- break;
+ return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
#endif
#ifdef TARGET_NR_msgsnd
case TARGET_NR_msgsnd:
- ret = do_msgsnd(arg1, arg2, arg3, arg4);
- break;
+ return do_msgsnd(arg1, arg2, arg3, arg4);
#endif
#ifdef TARGET_NR_shmget
case TARGET_NR_shmget:
- ret = get_errno(shmget(arg1, arg2, arg3));
- break;
+ return get_errno(shmget(arg1, arg2, arg3));
#endif
#ifdef TARGET_NR_shmctl
case TARGET_NR_shmctl:
- ret = do_shmctl(arg1, arg2, arg3);
- break;
+ return do_shmctl(arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_shmat
case TARGET_NR_shmat:
- ret = do_shmat(cpu_env, arg1, arg2, arg3);
- break;
+ return do_shmat(cpu_env, arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_shmdt
case TARGET_NR_shmdt:
- ret = do_shmdt(arg1);
- break;
+ return do_shmdt(arg1);
#endif
case TARGET_NR_fsync:
- ret = get_errno(fsync(arg1));
- break;
+ return get_errno(fsync(arg1));
case TARGET_NR_clone:
/* Linux manages to have three different orderings for its
* arguments to clone(); the BACKWARDS and BACKWARDS2 defines
@@ -10293,27 +10097,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#endif
- break;
+ return ret;
#ifdef __NR_exit_group
/* new thread calls */
case TARGET_NR_exit_group:
preexit_cleanup(cpu_env, arg1);
- ret = get_errno(exit_group(arg1));
- break;
+ return get_errno(exit_group(arg1));
#endif
case TARGET_NR_setdomainname:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(setdomainname(p, arg2));
unlock_user(p, arg1, 0);
- break;
+ return ret;
case TARGET_NR_uname:
/* no need to transcode because we use the linux syscall */
{
struct new_utsname * buf;
if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(sys_uname(buf));
if (!is_error(ret)) {
/* Overwrite the native machine name with whatever is being
@@ -10328,17 +10131,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user_struct(buf, arg1, 1);
}
- break;
+ return ret;
#ifdef TARGET_I386
case TARGET_NR_modify_ldt:
- ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
- break;
+ return do_modify_ldt(cpu_env, arg1, arg2, arg3);
#if !defined(TARGET_X86_64)
- case TARGET_NR_vm86old:
- goto unimplemented;
case TARGET_NR_vm86:
- ret = do_vm86(cpu_env, arg1, arg2);
- break;
+ return do_vm86(cpu_env, arg1, arg2);
#endif
#endif
case TARGET_NR_adjtimex:
@@ -10346,65 +10145,39 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct timex host_buf;
if (target_to_host_timex(&host_buf, arg1) != 0) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(adjtimex(&host_buf));
if (!is_error(ret)) {
if (host_to_target_timex(arg1, &host_buf) != 0) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
}
- break;
+ return ret;
#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
case TARGET_NR_clock_adjtime:
{
struct timex htx, *phtx = &htx;
if (target_to_host_timex(phtx, arg2) != 0) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(clock_adjtime(arg1, phtx));
if (!is_error(ret) && phtx) {
if (host_to_target_timex(arg2, phtx) != 0) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
}
- break;
-#endif
-#ifdef TARGET_NR_create_module
- case TARGET_NR_create_module:
-#endif
- case TARGET_NR_init_module:
- case TARGET_NR_delete_module:
-#ifdef TARGET_NR_get_kernel_syms
- case TARGET_NR_get_kernel_syms:
+ return ret;
#endif
- goto unimplemented;
- case TARGET_NR_quotactl:
- goto unimplemented;
case TARGET_NR_getpgid:
- ret = get_errno(getpgid(arg1));
- break;
+ return get_errno(getpgid(arg1));
case TARGET_NR_fchdir:
- ret = get_errno(fchdir(arg1));
- break;
-#ifdef TARGET_NR_bdflush /* not on x86_64 */
- case TARGET_NR_bdflush:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_sysfs
- case TARGET_NR_sysfs:
- goto unimplemented;
-#endif
+ return get_errno(fchdir(arg1));
case TARGET_NR_personality:
- ret = get_errno(personality(arg1));
- break;
-#ifdef TARGET_NR_afs_syscall
- case TARGET_NR_afs_syscall:
- goto unimplemented;
-#endif
+ return get_errno(personality(arg1));
#ifdef TARGET_NR__llseek /* Not on alpha */
case TARGET_NR__llseek:
{
@@ -10420,10 +10193,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
#endif
if ((ret == 0) && put_user_s64(res, arg4)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_getdents
case TARGET_NR_getdents:
@@ -10436,8 +10209,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
dirp = g_try_malloc(count);
if (!dirp) {
- ret = -TARGET_ENOMEM;
- goto fail;
+ return -TARGET_ENOMEM;
}
ret = get_errno(sys_getdents(arg1, dirp, count));
@@ -10451,7 +10223,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
count1 = 0;
de = dirp;
if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- goto efault;
+ return -TARGET_EFAULT;
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
@@ -10479,7 +10251,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long count = arg3;
if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) {
struct linux_dirent *de;
@@ -10508,7 +10280,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
if (!dirp) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(sys_getdents64(arg1, dirp, count));
if (!is_error(ret)) {
@@ -10555,7 +10327,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(dirp, arg2, ret);
}
#endif
- break;
+ return ret;
#endif /* TARGET_NR_getdents */
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
case TARGET_NR_getdents64:
@@ -10563,7 +10335,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct linux_dirent64 *dirp;
abi_long count = arg3;
if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(sys_getdents64(arg1, dirp, count));
if (!is_error(ret)) {
struct linux_dirent64 *de;
@@ -10583,12 +10355,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(dirp, arg2, ret);
}
- break;
+ return ret;
#endif /* TARGET_NR_getdents64 */
#if defined(TARGET_NR__newselect)
case TARGET_NR__newselect:
- ret = do_select(arg1, arg2, arg3, arg4, arg5);
- break;
+ return do_select(arg1, arg2, arg3, arg4, arg5);
#endif
#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
# ifdef TARGET_NR_poll
@@ -10607,14 +10378,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
target_pfd = NULL;
if (nfds) {
if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
target_pfd = lock_user(VERIFY_WRITE, arg1,
sizeof(struct target_pollfd) * nfds, 1);
if (!target_pfd) {
- goto efault;
+ return -TARGET_EFAULT;
}
pfd = alloca(sizeof(struct pollfd) * nfds);
@@ -10635,7 +10405,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
if (target_to_host_timespec(timeout_ts, arg3)) {
unlock_user(target_pfd, arg1, 0);
- goto efault;
+ return -TARGET_EFAULT;
}
} else {
timeout_ts = NULL;
@@ -10644,14 +10414,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg4) {
if (arg5 != sizeof(target_sigset_t)) {
unlock_user(target_pfd, arg1, 0);
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
if (!target_set) {
unlock_user(target_pfd, arg1, 0);
- goto efault;
+ return -TARGET_EFAULT;
}
target_to_host_sigset(set, target_set);
} else {
@@ -10699,13 +10468,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
}
- break;
+ return ret;
#endif
case TARGET_NR_flock:
/* NOTE: the flock constant seems to be the same for every
Linux platform */
- ret = get_errno(safe_flock(arg1, arg2));
- break;
+ return get_errno(safe_flock(arg1, arg2));
case TARGET_NR_readv:
{
struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
@@ -10716,7 +10484,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -host_to_target_errno(errno);
}
}
- break;
+ return ret;
case TARGET_NR_writev:
{
struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
@@ -10727,7 +10495,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -host_to_target_errno(errno);
}
}
- break;
+ return ret;
#if defined(TARGET_NR_preadv)
case TARGET_NR_preadv:
{
@@ -10742,7 +10510,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -host_to_target_errno(errno);
}
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_pwritev)
case TARGET_NR_pwritev:
@@ -10758,22 +10526,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -host_to_target_errno(errno);
}
}
- break;
+ return ret;
#endif
case TARGET_NR_getsid:
- ret = get_errno(getsid(arg1));
- break;
+ return get_errno(getsid(arg1));
#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
case TARGET_NR_fdatasync:
- ret = get_errno(fdatasync(arg1));
- break;
+ return get_errno(fdatasync(arg1));
#endif
#ifdef TARGET_NR__sysctl
case TARGET_NR__sysctl:
/* We don't implement this, but ENOTDIR is always a safe
return value. */
- ret = -TARGET_ENOTDIR;
- break;
+ return -TARGET_ENOTDIR;
#endif
case TARGET_NR_sched_getaffinity:
{
@@ -10785,8 +10550,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* care of mismatches between target ulong and host ulong sizes.
*/
if (arg2 & (sizeof(abi_ulong) - 1)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
@@ -10805,18 +10569,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
*/
int numcpus = sysconf(_SC_NPROCESSORS_CONF);
if (numcpus > arg2 * 8) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
ret = arg2;
}
if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
}
- break;
+ return ret;
case TARGET_NR_sched_setaffinity:
{
unsigned int mask_size;
@@ -10827,20 +10590,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* care of mismatches between target ulong and host ulong sizes.
*/
if (arg2 & (sizeof(abi_ulong) - 1)) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
mask = alloca(mask_size);
ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
if (ret) {
- break;
+ return ret;
}
- ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
+ return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
}
- break;
case TARGET_NR_getcpu:
{
unsigned cpu, node;
@@ -10848,16 +10609,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg2 ? &node : NULL,
NULL));
if (is_error(ret)) {
- goto fail;
+ return ret;
}
if (arg1 && put_user_u32(cpu, arg1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
if (arg2 && put_user_u32(node, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
case TARGET_NR_sched_setparam:
{
struct sched_param *target_schp;
@@ -10867,12 +10628,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
return -TARGET_EINVAL;
}
if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
- goto efault;
+ return -TARGET_EFAULT;
schp.sched_priority = tswap32(target_schp->sched_priority);
unlock_user_struct(target_schp, arg2, 0);
- ret = get_errno(sched_setparam(arg1, &schp));
+ return get_errno(sched_setparam(arg1, &schp));
}
- break;
case TARGET_NR_sched_getparam:
{
struct sched_param *target_schp;
@@ -10884,12 +10644,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sched_getparam(arg1, &schp));
if (!is_error(ret)) {
if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
- goto efault;
+ return -TARGET_EFAULT;
target_schp->sched_priority = tswap32(schp.sched_priority);
unlock_user_struct(target_schp, arg2, 1);
}
}
- break;
+ return ret;
case TARGET_NR_sched_setscheduler:
{
struct sched_param *target_schp;
@@ -10898,24 +10658,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
return -TARGET_EINVAL;
}
if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
- goto efault;
+ return -TARGET_EFAULT;
schp.sched_priority = tswap32(target_schp->sched_priority);
unlock_user_struct(target_schp, arg3, 0);
- ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
+ return get_errno(sched_setscheduler(arg1, arg2, &schp));
}
- break;
case TARGET_NR_sched_getscheduler:
- ret = get_errno(sched_getscheduler(arg1));
- break;
+ return get_errno(sched_getscheduler(arg1));
case TARGET_NR_sched_yield:
- ret = get_errno(sched_yield());
- break;
+ return get_errno(sched_yield());
case TARGET_NR_sched_get_priority_max:
- ret = get_errno(sched_get_priority_max(arg1));
- break;
+ return get_errno(sched_get_priority_max(arg1));
case TARGET_NR_sched_get_priority_min:
- ret = get_errno(sched_get_priority_min(arg1));
- break;
+ return get_errno(sched_get_priority_min(arg1));
case TARGET_NR_sched_rr_get_interval:
{
struct timespec ts;
@@ -10924,7 +10679,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = host_to_target_timespec(arg2, &ts);
}
}
- break;
+ return ret;
case TARGET_NR_nanosleep:
{
struct timespec req, rem;
@@ -10934,15 +10689,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
host_to_target_timespec(arg2, &rem);
}
}
- break;
-#ifdef TARGET_NR_query_module
- case TARGET_NR_query_module:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_nfsservctl
- case TARGET_NR_nfsservctl:
- goto unimplemented;
-#endif
+ return ret;
case TARGET_NR_prctl:
switch (arg1) {
case PR_GET_PDEATHSIG:
@@ -10951,32 +10698,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
if (!is_error(ret) && arg2
&& put_user_ual(deathsig, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
- break;
+ return ret;
}
#ifdef PR_GET_NAME
case PR_GET_NAME:
{
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
if (!name) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(prctl(arg1, (unsigned long)name,
arg3, arg4, arg5));
unlock_user(name, arg2, 16);
- break;
+ return ret;
}
case PR_SET_NAME:
{
void *name = lock_user(VERIFY_READ, arg2, 16, 1);
if (!name) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(prctl(arg1, (unsigned long)name,
arg3, arg4, arg5));
unlock_user(name, arg2, 0);
- break;
+ return ret;
}
#endif
#ifdef TARGET_AARCH64
@@ -11004,34 +10751,31 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
env->vfp.zcr_el[1] = vq - 1;
ret = vq * 16;
}
- break;
+ return ret;
case TARGET_PR_SVE_GET_VL:
ret = -TARGET_EINVAL;
if (arm_feature(cpu_env, ARM_FEATURE_SVE)) {
CPUARMState *env = cpu_env;
ret = ((env->vfp.zcr_el[1] & 0xf) + 1) * 16;
}
- break;
+ return ret;
#endif /* AARCH64 */
case PR_GET_SECCOMP:
case PR_SET_SECCOMP:
/* Disable seccomp to prevent the target disabling syscalls we
* need. */
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
default:
/* Most prctl options have no pointer arguments */
- ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
- break;
+ return get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
}
break;
#ifdef TARGET_NR_arch_prctl
case TARGET_NR_arch_prctl:
#if defined(TARGET_I386) && !defined(TARGET_ABI32)
- ret = do_arch_prctl(cpu_env, arg1, arg2);
- break;
+ return do_arch_prctl(cpu_env, arg1, arg2);
#else
- goto unimplemented;
+#error unreachable
#endif
#endif
#ifdef TARGET_NR_pread64
@@ -11041,27 +10785,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg5 = arg6;
}
if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
unlock_user(p, arg2, ret);
- break;
+ return ret;
case TARGET_NR_pwrite64:
if (regpairs_aligned(cpu_env, num)) {
arg4 = arg5;
arg5 = arg6;
}
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
case TARGET_NR_getcwd:
if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(sys_getcwd1(p, arg2));
unlock_user(p, arg1, ret);
- break;
+ return ret;
case TARGET_NR_capget:
case TARGET_NR_capset:
{
@@ -11074,7 +10818,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int data_items = 1;
if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
header.version = tswap32(target_header->version);
header.pid = tswap32(target_header->pid);
@@ -11094,7 +10838,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (!target_data) {
unlock_user_struct(target_header, arg1, 0);
- goto efault;
+ return -TARGET_EFAULT;
}
if (num == TARGET_NR_capset) {
@@ -11130,11 +10874,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(target_data, arg2, 0);
}
}
- break;
+ return ret;
}
case TARGET_NR_sigaltstack:
- ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
- break;
+ return do_sigaltstack(arg1, arg2,
+ get_sp_from_cpustate((CPUArchState *)cpu_env));
#ifdef CONFIG_SENDFILE
#ifdef TARGET_NR_sendfile
@@ -11145,7 +10889,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
ret = get_user_sal(off, arg3);
if (is_error(ret)) {
- break;
+ return ret;
}
offp = &off;
}
@@ -11156,7 +10900,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = ret2;
}
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_sendfile64
@@ -11167,7 +10911,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
ret = get_user_s64(off, arg3);
if (is_error(ret)) {
- break;
+ return ret;
}
offp = &off;
}
@@ -11178,31 +10922,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = ret2;
}
}
- break;
+ return ret;
}
#endif
-#else
- case TARGET_NR_sendfile:
-#ifdef TARGET_NR_sendfile64
- case TARGET_NR_sendfile64:
-#endif
- goto unimplemented;
-#endif
-
-#ifdef TARGET_NR_getpmsg
- case TARGET_NR_getpmsg:
- goto unimplemented;
-#endif
-#ifdef TARGET_NR_putpmsg
- case TARGET_NR_putpmsg:
- goto unimplemented;
#endif
#ifdef TARGET_NR_vfork
case TARGET_NR_vfork:
- ret = get_errno(do_fork(cpu_env,
- CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
- 0, 0, 0, 0));
- break;
+ return get_errno(do_fork(cpu_env,
+ CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
+ 0, 0, 0, 0));
#endif
#ifdef TARGET_NR_ugetrlimit
case TARGET_NR_ugetrlimit:
@@ -11213,53 +10941,54 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
struct target_rlimit *target_rlim;
if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
- goto efault;
+ return -TARGET_EFAULT;
target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
unlock_user_struct(target_rlim, arg2, 1);
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_truncate64
case TARGET_NR_truncate64:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_ftruncate64
case TARGET_NR_ftruncate64:
- ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
- break;
+ return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
#endif
#ifdef TARGET_NR_stat64
case TARGET_NR_stat64:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(stat(path(p), &st));
unlock_user(p, arg1, 0);
if (!is_error(ret))
ret = host_to_target_stat64(cpu_env, arg2, &st);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_lstat64
case TARGET_NR_lstat64:
- if (!(p = lock_user_string(arg1)))
- goto efault;
+ if (!(p = lock_user_string(arg1))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(lstat(path(p), &st));
unlock_user(p, arg1, 0);
if (!is_error(ret))
ret = host_to_target_stat64(cpu_env, arg2, &st);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_fstat64
case TARGET_NR_fstat64:
ret = get_errno(fstat(arg1, &st));
if (!is_error(ret))
ret = host_to_target_stat64(cpu_env, arg2, &st);
- break;
+ return ret;
#endif
#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
#ifdef TARGET_NR_fstatat64
@@ -11268,47 +10997,43 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_newfstatat
case TARGET_NR_newfstatat:
#endif
- if (!(p = lock_user_string(arg2)))
- goto efault;
+ if (!(p = lock_user_string(arg2))) {
+ return -TARGET_EFAULT;
+ }
ret = get_errno(fstatat(arg1, path(p), &st, arg4));
+ unlock_user(p, arg2, 0);
if (!is_error(ret))
ret = host_to_target_stat64(cpu_env, arg3, &st);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_lchown
case TARGET_NR_lchown:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_getuid
case TARGET_NR_getuid:
- ret = get_errno(high2lowuid(getuid()));
- break;
+ return get_errno(high2lowuid(getuid()));
#endif
#ifdef TARGET_NR_getgid
case TARGET_NR_getgid:
- ret = get_errno(high2lowgid(getgid()));
- break;
+ return get_errno(high2lowgid(getgid()));
#endif
#ifdef TARGET_NR_geteuid
case TARGET_NR_geteuid:
- ret = get_errno(high2lowuid(geteuid()));
- break;
+ return get_errno(high2lowuid(geteuid()));
#endif
#ifdef TARGET_NR_getegid
case TARGET_NR_getegid:
- ret = get_errno(high2lowgid(getegid()));
- break;
+ return get_errno(high2lowgid(getegid()));
#endif
case TARGET_NR_setreuid:
- ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
- break;
+ return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
case TARGET_NR_setregid:
- ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
- break;
+ return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
case TARGET_NR_getgroups:
{
int gidsetsize = arg1;
@@ -11319,17 +11044,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
grouplist = alloca(gidsetsize * sizeof(gid_t));
ret = get_errno(getgroups(gidsetsize, grouplist));
if (gidsetsize == 0)
- break;
+ return ret;
if (!is_error(ret)) {
target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
if (!target_grouplist)
- goto efault;
+ return -TARGET_EFAULT;
for(i = 0;i < ret; i++)
target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
}
}
- break;
+ return ret;
case TARGET_NR_setgroups:
{
int gidsetsize = arg1;
@@ -11340,35 +11065,31 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
grouplist = alloca(gidsetsize * sizeof(gid_t));
target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
if (!target_grouplist) {
- ret = -TARGET_EFAULT;
- goto fail;
+ return -TARGET_EFAULT;
}
for (i = 0; i < gidsetsize; i++) {
grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
}
unlock_user(target_grouplist, arg2, 0);
}
- ret = get_errno(setgroups(gidsetsize, grouplist));
+ return get_errno(setgroups(gidsetsize, grouplist));
}
- break;
case TARGET_NR_fchown:
- ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
- break;
+ return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
#if defined(TARGET_NR_fchownat)
case TARGET_NR_fchownat:
if (!(p = lock_user_string(arg2)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
low2highgid(arg4), arg5));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_setresuid
case TARGET_NR_setresuid:
- ret = get_errno(sys_setresuid(low2highuid(arg1),
- low2highuid(arg2),
- low2highuid(arg3)));
- break;
+ return get_errno(sys_setresuid(low2highuid(arg1),
+ low2highuid(arg2),
+ low2highuid(arg3)));
#endif
#ifdef TARGET_NR_getresuid
case TARGET_NR_getresuid:
@@ -11379,17 +11100,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (put_user_id(high2lowuid(ruid), arg1)
|| put_user_id(high2lowuid(euid), arg2)
|| put_user_id(high2lowuid(suid), arg3))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_getresgid
case TARGET_NR_setresgid:
- ret = get_errno(sys_setresgid(low2highgid(arg1),
- low2highgid(arg2),
- low2highgid(arg3)));
- break;
+ return get_errno(sys_setresgid(low2highgid(arg1),
+ low2highgid(arg2),
+ low2highgid(arg3)));
#endif
#ifdef TARGET_NR_getresgid
case TARGET_NR_getresgid:
@@ -11400,44 +11120,39 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (put_user_id(high2lowgid(rgid), arg1)
|| put_user_id(high2lowgid(egid), arg2)
|| put_user_id(high2lowgid(sgid), arg3))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_chown
case TARGET_NR_chown:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
case TARGET_NR_setuid:
- ret = get_errno(sys_setuid(low2highuid(arg1)));
- break;
+ return get_errno(sys_setuid(low2highuid(arg1)));
case TARGET_NR_setgid:
- ret = get_errno(sys_setgid(low2highgid(arg1)));
- break;
+ return get_errno(sys_setgid(low2highgid(arg1)));
case TARGET_NR_setfsuid:
- ret = get_errno(setfsuid(arg1));
- break;
+ return get_errno(setfsuid(arg1));
case TARGET_NR_setfsgid:
- ret = get_errno(setfsgid(arg1));
- break;
+ return get_errno(setfsgid(arg1));
#ifdef TARGET_NR_lchown32
case TARGET_NR_lchown32:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(lchown(p, arg2, arg3));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_getuid32
case TARGET_NR_getuid32:
- ret = get_errno(getuid());
- break;
+ return get_errno(getuid());
#endif
#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
@@ -11448,8 +11163,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
euid=geteuid();
((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
}
- ret = get_errno(getuid());
- break;
+ return get_errno(getuid());
#endif
#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
/* Alpha specific */
@@ -11459,8 +11173,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
egid=getegid();
((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
}
- ret = get_errno(getgid());
- break;
+ return get_errno(getgid());
#endif
#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
/* Alpha specific */
@@ -11483,7 +11196,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
if (put_user_u64 (swcr, arg2))
- goto efault;
+ return -TARGET_EFAULT;
ret = 0;
}
break;
@@ -11498,7 +11211,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
-- Grabs a copy of the HWRPB; surely not used.
*/
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
/* Alpha specific */
@@ -11510,7 +11223,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
uint64_t swcr, fpcr, orig_fpcr;
if (get_user_u64 (swcr, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
fpcr = orig_fpcr & FPCR_DYN_MASK;
@@ -11537,7 +11250,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int si_code;
if (get_user_u64(exc, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
@@ -11589,7 +11302,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
-- Not implemented in linux kernel
*/
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_osf_sigprocmask
/* Alpha specific. */
@@ -11610,8 +11323,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = SIG_SETMASK;
break;
default:
- ret = -TARGET_EINVAL;
- goto fail;
+ return -TARGET_EINVAL;
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
@@ -11621,33 +11333,28 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = mask;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_getgid32
case TARGET_NR_getgid32:
- ret = get_errno(getgid());
- break;
+ return get_errno(getgid());
#endif
#ifdef TARGET_NR_geteuid32
case TARGET_NR_geteuid32:
- ret = get_errno(geteuid());
- break;
+ return get_errno(geteuid());
#endif
#ifdef TARGET_NR_getegid32
case TARGET_NR_getegid32:
- ret = get_errno(getegid());
- break;
+ return get_errno(getegid());
#endif
#ifdef TARGET_NR_setreuid32
case TARGET_NR_setreuid32:
- ret = get_errno(setreuid(arg1, arg2));
- break;
+ return get_errno(setreuid(arg1, arg2));
#endif
#ifdef TARGET_NR_setregid32
case TARGET_NR_setregid32:
- ret = get_errno(setregid(arg1, arg2));
- break;
+ return get_errno(setregid(arg1, arg2));
#endif
#ifdef TARGET_NR_getgroups32
case TARGET_NR_getgroups32:
@@ -11660,19 +11367,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
grouplist = alloca(gidsetsize * sizeof(gid_t));
ret = get_errno(getgroups(gidsetsize, grouplist));
if (gidsetsize == 0)
- break;
+ return ret;
if (!is_error(ret)) {
target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
if (!target_grouplist) {
- ret = -TARGET_EFAULT;
- goto fail;
+ return -TARGET_EFAULT;
}
for(i = 0;i < ret; i++)
target_grouplist[i] = tswap32(grouplist[i]);
unlock_user(target_grouplist, arg2, gidsetsize * 4);
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_setgroups32
case TARGET_NR_setgroups32:
@@ -11685,25 +11391,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
grouplist = alloca(gidsetsize * sizeof(gid_t));
target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
if (!target_grouplist) {
- ret = -TARGET_EFAULT;
- goto fail;
+ return -TARGET_EFAULT;
}
for(i = 0;i < gidsetsize; i++)
grouplist[i] = tswap32(target_grouplist[i]);
unlock_user(target_grouplist, arg2, 0);
- ret = get_errno(setgroups(gidsetsize, grouplist));
+ return get_errno(setgroups(gidsetsize, grouplist));
}
- break;
#endif
#ifdef TARGET_NR_fchown32
case TARGET_NR_fchown32:
- ret = get_errno(fchown(arg1, arg2, arg3));
- break;
+ return get_errno(fchown(arg1, arg2, arg3));
#endif
#ifdef TARGET_NR_setresuid32
case TARGET_NR_setresuid32:
- ret = get_errno(sys_setresuid(arg1, arg2, arg3));
- break;
+ return get_errno(sys_setresuid(arg1, arg2, arg3));
#endif
#ifdef TARGET_NR_getresuid32
case TARGET_NR_getresuid32:
@@ -11714,15 +11416,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (put_user_u32(ruid, arg1)
|| put_user_u32(euid, arg2)
|| put_user_u32(suid, arg3))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_setresgid32
case TARGET_NR_setresgid32:
- ret = get_errno(sys_setresgid(arg1, arg2, arg3));
- break;
+ return get_errno(sys_setresgid(arg1, arg2, arg3));
#endif
#ifdef TARGET_NR_getresgid32
case TARGET_NR_getresgid32:
@@ -11733,62 +11434,52 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (put_user_u32(rgid, arg1)
|| put_user_u32(egid, arg2)
|| put_user_u32(sgid, arg3))
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_chown32
case TARGET_NR_chown32:
if (!(p = lock_user_string(arg1)))
- goto efault;
+ return -TARGET_EFAULT;
ret = get_errno(chown(p, arg2, arg3));
unlock_user(p, arg1, 0);
- break;
+ return ret;
#endif
#ifdef TARGET_NR_setuid32
case TARGET_NR_setuid32:
- ret = get_errno(sys_setuid(arg1));
- break;
+ return get_errno(sys_setuid(arg1));
#endif
#ifdef TARGET_NR_setgid32
case TARGET_NR_setgid32:
- ret = get_errno(sys_setgid(arg1));
- break;
+ return get_errno(sys_setgid(arg1));
#endif
#ifdef TARGET_NR_setfsuid32
case TARGET_NR_setfsuid32:
- ret = get_errno(setfsuid(arg1));
- break;
+ return get_errno(setfsuid(arg1));
#endif
#ifdef TARGET_NR_setfsgid32
case TARGET_NR_setfsgid32:
- ret = get_errno(setfsgid(arg1));
- break;
+ return get_errno(setfsgid(arg1));
#endif
-
- case TARGET_NR_pivot_root:
- goto unimplemented;
#ifdef TARGET_NR_mincore
case TARGET_NR_mincore:
{
- void *a;
- ret = -TARGET_ENOMEM;
- a = lock_user(VERIFY_READ, arg1, arg2, 0);
+ void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
if (!a) {
- goto fail;
+ return -TARGET_ENOMEM;
}
- ret = -TARGET_EFAULT;
p = lock_user_string(arg3);
if (!p) {
- goto mincore_fail;
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(mincore(a, arg2, p));
+ unlock_user(p, arg3, ret);
}
- ret = get_errno(mincore(a, arg2, p));
- unlock_user(p, arg3, ret);
- mincore_fail:
unlock_user(a, arg1, 0);
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_arm_fadvise64_64
case TARGET_NR_arm_fadvise64_64:
@@ -11800,8 +11491,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
*/
ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
target_offset64(arg5, arg6), arg2);
- ret = -host_to_target_errno(ret);
- break;
+ return -host_to_target_errno(ret);
#endif
#if TARGET_ABI_BITS == 32
@@ -11827,11 +11517,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg6 = arg7;
}
#endif
- ret = -host_to_target_errno(posix_fadvise(arg1,
- target_offset64(arg2, arg3),
- target_offset64(arg4, arg5),
- arg6));
- break;
+ ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
+ target_offset64(arg4, arg5), arg6);
+ return -host_to_target_errno(ret);
#endif
#ifdef TARGET_NR_fadvise64
@@ -11844,10 +11532,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg4 = arg5;
arg5 = arg6;
}
- ret = -host_to_target_errno(posix_fadvise(arg1,
- target_offset64(arg2, arg3),
- arg4, arg5));
- break;
+ ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
+ return -host_to_target_errno(ret);
#endif
#else /* not a 32-bit ABI */
@@ -11867,8 +11553,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
default: break;
}
#endif
- ret = -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
- break;
+ return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
#endif
#endif /* end of 64-bit ABI fadvise handling */
@@ -11878,8 +11563,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
turns private file-backed mappings into anonymous mappings.
This will break MADV_DONTNEED.
This is a hint, so ignoring and returning success is ok. */
- ret = get_errno(0);
- break;
+ return 0;
#endif
#if TARGET_ABI_BITS == 32
case TARGET_NR_fcntl64:
@@ -11898,8 +11582,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
cmd = target_to_host_fcntl_cmd(arg2);
if (cmd == -TARGET_EINVAL) {
- ret = cmd;
- break;
+ return cmd;
}
switch(arg2) {
@@ -11926,27 +11609,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_fcntl(arg1, arg2, arg3);
break;
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_cacheflush
case TARGET_NR_cacheflush:
/* self-modifying code is handled automatically, so nothing needed */
- ret = 0;
- break;
-#endif
-#ifdef TARGET_NR_security
- case TARGET_NR_security:
- goto unimplemented;
+ return 0;
#endif
#ifdef TARGET_NR_getpagesize
case TARGET_NR_getpagesize:
- ret = TARGET_PAGE_SIZE;
- break;
+ return TARGET_PAGE_SIZE;
#endif
case TARGET_NR_gettid:
- ret = get_errno(gettid());
- break;
+ return get_errno(gettid());
#ifdef TARGET_NR_readahead
case TARGET_NR_readahead:
#if TARGET_ABI_BITS == 32
@@ -11959,7 +11635,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = get_errno(readahead(arg1, arg2, arg3));
#endif
- break;
+ return ret;
#endif
#ifdef CONFIG_ATTR
#ifdef TARGET_NR_setxattr
@@ -11970,8 +11646,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg2) {
b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
if (!b) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
p = lock_user_string(arg1);
@@ -11986,7 +11661,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(p, arg1, 0);
unlock_user(b, arg2, arg3);
- break;
+ return ret;
}
case TARGET_NR_flistxattr:
{
@@ -11994,13 +11669,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg2) {
b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
if (!b) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
ret = get_errno(flistxattr(arg1, b, arg3));
unlock_user(b, arg2, arg3);
- break;
+ return ret;
}
case TARGET_NR_setxattr:
case TARGET_NR_lsetxattr:
@@ -12009,8 +11683,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
v = lock_user(VERIFY_READ, arg3, arg4, 1);
if (!v) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
p = lock_user_string(arg1);
@@ -12028,15 +11701,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(n, arg2, 0);
unlock_user(v, arg3, 0);
}
- break;
+ return ret;
case TARGET_NR_fsetxattr:
{
void *n, *v = 0;
if (arg3) {
v = lock_user(VERIFY_READ, arg3, arg4, 1);
if (!v) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
n = lock_user_string(arg2);
@@ -12048,7 +11720,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(n, arg2, 0);
unlock_user(v, arg3, 0);
}
- break;
+ return ret;
case TARGET_NR_getxattr:
case TARGET_NR_lgetxattr:
{
@@ -12056,8 +11728,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!v) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
p = lock_user_string(arg1);
@@ -12075,15 +11746,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(n, arg2, 0);
unlock_user(v, arg3, arg4);
}
- break;
+ return ret;
case TARGET_NR_fgetxattr:
{
void *n, *v = 0;
if (arg3) {
v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!v) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
}
n = lock_user_string(arg2);
@@ -12095,7 +11765,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(n, arg2, 0);
unlock_user(v, arg3, arg4);
}
- break;
+ return ret;
case TARGET_NR_removexattr:
case TARGET_NR_lremovexattr:
{
@@ -12114,7 +11784,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
unlock_user(n, arg2, 0);
}
- break;
+ return ret;
case TARGET_NR_fremovexattr:
{
void *n;
@@ -12126,15 +11796,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(n, arg2, 0);
}
- break;
+ return ret;
#endif
#endif /* CONFIG_ATTR */
#ifdef TARGET_NR_set_thread_area
case TARGET_NR_set_thread_area:
#if defined(TARGET_MIPS)
((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
- ret = 0;
- break;
+ return 0;
#elif defined(TARGET_CRIS)
if (arg1 & 0xff)
ret = -TARGET_EINVAL;
@@ -12142,39 +11811,35 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
ret = 0;
}
- break;
+ return ret;
#elif defined(TARGET_I386) && defined(TARGET_ABI32)
- ret = do_set_thread_area(cpu_env, arg1);
- break;
+ return do_set_thread_area(cpu_env, arg1);
#elif defined(TARGET_M68K)
{
TaskState *ts = cpu->opaque;
ts->tp_value = arg1;
- ret = 0;
- break;
+ return 0;
}
#else
- goto unimplemented_nowarn;
+ return -TARGET_ENOSYS;
#endif
#endif
#ifdef TARGET_NR_get_thread_area
case TARGET_NR_get_thread_area:
#if defined(TARGET_I386) && defined(TARGET_ABI32)
- ret = do_get_thread_area(cpu_env, arg1);
- break;
+ return do_get_thread_area(cpu_env, arg1);
#elif defined(TARGET_M68K)
{
TaskState *ts = cpu->opaque;
- ret = ts->tp_value;
- break;
+ return ts->tp_value;
}
#else
- goto unimplemented_nowarn;
+ return -TARGET_ENOSYS;
#endif
#endif
#ifdef TARGET_NR_getdomainname
case TARGET_NR_getdomainname:
- goto unimplemented_nowarn;
+ return -TARGET_ENOSYS;
#endif
#ifdef TARGET_NR_clock_settime
@@ -12186,7 +11851,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
ret = get_errno(clock_settime(arg1, &ts));
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_clock_gettime
@@ -12197,7 +11862,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
ret = host_to_target_timespec(arg2, &ts);
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_clock_getres
@@ -12208,7 +11873,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
host_to_target_timespec(arg2, &ts);
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_clock_nanosleep
@@ -12228,24 +11893,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
((CPUPPCState *)cpu_env)->crf[0] |= 1;
}
#endif
- break;
+ return ret;
}
#endif
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
case TARGET_NR_set_tid_address:
- ret = get_errno(set_tid_address((int *)g2h(arg1)));
- break;
+ return get_errno(set_tid_address((int *)g2h(arg1)));
#endif
case TARGET_NR_tkill:
- ret = get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
- break;
+ return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
case TARGET_NR_tgkill:
- ret = get_errno(safe_tgkill((int)arg1, (int)arg2,
- target_to_host_signal(arg3)));
- break;
+ return get_errno(safe_tgkill((int)arg1, (int)arg2,
+ target_to_host_signal(arg3)));
#ifdef TARGET_NR_set_robust_list
case TARGET_NR_set_robust_list:
@@ -12262,7 +11924,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* holding a mutex that is shared with another process via
* shared memory).
*/
- goto unimplemented_nowarn;
+ return -TARGET_ENOSYS;
#endif
#if defined(TARGET_NR_utimensat)
@@ -12280,25 +11942,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
else {
if (!(p = lock_user_string(arg2))) {
- ret = -TARGET_EFAULT;
- goto fail;
+ return -TARGET_EFAULT;
}
ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
unlock_user(p, arg2, 0);
}
}
- break;
+ return ret;
#endif
case TARGET_NR_futex:
- ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
- break;
+ return do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
case TARGET_NR_inotify_init:
ret = get_errno(sys_inotify_init());
if (ret >= 0) {
fd_trans_register(ret, &target_inotify_trans);
}
- break;
+ return ret;
#endif
#ifdef CONFIG_INOTIFY1
#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
@@ -12308,7 +11968,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (ret >= 0) {
fd_trans_register(ret, &target_inotify_trans);
}
- break;
+ return ret;
#endif
#endif
#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
@@ -12316,12 +11976,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
p = lock_user_string(arg2);
ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
unlock_user(p, arg2, 0);
- break;
+ return ret;
#endif
#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
case TARGET_NR_inotify_rm_watch:
- ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
- break;
+ return get_errno(sys_inotify_rm_watch(arg1, arg2));
#endif
#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
@@ -12335,28 +11994,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
pposix_mq_attr = NULL;
if (arg4) {
if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
- goto efault;
+ return -TARGET_EFAULT;
}
pposix_mq_attr = &posix_mq_attr;
}
p = lock_user_string(arg1 - 1);
if (!p) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
unlock_user (p, arg1, 0);
}
- break;
+ return ret;
case TARGET_NR_mq_unlink:
p = lock_user_string(arg1 - 1);
if (!p) {
- ret = -TARGET_EFAULT;
- break;
+ return -TARGET_EFAULT;
}
ret = get_errno(mq_unlink(p));
unlock_user (p, arg1, 0);
- break;
+ return ret;
case TARGET_NR_mq_timedsend:
{
@@ -12372,7 +12030,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user (p, arg2, arg3);
}
- break;
+ return ret;
case TARGET_NR_mq_timedreceive:
{
@@ -12393,7 +12051,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg4 != 0)
put_user_u32(prio, arg4);
}
- break;
+ return ret;
/* Not implemented for now... */
/* case TARGET_NR_mq_notify: */
@@ -12414,7 +12072,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
}
}
- break;
+ return ret;
#endif
#ifdef CONFIG_SPLICE
@@ -12423,7 +12081,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
ret = get_errno(tee(arg1,arg2,arg3,arg4));
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_splice
case TARGET_NR_splice:
@@ -12432,29 +12090,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
loff_t *ploff_in = NULL, *ploff_out = NULL;
if (arg2) {
if (get_user_u64(loff_in, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ploff_in = &loff_in;
}
if (arg4) {
if (get_user_u64(loff_out, arg4)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ploff_out = &loff_out;
}
ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
if (arg2) {
if (put_user_u64(loff_in, arg2)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
if (arg4) {
if (put_user_u64(loff_out, arg4)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
}
- break;
+ return ret;
#endif
#ifdef TARGET_NR_vmsplice
case TARGET_NR_vmsplice:
@@ -12467,7 +12125,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -host_to_target_errno(errno);
}
}
- break;
+ return ret;
#endif
#endif /* CONFIG_SPLICE */
#ifdef CONFIG_EVENTFD
@@ -12477,7 +12135,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (ret >= 0) {
fd_trans_register(ret, &target_eventfd_trans);
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_eventfd2)
case TARGET_NR_eventfd2:
@@ -12493,7 +12151,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (ret >= 0) {
fd_trans_register(ret, &target_eventfd_trans);
}
- break;
+ return ret;
}
#endif
#endif /* CONFIG_EVENTFD */
@@ -12505,7 +12163,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
#endif
- break;
+ return ret;
#endif
#if defined(CONFIG_SYNC_FILE_RANGE)
#if defined(TARGET_NR_sync_file_range)
@@ -12521,7 +12179,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
#endif
- break;
+ return ret;
#endif
#if defined(TARGET_NR_sync_file_range2)
case TARGET_NR_sync_file_range2:
@@ -12532,29 +12190,25 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#else
ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
#endif
- break;
+ return ret;
#endif
#endif
#if defined(TARGET_NR_signalfd4)
case TARGET_NR_signalfd4:
- ret = do_signalfd4(arg1, arg2, arg4);
- break;
+ return do_signalfd4(arg1, arg2, arg4);
#endif
#if defined(TARGET_NR_signalfd)
case TARGET_NR_signalfd:
- ret = do_signalfd4(arg1, arg2, 0);
- break;
+ return do_signalfd4(arg1, arg2, 0);
#endif
#if defined(CONFIG_EPOLL)
#if defined(TARGET_NR_epoll_create)
case TARGET_NR_epoll_create:
- ret = get_errno(epoll_create(arg1));
- break;
+ return get_errno(epoll_create(arg1));
#endif
#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
case TARGET_NR_epoll_create1:
- ret = get_errno(epoll_create1(arg1));
- break;
+ return get_errno(epoll_create1(arg1));
#endif
#if defined(TARGET_NR_epoll_ctl)
case TARGET_NR_epoll_ctl:
@@ -12564,7 +12218,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg4) {
struct target_epoll_event *target_ep;
if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ep.events = tswap32(target_ep->events);
/* The epoll_data_t union is just opaque data to the kernel,
@@ -12575,8 +12229,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(target_ep, arg4, 0);
epp = &ep;
}
- ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
- break;
+ return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
}
#endif
@@ -12595,21 +12248,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int timeout = arg4;
if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
- ret = -TARGET_EINVAL;
- break;
+ return -TARGET_EINVAL;
}
target_ep = lock_user(VERIFY_WRITE, arg2,
maxevents * sizeof(struct target_epoll_event), 1);
if (!target_ep) {
- goto efault;
+ return -TARGET_EFAULT;
}
ep = g_try_new(struct epoll_event, maxevents);
if (!ep) {
unlock_user(target_ep, arg2, 0);
- ret = -TARGET_ENOMEM;
- break;
+ return -TARGET_ENOMEM;
}
switch (num) {
@@ -12663,7 +12314,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(target_ep, arg2, 0);
}
g_free(ep);
- break;
+ return ret;
}
#endif
#endif
@@ -12676,7 +12327,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int resource = target_to_host_resource(arg2);
if (arg3) {
if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
rnew.rlim_max = tswap64(target_rnew->rlim_max);
@@ -12687,13 +12338,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
if (!is_error(ret) && arg4) {
if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
- goto efault;
+ return -TARGET_EFAULT;
}
target_rold->rlim_cur = tswap64(rold.rlim_cur);
target_rold->rlim_max = tswap64(rold.rlim_max);
unlock_user_struct(target_rold, arg4, 1);
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_gethostname
@@ -12706,7 +12357,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
} else {
ret = -TARGET_EFAULT;
}
- break;
+ return ret;
}
#endif
#ifdef TARGET_NR_atomic_cmpxchg_32
@@ -12727,17 +12378,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (mem_value == arg2)
put_user_u32(arg1, arg6);
- ret = mem_value;
- break;
+ return mem_value;
}
#endif
#ifdef TARGET_NR_atomic_barrier
case TARGET_NR_atomic_barrier:
- {
- /* Like the kernel implementation and the qemu arm barrier, no-op this? */
- ret = 0;
- break;
- }
+ /* Like the kernel implementation and the
+ qemu arm barrier, no-op this? */
+ return 0;
#endif
#ifdef TARGET_NR_timer_create
@@ -12759,7 +12407,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
phost_sevp = &host_sevp;
ret = target_to_host_sigevent(phost_sevp, arg2);
if (ret != 0) {
- break;
+ return ret;
}
}
@@ -12768,11 +12416,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
phtimer = NULL;
} else {
if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
}
- break;
+ return ret;
}
#endif
@@ -12792,15 +12440,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
if (target_to_host_itimerspec(&hspec_new, arg3)) {
- goto efault;
+ return -TARGET_EFAULT;
}
ret = get_errno(
timer_settime(htimer, arg2, &hspec_new, &hspec_old));
if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
}
#endif
@@ -12823,7 +12471,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -TARGET_EFAULT;
}
}
- break;
+ return ret;
}
#endif
@@ -12840,7 +12488,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(timer_getoverrun(htimer));
}
fd_trans_unregister(ret);
- break;
+ return ret;
}
#endif
@@ -12857,15 +12505,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(timer_delete(htimer));
g_posix_timers[timerid] = 0;
}
- break;
+ return ret;
}
#endif
#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
case TARGET_NR_timerfd_create:
- ret = get_errno(timerfd_create(arg1,
- target_to_host_bitmask(arg2, fcntl_flags_tbl)));
- break;
+ return get_errno(timerfd_create(arg1,
+ target_to_host_bitmask(arg2, fcntl_flags_tbl)));
#endif
#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
@@ -12876,10 +12523,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(timerfd_gettime(arg1, &its_curr));
if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
@@ -12889,7 +12536,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg3) {
if (target_to_host_itimerspec(&its_new, arg3)) {
- goto efault;
+ return -TARGET_EFAULT;
}
p_new = &its_new;
} else {
@@ -12899,64 +12546,82 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
- goto efault;
+ return -TARGET_EFAULT;
}
}
- break;
+ return ret;
#endif
#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
case TARGET_NR_ioprio_get:
- ret = get_errno(ioprio_get(arg1, arg2));
- break;
+ return get_errno(ioprio_get(arg1, arg2));
#endif
#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
case TARGET_NR_ioprio_set:
- ret = get_errno(ioprio_set(arg1, arg2, arg3));
- break;
+ return get_errno(ioprio_set(arg1, arg2, arg3));
#endif
#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
case TARGET_NR_setns:
- ret = get_errno(setns(arg1, arg2));
- break;
+ return get_errno(setns(arg1, arg2));
#endif
#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
case TARGET_NR_unshare:
- ret = get_errno(unshare(arg1));
- break;
+ return get_errno(unshare(arg1));
#endif
#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
case TARGET_NR_kcmp:
- ret = get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
- break;
+ return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
#endif
#ifdef TARGET_NR_swapcontext
case TARGET_NR_swapcontext:
/* PowerPC specific. */
- ret = do_swapcontext(cpu_env, arg1, arg2, arg3);
- break;
+ return do_swapcontext(cpu_env, arg1, arg2, arg3);
#endif
default:
- unimplemented:
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
- unimplemented_nowarn:
-#endif
- ret = -TARGET_ENOSYS;
- break;
+ return -TARGET_ENOSYS;
+ }
+ return ret;
+}
+
+abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4,
+ abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8)
+{
+ CPUState *cpu = ENV_GET_CPU(cpu_env);
+ abi_long ret;
+
+#ifdef DEBUG_ERESTARTSYS
+ /* Debug-only code for exercising the syscall-restart code paths
+ * in the per-architecture cpu main loops: restart every syscall
+ * the guest makes once before letting it through.
+ */
+ {
+ static bool flag;
+ flag = !flag;
+ if (flag) {
+ return -TARGET_ERESTARTSYS;
+ }
}
-fail:
-#ifdef DEBUG
- gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
#endif
- if(do_strace)
+
+ trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7, arg8);
+
+ if (unlikely(do_strace)) {
+ print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+ ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7, arg8);
print_syscall_ret(num, ret);
+ } else {
+ ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7, arg8);
+ }
+
trace_guest_user_syscall_ret(cpu, num, ret);
return ret;
-efault:
- ret = -TARGET_EFAULT;
- goto fail;
}
diff --git a/pc-bios/README b/pc-bios/README
index 99e15a737b..90f0fa7aa7 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/aik/SLOF, and the image currently in qemu is
- built from git tag qemu-slof-20180621.
+ built from git tag qemu-slof-20180702.
- 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 4e0e33f829..6274a67391 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index 67b721156f..87212b62f2 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -195,6 +195,12 @@ support page sizes < 4096 any longer.
These machine types are very old and likely can not be used for live migration
from old QEMU versions anymore. A newer machine type should be used instead.
+@subsection prep (PowerPC) (since 3.1)
+
+This machine type uses an unmaintained firmware, broken in lots of ways,
+and unable to start post-2004 operating systems. 40p machine type should be
+used instead.
+
@section Device options
@subsection Block device options
diff --git a/roms/SLOF b/roms/SLOF
-Subproject 7d37babcfa48a6eb08e726a8d13b745cb2eebe1
+Subproject 9b7ab2fa020341dee8bf9df6c9cf40003e0136d
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 4edcf62cf7..ec149349e2 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -481,6 +481,11 @@ struct ppc_slb_t {
#define msr_ts ((env->msr >> MSR_TS1) & 3)
#define msr_tm ((env->msr >> MSR_TM) & 1)
+#define DBCR0_ICMP (1 << 27)
+#define DBCR0_BRT (1 << 26)
+#define DBSR_ICMP (1 << 27)
+#define DBSR_BRT (1 << 26)
+
/* Hypervisor bit is more specific */
#if defined(TARGET_PPC64)
#define MSR_HVB (1ULL << MSR_SHV)
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index d6e97a90e0..0ec7ae1ad4 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -348,19 +348,16 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
case POWERPC_EXCP_ITLB: /* Instruction TLB error */
break;
case POWERPC_EXCP_DEBUG: /* Debug interrupt */
- switch (excp_model) {
- case POWERPC_EXCP_BOOKE:
+ if (env->flags & POWERPC_FLAG_DE) {
/* FIXME: choose one or the other based on CPU type */
srr0 = SPR_BOOKE_DSRR0;
srr1 = SPR_BOOKE_DSRR1;
asrr0 = SPR_BOOKE_CSRR0;
asrr1 = SPR_BOOKE_CSRR1;
- break;
- default:
- break;
+ /* DBSR already modified by caller */
+ } else {
+ cpu_abort(cs, "Debug exception triggered on unsupported model\n");
}
- /* XXX: TODO */
- cpu_abort(cs, "Debug exception is not implemented yet !\n");
break;
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 8675d931b6..b9bb1b856e 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -36,26 +36,72 @@ static inline float128 float128_snan_to_qnan(float128 x)
#define float32_snan_to_qnan(x) ((x) | 0x00400000)
#define float16_snan_to_qnan(x) ((x) | 0x0200)
+static inline bool fp_exceptions_enabled(CPUPPCState *env)
+{
+#ifdef CONFIG_USER_ONLY
+ return true;
+#else
+ return (env->msr & ((1U << MSR_FE0) | (1U << MSR_FE1))) != 0;
+#endif
+}
+
/*****************************************************************************/
/* Floating point operations helpers */
-uint64_t helper_float32_to_float64(CPUPPCState *env, uint32_t arg)
+
+/*
+ * This is the non-arithmatic conversion that happens e.g. on loads.
+ * In the Power ISA pseudocode, this is called DOUBLE.
+ */
+uint64_t helper_todouble(uint32_t arg)
{
- CPU_FloatU f;
- CPU_DoubleU d;
+ uint32_t abs_arg = arg & 0x7fffffff;
+ uint64_t ret;
- f.l = arg;
- d.d = float32_to_float64(f.f, &env->fp_status);
- return d.ll;
+ if (likely(abs_arg >= 0x00800000)) {
+ /* Normalized operand, or Inf, or NaN. */
+ ret = (uint64_t)extract32(arg, 30, 2) << 62;
+ ret |= ((extract32(arg, 30, 1) ^ 1) * (uint64_t)7) << 59;
+ ret |= (uint64_t)extract32(arg, 0, 30) << 29;
+ } else {
+ /* Zero or Denormalized operand. */
+ ret = (uint64_t)extract32(arg, 31, 1) << 63;
+ if (unlikely(abs_arg != 0)) {
+ /* Denormalized operand. */
+ int shift = clz32(abs_arg) - 9;
+ int exp = -126 - shift + 1023;
+ ret |= (uint64_t)exp << 52;
+ ret |= abs_arg << (shift + 29);
+ }
+ }
+ return ret;
}
-uint32_t helper_float64_to_float32(CPUPPCState *env, uint64_t arg)
+/*
+ * This is the non-arithmatic conversion that happens e.g. on stores.
+ * In the Power ISA pseudocode, this is called SINGLE.
+ */
+uint32_t helper_tosingle(uint64_t arg)
{
- CPU_FloatU f;
- CPU_DoubleU d;
+ int exp = extract64(arg, 52, 11);
+ uint32_t ret;
- d.ll = arg;
- f.f = float64_to_float32(d.d, &env->fp_status);
- return f.l;
+ if (likely(exp > 896)) {
+ /* No denormalization required (includes Inf, NaN). */
+ ret = extract64(arg, 62, 2) << 30;
+ ret |= extract64(arg, 29, 30);
+ } else {
+ /* Zero or Denormal result. If the exponent is in bounds for
+ * a single-precision denormal result, extract the proper bits.
+ * If the input is not zero, and the exponent is out of bounds,
+ * then the result is undefined; this underflows to zero.
+ */
+ ret = extract64(arg, 63, 1) << 31;
+ if (unlikely(exp >= 874)) {
+ /* Denormal result. */
+ ret |= ((1ULL << 52) | extract64(arg, 0, 52)) >> (896 + 30 - exp);
+ }
+ }
+ return ret;
}
static inline int ppc_float32_get_unbiased_exp(float32 f)
@@ -207,7 +253,7 @@ uint64_t float_invalid_op_excp(CPUPPCState *env, int op, int set_fpcc)
if (ve != 0) {
/* Update the floating-point enabled exception summary */
env->fpscr |= 1 << FPSCR_FEX;
- if (msr_fe0 != 0 || msr_fe1 != 0) {
+ if (fp_exceptions_enabled(env)) {
/* GETPC() works here because this is inline */
raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_FP | op, GETPC());
@@ -225,7 +271,7 @@ static inline void float_zero_divide_excp(CPUPPCState *env, uintptr_t raddr)
if (fpscr_ze != 0) {
/* Update the floating-point enabled exception summary */
env->fpscr |= 1 << FPSCR_FEX;
- if (msr_fe0 != 0 || msr_fe1 != 0) {
+ if (fp_exceptions_enabled(env)) {
raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_FP | POWERPC_EXCP_FP_ZX,
raddr);
@@ -536,9 +582,7 @@ static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
int status = get_float_exception_flags(&env->fp_status);
bool inexact_happened = false;
- if (status & float_flag_divbyzero) {
- float_zero_divide_excp(env, raddr);
- } else if (status & float_flag_overflow) {
+ if (status & float_flag_overflow) {
float_overflow_excp(env);
} else if (status & float_flag_underflow) {
float_underflow_excp(env);
@@ -555,7 +599,7 @@ static void do_float_check_status(CPUPPCState *env, uintptr_t raddr)
if (cs->exception_index == POWERPC_EXCP_PROGRAM &&
(env->error_code & POWERPC_EXCP_FP)) {
/* Differred floating-point exception after target FPR update */
- if (msr_fe0 != 0 || msr_fe1 != 0) {
+ if (fp_exceptions_enabled(env)) {
raise_exception_err_ra(env, cs->exception_index,
env->error_code, raddr);
}
@@ -580,102 +624,93 @@ void helper_reset_fpstatus(CPUPPCState *env)
}
/* fadd - fadd. */
-uint64_t helper_fadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
+float64 helper_fadd(CPUPPCState *env, float64 arg1, float64 arg2)
{
- CPU_DoubleU farg1, farg2;
-
- farg1.ll = arg1;
- farg2.ll = arg2;
+ float64 ret = float64_add(arg1, arg2, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
- /* Magnitude subtraction of infinities */
- farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
- } else {
- if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
- float64_is_signaling_nan(farg2.d, &env->fp_status))) {
+ if (unlikely(status & float_flag_invalid)) {
+ if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
+ /* Magnitude subtraction of infinities */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+ } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
+ float64_is_signaling_nan(arg2, &env->fp_status)) {
/* sNaN addition */
float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
}
- farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
- return farg1.ll;
+ return ret;
}
/* fsub - fsub. */
-uint64_t helper_fsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
+float64 helper_fsub(CPUPPCState *env, float64 arg1, float64 arg2)
{
- CPU_DoubleU farg1, farg2;
-
- farg1.ll = arg1;
- farg2.ll = arg2;
+ float64 ret = float64_sub(arg1, arg2, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
- /* Magnitude subtraction of infinities */
- farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
- } else {
- if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
- float64_is_signaling_nan(farg2.d, &env->fp_status))) {
- /* sNaN subtraction */
+ if (unlikely(status & float_flag_invalid)) {
+ if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
+ /* Magnitude subtraction of infinities */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+ } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
+ float64_is_signaling_nan(arg2, &env->fp_status)) {
+ /* sNaN addition */
float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
}
- farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
- return farg1.ll;
+ return ret;
}
/* fmul - fmul. */
-uint64_t helper_fmul(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
+float64 helper_fmul(CPUPPCState *env, float64 arg1, float64 arg2)
{
- CPU_DoubleU farg1, farg2;
-
- farg1.ll = arg1;
- farg2.ll = arg2;
+ float64 ret = float64_mul(arg1, arg2, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
- /* Multiplication of zero by infinity */
- farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
- } else {
- if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
- float64_is_signaling_nan(farg2.d, &env->fp_status))) {
+ if (unlikely(status & float_flag_invalid)) {
+ if ((float64_is_infinity(arg1) && float64_is_zero(arg2)) ||
+ (float64_is_zero(arg1) && float64_is_infinity(arg2))) {
+ /* Multiplication of zero by infinity */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
+ } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
+ float64_is_signaling_nan(arg2, &env->fp_status)) {
/* sNaN multiplication */
float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
}
- farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
}
- return farg1.ll;
+ return ret;
}
/* fdiv - fdiv. */
-uint64_t helper_fdiv(CPUPPCState *env, uint64_t arg1, uint64_t arg2)
+float64 helper_fdiv(CPUPPCState *env, float64 arg1, float64 arg2)
{
- CPU_DoubleU farg1, farg2;
-
- farg1.ll = arg1;
- farg2.ll = arg2;
+ float64 ret = float64_div(arg1, arg2, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_infinity(farg1.d) &&
- float64_is_infinity(farg2.d))) {
- /* Division of infinity by infinity */
- farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
- } else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
- /* Division of zero by zero */
- farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
- } else {
- if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
- float64_is_signaling_nan(farg2.d, &env->fp_status))) {
- /* sNaN division */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ if (unlikely(status)) {
+ if (status & float_flag_invalid) {
+ /* Determine what kind of invalid operation was seen. */
+ if (float64_is_infinity(arg1) && float64_is_infinity(arg2)) {
+ /* Division of infinity by infinity */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, 1);
+ } else if (float64_is_zero(arg1) && float64_is_zero(arg2)) {
+ /* Division of zero by zero */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
+ } else if (float64_is_signaling_nan(arg1, &env->fp_status) ||
+ float64_is_signaling_nan(arg2, &env->fp_status)) {
+ /* sNaN division */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ }
+ }
+ if (status & float_flag_divbyzero) {
+ float_zero_divide_excp(env, GETPC());
}
- farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
- return farg1.ll;
+ return ret;
}
@@ -860,40 +895,48 @@ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg)
}
/* fsqrt - fsqrt. */
-uint64_t helper_fsqrt(CPUPPCState *env, uint64_t arg)
+float64 helper_fsqrt(CPUPPCState *env, float64 arg)
{
- CPU_DoubleU farg;
-
- farg.ll = arg;
+ float64 ret = float64_sqrt(arg, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_any_nan(farg.d))) {
- if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
- /* sNaN reciprocal square root */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
- farg.ll = float64_snan_to_qnan(farg.ll);
+ if (unlikely(status & float_flag_invalid)) {
+ if (unlikely(float64_is_any_nan(arg))) {
+ if (unlikely(float64_is_signaling_nan(arg, &env->fp_status))) {
+ /* sNaN square root */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ }
+ } else {
+ /* Square root of a negative nonzero number */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
}
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
- /* Square root of a negative nonzero number */
- farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
- } else {
- farg.d = float64_sqrt(farg.d, &env->fp_status);
}
- return farg.ll;
+
+ return ret;
}
/* fre - fre. */
-uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
+float64 helper_fre(CPUPPCState *env, float64 arg)
{
- CPU_DoubleU farg;
-
- farg.ll = arg;
+ /* "Estimate" the reciprocal with actual division. */
+ float64 ret = float64_div(float64_one, arg, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
- /* sNaN reciprocal */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ if (unlikely(status)) {
+ if (status & float_flag_invalid) {
+ if (float64_is_signaling_nan(arg, &env->fp_status)) {
+ /* sNaN reciprocal */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ }
+ }
+ if (status & float_flag_divbyzero) {
+ float_zero_divide_excp(env, GETPC());
+ /* For FPSCR.ZE == 0, the result is 1/2. */
+ ret = float64_set_sign(float64_half, float64_is_neg(arg));
+ }
}
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
- return farg.d;
+
+ return ret;
}
/* fres - fres. */
@@ -916,27 +959,30 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
}
/* frsqrte - frsqrte. */
-uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
+float64 helper_frsqrte(CPUPPCState *env, float64 arg)
{
- CPU_DoubleU farg;
-
- farg.ll = arg;
+ /* "Estimate" the reciprocal with actual division. */
+ float64 rets = float64_sqrt(arg, &env->fp_status);
+ float64 retd = float64_div(float64_one, rets, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- if (unlikely(float64_is_any_nan(farg.d))) {
- if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
- /* sNaN reciprocal square root */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
- farg.ll = float64_snan_to_qnan(farg.ll);
+ if (unlikely(status)) {
+ if (status & float_flag_invalid) {
+ if (float64_is_signaling_nan(arg, &env->fp_status)) {
+ /* sNaN reciprocal */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ } else {
+ /* Square root of a negative nonzero number */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+ }
+ }
+ if (status & float_flag_divbyzero) {
+ /* Reciprocal of (square root of) zero. */
+ float_zero_divide_excp(env, GETPC());
}
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
- /* Reciprocal square root of a negative nonzero number */
- farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
- } else {
- farg.d = float64_sqrt(farg.d, &env->fp_status);
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
}
- return farg.ll;
+ return retd;
}
/* fsel - fsel. */
@@ -1920,6 +1966,9 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
+ if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) { \
+ float_zero_divide_excp(env, GETPC()); \
+ } \
\
if (r2sp) { \
xt.fld = helper_frsp(env, xt.fld); \
@@ -1969,6 +2018,9 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
}
}
+ if (unlikely(tstat.float_exception_flags & float_flag_divbyzero)) {
+ float_zero_divide_excp(env, GETPC());
+ }
helper_compute_fprf_float128(env, xt.f128);
putVSR(rD(opcode) + 32, &xt, env);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 5706c2497f..ef64248bc4 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -61,8 +61,8 @@ DEF_HELPER_2(compute_fprf_float64, void, env, i64)
DEF_HELPER_3(store_fpscr, void, env, i64, i32)
DEF_HELPER_2(fpscr_clrbit, void, env, i32)
DEF_HELPER_2(fpscr_setbit, void, env, i32)
-DEF_HELPER_2(float64_to_float32, i32, env, i64)
-DEF_HELPER_2(float32_to_float64, i64, env, i32)
+DEF_HELPER_FLAGS_1(todouble, TCG_CALL_NO_RWG_SE, i64, i32)
+DEF_HELPER_FLAGS_1(tosingle, TCG_CALL_NO_RWG_SE, i32, i64)
DEF_HELPER_4(fcmpo, void, env, i64, i64, i32)
DEF_HELPER_4(fcmpu, void, env, i64, i64, i32)
@@ -85,15 +85,15 @@ DEF_HELPER_2(friz, i64, env, i64)
DEF_HELPER_2(frip, i64, env, i64)
DEF_HELPER_2(frim, i64, env, i64)
-DEF_HELPER_3(fadd, i64, env, i64, i64)
-DEF_HELPER_3(fsub, i64, env, i64, i64)
-DEF_HELPER_3(fmul, i64, env, i64, i64)
-DEF_HELPER_3(fdiv, i64, env, i64, i64)
+DEF_HELPER_3(fadd, f64, env, f64, f64)
+DEF_HELPER_3(fsub, f64, env, f64, f64)
+DEF_HELPER_3(fmul, f64, env, f64, f64)
+DEF_HELPER_3(fdiv, f64, env, f64, f64)
DEF_HELPER_4(fmadd, i64, env, i64, i64, i64)
DEF_HELPER_4(fmsub, i64, env, i64, i64, i64)
DEF_HELPER_4(fnmadd, i64, env, i64, i64, i64)
DEF_HELPER_4(fnmsub, i64, env, i64, i64, i64)
-DEF_HELPER_2(fsqrt, i64, env, i64)
+DEF_HELPER_2(fsqrt, f64, env, f64)
DEF_HELPER_2(fre, i64, env, i64)
DEF_HELPER_2(fres, i64, env, i64)
DEF_HELPER_2(frsqrte, i64, env, i64)
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index d52338ed71..fcac90a4a9 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2671,16 +2671,14 @@ static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
return 0;
}
-static int bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
+static void bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
int *overflow)
{
int carry = 0;
int i;
- int is_zero = 1;
for (i = 1; i <= 31; i++) {
uint8_t digit = bcd_get_digit(a, i, invalid) +
bcd_get_digit(b, i, invalid) + carry;
- is_zero &= (digit == 0);
if (digit > 9) {
carry = 1;
digit -= 10;
@@ -2689,26 +2687,20 @@ static int bcd_add_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
}
bcd_put_digit(t, digit, i);
-
- if (unlikely(*invalid)) {
- return -1;
- }
}
*overflow = carry;
- return is_zero;
}
-static int bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
+static void bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
int *overflow)
{
int carry = 0;
int i;
- int is_zero = 1;
+
for (i = 1; i <= 31; i++) {
uint8_t digit = bcd_get_digit(a, i, invalid) -
bcd_get_digit(b, i, invalid) + carry;
- is_zero &= (digit == 0);
if (digit & 0x80) {
carry = -1;
digit += 10;
@@ -2717,14 +2709,9 @@ static int bcd_sub_mag(ppc_avr_t *t, ppc_avr_t *a, ppc_avr_t *b, int *invalid,
}
bcd_put_digit(t, digit, i);
-
- if (unlikely(*invalid)) {
- return -1;
- }
}
*overflow = carry;
- return is_zero;
}
uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
@@ -2734,23 +2721,28 @@ uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
int sgnb = bcd_get_sgn(b);
int invalid = (sgna == 0) || (sgnb == 0);
int overflow = 0;
- int zero = 0;
uint32_t cr = 0;
ppc_avr_t result = { .u64 = { 0, 0 } };
if (!invalid) {
if (sgna == sgnb) {
result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(sgna, ps);
- zero = bcd_add_mag(&result, a, b, &invalid, &overflow);
- cr = (sgna > 0) ? CRF_GT : CRF_LT;
- } else if (bcd_cmp_mag(a, b) > 0) {
- result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(sgna, ps);
- zero = bcd_sub_mag(&result, a, b, &invalid, &overflow);
- cr = (sgna > 0) ? CRF_GT : CRF_LT;
+ bcd_add_mag(&result, a, b, &invalid, &overflow);
+ cr = bcd_cmp_zero(&result);
} else {
- result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(sgnb, ps);
- zero = bcd_sub_mag(&result, b, a, &invalid, &overflow);
- cr = (sgnb > 0) ? CRF_GT : CRF_LT;
+ int magnitude = bcd_cmp_mag(a, b);
+ if (magnitude > 0) {
+ result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(sgna, ps);
+ bcd_sub_mag(&result, a, b, &invalid, &overflow);
+ cr = (sgna > 0) ? CRF_GT : CRF_LT;
+ } else if (magnitude < 0) {
+ result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(sgnb, ps);
+ bcd_sub_mag(&result, b, a, &invalid, &overflow);
+ cr = (sgnb > 0) ? CRF_GT : CRF_LT;
+ } else {
+ result.u8[BCD_DIG_BYTE(0)] = bcd_preferred_sgn(0, ps);
+ cr = CRF_EQ;
+ }
}
}
@@ -2759,8 +2751,6 @@ uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
cr = CRF_SO;
} else if (overflow) {
cr |= CRF_SO;
- } else if (zero) {
- cr = CRF_EQ;
}
*r = result;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 9eaa10b421..881743571b 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -211,6 +211,7 @@ struct DisasContext {
bool gtse;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled;
+ uint32_t flags;
uint64_t insns_flags;
uint64_t insns_flags2;
};
@@ -251,6 +252,17 @@ struct opc_handler_t {
#endif
};
+/* SPR load/store helpers */
+static inline void gen_load_spr(TCGv t, int reg)
+{
+ tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
+}
+
+static inline void gen_store_spr(int reg, TCGv t)
+{
+ tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
+}
+
static inline void gen_set_access_type(DisasContext *ctx, int access_type)
{
if (ctx->need_access_type && ctx->access_type != access_type) {
@@ -313,6 +325,38 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->exception = (excp);
}
+/* Translates the EXCP_TRACE/BRANCH exceptions used on most PowerPCs to
+ * EXCP_DEBUG, if we are running on cores using the debug enable bit (e.g.
+ * BookE).
+ */
+static uint32_t gen_prep_dbgex(DisasContext *ctx, uint32_t excp)
+{
+ if ((ctx->singlestep_enabled & CPU_SINGLE_STEP)
+ && (excp == POWERPC_EXCP_BRANCH)) {
+ /* Trace excpt. has priority */
+ excp = POWERPC_EXCP_TRACE;
+ }
+ if (ctx->flags & POWERPC_FLAG_DE) {
+ target_ulong dbsr = 0;
+ switch (excp) {
+ case POWERPC_EXCP_TRACE:
+ dbsr = DBCR0_ICMP;
+ break;
+ case POWERPC_EXCP_BRANCH:
+ dbsr = DBCR0_BRT;
+ break;
+ }
+ TCGv t0 = tcg_temp_new();
+ gen_load_spr(t0, SPR_BOOKE_DBSR);
+ tcg_gen_ori_tl(t0, t0, dbsr);
+ gen_store_spr(SPR_BOOKE_DBSR, t0);
+ tcg_temp_free(t0);
+ return POWERPC_EXCP_DEBUG;
+ } else {
+ return excp;
+ }
+}
+
static void gen_debug_exception(DisasContext *ctx)
{
TCGv_i32 t0;
@@ -575,17 +619,6 @@ typedef struct opcode_t {
}
#endif
-/* SPR load/store helpers */
-static inline void gen_load_spr(TCGv t, int reg)
-{
- tcg_gen_ld_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
-}
-
-static inline void gen_store_spr(int reg, TCGv t)
-{
- tcg_gen_st_tl(t, cpu_env, offsetof(CPUPPCState, spr[reg]));
-}
-
/* Invalid instruction */
static void gen_invalid(DisasContext *ctx)
{
@@ -3602,6 +3635,24 @@ static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
#endif
}
+static void gen_lookup_and_goto_ptr(DisasContext *ctx)
+{
+ int sse = ctx->singlestep_enabled;
+ if (unlikely(sse)) {
+ if (sse & GDBSTUB_SINGLE_STEP) {
+ gen_debug_exception(ctx);
+ } else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
+ uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_BRANCH);
+ if (excp != POWERPC_EXCP_NONE) {
+ gen_exception(ctx, excp);
+ }
+ }
+ tcg_gen_exit_tb(NULL, 0);
+ } else {
+ tcg_gen_lookup_and_goto_ptr();
+ }
+}
+
/*** Branch ***/
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
{
@@ -3614,18 +3665,7 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
tcg_gen_exit_tb(ctx->base.tb, n);
} else {
tcg_gen_movi_tl(cpu_nip, dest & ~3);
- if (unlikely(ctx->singlestep_enabled)) {
- if ((ctx->singlestep_enabled &
- (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
- (ctx->exception == POWERPC_EXCP_BRANCH ||
- ctx->exception == POWERPC_EXCP_TRACE)) {
- gen_exception_nip(ctx, POWERPC_EXCP_TRACE, dest);
- }
- if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
- gen_debug_exception(ctx);
- }
- }
- tcg_gen_lookup_and_goto_ptr();
+ gen_lookup_and_goto_ptr(ctx);
}
}
@@ -3668,8 +3708,8 @@ static void gen_bcond(DisasContext *ctx, int type)
uint32_t bo = BO(ctx->opcode);
TCGLabel *l1;
TCGv target;
-
ctx->exception = POWERPC_EXCP_BRANCH;
+
if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
target = tcg_temp_local_new();
if (type == BCOND_CTR)
@@ -3733,10 +3773,11 @@ static void gen_bcond(DisasContext *ctx, int type)
} else {
tcg_gen_andi_tl(cpu_nip, target, ~3);
}
- tcg_gen_lookup_and_goto_ptr();
+ gen_lookup_and_goto_ptr(ctx);
tcg_temp_free(target);
}
if ((bo & 0x14) != 0x14) {
+ /* fallthrough case */
gen_set_label(l1);
gen_goto_tb(ctx, 1, ctx->base.pc_next);
}
@@ -7419,6 +7460,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->need_access_type = !(env->mmu_model & POWERPC_MMU_64B);
ctx->le_mode = !!(env->hflags & (1 << MSR_LE));
ctx->default_tcg_memop_mask = ctx->le_mode ? MO_LE : MO_BE;
+ ctx->flags = env->flags;
#if defined(TARGET_PPC64)
ctx->sf_mode = msr_is_64bit(env, env->msr);
ctx->has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
@@ -7455,6 +7497,17 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->singlestep_enabled = 0;
if ((env->flags & POWERPC_FLAG_BE) && msr_be)
ctx->singlestep_enabled |= CPU_BRANCH_STEP;
+ if ((env->flags & POWERPC_FLAG_DE) && msr_de) {
+ ctx->singlestep_enabled = 0;
+ target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0];
+ if (dbcr0 & DBCR0_ICMP) {
+ ctx->singlestep_enabled |= CPU_SINGLE_STEP;
+ }
+ if (dbcr0 & DBCR0_BRT) {
+ ctx->singlestep_enabled |= CPU_BRANCH_STEP;
+ }
+
+ }
if (unlikely(ctx->base.singlestep_enabled)) {
ctx->singlestep_enabled |= GDBSTUB_SINGLE_STEP;
}
@@ -7565,7 +7618,9 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
ctx->exception != POWERPC_SYSCALL &&
ctx->exception != POWERPC_EXCP_TRAP &&
ctx->exception != POWERPC_EXCP_BRANCH)) {
- gen_exception_nip(ctx, POWERPC_EXCP_TRACE, ctx->base.pc_next);
+ uint32_t excp = gen_prep_dbgex(ctx, POWERPC_EXCP_TRACE);
+ if (excp != POWERPC_EXCP_NONE)
+ gen_exception_nip(ctx, excp, ctx->base.pc_next);
}
if (tcg_check_temp_count()) {
diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c
index 2fbd4d4f38..a6f522b85c 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -660,15 +660,12 @@ GEN_LDUF(name, ldop, op | 0x21, type); \
GEN_LDUXF(name, ldop, op | 0x01, type); \
GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
-static inline void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
+static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr)
{
- TCGv t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new_i32();
- gen_qemu_ld32u(ctx, t0, arg2);
- tcg_gen_trunc_tl_i32(t1, t0);
- tcg_temp_free(t0);
- gen_helper_float32_to_float64(arg1, cpu_env, t1);
- tcg_temp_free_i32(t1);
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
+ gen_helper_todouble(dest, tmp);
+ tcg_temp_free_i32(tmp);
}
/* lfd lfdu lfdux lfdx */
@@ -836,15 +833,12 @@ GEN_STUF(name, stop, op | 0x21, type); \
GEN_STUXF(name, stop, op | 0x01, type); \
GEN_STXF(name, stop, 0x17, op | 0x00, type)
-static inline void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
+static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr)
{
- TCGv_i32 t0 = tcg_temp_new_i32();
- TCGv t1 = tcg_temp_new();
- gen_helper_float64_to_float32(t0, cpu_env, arg1);
- tcg_gen_extu_i32_tl(t1, t0);
- tcg_temp_free_i32(t0);
- gen_qemu_st32(ctx, t1, arg2);
- tcg_temp_free(t1);
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ gen_helper_tosingle(tmp, src);
+ tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
+ tcg_temp_free_i32(tmp);
}
/* stfd stfdu stfdux stfdx */
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 7813b1b004..d920d3e538 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -498,6 +498,7 @@ static void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn)
static void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn)
{
+ gen_store_spr(sprn, cpu_gpr[gprn]);
gen_helper_store_40x_dbcr0(cpu_env, cpu_gpr[gprn]);
/* We must stop translation as we may have rebooted */
gen_stop_exception(ctx);
@@ -1769,6 +1770,14 @@ static void gen_spr_BookE(CPUPPCState *env, uint64_t ivor_mask)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ spr_register(env, SPR_BOOKE_DSRR0, "DSRR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_BOOKE_DSRR1, "DSRR1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
/* XXX : not implemented */
spr_register(env, SPR_BOOKE_DBSR, "DBSR",
SPR_NOACCESS, SPR_NOACCESS,
@@ -1841,6 +1850,14 @@ static void gen_spr_BookE(CPUPPCState *env, uint64_t ivor_mask)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
+ spr_register(env, SPR_BOOKE_SPRG8, "SPRG8",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_BOOKE_SPRG9, "SPRG9",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
}
static inline uint32_t gen_tlbncfg(uint32_t assoc, uint32_t minsize,
@@ -10278,6 +10295,8 @@ static void ppc_cpu_reset(CPUState *s)
#endif
#if defined(CONFIG_USER_ONLY)
msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+ msr |= (target_ulong)1 << MSR_FE0; /* Allow floating point exceptions */
+ msr |= (target_ulong)1 << MSR_FE1;
msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
msr |= (target_ulong)1 << MSR_VSX; /* Allow VSX usage */
msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index fca5f2f5da..f123b15e3e 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -75,13 +75,11 @@ typedef struct testdef {
static testdef_t tests[] = {
{ "alpha", "clipper", "", "PCI:" },
{ "ppc", "ppce500", "", "U-Boot" },
- { "ppc", "prep", "-m 96", "Memory size: 96 MB" },
{ "ppc", "40p", "-boot d", "Booting from device d" },
{ "ppc", "g3beige", "", "PowerPC,750" },
{ "ppc", "mac99", "", "PowerPC,G4" },
{ "ppc", "sam460ex", "-m 256", "DRAM: 256 MiB" },
{ "ppc64", "ppce500", "", "U-Boot" },
- { "ppc64", "prep", "-boot e", "Booting from device e" },
{ "ppc64", "40p", "-m 192", "Memory size: 192 MB" },
{ "ppc64", "mac99", "", "PowerPC,970FX" },
{ "ppc64", "pseries", "", "Open Firmware" },
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
new file mode 100755
index 0000000000..ff851ec431
--- /dev/null
+++ b/tests/qemu-iotests/229
@@ -0,0 +1,95 @@
+#!/bin/bash
+#
+# Test for force canceling a running blockjob that is paused in
+# an error state.
+#
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_qemu
+ _cleanup_test_img
+ rm -f "$TEST_IMG" "$DEST_IMG"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+# Needs backing file and backing format support
+_supported_fmt qcow2 qed
+_supported_proto file
+_supported_os Linux
+
+
+DEST_IMG="$TEST_DIR/d.$IMGFMT"
+TEST_IMG="$TEST_DIR/b.$IMGFMT"
+
+_make_test_img 2M
+
+# destination for mirror will be too small, causing error
+TEST_IMG=$DEST_IMG _make_test_img 1M
+
+$QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io
+
+_launch_qemu -drive id=testdisk,file="$TEST_IMG",format="$IMGFMT"
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'qmp_capabilities'}" \
+ 'return'
+
+echo
+echo '=== Starting drive-mirror, causing error & stop ==='
+echo
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'drive-mirror',
+ 'arguments': {'device': 'testdisk',
+ 'mode': 'absolute-paths',
+ 'format': '$IMGFMT',
+ 'target': '$DEST_IMG',
+ 'sync': 'full',
+ 'mode': 'existing',
+ 'on-source-error': 'stop',
+ 'on-target-error': 'stop' }}" \
+ "JOB_STATUS_CHANGE.*pause"
+
+echo
+echo '=== Force cancel job paused in error state ==='
+echo
+
+success_or_failure="y" _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-job-cancel',
+ 'arguments': { 'device': 'testdisk',
+ 'force': true}}" \
+ "BLOCK_JOB_CANCELLED" "Assertion"
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
new file mode 100644
index 0000000000..4c4112805f
--- /dev/null
+++ b/tests/qemu-iotests/229.out
@@ -0,0 +1,23 @@
+QA output created by 229
+Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=2097152
+Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=1048576
+wrote 2097152/2097152 bytes at offset 0
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+
+=== Starting drive-mirror, causing error & stop ===
+
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "testdisk"}}
+
+=== Force cancel job paused in error state ===
+
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "testdisk", "operation": "write", "action": "stop"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index b973dc842d..743790745b 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -225,3 +225,4 @@
225 rw auto quick
226 auto quick
227 auto quick
+229 auto quick