summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rwxr-xr-xconfigure48
-rw-r--r--device_tree.c27
-rw-r--r--exec.c13
-rw-r--r--fsdev/qemu-fsdev.c2
-rw-r--r--hw/9pfs/virtio-9p-device.c26
-rw-r--r--hw/arm/boot.c8
-rw-r--r--hw/i2c/pm_smbus.c25
-rw-r--r--hw/microblaze/boot.c27
-rw-r--r--hw/ppc/e500.c25
-rw-r--r--hw/ppc/spapr.c28
-rw-r--r--include/exec/cpu-all.h1
-rw-r--r--include/sysemu/sysemu.h2
-rw-r--r--kvm-all.c5
-rw-r--r--linux-user/ioctls.h6
-rw-r--r--linux-user/mmap.c4
-rw-r--r--linux-user/signal.c4
-rw-r--r--linux-user/socket.h381
-rw-r--r--linux-user/syscall.c188
-rw-r--r--qemu-char.c13
-rw-r--r--qemu-options.hx8
-rw-r--r--qom/object.c6
-rw-r--r--target-i386/kvm.c17
-rw-r--r--tcg/aarch64/tcg-target.h2
-rw-r--r--tcg/arm/tcg-target.c178
-rw-r--r--tcg/arm/tcg-target.h15
-rw-r--r--tcg/hppa/tcg-target.c35
-rw-r--r--tcg/hppa/tcg-target.h1
-rw-r--r--tcg/i386/tcg-target.c45
-rw-r--r--tcg/ia64/tcg-target.h2
-rw-r--r--tcg/mips/tcg-target.h1
-rw-r--r--tcg/ppc/tcg-target.c14
-rw-r--r--tcg/ppc/tcg-target.h1
-rw-r--r--tcg/ppc64/tcg-target.c26
-rw-r--r--tcg/ppc64/tcg-target.h2
-rw-r--r--tcg/sparc/tcg-target.c35
-rw-r--r--tcg/sparc/tcg-target.h2
-rw-r--r--tcg/tcg-op.h32
-rw-r--r--tcg/tcg-opc.h36
-rw-r--r--tcg/tcg.c26
-rw-r--r--tcg/tcg.h6
-rw-r--r--tcg/tci/tcg-target.h6
-rw-r--r--user-exec.c8
-rw-r--r--util/qemu-option.c22
-rw-r--r--vl.c51
45 files changed, 837 insertions, 574 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 780f480725..93ad19d90e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,7 @@ Tiny Code Generator (TCG)
-------------------------
Common code
M: qemu-devel@nongnu.org
+M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: tcg/
diff --git a/configure b/configure
index 0e0adde410..cb0f870b95 100755
--- a/configure
+++ b/configure
@@ -3445,6 +3445,36 @@ if test "$cpu" = "s390x" ; then
roms="$roms s390-ccw"
fi
+# Probe for the need for relocating the user-only binary.
+if test "$pie" = "no" ; then
+ textseg_addr=
+ case "$cpu" in
+ arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64)
+ textseg_addr=0x60000000
+ ;;
+ mips)
+ textseg_addr=0x400000
+ ;;
+ esac
+ if [ -n "$textseg_addr" ]; then
+ cat > $TMPC <<EOF
+ int main(void) { return 0; }
+EOF
+ textseg_ldflags="-Wl,-Ttext-segment=$textseg_addr"
+ if ! compile_prog "" "$textseg_ldflags"; then
+ # In case ld does not support -Ttext-segment, edit the default linker
+ # script via sed to set the .text start addr. This is needed on FreeBSD
+ # at least.
+ $ld --verbose | sed \
+ -e '1,/==================================================/d' \
+ -e '/==================================================/,$d' \
+ -e "s/[.] = [0-9a-fx]* [+] SIZEOF_HEADERS/. = $textseg_addr + SIZEOF_HEADERS/" \
+ -e "s/__executable_start = [0-9a-fx]*/__executable_start = $textseg_addr/" > config-host.ld
+ textseg_ldflags="-Wl,-T../config-host.ld"
+ fi
+ fi
+fi
+
# add pixman flags after all config tests are done
QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags"
libs_softmmu="$libs_softmmu $pixman_libs"
@@ -4073,9 +4103,6 @@ if test "$gcov" = "yes" ; then
echo "GCOV=$gcov_tool" >> $config_host_mak
fi
-# generate list of library paths for linker script
-$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld
-
# use included Linux headers
if test "$linux" = "yes" ; then
mkdir -p linux-headers
@@ -4438,21 +4465,8 @@ if test "$gprof" = "yes" ; then
fi
fi
-if test "$ARCH" = "tci"; then
- linker_script=""
-else
- linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld"
-fi
-
if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
- case "$ARCH" in
- alpha | s390x | aarch64)
- # The default placement of the application is fine.
- ;;
- *)
- ldflags="$linker_script $ldflags"
- ;;
- esac
+ ldflags="$ldflags $textseg_ldflags"
fi
echo "LDFLAGS+=$ldflags" >> $config_target_mak
diff --git a/device_tree.c b/device_tree.c
index 69be9da8e4..10cf3d0b60 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "qemu-common.h"
#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
#include "hw/loader.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
@@ -239,15 +240,8 @@ uint32_t qemu_devtree_alloc_phandle(void *fdt)
* which phandle id to start allocting phandles.
*/
if (!phandle) {
- QemuOpts *machine_opts;
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- const char *phandle_start;
- phandle_start = qemu_opt_get(machine_opts, "phandle_start");
- if (phandle_start) {
- phandle = strtoul(phandle_start, NULL, 0);
- }
- }
+ phandle = qemu_opt_get_number(qemu_get_machine_opts(),
+ "phandle_start", 0);
}
if (!phandle) {
@@ -307,15 +301,10 @@ int qemu_devtree_add_subnode(void *fdt, const char *name)
void qemu_devtree_dumpdtb(void *fdt, int size)
{
- QemuOpts *machine_opts;
-
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb");
- if (dumpdtb) {
- /* Dump the dtb to a file and quit */
- exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
- }
- }
+ const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
+ if (dumpdtb) {
+ /* Dump the dtb to a file and quit */
+ exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1);
+ }
}
diff --git a/exec.c b/exec.c
index f01e3b684f..80ee2abbc2 100644
--- a/exec.c
+++ b/exec.c
@@ -31,6 +31,7 @@
#include "hw/qdev.h"
#include "qemu/osdep.h"
#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
#include "hw/xen/xen.h"
#include "qemu/timer.h"
#include "qemu/config-file.h"
@@ -53,7 +54,6 @@
//#define DEBUG_SUBPAGE
#if !defined(CONFIG_USER_ONLY)
-int phys_ram_fd;
static int in_migration;
RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) };
@@ -1039,12 +1039,10 @@ ram_addr_t last_ram_offset(void)
static void qemu_ram_setup_dump(void *addr, ram_addr_t size)
{
int ret;
- QemuOpts *machine_opts;
/* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts &&
- !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) {
+ if (!qemu_opt_get_bool(qemu_get_machine_opts(),
+ "dump-guest-core", true)) {
ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP);
if (ret) {
perror("qemu_madvise");
@@ -1091,10 +1089,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
static int memory_try_enable_merging(void *addr, size_t len)
{
- QemuOpts *opts;
-
- opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) {
+ if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) {
/* disabled by the user */
return 0;
}
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 6eaf36dbfa..ccfec139ab 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -76,6 +76,8 @@ int qemu_fsdev_add(QemuOpts *opts)
if (fsle->fse.ops->parse_opts) {
if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+ g_free(fsle->fse.fsdev_id);
+ g_free(fsle);
return -1;
}
}
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index dc6f4e404f..35e2af47b2 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -68,14 +68,14 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
"id = %s\n",
s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
- return -1;
+ goto out;
}
if (!s->fsconf.tag) {
/* we haven't specified a mount_tag */
fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
s->fsconf.fsdev_id);
- return -1;
+ goto out;
}
s->ctx.export_flags = fse->export_flags;
@@ -85,10 +85,10 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
if (len > MAX_TAG_LEN - 1) {
fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
"maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
- return -1;
+ goto out;
}
- s->tag = strdup(s->fsconf.tag);
+ s->tag = g_strdup(s->fsconf.tag);
s->ctx.uid = -1;
s->ops = fse->ops;
@@ -99,11 +99,11 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
if (s->ops->init(&s->ctx) < 0) {
fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s"
" and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root);
- return -1;
+ goto out;
}
if (v9fs_init_worker_threads() < 0) {
fprintf(stderr, "worker thread initialization failed\n");
- return -1;
+ goto out;
}
/*
@@ -115,18 +115,26 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
fprintf(stderr,
"error in converting name to path %s", strerror(errno));
- return -1;
+ goto out;
}
if (s->ops->lstat(&s->ctx, &path, &stat)) {
fprintf(stderr, "share path %s does not exist\n", fse->path);
- return -1;
+ goto out;
} else if (!S_ISDIR(stat.st_mode)) {
fprintf(stderr, "share path %s is not a directory\n", fse->path);
- return -1;
+ goto out;
}
v9fs_path_free(&path);
return 0;
+out:
+ g_free(s->ctx.fs_root);
+ g_free(s->tag);
+ virtio_cleanup(vdev);
+ v9fs_path_free(&path);
+
+ return -1;
+
}
/* virtio-9p device */
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 2b33444cf1..a2e4032f42 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -359,7 +359,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
uint64_t elf_entry;
hwaddr entry;
int big_endian;
- QemuOpts *machine_opts;
/* Load the kernel. */
if (!info->kernel_filename) {
@@ -367,12 +366,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
exit(1);
}
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- info->dtb_filename = qemu_opt_get(machine_opts, "dtb");
- } else {
- info->dtb_filename = NULL;
- }
+ info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
if (!info->secondary_cpu_reset_hook) {
info->secondary_cpu_reset_hook = default_reset_secondary;
diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
index 6df0fa916d..c98e447533 100644
--- a/hw/i2c/pm_smbus.c
+++ b/hw/i2c/pm_smbus.c
@@ -32,6 +32,18 @@
#define SMBHSTDAT1 0x06
#define SMBBLKDAT 0x07
+#define STS_HOST_BUSY (1)
+#define STS_INTR (1<<1)
+#define STS_DEV_ERR (1<<2)
+#define STS_BUS_ERR (1<<3)
+#define STS_FAILED (1<<4)
+#define STS_SMBALERT (1<<5)
+#define STS_INUSE_STS (1<<6)
+#define STS_BYTE_DONE (1<<7)
+/* Signs of successfully transaction end :
+* ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
+*/
+
//#define DEBUG
#ifdef DEBUG
@@ -50,9 +62,14 @@ static void smb_transaction(PMSMBus *s)
i2c_bus *bus = s->smbus;
SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
+ /* Transaction isn't exec if STS_DEV_ERR bit set */
+ if ((s->smb_stat & STS_DEV_ERR) != 0) {
+ goto error;
+ }
switch(prot) {
case 0x0:
smbus_quick_command(bus, addr, read);
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x1:
if (read) {
@@ -60,6 +77,7 @@ static void smb_transaction(PMSMBus *s)
} else {
smbus_send_byte(bus, addr, cmd);
}
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x2:
if (read) {
@@ -67,6 +85,7 @@ static void smb_transaction(PMSMBus *s)
} else {
smbus_write_byte(bus, addr, cmd, s->smb_data0);
}
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x3:
if (read) {
@@ -77,6 +96,7 @@ static void smb_transaction(PMSMBus *s)
} else {
smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
}
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
case 0x5:
if (read) {
@@ -84,6 +104,7 @@ static void smb_transaction(PMSMBus *s)
} else {
smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
}
+ s->smb_stat |= STS_BYTE_DONE | STS_INTR;
break;
default:
goto error;
@@ -91,7 +112,7 @@ static void smb_transaction(PMSMBus *s)
return;
error:
- s->smb_stat |= 0x04;
+ s->smb_stat |= STS_DEV_ERR;
}
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
@@ -102,7 +123,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
switch(addr) {
case SMBHSTSTS:
- s->smb_stat = 0;
+ s->smb_stat = (~(val & 0xff)) & s->smb_stat;
s->smb_index = 0;
break;
case SMBHSTCNT:
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 3f1d70ef9b..5b057f7880 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -28,6 +28,7 @@
#include "qemu/config-file.h"
#include "qemu-common.h"
#include "sysemu/device_tree.h"
+#include "sysemu/sysemu.h"
#include "hw/loader.h"
#include "elf.h"
@@ -93,20 +94,18 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
void (*machine_cpu_reset)(MicroBlazeCPU *))
{
QemuOpts *machine_opts;
- const char *kernel_filename = NULL;
- const char *kernel_cmdline = NULL;
-
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- const char *dtb_arg;
- kernel_filename = qemu_opt_get(machine_opts, "kernel");
- kernel_cmdline = qemu_opt_get(machine_opts, "append");
- dtb_arg = qemu_opt_get(machine_opts, "dtb");
- if (dtb_arg) { /* Preference a -dtb argument */
- dtb_filename = dtb_arg;
- } else { /* default to pcbios dtb as passed by machine_init */
- dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
- }
+ const char *kernel_filename;
+ const char *kernel_cmdline;
+ const char *dtb_arg;
+
+ machine_opts = qemu_get_machine_opts();
+ kernel_filename = qemu_opt_get(machine_opts, "kernel");
+ kernel_cmdline = qemu_opt_get(machine_opts, "append");
+ dtb_arg = qemu_opt_get(machine_opts, "dtb");
+ if (dtb_arg) { /* Preference a -dtb argument */
+ dtb_filename = dtb_arg;
+ } else { /* default to pcbios dtb as passed by machine_init */
+ dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
}
boot_info.machine_cpu_reset = machine_cpu_reset;
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 960059930f..f00a62a1ca 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -137,7 +137,6 @@ static int ppce500_load_device_tree(CPUPPCState *env,
uint32_t clock_freq = 400000000;
uint32_t tb_freq = 400000000;
int i;
- const char *toplevel_compat = NULL; /* user override */
char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus";
char soc[128];
char mpic[128];
@@ -158,14 +157,9 @@ static int ppce500_load_device_tree(CPUPPCState *env,
0x0, 0xe1000000,
0x0, 0x10000,
};
- QemuOpts *machine_opts;
- const char *dtb_file = NULL;
-
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- dtb_file = qemu_opt_get(machine_opts, "dtb");
- toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
- }
+ QemuOpts *machine_opts = qemu_get_machine_opts();
+ const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
+ const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
if (dtb_file) {
char *filename;
@@ -525,7 +519,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params,
static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
qemu_irq **irqs)
{
- QemuOptsList *list;
qemu_irq *mpic;
DeviceState *dev = NULL;
SysBusDevice *s;
@@ -534,15 +527,11 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,
mpic = g_new(qemu_irq, 256);
if (kvm_enabled()) {
- bool irqchip_allowed = true, irqchip_required = false;
-
- list = qemu_find_opts("machine");
- if (!QTAILQ_EMPTY(&list->head)) {
- irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
+ QemuOpts *machine_opts = qemu_get_machine_opts();
+ bool irqchip_allowed = qemu_opt_get_bool(machine_opts,
"kernel_irqchip", true);
- irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
- "kernel_irqchip", false);
- }
+ bool irqchip_required = qemu_opt_get_bool(machine_opts,
+ "kernel_irqchip", false);
if (irqchip_allowed) {
dev = ppce500_init_mpic_kvm(params, irqs);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index e46aad30d9..5c31ad36bd 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -675,27 +675,19 @@ static void spapr_cpu_reset(void *opaque)
static void spapr_create_nvram(sPAPREnvironment *spapr)
{
- QemuOpts *machine_opts;
- DeviceState *dev;
+ DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+ const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram");
- dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+ if (drivename) {
+ BlockDriverState *bs;
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- const char *drivename;
-
- drivename = qemu_opt_get(machine_opts, "nvram");
- if (drivename) {
- BlockDriverState *bs;
-
- bs = bdrv_find(drivename);
- if (!bs) {
- fprintf(stderr, "No such block device \"%s\" for nvram\n",
- drivename);
- exit(1);
- }
- qdev_prop_set_drive_nofail(dev, "drive", bs);
+ bs = bdrv_find(drivename);
+ if (!bs) {
+ fprintf(stderr, "No such block device \"%s\" for nvram\n",
+ drivename);
+ exit(1);
}
+ qdev_prop_set_drive_nofail(dev, "drive", bs);
}
qdev_init_nofail(dev);
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 6499cd0f2e..5084202217 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -443,7 +443,6 @@ hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr);
/* memory API */
-extern int phys_ram_fd;
extern ram_addr_t ram_size;
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 2fb71afa25..d85bdc0cac 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -185,6 +185,8 @@ char *get_boot_devices_list(size_t *size);
DeviceState *get_boot_device(uint32_t position);
+QemuOpts *qemu_get_machine_opts(void);
+
bool usb_enabled(bool default_usb);
extern QemuOptsList qemu_drive_opts;
diff --git a/kvm-all.c b/kvm-all.c
index c130705319..232c39a610 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1288,12 +1288,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
static int kvm_irqchip_create(KVMState *s)
{
- QemuOptsList *list = qemu_find_opts("machine");
int ret;
- if (QTAILQ_EMPTY(&list->head) ||
- !qemu_opt_get_bool(QTAILQ_FIRST(&list->head),
- "kernel_irqchip", true) ||
+ if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) ||
!kvm_check_extension(s, KVM_CAP_IRQCHIP)) {
return 0;
}
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8a4776756a..439c2a9e32 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -88,8 +88,6 @@
#endif
IOCTL(SIOCATMARK, 0, TYPE_NULL)
- IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
- IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
@@ -379,3 +377,7 @@
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm,
MK_PTR(MK_STRUCT(STRUCT_dm_ioctl)))
+ IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt,
+ MK_PTR(MK_STRUCT(STRUCT_rtentry)))
+ IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
+ MK_PTR(MK_STRUCT(STRUCT_rtentry)))
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index b412e3fe0a..de2219768d 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -483,6 +483,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
if (!(flags & MAP_ANONYMOUS)) {
p = mmap(g2h(start), len, prot,
flags | MAP_FIXED, fd, host_offset);
+ if (p == MAP_FAILED) {
+ munmap(g2h(start), host_len);
+ goto fail;
+ }
host_start += offset - host_offset;
}
start = h2g(host_start);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 42d8911070..d0727becc2 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -102,14 +102,14 @@ static inline int sas_ss_flags(unsigned long sp)
int host_to_target_signal(int sig)
{
- if (sig >= _NSIG)
+ if (sig < 0 || sig >= _NSIG)
return sig;
return host_to_target_signal_table[sig];
}
int target_to_host_signal(int sig)
{
- if (sig >= _NSIG)
+ if (sig < 0 || sig >= _NSIG)
return sig;
return target_to_host_signal_table[sig];
}
diff --git a/linux-user/socket.h b/linux-user/socket.h
index 339cae5a16..ae17959902 100644
--- a/linux-user/socket.h
+++ b/linux-user/socket.h
@@ -1,91 +1,104 @@
#if defined(TARGET_MIPS)
- // MIPS special values for constants
-
- /*
- * For setsockopt(2)
- *
- * This defines are ABI conformant as far as Linux supports these ...
- */
- #define TARGET_SOL_SOCKET 0xffff
-
- #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */
- #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */
- #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send
- SIGPIPE when they die. */
- #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */
- #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
- broadcast messages. */
- #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
- socket to transmit pending data. */
- #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */
- #if 0
- To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
- #endif
-
- #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
- #define TARGET_SO_STYLE SO_TYPE /* Synonym */
- #define TARGET_SO_ERROR 0x1007 /* get error status and clear */
- #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */
- #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */
- #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */
- #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */
- #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */
- #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */
- #define TARGET_SO_ACCEPTCONN 0x1009
-
- /* linux-specific, might as well be the same as on i386 */
- #define TARGET_SO_NO_CHECK 11
- #define TARGET_SO_PRIORITY 12
- #define TARGET_SO_BSDCOMPAT 14
-
- #define TARGET_SO_PASSCRED 17
- #define TARGET_SO_PEERCRED 18
-
- /* Security levels - as per NRL IPv6 - don't actually do anything */
- #define TARGET_SO_SECURITY_AUTHENTICATION 22
- #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
- #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
-
- #define TARGET_SO_BINDTODEVICE 25
-
- /* Socket filtering */
- #define TARGET_SO_ATTACH_FILTER 26
- #define TARGET_SO_DETACH_FILTER 27
-
- #define TARGET_SO_PEERNAME 28
- #define TARGET_SO_TIMESTAMP 29
- #define SCM_TIMESTAMP SO_TIMESTAMP
-
- #define TARGET_SO_PEERSEC 30
- #define TARGET_SO_SNDBUFFORCE 31
- #define TARGET_SO_RCVBUFFORCE 33
-
- /** sock_type - Socket types
- *
- * Please notice that for binary compat reasons MIPS has to
- * override the enum sock_type in include/linux/net.h, so
- * we define ARCH_HAS_SOCKET_TYPES here.
- *
- * @SOCK_DGRAM - datagram (conn.less) socket
- * @SOCK_STREAM - stream (connection) socket
- * @SOCK_RAW - raw socket
- * @SOCK_RDM - reliably-delivered message
- * @SOCK_SEQPACKET - sequential packet socket
- * @SOCK_PACKET - linux specific way of getting packets at the dev level.
- * For writing rarp and other similar things on the user level.
- */
- enum sock_type {
- TARGET_SOCK_DGRAM = 1,
- TARGET_SOCK_STREAM = 2,
- TARGET_SOCK_RAW = 3,
- TARGET_SOCK_RDM = 4,
- TARGET_SOCK_SEQPACKET = 5,
- TARGET_SOCK_DCCP = 6,
- TARGET_SOCK_PACKET = 10,
- };
-
- #define TARGET_SOCK_MAX (SOCK_PACKET + 1)
+ /* MIPS special values for constants */
+
+ /*
+ * For setsockopt(2)
+ *
+ * This defines are ABI conformant as far as Linux supports these ...
+ */
+ #define TARGET_SOL_SOCKET 0xffff
+
+ #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */
+ #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */
+ #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send
+ SIGPIPE when they die. */
+ #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */
+ #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
+ broadcast messages. */
+ #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
+ * socket to transmit pending data.
+ */
+ #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band.
+ */
+ #if 0
+ /* To add: Allow local address and port reuse. */
+ #define TARGET_SO_REUSEPORT 0x0200
+ #endif
+
+ #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
+ #define TARGET_SO_STYLE SO_TYPE /* Synonym */
+ #define TARGET_SO_ERROR 0x1007 /* get error status and clear */
+ #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */
+ #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */
+ #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */
+ #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */
+ #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */
+ #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */
+ #define TARGET_SO_ACCEPTCONN 0x1009
+
+ /* linux-specific, might as well be the same as on i386 */
+ #define TARGET_SO_NO_CHECK 11
+ #define TARGET_SO_PRIORITY 12
+ #define TARGET_SO_BSDCOMPAT 14
+
+ #define TARGET_SO_PASSCRED 17
+ #define TARGET_SO_PEERCRED 18
+
+ /* Security levels - as per NRL IPv6 - don't actually do anything */
+ #define TARGET_SO_SECURITY_AUTHENTICATION 22
+ #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
+ #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
+
+ #define TARGET_SO_BINDTODEVICE 25
+
+ /* Socket filtering */
+ #define TARGET_SO_ATTACH_FILTER 26
+ #define TARGET_SO_DETACH_FILTER 27
+
+ #define TARGET_SO_PEERNAME 28
+ #define TARGET_SO_TIMESTAMP 29
+ #define SCM_TIMESTAMP SO_TIMESTAMP
+
+ #define TARGET_SO_PEERSEC 30
+ #define TARGET_SO_SNDBUFFORCE 31
+ #define TARGET_SO_RCVBUFFORCE 33
+
+ /** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons MIPS has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket
+ * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ * For writing rarp and other similar things on the user
+ * level.
+ * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+ * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+ */
+
+ #define ARCH_HAS_SOCKET_TYPES 1
+
+ enum sock_type {
+ TARGET_SOCK_DGRAM = 1,
+ TARGET_SOCK_STREAM = 2,
+ TARGET_SOCK_RAW = 3,
+ TARGET_SOCK_RDM = 4,
+ TARGET_SOCK_SEQPACKET = 5,
+ TARGET_SOCK_DCCP = 6,
+ TARGET_SOCK_PACKET = 10,
+ TARGET_SOCK_CLOEXEC = 02000000,
+ TARGET_SOCK_NONBLOCK = 0200,
+ };
+
+ #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+ #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#elif defined(TARGET_ALPHA)
@@ -156,61 +169,167 @@
/* Instruct lower device to use last 4-bytes of skb data as FCS */
#define TARGET_SO_NOFCS 43
+ /** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons ALPHA has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket
+ * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ * For writing rarp and other similar things on the user
+ * level.
+ * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+ * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+ */
+
+ #define ARCH_HAS_SOCKET_TYPES 1
+
+ enum sock_type {
+ TARGET_SOCK_STREAM = 1,
+ TARGET_SOCK_DGRAM = 2,
+ TARGET_SOCK_RAW = 3,
+ TARGET_SOCK_RDM = 4,
+ TARGET_SOCK_SEQPACKET = 5,
+ TARGET_SOCK_DCCP = 6,
+ TARGET_SOCK_PACKET = 10,
+ TARGET_SOCK_CLOEXEC = 010000000,
+ TARGET_SOCK_NONBLOCK = 010000000000,
+ };
+
+ #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+ #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#else
- /* For setsockopt(2) */
- #define TARGET_SOL_SOCKET 1
-
- #define TARGET_SO_DEBUG 1
- #define TARGET_SO_REUSEADDR 2
- #define TARGET_SO_TYPE 3
- #define TARGET_SO_ERROR 4
- #define TARGET_SO_DONTROUTE 5
- #define TARGET_SO_BROADCAST 6
- #define TARGET_SO_SNDBUF 7
- #define TARGET_SO_RCVBUF 8
- #define TARGET_SO_SNDBUFFORCE 32
- #define TARGET_SO_RCVBUFFORCE 33
- #define TARGET_SO_KEEPALIVE 9
- #define TARGET_SO_OOBINLINE 10
- #define TARGET_SO_NO_CHECK 11
- #define TARGET_SO_PRIORITY 12
- #define TARGET_SO_LINGER 13
- #define TARGET_SO_BSDCOMPAT 14
- /* To add :#define TARGET_SO_REUSEPORT 15 */
+#if defined(TARGET_SPARC)
+ /** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons SPARC has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket
+ * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ * For writing rarp and other similar things on the user
+ * level.
+ * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+ * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+ */
+
+ #define ARCH_HAS_SOCKET_TYPES 1
+
+ enum sock_type {
+ TARGET_SOCK_STREAM = 1,
+ TARGET_SOCK_DGRAM = 2,
+ TARGET_SOCK_RAW = 3,
+ TARGET_SOCK_RDM = 4,
+ TARGET_SOCK_SEQPACKET = 5,
+ TARGET_SOCK_DCCP = 6,
+ TARGET_SOCK_PACKET = 10,
+ TARGET_SOCK_CLOEXEC = 020000000,
+ TARGET_SOCK_NONBLOCK = 040000,
+ };
+
+ #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+ #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
+#endif
+
+ /* For setsockopt(2) */
+ #define TARGET_SOL_SOCKET 1
+
+ #define TARGET_SO_DEBUG 1
+ #define TARGET_SO_REUSEADDR 2
+ #define TARGET_SO_TYPE 3
+ #define TARGET_SO_ERROR 4
+ #define TARGET_SO_DONTROUTE 5
+ #define TARGET_SO_BROADCAST 6
+ #define TARGET_SO_SNDBUF 7
+ #define TARGET_SO_RCVBUF 8
+ #define TARGET_SO_SNDBUFFORCE 32
+ #define TARGET_SO_RCVBUFFORCE 33
+ #define TARGET_SO_KEEPALIVE 9
+ #define TARGET_SO_OOBINLINE 10
+ #define TARGET_SO_NO_CHECK 11
+ #define TARGET_SO_PRIORITY 12
+ #define TARGET_SO_LINGER 13
+ #define TARGET_SO_BSDCOMPAT 14
+ /* To add :#define TARGET_SO_REUSEPORT 15 */
#if defined(TARGET_PPC)
- #define TARGET_SO_RCVLOWAT 16
- #define TARGET_SO_SNDLOWAT 17
- #define TARGET_SO_RCVTIMEO 18
- #define TARGET_SO_SNDTIMEO 19
- #define TARGET_SO_PASSCRED 20
- #define TARGET_SO_PEERCRED 21
+ #define TARGET_SO_RCVLOWAT 16
+ #define TARGET_SO_SNDLOWAT 17
+ #define TARGET_SO_RCVTIMEO 18
+ #define TARGET_SO_SNDTIMEO 19
+ #define TARGET_SO_PASSCRED 20
+ #define TARGET_SO_PEERCRED 21
#else
- #define TARGET_SO_PASSCRED 16
- #define TARGET_SO_PEERCRED 17
- #define TARGET_SO_RCVLOWAT 18
- #define TARGET_SO_SNDLOWAT 19
- #define TARGET_SO_RCVTIMEO 20
- #define TARGET_SO_SNDTIMEO 21
+ #define TARGET_SO_PASSCRED 16
+ #define TARGET_SO_PEERCRED 17
+ #define TARGET_SO_RCVLOWAT 18
+ #define TARGET_SO_SNDLOWAT 19
+ #define TARGET_SO_RCVTIMEO 20
+ #define TARGET_SO_SNDTIMEO 21
#endif
- /* Security levels - as per NRL IPv6 - don't actually do anything */
- #define TARGET_SO_SECURITY_AUTHENTICATION 22
- #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
- #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
+ /* Security levels - as per NRL IPv6 - don't actually do anything */
+ #define TARGET_SO_SECURITY_AUTHENTICATION 22
+ #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
+ #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
- #define TARGET_SO_BINDTODEVICE 25
+ #define TARGET_SO_BINDTODEVICE 25
- /* Socket filtering */
- #define TARGET_SO_ATTACH_FILTER 26
- #define TARGET_SO_DETACH_FILTER 27
+ /* Socket filtering */
+ #define TARGET_SO_ATTACH_FILTER 26
+ #define TARGET_SO_DETACH_FILTER 27
+
+ #define TARGET_SO_PEERNAME 28
+ #define TARGET_SO_TIMESTAMP 29
+ #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP
- #define TARGET_SO_PEERNAME 28
- #define TARGET_SO_TIMESTAMP 29
- #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP
+ #define TARGET_SO_ACCEPTCONN 30
- #define TARGET_SO_ACCEPTCONN 30
+ #define TARGET_SO_PEERSEC 31
+
+#endif
- #define TARGET_SO_PEERSEC 31
+#ifndef ARCH_HAS_SOCKET_TYPES
+ /** sock_type - Socket types - default values
+ *
+ *
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket
+ * @SOCK_DCCP - Datagram Congestion Control Protocol socket
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ * For writing rarp and other similar things on the user
+ * level.
+ * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
+ * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
+ */
+ enum sock_type {
+ TARGET_SOCK_STREAM = 1,
+ TARGET_SOCK_DGRAM = 2,
+ TARGET_SOCK_RAW = 3,
+ TARGET_SOCK_RDM = 4,
+ TARGET_SOCK_SEQPACKET = 5,
+ TARGET_SOCK_DCCP = 6,
+ TARGET_SOCK_PACKET = 10,
+ TARGET_SOCK_CLOEXEC = 02000000,
+ TARGET_SOCK_NONBLOCK = 04000,
+ };
+
+ #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
+ #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 433d3ba990..00a0390ea9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -105,6 +105,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include <linux/vt.h>
#include <linux/dm-ioctl.h>
#include <linux/reboot.h>
+#include <linux/route.h>
#include "linux_loop.h"
#include "cpu-uname.h"
@@ -338,6 +339,7 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
}
#endif
+#ifdef TARGET_NR_utimensat
#ifdef CONFIG_UTIMENSAT
static int sys_utimensat(int dirfd, const char *pathname,
const struct timespec times[2], int flags)
@@ -347,12 +349,19 @@ static int sys_utimensat(int dirfd, const char *pathname,
else
return utimensat(dirfd, pathname, times, flags);
}
-#else
-#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+#elif defined(__NR_utimensat)
+#define __NR_sys_utimensat __NR_utimensat
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
const struct timespec *,tsp,int,flags)
+#else
+static int sys_utimensat(int dirfd, const char *pathname,
+ const struct timespec times[2], int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
#endif
-#endif /* CONFIG_UTIMENSAT */
+#endif /* TARGET_NR_utimensat */
#ifdef CONFIG_INOTIFY
#include <sys/inotify.h>
@@ -1696,31 +1705,36 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
free(vec);
}
-/* do_socket() Must return target values and target errnos. */
-static abi_long do_socket(int domain, int type, int protocol)
+static inline void target_to_host_sock_type(int *type)
{
-#if defined(TARGET_MIPS)
- switch(type) {
+ int host_type = 0;
+ int target_type = *type;
+
+ switch (target_type & TARGET_SOCK_TYPE_MASK) {
case TARGET_SOCK_DGRAM:
- type = SOCK_DGRAM;
+ host_type = SOCK_DGRAM;
break;
case TARGET_SOCK_STREAM:
- type = SOCK_STREAM;
- break;
- case TARGET_SOCK_RAW:
- type = SOCK_RAW;
+ host_type = SOCK_STREAM;
break;
- case TARGET_SOCK_RDM:
- type = SOCK_RDM;
- break;
- case TARGET_SOCK_SEQPACKET:
- type = SOCK_SEQPACKET;
- break;
- case TARGET_SOCK_PACKET:
- type = SOCK_PACKET;
+ default:
+ host_type = target_type & TARGET_SOCK_TYPE_MASK;
break;
}
-#endif
+ if (target_type & TARGET_SOCK_CLOEXEC) {
+ host_type |= SOCK_CLOEXEC;
+ }
+ if (target_type & TARGET_SOCK_NONBLOCK) {
+ host_type |= SOCK_NONBLOCK;
+ }
+ *type = host_type;
+}
+
+/* do_socket() Must return target values and target errnos. */
+static abi_long do_socket(int domain, int type, int protocol)
+{
+ target_to_host_sock_type(&type);
+
if (domain == PF_NETLINK)
return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
return get_errno(socket(domain, type, protocol));
@@ -1953,6 +1967,8 @@ static abi_long do_socketpair(int domain, int type, int protocol,
int tab[2];
abi_long ret;
+ target_to_host_sock_type(&type);
+
ret = get_errno(socketpair(domain, type, protocol, tab));
if (!is_error(ret)) {
if (put_user_s32(tab[0], target_tab_addr)
@@ -3551,6 +3567,69 @@ out:
return ret;
}
+static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, abi_long cmd, abi_long arg)
+{
+ const argtype *arg_type = ie->arg_type;
+ const StructEntry *se;
+ const argtype *field_types;
+ const int *dst_offsets, *src_offsets;
+ int target_size;
+ void *argptr;
+ abi_ulong *target_rt_dev_ptr;
+ unsigned long *host_rt_dev_ptr;
+ abi_long ret;
+ int i;
+
+ assert(ie->access == IOC_W);
+ assert(*arg_type == TYPE_PTR);
+ arg_type++;
+ assert(*arg_type == TYPE_STRUCT);
+ target_size = thunk_type_size(arg_type, 0);
+ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+ if (!argptr) {
+ return -TARGET_EFAULT;
+ }
+ arg_type++;
+ assert(*arg_type == (int)STRUCT_rtentry);
+ se = struct_entries + *arg_type++;
+ assert(se->convert[0] == NULL);
+ /* convert struct here to be able to catch rt_dev string */
+ field_types = se->field_types;
+ dst_offsets = se->field_offsets[THUNK_HOST];
+ src_offsets = se->field_offsets[THUNK_TARGET];
+ for (i = 0; i < se->nb_fields; i++) {
+ if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
+ assert(*field_types == TYPE_PTRVOID);
+ target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
+ host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
+ if (*target_rt_dev_ptr != 0) {
+ *host_rt_dev_ptr = (unsigned long)lock_user_string(
+ tswapal(*target_rt_dev_ptr));
+ if (!*host_rt_dev_ptr) {
+ unlock_user(argptr, arg, 0);
+ return -TARGET_EFAULT;
+ }
+ } else {
+ *host_rt_dev_ptr = 0;
+ }
+ field_types++;
+ continue;
+ }
+ field_types = thunk_convert(buf_temp + dst_offsets[i],
+ argptr + src_offsets[i],
+ field_types, THUNK_HOST);
+ }
+ unlock_user(argptr, arg, 0);
+
+ ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+ if (*host_rt_dev_ptr != 0) {
+ unlock_user((void *)*host_rt_dev_ptr,
+ *target_rt_dev_ptr, 0);
+ }
+ return ret;
+}
+
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
@@ -4973,6 +5052,30 @@ static int open_self_auxv(void *cpu_env, int fd)
return 0;
}
+static int is_proc_myself(const char *filename, const char *entry)
+{
+ if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
+ filename += strlen("/proc/");
+ if (!strncmp(filename, "self/", strlen("self/"))) {
+ filename += strlen("self/");
+ } else if (*filename >= '1' && *filename <= '9') {
+ char myself[80];
+ snprintf(myself, sizeof(myself), "%d/", getpid());
+ if (!strncmp(filename, myself, strlen(myself))) {
+ filename += strlen(myself);
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ if (!strcmp(filename, entry)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
{
struct fake_open {
@@ -4981,15 +5084,14 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
};
const struct fake_open *fake_open;
static const struct fake_open fakes[] = {
- { "/proc/self/maps", open_self_maps },
- { "/proc/self/stat", open_self_stat },
- { "/proc/self/auxv", open_self_auxv },
+ { "maps", open_self_maps },
+ { "stat", open_self_stat },
+ { "auxv", open_self_auxv },
{ NULL, NULL }
};
for (fake_open = fakes; fake_open->filename; fake_open++) {
- if (!strncmp(pathname, fake_open->filename,
- strlen(fake_open->filename))) {
+ if (is_proc_myself(pathname, fake_open->filename)) {
break;
}
}
@@ -6266,20 +6368,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
case TARGET_NR_readlink:
{
- void *p2, *temp;
+ void *p2;
p = lock_user_string(arg1);
p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
- if (!p || !p2)
+ if (!p || !p2) {
ret = -TARGET_EFAULT;
- else {
- if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
- char real[PATH_MAX];
- temp = realpath(exec_path,real);
- ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
- snprintf((char *)p2, arg3, "%s", real);
- }
- else
- ret = get_errno(readlink(path(p), p2, arg3));
+ } else if (is_proc_myself((const char *)p, "exe")) {
+ char real[PATH_MAX], *temp;
+ temp = realpath(exec_path, real);
+ ret = temp == NULL ? get_errno(-1) : strlen(real) ;
+ snprintf((char *)p2, arg3, "%s", real);
+ } else {
+ ret = get_errno(readlink(path(p), p2, arg3));
}
unlock_user(p2, arg2, ret);
unlock_user(p, arg1, 0);
@@ -6291,10 +6391,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
void *p2;
p = lock_user_string(arg2);
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
- if (!p || !p2)
- ret = -TARGET_EFAULT;
- else
+ if (!p || !p2) {
+ ret = -TARGET_EFAULT;
+ } else if (is_proc_myself((const char *)p, "exe")) {
+ char real[PATH_MAX], *temp;
+ temp = realpath(exec_path, real);
+ ret = temp == NULL ? get_errno(-1) : strlen(real) ;
+ snprintf((char *)p2, arg4, "%s", real);
+ } else {
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
+ }
unlock_user(p2, arg3, ret);
unlock_user(p, arg2, 0);
}
@@ -8540,7 +8646,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto unimplemented_nowarn;
#endif
-#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
+#if defined(TARGET_NR_utimensat)
case TARGET_NR_utimensat:
{
struct timespec *tsp, ts[2];
diff --git a/qemu-char.c b/qemu-char.c
index 6cec5d7114..18c42a39da 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -926,7 +926,6 @@ static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
}
- /* if graphical mode, we allow Ctrl-C handling */
if (!stdio_allow_signal)
tty.c_lflag &= ~ISIG;
@@ -955,7 +954,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
chr->chr_set_echo = qemu_chr_set_echo_stdio;
- stdio_allow_signal = display_type != DT_NOGRAPHIC;
if (opts->has_signal) {
stdio_allow_signal = opts->signal;
}
@@ -2932,6 +2930,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
if (strstart(filename, "mon:", &p)) {
filename = p;
qemu_opt_set(opts, "mux", "on");
+ if (strcmp(filename, "stdio") == 0) {
+ /* Monitor is muxed to stdio: do not exit on Ctrl+C by default
+ * but pass it to the guest. Handle this only for compat syntax,
+ * for -chardev syntax we have special option for this.
+ * This is what -nographic did, redirecting+muxing serial+monitor
+ * to stdio causing Ctrl+C to be passed to guest. */
+ qemu_opt_set(opts, "signal", "off");
+ }
}
if (strcmp(filename, "null") == 0 ||
@@ -3060,8 +3066,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
{
backend->stdio = g_new0(ChardevStdio, 1);
backend->stdio->has_signal = true;
- backend->stdio->signal =
- qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC);
+ backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
}
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
diff --git a/qemu-options.hx b/qemu-options.hx
index 137a39b7ad..7cc4d8ef25 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -842,7 +842,8 @@ STEXI
Normally, QEMU uses SDL to display the VGA output. With this option,
you can totally disable graphical output so that QEMU is a simple
command line application. The emulated serial port is redirected on
-the console. Therefore, you can still use QEMU to debug a Linux kernel
+the console and muxed with the monitor (unless redirected elsewhere
+explicitly). Therefore, you can still use QEMU to debug a Linux kernel
with a serial console.
ETEXI
@@ -2485,14 +2486,15 @@ same as if you had specified @code{-serial tcp} except the unix domain socket
@item mon:@var{dev_string}
This is a special option to allow the monitor to be multiplexed onto
another serial port. The monitor is accessed with key sequence of
-@key{Control-a} and then pressing @key{c}. See monitor access
-@ref{pcsys_keys} in the -nographic section for more keys.
+@key{Control-a} and then pressing @key{c}.
@var{dev_string} should be any one of the serial devices specified
above. An example to multiplex the monitor onto a telnet server
listening on port 4444 would be:
@table @code
@item -serial mon:telnet::4444,server,nowait
@end table
+When monitor is multiplexed to stdio this way, Ctrl+C will not terminate
+QEMU anymore but will be passed to the guest instead.
@item braille
Braille device. This will use BrlAPI to display the braille output on a real
diff --git a/qom/object.c b/qom/object.c
index cbd7e86033..b2479d1c06 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -531,14 +531,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
#ifdef CONFIG_QOM_CAST_DEBUG
int i;
- for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) {
+ for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
if (class->cast_cache[i] == typename) {
ret = class;
goto out;
}
}
#else
- if (!class->interfaces) {
+ if (!class || !class->interfaces) {
return class;
}
#endif
@@ -551,7 +551,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
}
#ifdef CONFIG_QOM_CAST_DEBUG
- if (ret == class) {
+ if (class && ret == class) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
class->cast_cache[i - 1] = class->cast_cache[i];
}
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 935ef6393d..8315489989 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -743,7 +743,6 @@ static int kvm_get_supported_msrs(KVMState *s)
int kvm_arch_init(KVMState *s)
{
- QemuOptsList *list = qemu_find_opts("machine");
uint64_t identity_base = 0xfffbc000;
uint64_t shadow_mem;
int ret;
@@ -792,15 +791,13 @@ int kvm_arch_init(KVMState *s)
}
qemu_register_reset(kvm_unpoison_all, NULL);
- if (!QTAILQ_EMPTY(&list->head)) {
- shadow_mem = qemu_opt_get_size(QTAILQ_FIRST(&list->head),
- "kvm_shadow_mem", -1);
- if (shadow_mem != -1) {
- shadow_mem /= 4096;
- ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
- if (ret < 0) {
- return ret;
- }
+ shadow_mem = qemu_opt_get_size(qemu_get_machine_opts(),
+ "kvm_shadow_mem", -1);
+ if (shadow_mem != -1) {
+ shadow_mem /= 4096;
+ ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem);
+ if (ret < 0) {
+ return ret;
}
}
return 0;
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index 97e4a5baa7..51e50920b2 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -40,6 +40,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
+#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
#define TCG_TARGET_HAS_ext8u_i32 1
@@ -62,6 +63,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_div_i64 0
+#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 6be736b75e..6c4854dbb0 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -22,50 +22,43 @@
* THE SOFTWARE.
*/
-#if defined(__ARM_ARCH_7__) || \
- defined(__ARM_ARCH_7A__) || \
- defined(__ARM_ARCH_7EM__) || \
- defined(__ARM_ARCH_7M__) || \
- defined(__ARM_ARCH_7R__)
-#define USE_ARMV7_INSTRUCTIONS
+/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
+#ifndef __ARM_ARCH
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7EM__)
+# define __ARM_ARCH 7
+# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
+# define __ARM_ARCH 6
+# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
+ || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
+# define __ARM_ARCH 5
+# else
+# define __ARM_ARCH 4
+# endif
#endif
-#if defined(USE_ARMV7_INSTRUCTIONS) || \
- defined(__ARM_ARCH_6J__) || \
- defined(__ARM_ARCH_6K__) || \
- defined(__ARM_ARCH_6T2__) || \
- defined(__ARM_ARCH_6Z__) || \
- defined(__ARM_ARCH_6ZK__)
-#define USE_ARMV6_INSTRUCTIONS
-#endif
-
-#if defined(USE_ARMV6_INSTRUCTIONS) || \
- defined(__ARM_ARCH_5T__) || \
- defined(__ARM_ARCH_5TE__) || \
- defined(__ARM_ARCH_5TEJ__)
-#define USE_ARMV5_INSTRUCTIONS
-#endif
+static int arm_arch = __ARM_ARCH;
-#ifdef USE_ARMV5_INSTRUCTIONS
-static const int use_armv5_instructions = 1;
+#if defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
+# define use_armv5t_instructions 1
#else
-static const int use_armv5_instructions = 0;
+# define use_armv5t_instructions use_armv6_instructions
#endif
-#undef USE_ARMV5_INSTRUCTIONS
-#ifdef USE_ARMV6_INSTRUCTIONS
-static const int use_armv6_instructions = 1;
-#else
-static const int use_armv6_instructions = 0;
-#endif
-#undef USE_ARMV6_INSTRUCTIONS
+#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
+#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
-#ifdef USE_ARMV7_INSTRUCTIONS
-static const int use_armv7_instructions = 1;
-#else
-static const int use_armv7_instructions = 0;
+#ifndef use_idiv_instructions
+bool use_idiv_instructions;
+#endif
+#ifdef CONFIG_GETAUXVAL
+# include <sys/auxv.h>
#endif
-#undef USE_ARMV7_INSTRUCTIONS
#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -1023,7 +1016,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
if (addr & 1) {
/* Use BLX if the target is in Thumb mode */
- if (!use_armv5_instructions) {
+ if (!use_armv5t_instructions) {
tcg_abort();
}
tcg_out_blx_imm(s, val);
@@ -1042,7 +1035,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
{
- if (use_armv5_instructions) {
+ if (use_armv5t_instructions) {
tcg_out_blx(s, cond, arg);
} else {
tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
@@ -1926,18 +1919,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_divu_i32:
tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
break;
- case INDEX_op_rem_i32:
- tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
- tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
- tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
- SHIFT_IMM_LSL(0));
- break;
- case INDEX_op_remu_i32:
- tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
- tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
- tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
- SHIFT_IMM_LSL(0));
- break;
default:
tcg_abort();
@@ -2041,18 +2022,31 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
-#if TCG_TARGET_HAS_div_i32
{ INDEX_op_div_i32, { "r", "r", "r" } },
- { INDEX_op_rem_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
- { INDEX_op_remu_i32, { "r", "r", "r" } },
-#endif
{ -1 },
};
static void tcg_target_init(TCGContext *s)
{
+#if defined(CONFIG_GETAUXVAL)
+ /* Only probe for the platform and capabilities if we havn't already
+ determined maximum values at compile time. */
+# if !defined(use_idiv_instructions)
+ {
+ unsigned long hwcap = getauxval(AT_HWCAP);
+ use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
+ }
+# endif
+ if (__ARM_ARCH < 7) {
+ const char *pl = (const char *)getauxval(AT_PLATFORM);
+ if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
+ arm_arch = pl[1] - '0';
+ }
+ }
+#endif /* GETAUXVAL */
+
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
@@ -2094,23 +2088,31 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
tcg_out_movi32(s, COND_AL, ret, arg);
}
+/* Compute frame size via macros, to share between tcg_target_qemu_prologue
+ and tcg_register_jit. */
+
+#define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
+
+#define FRAME_SIZE \
+ ((PUSH_SIZE \
+ + TCG_STATIC_CALL_ARGS_SIZE \
+ + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+ & -TCG_TARGET_STACK_ALIGN)
+
static void tcg_target_qemu_prologue(TCGContext *s)
{
- int frame_size;
+ int stack_addend;
/* Calling convention requires us to save r4-r11 and lr. */
/* stmdb sp!, { r4 - r11, lr } */
tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
- /* Allocate the local stack frame. */
- frame_size = TCG_STATIC_CALL_ARGS_SIZE;
- frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
- /* We saved an odd number of registers above; keep an 8 aligned stack. */
- frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
- & -TCG_TARGET_STACK_ALIGN) + 4;
+ /* Reserve callee argument and tcg temp space. */
+ stack_addend = FRAME_SIZE - PUSH_SIZE;
tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
- TCG_REG_CALL_STACK, frame_size, 1);
+ TCG_REG_CALL_STACK, stack_addend, 1);
tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
CPU_TEMP_BUF_NLONGS * sizeof(long));
@@ -2121,8 +2123,58 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* Epilogue. We branch here via tb_ret_addr. */
tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
- TCG_REG_CALL_STACK, frame_size, 1);
+ TCG_REG_CALL_STACK, stack_addend, 1);
/* ldmia sp!, { r4 - r11, pc } */
tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
}
+
+typedef struct {
+ DebugFrameCIE cie;
+ DebugFrameFDEHeader fde;
+ uint8_t fde_def_cfa[4];
+ uint8_t fde_reg_ofs[18];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_ARM
+
+/* We're expecting a 2 byte uleb128 encoded value. */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
+static DebugFrame debug_frame = {
+ .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+ .cie.id = -1,
+ .cie.version = 1,
+ .cie.code_align = 1,
+ .cie.data_align = 0x7c, /* sleb128 -4 */
+ .cie.return_column = 14,
+
+ /* Total FDE size does not include the "len" member. */
+ .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+ .fde_def_cfa = {
+ 12, 13, /* DW_CFA_def_cfa sp, ... */
+ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
+ (FRAME_SIZE >> 7)
+ },
+ .fde_reg_ofs = {
+ /* The following must match the stmdb in the prologue. */
+ 0x8e, 1, /* DW_CFA_offset, lr, -4 */
+ 0x8b, 2, /* DW_CFA_offset, r11, -8 */
+ 0x8a, 3, /* DW_CFA_offset, r10, -12 */
+ 0x89, 4, /* DW_CFA_offset, r9, -16 */
+ 0x88, 5, /* DW_CFA_offset, r8, -20 */
+ 0x87, 6, /* DW_CFA_offset, r7, -24 */
+ 0x86, 7, /* DW_CFA_offset, r6, -28 */
+ 0x85, 8, /* DW_CFA_offset, r5, -32 */
+ 0x84, 9, /* DW_CFA_offset, r4, -36 */
+ }
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+ debug_frame.fde.func_start = (tcg_target_long) buf;
+ debug_frame.fde.func_len = buf_size;
+
+ tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 3be41cce3c..5cd9d6a679 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -49,6 +49,13 @@ typedef enum {
#define TCG_TARGET_NB_REGS 16
+#ifdef __ARM_ARCH_EXT_IDIV__
+#define use_idiv_instructions 1
+#else
+extern bool use_idiv_instructions;
+#endif
+
+
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_R13
#define TCG_TARGET_STACK_ALIGN 8
@@ -73,12 +80,8 @@ typedef enum {
#define TCG_TARGET_HAS_deposit_i32 1
#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_muls2_i32 1
-
-#ifdef __ARM_ARCH_EXT_IDIV__
-#define TCG_TARGET_HAS_div_i32 1
-#else
-#define TCG_TARGET_HAS_div_i32 0
-#endif
+#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
+#define TCG_TARGET_HAS_rem_i32 0
extern bool tcg_target_deposit_valid(int ofs, int len);
#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 656e73621a..68f77ba4dd 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1766,28 +1766,11 @@ static void tcg_target_init(TCGContext *s)
}
typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t id;
- uint8_t version;
- char augmentation[1];
- uint8_t code_align;
- uint8_t data_align;
- uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t cie_offset;
- tcg_target_long func_start __attribute__((packed));
- tcg_target_long func_len __attribute__((packed));
- uint8_t def_cfa[4];
- uint8_t ret_ofs[3];
- uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
-} DebugFrameFDE;
-
-typedef struct {
DebugFrameCIE cie;
- DebugFrameFDE fde;
+ DebugFrameFDEHeader fde;
+ uint8_t fde_def_cfa[4];
+ uint8_t fde_ret_ofs[3];
+ uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
} DebugFrame;
#define ELF_HOST_MACHINE EM_PARISC
@@ -1806,16 +1789,18 @@ static DebugFrame debug_frame = {
.cie.data_align = 1,
.cie.return_column = 2,
- .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
- .fde.def_cfa = {
+ /* Total FDE size does not include the "len" member. */
+ .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+ .fde_def_cfa = {
0x12, 30, /* DW_CFA_def_cfa_sf sp, ... */
(-FRAME_SIZE & 0x7f) | 0x80, /* ... sleb128 -FRAME_SIZE */
(-FRAME_SIZE >> 7) & 0x7f
},
- .fde.ret_ofs = {
+ .fde_ret_ofs = {
0x11, 2, (-20 / 4) & 0x7f /* DW_CFA_offset_extended_sf r2, 20 */
},
- .fde.reg_ofs = {
+ .fde_reg_ofs = {
/* This must match the ordering in tcg_target_callee_save_regs. */
0x80 + 4, 0, /* DW_CFA_offset r4, 0 */
0x80 + 5, 4, /* DW_CFA_offset r5, 4 */
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index ebd53d9e36..25467bdd43 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -85,6 +85,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
+#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9e95477ef4..87eeab3d30 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -2312,29 +2312,15 @@ static void tcg_target_init(TCGContext *s)
}
typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t id;
- uint8_t version;
- char augmentation[1];
- uint8_t code_align;
- uint8_t data_align;
- uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t cie_offset;
- tcg_target_long func_start __attribute__((packed));
- tcg_target_long func_len __attribute__((packed));
- uint8_t def_cfa[4];
- uint8_t reg_ofs[14];
-} DebugFrameFDE;
-
-typedef struct {
DebugFrameCIE cie;
- DebugFrameFDE fde;
+ DebugFrameFDEHeader fde;
+ uint8_t fde_def_cfa[4];
+ uint8_t fde_reg_ofs[14];
} DebugFrame;
+/* We're expecting a 2 byte uleb128 encoded value. */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
+
#if !defined(__ELF__)
/* Host machine without ELF. */
#elif TCG_TARGET_REG_BITS == 64
@@ -2347,13 +2333,15 @@ static DebugFrame debug_frame = {
.cie.data_align = 0x78, /* sleb128 -8 */
.cie.return_column = 16,
- .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
- .fde.def_cfa = {
+ /* Total FDE size does not include the "len" member. */
+ .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+ .fde_def_cfa = {
12, 7, /* DW_CFA_def_cfa %rsp, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
- .fde.reg_ofs = {
+ .fde_reg_ofs = {
0x90, 1, /* DW_CFA_offset, %rip, -8 */
/* The following ordering must match tcg_target_callee_save_regs. */
0x86, 2, /* DW_CFA_offset, %rbp, -16 */
@@ -2374,13 +2362,15 @@ static DebugFrame debug_frame = {
.cie.data_align = 0x7c, /* sleb128 -4 */
.cie.return_column = 8,
- .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
- .fde.def_cfa = {
+ /* Total FDE size does not include the "len" member. */
+ .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+ .fde_def_cfa = {
12, 4, /* DW_CFA_def_cfa %esp, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
- .fde.reg_ofs = {
+ .fde_reg_ofs = {
0x88, 1, /* DW_CFA_offset, %eip, -4 */
/* The following ordering must match tcg_target_callee_save_regs. */
0x85, 2, /* DW_CFA_offset, %ebp, -8 */
@@ -2394,9 +2384,6 @@ static DebugFrame debug_frame = {
#if defined(ELF_HOST_MACHINE)
void tcg_register_jit(void *buf, size_t buf_size)
{
- /* We're expecting a 2 byte uleb128 encoded value. */
- assert(FRAME_SIZE >> 14 == 0);
-
debug_frame.fde.func_start = (tcg_target_long) buf;
debug_frame.fde.func_len = buf_size;
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index e3d72ea52f..f32d5199cb 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -104,7 +104,9 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
+#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_div_i64 0
+#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_bswap16_i32 1
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 6155327a9a..a438950bc1 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -79,6 +79,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
+#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 29ca934e66..453ab6b580 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -1671,18 +1671,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
break;
- case INDEX_op_rem_i32:
- tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
-
- case INDEX_op_remu_i32:
- tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
-
case INDEX_op_mulu2_i32:
if (args[0] == args[2] || args[0] == args[3]) {
tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
@@ -1992,8 +1980,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i32, { "r", "r", "ri" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
- { INDEX_op_rem_i32, { "r", "r", "r" } },
- { INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
{ INDEX_op_sub_i32, { "r", "r", "ri" } },
{ INDEX_op_and_i32, { "r", "r", "ri" } },
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 17a6bb367a..b42d97cc24 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -78,6 +78,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
+#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 606b73defc..0678de2045 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -1617,18 +1617,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
break;
- case INDEX_op_rem_i32:
- tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
-
- case INDEX_op_remu_i32:
- tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
-
case INDEX_op_shl_i32:
if (const_args[2]) {
tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
@@ -1786,16 +1774,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_divu_i64:
tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
break;
- case INDEX_op_rem_i64:
- tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
- case INDEX_op_remu_i64:
- tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
- tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
- tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
- break;
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld (s, args, 0);
@@ -2064,8 +2042,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i32, { "r", "r", "rI" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
- { INDEX_op_rem_i32, { "r", "r", "r" } },
- { INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_sub_i32, { "r", "rI", "ri" } },
{ INDEX_op_and_i32, { "r", "r", "ri" } },
{ INDEX_op_or_i32, { "r", "r", "ri" } },
@@ -2108,8 +2084,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i64, { "r", "r", "rI" } },
{ INDEX_op_div_i64, { "r", "r", "r" } },
{ INDEX_op_divu_i64, { "r", "r", "r" } },
- { INDEX_op_rem_i64, { "r", "r", "r" } },
- { INDEX_op_remu_i64, { "r", "r", "r" } },
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index cb77634714..48fc6e2e54 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -76,6 +76,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
+#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
@@ -96,6 +97,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_div_i64 1
+#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 025af9b379..5bfd29c3b4 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -1647,28 +1647,11 @@ static void tcg_target_init(TCGContext *s)
#endif
typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t id;
- uint8_t version;
- char augmentation[1];
- uint8_t code_align;
- uint8_t data_align;
- uint8_t return_column;
-} DebugFrameCIE;
-
-typedef struct {
- uint32_t len __attribute__((aligned((sizeof(void *)))));
- uint32_t cie_offset;
- tcg_target_long func_start __attribute__((packed));
- tcg_target_long func_len __attribute__((packed));
- uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
- uint8_t win_save;
- uint8_t ret_save[3];
-} DebugFrameFDE;
-
-typedef struct {
DebugFrameCIE cie;
- DebugFrameFDE fde;
+ DebugFrameFDEHeader fde;
+ uint8_t fde_def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
+ uint8_t fde_win_save;
+ uint8_t fde_ret_save[3];
} DebugFrame;
static DebugFrame debug_frame = {
@@ -1679,8 +1662,10 @@ static DebugFrame debug_frame = {
.cie.data_align = -sizeof(void *) & 0x7f,
.cie.return_column = 15, /* o7 */
- .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
- .fde.def_cfa = {
+ /* Total FDE size does not include the "len" member. */
+ .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
+
+ .fde_def_cfa = {
#if TCG_TARGET_REG_BITS == 64
12, 30, /* DW_CFA_def_cfa i6, 2047 */
(2047 & 0x7f) | 0x80, (2047 >> 7)
@@ -1688,8 +1673,8 @@ static DebugFrame debug_frame = {
13, 30 /* DW_CFA_def_cfa_register i6 */
#endif
},
- .fde.win_save = 0x2d, /* DW_CFA_GNU_window_save */
- .fde.ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
+ .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
+ .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
};
void tcg_register_jit(void *buf, size_t buf_size)
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index b5217bef25..dab52d7176 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -86,6 +86,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
+#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_rot_i32 0
#define TCG_TARGET_HAS_ext8s_i32 0
#define TCG_TARGET_HAS_ext16s_i32 0
@@ -109,6 +110,7 @@ typedef enum {
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div_i64 1
+#define TCG_TARGET_HAS_rem_i64 1
#define TCG_TARGET_HAS_rot_i64 0
#define TCG_TARGET_HAS_ext8s_i64 0
#define TCG_TARGET_HAS_ext16s_i64 0
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 94f6043786..364964d8d4 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -731,8 +731,14 @@ static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- if (TCG_TARGET_HAS_div_i32) {
+ if (TCG_TARGET_HAS_rem_i32) {
tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
+ } else if (TCG_TARGET_HAS_div_i32) {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
+ tcg_gen_mul_i32(t0, t0, arg2);
+ tcg_gen_sub_i32(ret, arg1, t0);
+ tcg_temp_free_i32(t0);
} else if (TCG_TARGET_HAS_div2_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_sari_i32(t0, arg1, 31);
@@ -769,8 +775,14 @@ static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- if (TCG_TARGET_HAS_div_i32) {
+ if (TCG_TARGET_HAS_rem_i32) {
tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
+ } else if (TCG_TARGET_HAS_div_i32) {
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
+ tcg_gen_mul_i32(t0, t0, arg2);
+ tcg_gen_sub_i32(ret, arg1, t0);
+ tcg_temp_free_i32(t0);
} else if (TCG_TARGET_HAS_div2_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_movi_i32(t0, 0);
@@ -1361,8 +1373,14 @@ static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- if (TCG_TARGET_HAS_div_i64) {
+ if (TCG_TARGET_HAS_rem_i64) {
tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
+ } else if (TCG_TARGET_HAS_div_i64) {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
+ tcg_gen_mul_i64(t0, t0, arg2);
+ tcg_gen_sub_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
} else if (TCG_TARGET_HAS_div2_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_sari_i64(t0, arg1, 63);
@@ -1399,8 +1417,14 @@ static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- if (TCG_TARGET_HAS_div_i64) {
+ if (TCG_TARGET_HAS_rem_i64) {
tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
+ } else if (TCG_TARGET_HAS_div_i64) {
+ TCGv_i64 t0 = tcg_temp_new_i64();
+ tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
+ tcg_gen_mul_i64(t0, t0, arg2);
+ tcg_gen_sub_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
} else if (TCG_TARGET_HAS_div2_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_movi_i64(t0, 0);
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 4246e9c1fa..a8af5b96a4 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -27,20 +27,24 @@
*/
/* predefined ops */
-DEF(end, 0, 0, 0, 0) /* must be kept first */
-DEF(nop, 0, 0, 0, 0)
-DEF(nop1, 0, 0, 1, 0)
-DEF(nop2, 0, 0, 2, 0)
-DEF(nop3, 0, 0, 3, 0)
-DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
+DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */
+DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT)
+DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT)
+DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT)
+DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT)
-DEF(discard, 1, 0, 0, 0)
+/* variable number of parameters */
+DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT)
+
+DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
+DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
+
+/* variable number of parameters */
+DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
-DEF(set_label, 0, 0, 1, TCG_OPF_BB_END)
-DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) /* variable number of parameters */
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
-#define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT)
+#define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0)
#if TCG_TARGET_REG_BITS == 32
# define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT
#else
@@ -66,8 +70,8 @@ DEF(sub_i32, 1, 2, 0, 0)
DEF(mul_i32, 1, 2, 0, 0)
DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
-DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
-DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
+DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
+DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
DEF(and_i32, 1, 2, 0, 0)
@@ -126,8 +130,8 @@ DEF(sub_i64, 1, 2, 0, IMPL64)
DEF(mul_i64, 1, 2, 0, IMPL64)
DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
-DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
-DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
+DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
+DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
DEF(and_i64, 1, 2, 0, IMPL64)
@@ -166,9 +170,9 @@ DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64))
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF(debug_insn_start, 0, 0, 2, 0)
+DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
#else
-DEF(debug_insn_start, 0, 0, 1, 0)
+DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
#endif
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1d8099cca8..dac8224024 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -68,6 +68,24 @@ static void tcg_target_qemu_prologue(TCGContext *s);
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
+/* The CIE and FDE header definitions will be common to all hosts. */
+typedef struct {
+ uint32_t len __attribute__((aligned((sizeof(void *)))));
+ uint32_t id;
+ uint8_t version;
+ char augmentation[1];
+ uint8_t code_align;
+ uint8_t data_align;
+ uint8_t return_column;
+} DebugFrameCIE;
+
+typedef struct QEMU_PACKED {
+ uint32_t len __attribute__((aligned((sizeof(void *)))));
+ uint32_t cie_offset;
+ tcg_target_long func_start;
+ tcg_target_long func_len;
+} DebugFrameFDEHeader;
+
static void tcg_register_jit_int(void *buf, size_t size,
void *debug_frame, size_t debug_frame_size)
__attribute__((unused));
@@ -1160,9 +1178,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
i = 0;
for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
const TCGOpDef *def = &tcg_op_defs[op];
- if (op < INDEX_op_call
- || op == INDEX_op_debug_insn_start
- || (def->flags & TCG_OPF_NOT_PRESENT)) {
+ if (def->flags & TCG_OPF_NOT_PRESENT) {
/* Wrong entry in op definitions? */
if (def->used) {
fprintf(stderr, "Invalid op definition for %s\n", def->name);
@@ -2659,9 +2675,9 @@ static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
img->sym[1].st_size = buf_size;
img->di.cu_low_pc = buf;
- img->di.cu_high_pc = buf_size;
+ img->di.cu_high_pc = buf + buf_size;
img->di.fn_low_pc = buf;
- img->di.fn_high_pc = buf_size;
+ img->di.fn_high_pc = buf + buf_size;
#ifdef DEBUG_JIT
/* Enable this block to be able to debug the ELF image file creation.
diff --git a/tcg/tcg.h b/tcg/tcg.h
index df375cf31e..f3f9889694 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -60,6 +60,7 @@ typedef uint64_t TCGRegSet;
#if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_div_i64 0
+#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_div2_i64 0
#define TCG_TARGET_HAS_rot_i64 0
#define TCG_TARGET_HAS_ext8s_i64 0
@@ -102,11 +103,13 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_div2_i32 0
#elif defined(TCG_TARGET_HAS_div2_i32)
#define TCG_TARGET_HAS_div_i32 0
+#define TCG_TARGET_HAS_rem_i32 0
#endif
#if defined(TCG_TARGET_HAS_div_i64)
#define TCG_TARGET_HAS_div2_i64 0
#elif defined(TCG_TARGET_HAS_div2_i64)
#define TCG_TARGET_HAS_div_i64 0
+#define TCG_TARGET_HAS_rem_i64 0
#endif
typedef enum TCGOpcode {
@@ -593,7 +596,8 @@ enum {
TCG_OPF_SIDE_EFFECTS = 0x04,
/* Instruction operands are 64-bits (otherwise 32-bits). */
TCG_OPF_64BIT = 0x08,
- /* Instruction is optional and not implemented by the host. */
+ /* Instruction is optional and not implemented by the host, or insn
+ is generic and should not be implemened by the host. */
TCG_OPF_NOT_PRESENT = 0x10,
};
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 0395bbb8e4..d7fc14eb17 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -59,9 +59,8 @@
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
-/* Not more than one of the next two defines must be 1. */
#define TCG_TARGET_HAS_div_i32 1
-#define TCG_TARGET_HAS_div2_i32 0
+#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
#define TCG_TARGET_HAS_ext8u_i32 1
@@ -83,9 +82,8 @@
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_deposit_i64 1
-/* Not more than one of the next two defines must be 1. */
#define TCG_TARGET_HAS_div_i64 0
-#define TCG_TARGET_HAS_div2_i64 0
+#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1
diff --git a/user-exec.c b/user-exec.c
index 26cde7c57c..d45ca8e877 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -20,6 +20,7 @@
#include "cpu.h"
#include "disas/disas.h"
#include "tcg.h"
+#include "qemu/bitops.h"
#undef EAX
#undef ECX
@@ -442,8 +443,11 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#else
pc = uc->uc_mcontext.arm_pc;
#endif
- /* XXX: compute is_write */
- is_write = 0;
+
+ /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or
+ * later processor; on v5 we will always report this as a read).
+ */
+ is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 412c425518..e0ef426daa 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -706,16 +706,12 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
QemuOpts *opts;
QTAILQ_FOREACH(opts, &list->head, next) {
- if (!opts->id) {
- if (!id) {
- return opts;
- }
- continue;
+ if (!opts->id && !id) {
+ return opts;
}
- if (strcmp(opts->id, id) != 0) {
- continue;
+ if (opts->id && id && !strcmp(opts->id, id)) {
+ return opts;
}
- return opts;
}
return NULL;
}
@@ -918,15 +914,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
get_opt_value(value, sizeof(value), p+4);
id = value;
}
- if (defaults) {
- if (!id && !QTAILQ_EMPTY(&list->head)) {
- opts = qemu_opts_find(list, NULL);
- } else {
- opts = qemu_opts_create(list, id, 0, &local_err);
- }
- } else {
- opts = qemu_opts_create(list, id, 1, &local_err);
- }
+ opts = qemu_opts_create(list, id, !defaults, &local_err);
if (opts == NULL) {
if (error_is_set(&local_err)) {
qerror_report_err(local_err);
diff --git a/vl.c b/vl.c
index 6d9fd7d807..bea1a10cc6 100644
--- a/vl.c
+++ b/vl.c
@@ -409,7 +409,7 @@ static QemuOptsList qemu_machine_opts = {
.help = "Dump current dtb to a file and quit",
}, {
.name = "phandle_start",
- .type = QEMU_OPT_STRING,
+ .type = QEMU_OPT_NUMBER,
.help = "The first phandle ID we may generate dynamically",
}, {
.name = "dt_compatible",
@@ -516,6 +516,25 @@ static QemuOptsList qemu_realtime_opts = {
},
};
+/**
+ * Get machine options
+ *
+ * Returns: machine options (never null).
+ */
+QemuOpts *qemu_get_machine_opts(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+
+ list = qemu_find_opts("machine");
+ assert(list);
+ opts = qemu_opts_find(list, NULL);
+ if (!opts) {
+ opts = qemu_opts_create_nofail(list);
+ }
+ return opts;
+}
+
const char *qemu_get_vm_name(void)
{
return qemu_name;
@@ -1017,15 +1036,9 @@ static int parse_sandbox(QemuOpts *opts, void *opaque)
return 0;
}
-/*********QEMU USB setting******/
bool usb_enabled(bool default_usb)
{
- QemuOpts *mach_opts;
- mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (mach_opts) {
- return qemu_opt_get_bool(mach_opts, "usb", default_usb);
- }
- return default_usb;
+ return qemu_opt_get_bool(qemu_get_machine_opts(), "usb", default_usb);
}
#ifndef _WIN32
@@ -2672,17 +2685,13 @@ static struct {
static int configure_accelerator(void)
{
- const char *p = NULL;
+ const char *p;
char buf[10];
int i, ret;
bool accel_initialised = false;
bool init_failed = false;
- QemuOptsList *list = qemu_find_opts("machine");
- if (!QTAILQ_EMPTY(&list->head)) {
- p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel");
- }
-
+ p = qemu_opt_get(qemu_get_machine_opts(), "accel");
if (p == NULL) {
/* Use the default "accelerator", tcg */
p = "tcg";
@@ -4080,14 +4089,10 @@ int main(int argc, char **argv, char **envp)
qtest_init();
}
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- kernel_filename = qemu_opt_get(machine_opts, "kernel");
- initrd_filename = qemu_opt_get(machine_opts, "initrd");
- kernel_cmdline = qemu_opt_get(machine_opts, "append");
- } else {
- kernel_filename = initrd_filename = kernel_cmdline = NULL;
- }
+ machine_opts = qemu_get_machine_opts();
+ kernel_filename = qemu_opt_get(machine_opts, "kernel");
+ initrd_filename = qemu_opt_get(machine_opts, "initrd");
+ kernel_cmdline = qemu_opt_get(machine_opts, "append");
if (!boot_order) {
boot_order = machine->boot_order;
@@ -4130,7 +4135,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) {
+ if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) {
fprintf(stderr, "-dtb only allowed with -kernel option\n");
exit(1);
}