diff options
author | Avi Kivity <avi@redhat.com> | 2011-07-31 12:01:24 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-07-31 12:01:24 +0300 |
commit | 38bb57d378345fb429f071715429041b04cd64a4 (patch) | |
tree | cbd701582069815d1744b6505f12afa8767f944e | |
parent | 8d0159316d202df2370ccea623b7ef6c9303ce1f (diff) | |
parent | 9dc9f2b8206e4c678815943e8da30c4ba43bcb81 (diff) |
Merge remote-tracking branch 'upstream/stable-0.15' into stable-0.15
* upstream/stable-0.15: (24 commits)
Bump version to 0.15.0-rc1
virtio-balloon: Unregister savevm section on device unplug
virtio-balloon: Add exit handler, fix memleaks
balloon: Reject negative balloon values
virtio-balloon: Check if balloon registration failed
balloon: Don't allow multiple balloon handler registrations
target-arm: UNDEF on a VCVTT/VCVTB UNPREDICTABLE to avoid TCG assert
target-arm: Handle UNDEF and UNPREDICTABLE cases for VLDM, VSTM
target-arm: Support v6 barriers in linux-user mode
target-arm: Mark 1136r1 as a v6K core
virtio-balloon: Fix header comment; add Copyright
balloon: Fix header comment; add Copyright
balloon: Separate out stat and balloon handling
virtio-balloon: Separate status handling into separate function
balloon: Simplify code flow
balloon: Add braces around if statements
balloon: Make functions, local vars static
Let users select their pythons
simpletrace: suppress a warning from unused variable
Wrap recv to avoid warnings
...
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | balloon.c | 61 | ||||
-rw-r--r-- | balloon.h | 12 | ||||
-rw-r--r-- | block/sheepdog.c | 2 | ||||
-rwxr-xr-x | configure | 19 | ||||
-rw-r--r-- | gdbstub.c | 2 | ||||
-rw-r--r-- | hw/baum.h | 2 | ||||
-rw-r--r-- | hw/virtio-balloon.c | 76 | ||||
-rw-r--r-- | hw/virtio-pci.c | 14 | ||||
-rw-r--r-- | hw/virtio.h | 1 | ||||
-rw-r--r-- | linux-user/syscall.c | 2 | ||||
-rw-r--r-- | nbd.c | 2 | ||||
-rw-r--r-- | net/socket.c | 4 | ||||
-rw-r--r-- | qemu-char.c | 11 | ||||
-rw-r--r-- | qemu-common.h | 6 | ||||
-rw-r--r-- | qemu-ga.c | 35 | ||||
-rw-r--r-- | qga/guest-agent-commands.c | 12 | ||||
-rw-r--r-- | savevm.c | 2 | ||||
-rw-r--r-- | simpletrace.c | 2 | ||||
-rw-r--r-- | slirp/ip_icmp.c | 2 | ||||
-rw-r--r-- | slirp/slirp.c | 2 | ||||
-rw-r--r-- | slirp/socket.c | 4 | ||||
-rw-r--r-- | target-arm/cpu.h | 1 | ||||
-rw-r--r-- | target-arm/helper.c | 21 | ||||
-rw-r--r-- | target-arm/translate.c | 108 | ||||
-rw-r--r-- | ui/vnc-tls.c | 2 | ||||
-rw-r--r-- | ui/vnc.c | 2 |
28 files changed, 270 insertions, 151 deletions
@@ -168,22 +168,22 @@ test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-di $(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h $(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") $(qapi-dir)/test-qapi-visit.c: $(qapi-dir)/test-qapi-visit.h $(qapi-dir)/test-qapi-visit.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") $(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c $(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@") $(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h $(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") $(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h $(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") $(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py - $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@") test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y) test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o @@ -1 +1 @@ -0.14.90 +0.15.51 @@ -1,7 +1,9 @@ /* - * QEMU System Emulator + * Generic Balloon handlers and management * * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,44 +32,53 @@ #include "balloon.h" #include "trace.h" +static QEMUBalloonEvent *balloon_event_fn; +static QEMUBalloonStatus *balloon_stat_fn; +static void *balloon_opaque; -static QEMUBalloonEvent *qemu_balloon_event; -void *qemu_balloon_event_opaque; - -void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque) +int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, + QEMUBalloonStatus *stat_func, void *opaque) { - qemu_balloon_event = func; - qemu_balloon_event_opaque = opaque; + if (balloon_event_fn || balloon_stat_fn || balloon_opaque) { + /* We're already registered one balloon handler. How many can + * a guest really have? + */ + error_report("Another balloon device already registered"); + return -1; + } + balloon_event_fn = event_func; + balloon_stat_fn = stat_func; + balloon_opaque = opaque; + return 0; } -int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque) +static int qemu_balloon(ram_addr_t target) { - if (qemu_balloon_event) { - trace_balloon_event(qemu_balloon_event_opaque, target); - qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque); - return 1; - } else { + if (!balloon_event_fn) { return 0; } + trace_balloon_event(balloon_opaque, target); + balloon_event_fn(balloon_opaque, target); + return 1; } -int qemu_balloon_status(MonitorCompletion cb, void *opaque) +static int qemu_balloon_status(MonitorCompletion cb, void *opaque) { - if (qemu_balloon_event) { - qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque); - return 1; - } else { + if (!balloon_stat_fn) { return 0; } + balloon_stat_fn(balloon_opaque, cb, opaque); + return 1; } static void print_balloon_stat(const char *key, QObject *obj, void *opaque) { Monitor *mon = opaque; - if (strcmp(key, "actual")) + if (strcmp(key, "actual")) { monitor_printf(mon, ",%s=%" PRId64, key, qint_get_int(qobject_to_qint(obj))); + } } void monitor_print_balloon(Monitor *mon, const QObject *data) @@ -75,9 +86,9 @@ void monitor_print_balloon(Monitor *mon, const QObject *data) QDict *qdict; qdict = qobject_to_qdict(data); - if (!qdict_haskey(qdict, "actual")) + if (!qdict_haskey(qdict, "actual")) { return; - + } monitor_printf(mon, "balloon: actual=%" PRId64, qdict_get_int(qdict, "actual") >> 20); qdict_iter(qdict, print_balloon_stat, mon); @@ -129,6 +140,7 @@ int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque) int do_balloon(Monitor *mon, const QDict *params, MonitorCompletion cb, void *opaque) { + int64_t target; int ret; if (kvm_enabled() && !kvm_has_sync_mmu()) { @@ -136,7 +148,12 @@ int do_balloon(Monitor *mon, const QDict *params, return -1; } - ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque); + target = qdict_get_int(params, "value"); + if (target <= 0) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size"); + return -1; + } + ret = qemu_balloon(target); if (ret == 0) { qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon"); return -1; @@ -16,14 +16,12 @@ #include "monitor.h" -typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target, - MonitorCompletion cb, void *cb_data); +typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target); +typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb, + void *cb_data); -void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque); - -int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque); - -int qemu_balloon_status(MonitorCompletion cb, void *opaque); +int qemu_add_balloon_handler(QEMUBalloonEvent *event_func, + QEMUBalloonStatus *stat_func, void *opaque); void monitor_print_balloon(Monitor *mon, const QObject *data); int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque); diff --git a/block/sheepdog.c b/block/sheepdog.c index 77a4de510..e150ac012 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -496,7 +496,7 @@ static ssize_t recvmsg(int s, struct msghdr *msg, int flags) } buf = qemu_malloc(size); - ret = recv(s, buf, size, flags); + ret = qemu_recv(s, buf, size, flags); if (ret < 0) { goto out; } @@ -495,6 +495,7 @@ fi : ${make=${MAKE-make}} : ${install=${INSTALL-install}} +: ${python=${PYTHON-python}} if test "$mingw32" = "yes" ; then EXESUF=".exe" @@ -536,6 +537,8 @@ for opt do ;; --install=*) install="$optarg" ;; + --python=*) python="$optarg" + ;; --extra-cflags=*) ;; --extra-ldflags=*) @@ -954,6 +957,7 @@ echo " --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS" echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS" echo " --make=MAKE use specified make [$make]" echo " --install=INSTALL use specified install [$install]" +echo " --python=PYTHON use specified python [$python]" echo " --static enable static build [$static]" echo " --mandir=PATH install man pages in PATH" echo " --datadir=PATH install firmware in PATH" @@ -1119,6 +1123,13 @@ if test "$solaris" = "yes" ; then fi fi +if has $python; then + : +else + echo "Python not found. Use --python=/path/to/python" + exit 1 +fi + if test -z "$target_list" ; then target_list="$default_target_list" else @@ -1846,9 +1857,9 @@ fi ########################################## # glib support probe -if $pkg_config --modversion gthread-2.0 gio-2.0 > /dev/null 2>&1 ; then - glib_cflags=`$pkg_config --cflags gthread-2.0 gio-2.0 2>/dev/null` - glib_libs=`$pkg_config --libs gthread-2.0 gio-2.0 2>/dev/null` +if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then + glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null` + glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null` libs_softmmu="$glib_libs $libs_softmmu" libs_tools="$glib_libs $libs_tools" else @@ -2647,6 +2658,7 @@ echo "QEMU_CFLAGS $QEMU_CFLAGS" echo "LDFLAGS $LDFLAGS" echo "make $make" echo "install $install" +echo "python $python" echo "host CPU $cpu" echo "host big endian $bigendian" echo "target list $target_list" @@ -3067,6 +3079,7 @@ echo "INSTALL=$install" >> $config_host_mak echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak echo "INSTALL_DATA=$install -m0644 -p" >> $config_host_mak echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak +echo "PYTHON=$python" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak @@ -319,7 +319,7 @@ static int get_char(GDBState *s) int ret; for(;;) { - ret = recv(s->fd, &ch, 1, 0); + ret = qemu_recv(s->fd, &ch, 1, 0); if (ret < 0) { if (errno == ECONNRESET) s->fd = -1; @@ -23,4 +23,4 @@ */ /* char device */ -CharDriverState *chr_baum_init(QemuOpts *opts); +int chr_baum_init(QemuOpts *opts, CharDriverState **_chr); diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c index 70a871034..072a88a38 100644 --- a/hw/virtio-balloon.c +++ b/hw/virtio-balloon.c @@ -1,7 +1,9 @@ /* - * Virtio Block Device + * Virtio Balloon Device * * Copyright IBM, Corp. 2008 + * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com> * * Authors: * Anthony Liguori <aliguori@us.ibm.com> @@ -43,6 +45,7 @@ typedef struct VirtIOBalloon size_t stats_vq_offset; MonitorCompletion *stats_callback; void *stats_opaque_callback_data; + DeviceState *qdev; } VirtIOBalloon; static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev) @@ -199,36 +202,44 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) return f; } -static void virtio_balloon_to_target(void *opaque, ram_addr_t target, - MonitorCompletion cb, void *cb_data) +static void virtio_balloon_stat(void *opaque, MonitorCompletion cb, + void *cb_data) { VirtIOBalloon *dev = opaque; - if (target > ram_size) - target = ram_size; + /* For now, only allow one request at a time. This restriction can be + * removed later by queueing callback and data pairs. + */ + if (dev->stats_callback != NULL) { + return; + } + dev->stats_callback = cb; + dev->stats_opaque_callback_data = cb_data; + + if (ENABLE_GUEST_STATS + && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) { + virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset); + virtio_notify(&dev->vdev, dev->svq); + return; + } + + /* Stats are not supported. Clear out any stale values that might + * have been set by a more featureful guest kernel. + */ + reset_stats(dev); + complete_stats_request(dev); +} +static void virtio_balloon_to_target(void *opaque, ram_addr_t target) +{ + VirtIOBalloon *dev = opaque; + + if (target > ram_size) { + target = ram_size; + } if (target) { dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT; virtio_notify_config(&dev->vdev); - } else { - /* For now, only allow one request at a time. This restriction can be - * removed later by queueing callback and data pairs. - */ - if (dev->stats_callback != NULL) { - return; - } - dev->stats_callback = cb; - dev->stats_opaque_callback_data = cb_data; - if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) { - virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset); - virtio_notify(&dev->vdev, dev->svq); - } else { - /* Stats are not supported. Clear out any stale values that might - * have been set by a more featureful guest kernel. - */ - reset_stats(dev); - complete_stats_request(dev); - } } } @@ -259,6 +270,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id) VirtIODevice *virtio_balloon_init(DeviceState *dev) { VirtIOBalloon *s; + int ret; s = (VirtIOBalloon *)virtio_common_init("virtio-balloon", VIRTIO_ID_BALLOON, @@ -268,15 +280,29 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev) s->vdev.set_config = virtio_balloon_set_config; s->vdev.get_features = virtio_balloon_get_features; + ret = qemu_add_balloon_handler(virtio_balloon_to_target, + virtio_balloon_stat, s); + if (ret < 0) { + virtio_cleanup(&s->vdev); + return NULL; + } + s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output); s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output); s->svq = virtio_add_queue(&s->vdev, 128, virtio_balloon_receive_stats); reset_stats(s); - qemu_add_balloon_handler(virtio_balloon_to_target, s); + s->qdev = dev; register_savevm(dev, "virtio-balloon", -1, 1, virtio_balloon_save, virtio_balloon_load, s); return &s->vdev; } + +void virtio_balloon_exit(VirtIODevice *vdev) +{ + VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev); + unregister_savevm(s->qdev, "virtio-balloon", s); + virtio_cleanup(vdev); +} diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index c5bfb6277..6e3108aa8 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -864,10 +864,22 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev) VirtIODevice *vdev; vdev = virtio_balloon_init(&pci_dev->qdev); + if (!vdev) { + return -1; + } virtio_init_pci(proxy, vdev); return 0; } +static int virtio_balloon_exit_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + + virtio_pci_stop_ioeventfd(proxy); + virtio_balloon_exit(proxy->vdev); + return virtio_exit_pci(pci_dev); +} + static PCIDeviceInfo virtio_info[] = { { .qdev.name = "virtio-blk-pci", @@ -942,7 +954,7 @@ static PCIDeviceInfo virtio_info[] = { .qdev.alias = "virtio-balloon", .qdev.size = sizeof(VirtIOPCIProxy), .init = virtio_balloon_init_pci, - .exit = virtio_exit_pci, + .exit = virtio_balloon_exit_pci, .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON, .revision = VIRTIO_PCI_ABI_VERSION, diff --git a/hw/virtio.h b/hw/virtio.h index 0fd0bb0ac..c1292647f 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -213,6 +213,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf); void virtio_net_exit(VirtIODevice *vdev); void virtio_blk_exit(VirtIODevice *vdev); void virtio_serial_exit(VirtIODevice *vdev); +void virtio_balloon_exit(VirtIODevice *vdev); #define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ DEFINE_PROP_BIT("indirect_desc", _state, _field, \ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1dd7aad43..73f9baa6f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2004,7 +2004,7 @@ static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); } else { addr = NULL; /* To keep compiler quiet. */ - ret = get_errno(recv(fd, host_msg, len, flags)); + ret = get_errno(qemu_recv(fd, host_msg, len, flags)); } if (!is_error(ret)) { if (target_addr) { @@ -78,7 +78,7 @@ size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read) ssize_t len; if (do_read) { - len = recv(fd, buffer + offset, size - offset, 0); + len = qemu_recv(fd, buffer + offset, size - offset, 0); } else { len = send(fd, buffer + offset, size - offset, 0); } diff --git a/net/socket.c b/net/socket.c index bc1bf5889..11fe5f383 100644 --- a/net/socket.c +++ b/net/socket.c @@ -76,7 +76,7 @@ static void net_socket_send(void *opaque) uint8_t buf1[4096]; const uint8_t *buf; - size = recv(s->fd, (void *)buf1, sizeof(buf1), 0); + size = qemu_recv(s->fd, buf1, sizeof(buf1), 0); if (size < 0) { err = socket_error(); if (err != EWOULDBLOCK) @@ -138,7 +138,7 @@ static void net_socket_send_dgram(void *opaque) NetSocketState *s = opaque; int size; - size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0); + size = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0); if (size < 0) return; if (size == 0) { diff --git a/qemu-char.c b/qemu-char.c index dcf706592..8e8cf31a2 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1782,7 +1782,7 @@ static int qemu_chr_open_win_pipe(QemuOpts *opts, CharDriverState **_chr) return 0; } -static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) +static int qemu_chr_open_win_file(HANDLE fd_out, CharDriverState **pchr) { CharDriverState *chr; WinCharState *s; @@ -1793,10 +1793,11 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) chr->opaque = s; chr->chr_write = win_chr_write; qemu_chr_generic_open(chr); - return chr; + *pchr = chr; + return 0; } -static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **_chr) +static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **chr) { return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE), chr); } @@ -1859,7 +1860,7 @@ static void udp_chr_read(void *opaque) if (s->max_size == 0) return; - s->bufcnt = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0); + s->bufcnt = qemu_recv(s->fd, s->buf, sizeof(s->buf), 0); s->bufptr = s->bufcnt; if (s->bufcnt <= 0) return; @@ -2077,7 +2078,7 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) { TCPCharDriver *s = chr->opaque; - return recv(s->fd, buf, len, 0); + return qemu_recv(s->fd, buf, len, 0); } #endif diff --git a/qemu-common.h b/qemu-common.h index ba5571970..391fadda5 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -200,6 +200,12 @@ int qemu_eventfd(int pipefd[2]); int qemu_pipe(int pipefd[2]); #endif +#ifdef _WIN32 +#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags) +#else +#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags) +#endif + /* Error handling. */ void QEMU_NORETURN hw_error(const char *fmt, ...) GCC_FMT_ATTR(1, 2); @@ -14,7 +14,6 @@ #include <stdio.h> #include <stdbool.h> #include <glib.h> -#include <gio/gio.h> #include <getopt.h> #include <termios.h> #include <syslog.h> @@ -37,9 +36,7 @@ struct GAState { JSONMessageParser parser; GMainLoop *main_loop; - GSocket *conn_sock; GIOChannel *conn_channel; - GSocket *listen_sock; GIOChannel *listen_channel; const char *path; const char *method; @@ -412,18 +409,20 @@ static gboolean listen_channel_accept(GIOChannel *channel, GIOCondition condition, gpointer data) { GAState *s = data; - GError *err = NULL; g_assert(channel != NULL); - int ret; + int ret, conn_fd; bool accepted = false; + struct sockaddr_un addr; + socklen_t addrlen = sizeof(addr); - s->conn_sock = g_socket_accept(s->listen_sock, NULL, &err); - if (err != NULL) { - g_warning("error converting fd to gsocket: %s", err->message); - g_error_free(err); + conn_fd = qemu_accept(g_io_channel_unix_get_fd(s->listen_channel), + (struct sockaddr *)&addr, &addrlen); + if (conn_fd == -1) { + g_warning("error converting fd to gsocket: %s", strerror(errno)); goto out; } - ret = conn_channel_add(s, g_socket_get_fd(s->conn_sock)); + fcntl(conn_fd, F_SETFL, O_NONBLOCK); + ret = conn_channel_add(s, conn_fd); if (ret) { g_warning("error setting up connection"); goto out; @@ -440,19 +439,8 @@ out: */ static int listen_channel_add(GAState *s, int listen_fd, bool new) { - GError *err = NULL; - if (new) { s->listen_channel = g_io_channel_unix_new(listen_fd); - if (s->listen_sock) { - g_object_unref(s->listen_sock); - } - s->listen_sock = g_socket_new_from_fd(listen_fd, &err); - if (err != NULL) { - g_warning("error converting fd to gsocket: %s", err->message); - g_error_free(err); - return -1; - } } g_io_add_watch(s->listen_channel, G_IO_IN, listen_channel_accept, s); @@ -466,8 +454,6 @@ static void conn_channel_close(GAState *s) { if (strcmp(s->method, "unix-listen") == 0) { g_io_channel_shutdown(s->conn_channel, true, NULL); - g_object_unref(s->conn_sock); - s->conn_sock = NULL; listen_channel_add(s, 0, false); } else if (strcmp(s->method, "virtio-serial") == 0) { /* we spin on EOF for virtio-serial, so back off a bit. also, @@ -624,9 +610,6 @@ int main(int argc, char **argv) become_daemon(pidfile); } - g_type_init(); - g_thread_init(NULL); - s = qemu_mallocz(sizeof(GAState)); s->conn_channel = NULL; s->path = path; diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c index 624972e84..30c406848 100644 --- a/qga/guest-agent-commands.c +++ b/qga/guest-agent-commands.c @@ -10,15 +10,17 @@ * See the COPYING file in the top-level directory. */ -#if defined(__linux__) -#define CONFIG_FSFREEZE -#endif - #include <glib.h> -#if defined(CONFIG_FSFREEZE) + +#if defined(__linux__) #include <mntent.h> #include <linux/fs.h> + +#if defined(__linux__) && defined(FIFREEZE) +#define CONFIG_FSFREEZE #endif +#endif + #include <sys/types.h> #include <sys/ioctl.h> #include "qga/guest-agent-core.h" @@ -194,7 +194,7 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size) ssize_t len; do { - len = recv(s->fd, (void *)buf, size, 0); + len = qemu_recv(s->fd, buf, size, 0); } while (len == -1 && socket_error() == EINTR); if (len == -1) diff --git a/simpletrace.c b/simpletrace.c index f1dbb5e50..de355e967 100644 --- a/simpletrace.c +++ b/simpletrace.c @@ -119,7 +119,7 @@ static void *writeout_thread(void *opaque) TraceRecord record; unsigned int writeout_idx = 0; unsigned int num_available, idx; - size_t unused; + size_t unused __attribute__ ((unused)); for (;;) { wait_for_trace_records_available(); diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 14a5312c8..4b43994db 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -415,7 +415,7 @@ void icmp_receive(struct socket *so) icp = mtod(m, struct icmp *); id = icp->icmp_id; - len = recv(so->s, icp, m->m_len, 0); + len = qemu_recv(so->s, icp, m->m_len, 0); icp->icmp_id = id; m->m_data -= hlen; diff --git a/slirp/slirp.c b/slirp/slirp.c index faaa2f36c..df787ea1d 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -522,7 +522,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, */ #ifdef PROBE_CONN if (so->so_state & SS_ISFCONNECTING) { - ret = recv(so->s, (char *)&ret, 0,0); + ret = qemu_recv(so->s, &ret, 0,0); if (ret < 0) { /* XXX */ diff --git a/slirp/socket.c b/slirp/socket.c index 9b8ae13f5..77b0c9819 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -166,7 +166,7 @@ soread(struct socket *so) nn = readv(so->s, (struct iovec *)iov, n); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); #else - nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); + nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); #endif if (nn <= 0) { if (nn < 0 && (errno == EINTR || errno == EAGAIN)) @@ -191,7 +191,7 @@ soread(struct socket *so) */ if (n == 2 && nn == iov[0].iov_len) { int ret; - ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0); + ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn += ret; } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index adef42785..1974d82ff 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -374,6 +374,7 @@ enum arm_features { ARM_FEATURE_V4T, ARM_FEATURE_V5, ARM_FEATURE_STRONGARM, + ARM_FEATURE_VAPA, /* cp15 VA to PA lookups */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/helper.c b/target-arm/helper.c index ae4f334e4..5b0b4921a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -70,13 +70,24 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) env->cp15.c0_cachetype = 0x1dd20d2; env->cp15.c1_sys = 0x00090078; break; - case ARM_CPUID_ARM1136_R2: case ARM_CPUID_ARM1136: + /* This is the 1136 r1, which is a v6K core */ + set_feature(env, ARM_FEATURE_V6K); + /* Fall through */ + case ARM_CPUID_ARM1136_R2: + /* What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an + * older core than plain "arm1136". In particular this does not + * have the v6K features. + */ set_feature(env, ARM_FEATURE_V4T); set_feature(env, ARM_FEATURE_V5); set_feature(env, ARM_FEATURE_V6); set_feature(env, ARM_FEATURE_VFP); set_feature(env, ARM_FEATURE_AUXCR); + /* These ID register values are correct for 1136 but may be wrong + * for 1136_r2 (in particular r0p2 does not actually implement most + * of the ID registers). + */ env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4; env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111; env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000; @@ -92,6 +103,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) set_feature(env, ARM_FEATURE_V6K); set_feature(env, ARM_FEATURE_VFP); set_feature(env, ARM_FEATURE_AUXCR); + set_feature(env, ARM_FEATURE_VAPA); env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4; env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111; env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000; @@ -222,6 +234,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) cpu_abort(env, "Bad CPU ID: %x\n", id); break; } + + /* Some features automatically imply others: */ + if (arm_feature(env, ARM_FEATURE_V7)) { + set_feature(env, ARM_FEATURE_VAPA); + } } void cpu_reset(CPUARMState *env) @@ -1502,7 +1519,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val) goto bad_reg; } /* No cache, so nothing to do except VA->PA translations. */ - if (arm_feature(env, ARM_FEATURE_V6K)) { + if (arm_feature(env, ARM_FEATURE_VAPA)) { switch (crm) { case 4: if (arm_feature(env, ARM_FEATURE_V7)) { diff --git a/target-arm/translate.c b/target-arm/translate.c index 34d5e6ef1..fcb41d1cb 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -2498,12 +2498,6 @@ static int cp15_user_ok(CPUState *env, uint32_t insn) if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT))) return 1; } - if (cpn == 7) { - /* ISB, DSB, DMB. */ - if ((cpm == 5 && op == 4) - || (cpm == 10 && (op == 4 || op == 5))) - return 1; - } return 0; } @@ -2579,39 +2573,60 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) /* cdp */ return 1; } - if (IS_USER(s) && !cp15_user_ok(env, insn)) { - return 1; - } - - /* Pre-v7 versions of the architecture implemented WFI via coprocessor - * instructions rather than a separate instruction. + /* We special case a number of cp15 instructions which were used + * for things which are real instructions in ARMv7. This allows + * them to work in linux-user mode which doesn't provide functional + * get_cp15/set_cp15 helpers, and is more efficient anyway. */ - if ((insn & 0x0fff0fff) == 0x0e070f90) { + switch ((insn & 0x0fff0fff)) { + case 0x0e070f90: /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores). * In v7, this must NOP. */ + if (IS_USER(s)) { + return 1; + } if (!arm_feature(env, ARM_FEATURE_V7)) { /* Wait for interrupt. */ gen_set_pc_im(s->pc); s->is_jmp = DISAS_WFI; } return 0; - } - - if ((insn & 0x0fff0fff) == 0x0e070f58) { + case 0x0e070f58: /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI, * so this is slightly over-broad. */ - if (!arm_feature(env, ARM_FEATURE_V6)) { + if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) { /* Wait for interrupt. */ gen_set_pc_im(s->pc); s->is_jmp = DISAS_WFI; return 0; } - /* Otherwise fall through to handle via helper function. + /* Otherwise continue to handle via helper function. * In particular, on v7 and some v6 cores this is one of * the VA-PA registers. */ + break; + case 0x0e070f3d: + /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */ + if (arm_feature(env, ARM_FEATURE_V6)) { + return IS_USER(s) ? 1 : 0; + } + break; + case 0x0e070f95: /* 0,c7,c5,4 : ISB */ + case 0x0e070f9a: /* 0,c7,c10,4: DSB */ + case 0x0e070fba: /* 0,c7,c10,5: DMB */ + /* Barriers in both v6 and v7 */ + if (arm_feature(env, ARM_FEATURE_V6)) { + return 0; + } + break; + default: + break; + } + + if (IS_USER(s) && !cp15_user_ok(env, insn)) { + return 1; } rd = (insn >> 12) & 0xf; @@ -3056,6 +3071,17 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) /* Source and destination the same. */ gen_mov_F0_vreg(dp, rd); break; + case 4: + case 5: + case 6: + case 7: + /* VCVTB, VCVTT: only present with the halfprec extension, + * UNPREDICTABLE if bit 8 is set (we choose to UNDEF) + */ + if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) { + return 1; + } + /* Otherwise fall through */ default: /* One source operand. */ gen_mov_F0_vreg(dp, rm); @@ -3152,24 +3178,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) gen_vfp_sqrt(dp); break; case 4: /* vcvtb.f32.f16 */ - if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) - return 1; tmp = gen_vfp_mrs(); tcg_gen_ext16u_i32(tmp, tmp); gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); tcg_temp_free_i32(tmp); break; case 5: /* vcvtt.f32.f16 */ - if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) - return 1; tmp = gen_vfp_mrs(); tcg_gen_shri_i32(tmp, tmp, 16); gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); tcg_temp_free_i32(tmp); break; case 6: /* vcvtb.f16.f32 */ - if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) - return 1; tmp = tcg_temp_new_i32(); gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); gen_mov_F0_vreg(0, rd); @@ -3180,8 +3200,6 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) gen_vfp_msr(tmp); break; case 7: /* vcvtt.f16.f32 */ - if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) - return 1; tmp = tcg_temp_new_i32(); gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); tcg_gen_shli_i32(tmp, tmp, 16); @@ -3382,17 +3400,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) VFP_DREG_D(rd, insn); else rd = VFP_SREG_D(insn); - if (s->thumb && rn == 15) { - addr = tcg_temp_new_i32(); - tcg_gen_movi_i32(addr, s->pc & ~2); - } else { - addr = load_reg(s, rn); - } if ((insn & 0x01200000) == 0x01000000) { /* Single load/store */ offset = (insn & 0xff) << 2; if ((insn & (1 << 23)) == 0) offset = -offset; + if (s->thumb && rn == 15) { + /* This is actually UNPREDICTABLE */ + addr = tcg_temp_new_i32(); + tcg_gen_movi_i32(addr, s->pc & ~2); + } else { + addr = load_reg(s, rn); + } tcg_gen_addi_i32(addr, addr, offset); if (insn & (1 << 20)) { gen_vfp_ld(s, dp, addr); @@ -3404,11 +3423,34 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) tcg_temp_free_i32(addr); } else { /* load/store multiple */ + int w = insn & (1 << 21); if (dp) n = (insn >> 1) & 0x7f; else n = insn & 0xff; + if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) { + /* P == U , W == 1 => UNDEF */ + return 1; + } + if (n == 0 || (rd + n) > 32 || (dp && n > 16)) { + /* UNPREDICTABLE cases for bad immediates: we choose to + * UNDEF to avoid generating huge numbers of TCG ops + */ + return 1; + } + if (rn == 15 && w) { + /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */ + return 1; + } + + if (s->thumb && rn == 15) { + /* This is actually UNPREDICTABLE */ + addr = tcg_temp_new_i32(); + tcg_gen_movi_i32(addr, s->pc & ~2); + } else { + addr = load_reg(s, rn); + } if (insn & (1 << 24)) /* pre-decrement */ tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); @@ -3428,7 +3470,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) } tcg_gen_addi_i32(addr, addr, offset); } - if (insn & (1 << 21)) { + if (w) { /* writeback */ if (insn & (1 << 24)) offset = -offset * n; diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index dec626c53..31f1467ad 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -89,7 +89,7 @@ static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport, int ret; retry: - ret = recv(vs->csock, data, len, 0); + ret = qemu_recv(vs->csock, data, len, 0); if (ret < 0) { if (errno == EINTR) goto retry; @@ -1199,7 +1199,7 @@ long vnc_client_read_buf(VncState *vs, uint8_t *data, size_t datalen) } } else #endif /* CONFIG_VNC_TLS */ - ret = recv(vs->csock, (void *)data, datalen, 0); + ret = qemu_recv(vs->csock, data, datalen, 0); VNC_DEBUG("Read wire %p %zd -> %ld\n", data, datalen, ret); return vnc_client_io_error(vs, ret, socket_error()); } |