diff options
109 files changed, 1834 insertions, 3044 deletions
@@ -134,14 +134,14 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS) -CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) +CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) qemu-tool.o check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS) check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS) check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS) check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS) check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS) -check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS) +check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS) QEMULIBS=libhw32 libhw64 libuser libdis libdis-user @@ -185,6 +185,7 @@ ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \ pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \ bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \ +mpc8544ds.dtb \ multiboot.bin linuxboot.bin \ s390-zipl.rom \ spapr-rtas.bin slof.bin diff --git a/Makefile.objs b/Makefile.objs index 90838f6a0d..52d8b23045 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -2,7 +2,7 @@ # QObject qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o -qobject-obj-y += qerror.o +qobject-obj-y += qerror.o error.o ####################################################################### # oslib-obj-y is code depending on the OS (win32 vs posix) @@ -45,12 +45,14 @@ net-nested-$(CONFIG_SLIRP) += slirp.o net-nested-$(CONFIG_VDE) += vde.o net-obj-y += $(addprefix net/, $(net-nested-y)) -ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy) +ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy) # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. # only pull in the actual virtio-9p device if we also enabled virtio. CONFIG_REALLY_VIRTFS=y +fsdev-nested-y = qemu-fsdev.o +else +fsdev-nested-y = qemu-fsdev-dummy.o endif -fsdev-nested-$(CONFIG_VIRTFS) = qemu-fsdev.o fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y)) ###################################################################### @@ -170,6 +172,7 @@ user-obj-y += cutils.o cache-utils.o hw-obj-y = hw-obj-y += vl.o loader.o hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o +hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o hw-obj-y += fw_cfg.o hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o hw-obj-$(CONFIG_PCI) += msix.o msi.o @@ -285,12 +288,11 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0 hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) -9pfs-nested-$(CONFIG_REALLY_VIRTFS) = virtio-9p-debug.o +9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -hw-obj-$(CONFIG_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) -$(addprefix 9pfs/, $(9pfs-nested-y)): CFLAGS += -I$(SRC_PATH)/hw/ +hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) ###################################################################### diff --git a/Makefile.target b/Makefile.target index 602d50dc64..f7cb17de80 100644 --- a/Makefile.target +++ b/Makefile.target @@ -71,8 +71,7 @@ all: $(PROGS) stap # cpu emulator library libobj-y = exec.o translate-all.o cpu-exec.o translate.o libobj-y += tcg/tcg.o -libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o -libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o +libobj-y += fpu/softfloat.o libobj-y += op_helper.o helper.o ifeq ($(TARGET_BASE_ARCH), i386) libobj-y += cpuid.o @@ -191,10 +190,9 @@ obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o # need to fix this properly obj-$(CONFIG_NO_PCI) += pci-stub.o obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o -obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o obj-y += vhost_net.o obj-$(CONFIG_VHOST_NET) += vhost.o -obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p.o +obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o obj-y += rwhandler.o obj-$(CONFIG_KVM) += kvm.o kvm-all.o obj-$(CONFIG_NO_KVM) += kvm-stub.o @@ -232,7 +230,7 @@ obj-$(CONFIG_IVSHMEM) += ivshmem.o # Hardware support obj-i386-y += vga.o obj-i386-y += mc146818rtc.o i8259.o pc.o -obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o +obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o obj-i386-y += vmport.o obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o obj-i386-y += debugcon.o multiboot.o @@ -413,8 +411,6 @@ hmp-commands.h: $(SRC_PATH)/hmp-commands.hx qmp-commands.h: $(SRC_PATH)/qmp-commands.hx $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@") -9pfs/virtio-9p.o: CFLAGS += -I$(SRC_PATH)/hw/ - clean: rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c index 908c569a92..9a9c306a9c 100644 --- a/audio/audio_pt_int.c +++ b/audio/audio_pt_int.c @@ -6,8 +6,6 @@ #include "audio_int.h" #include "audio_pt_int.h" -#include <signal.h> - static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err, const char *fmt, ...) { diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index a847aa90f7..d24daa5ead 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -32,7 +32,6 @@ #elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) #include <pthread.h> #endif -#include <signal.h> #endif #define AUDIO_CAP "sdl" @@ -439,13 +439,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, bs->drv = drv; bs->opaque = qemu_mallocz(drv->instance_size); - /* - * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a - * write cache to the guest. We do need the fdatasync to flush - * out transactions for block allocations, and we maybe have a - * volatile write cache in our backing device to deal with. - */ - if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE)) + if (flags & BDRV_O_CACHE_WB) bs->enable_write_cache = 1; /* @@ -2887,7 +2881,7 @@ int bdrv_img_create(const char *filename, const char *fmt, char *options, uint64_t img_size, int flags) { QEMUOptionParameter *param = NULL, *create_options = NULL; - QEMUOptionParameter *backing_fmt, *backing_file; + QEMUOptionParameter *backing_fmt, *backing_file, *size; BlockDriverState *bs = NULL; BlockDriver *drv, *proto_drv; BlockDriver *backing_drv = NULL; @@ -2970,7 +2964,8 @@ int bdrv_img_create(const char *filename, const char *fmt, // The size for the image must always be specified, with one exception: // If we are using a backing file, we can obtain the size from there - if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) { + size = get_option_parameter(param, BLOCK_OPT_SIZE); + if (size && size->value.n == -1) { if (backing_file && backing_file->value.s) { uint64_t size; char buf[32]; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 750abe37d4..c9e7bbd9d6 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -70,7 +70,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size) ret = qcow2_cache_flush(bs, s->refcount_block_cache); if (ret < 0) { - return ret; + goto fail; } BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE); diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index d62dc1c091..ac95b88fe1 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1086,7 +1086,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res) ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, s->l1_table_offset, s->l1_size, 1); if (ret < 0) { - return ret; + goto fail; } /* snapshots */ @@ -1095,7 +1095,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res) ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, sn->l1_table_offset, sn->l1_size, 0); if (ret < 0) { - return ret; + goto fail; } } inc_refcounts(bs, res, refcount_table, nb_clusters, @@ -1159,8 +1159,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res) } } + ret = 0; + +fail: qemu_free(refcount_table); - return 0; + return ret; } diff --git a/block/qcow2.c b/block/qcow2.c index 75b8becc0a..8451ded9a3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -229,7 +229,7 @@ static int qcow2_open(BlockDriverState *bs, int flags) } /* alloc L2 table/refcount block cache */ - writethrough = ((flags & BDRV_O_CACHE_MASK) == 0); + writethrough = ((flags & BDRV_O_CACHE_WB) == 0); s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, writethrough); s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE, writethrough); @@ -1036,7 +1036,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options) const char *backing_fmt = NULL; uint64_t sectors = 0; int flags = 0; - size_t cluster_size = 65536; + size_t cluster_size = DEFAULT_CLUSTER_SIZE; int prealloc = 0; /* Read out options */ @@ -1343,7 +1343,8 @@ static QEMUOptionParameter qcow2_create_options[] = { { .name = BLOCK_OPT_CLUSTER_SIZE, .type = OPT_SIZE, - .help = "qcow2 cluster size" + .help = "qcow2 cluster size", + .value = { .n = DEFAULT_CLUSTER_SIZE }, }, { .name = BLOCK_OPT_PREALLOC, diff --git a/block/qcow2.h b/block/qcow2.h index a019831838..e1ae3e8c2b 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -54,6 +54,8 @@ /* Must be at least 4 to cover all cases of refcount table growth */ #define REFCOUNT_CACHE_SIZE 4 +#define DEFAULT_CLUSTER_SIZE 65536 + typedef struct QCowHeader { uint32_t magic; uint32_t version; diff --git a/block/qed.c b/block/qed.c index da0bf3127b..39703793e9 100644 --- a/block/qed.c +++ b/block/qed.c @@ -1464,7 +1464,8 @@ static QEMUOptionParameter qed_create_options[] = { }, { .name = BLOCK_OPT_CLUSTER_SIZE, .type = OPT_SIZE, - .help = "Cluster size (in bytes)" + .help = "Cluster size (in bytes)", + .value = { .n = QED_DEFAULT_CLUSTER_SIZE }, }, { .name = BLOCK_OPT_TABLE_SIZE, .type = OPT_SIZE, diff --git a/block/raw-posix.c b/block/raw-posix.c index 6b72470599..4cd7d7afbb 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -43,7 +43,6 @@ #ifdef __sun__ #define _POSIX_PTHREAD_SEMANTICS 1 -#include <signal.h> #include <sys/dkio.h> #endif #ifdef __linux__ @@ -53,7 +52,6 @@ #include <linux/fd.h> #endif #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) -#include <signal.h> #include <sys/disk.h> #include <sys/cdio.h> #endif @@ -64,6 +62,13 @@ #include <sys/dkio.h> #endif +#ifdef __NetBSD__ +#include <sys/ioctl.h> +#include <sys/disklabel.h> +#include <sys/dkio.h> +#include <sys/disk.h> +#endif + #ifdef __DragonFly__ #include <sys/ioctl.h> #include <sys/diskslice.h> @@ -136,12 +141,55 @@ static int64_t raw_getlength(BlockDriverState *bs); static int cdrom_reopen(BlockDriverState *bs); #endif +#if defined(__NetBSD__) +static int raw_normalize_devicepath(const char **filename) +{ + static char namebuf[PATH_MAX]; + const char *dp, *fname; + struct stat sb; + + fname = *filename; + dp = strrchr(fname, '/'); + if (lstat(fname, &sb) < 0) { + fprintf(stderr, "%s: stat failed: %s\n", + fname, strerror(errno)); + return -errno; + } + + if (!S_ISBLK(sb.st_mode)) { + return 0; + } + + if (dp == NULL) { + snprintf(namebuf, PATH_MAX, "r%s", fname); + } else { + snprintf(namebuf, PATH_MAX, "%.*s/r%s", + (int)(dp - fname), fname, dp + 1); + } + fprintf(stderr, "%s is a block device", fname); + *filename = namebuf; + fprintf(stderr, ", using %s\n", *filename); + + return 0; +} +#else +static int raw_normalize_devicepath(const char **filename) +{ + return 0; +} +#endif + static int raw_open_common(BlockDriverState *bs, const char *filename, int bdrv_flags, int open_flags) { BDRVRawState *s = bs->opaque; int fd, ret; + ret = raw_normalize_devicepath(&filename); + if (ret != 0) { + return ret; + } + s->open_flags = open_flags | O_BINARY; s->open_flags &= ~O_ACCMODE; if (bdrv_flags & BDRV_O_RDWR) { @@ -154,7 +202,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, * and O_DIRECT for no caching. */ if ((bdrv_flags & BDRV_O_NOCACHE)) s->open_flags |= O_DIRECT; - else if (!(bdrv_flags & BDRV_O_CACHE_WB)) + if (!(bdrv_flags & BDRV_O_CACHE_WB)) s->open_flags |= O_DSYNC; s->fd = -1; @@ -622,6 +670,31 @@ static int64_t raw_getlength(BlockDriverState *bs) } else return st.st_size; } +#elif defined(__NetBSD__) +static int64_t raw_getlength(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + int fd = s->fd; + struct stat st; + + if (fstat(fd, &st)) + return -1; + if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { + struct dkwedge_info dkw; + + if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) { + return dkw.dkw_size * 512; + } else { + struct disklabel dl; + + if (ioctl(fd, DIOCGDINFO, &dl)) + return -1; + return (uint64_t)dl.d_secsize * + dl.d_partitions[DISKPART(st.st_rdev)].p_size; + } + } else + return st.st_size; +} #elif defined(__sun__) static int64_t raw_getlength(BlockDriverState *bs) { diff --git a/block/raw-win32.c b/block/raw-win32.c index c204a80d79..56bd7195a1 100644 --- a/block/raw-win32.c +++ b/block/raw-win32.c @@ -88,9 +88,9 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags) } overlapped = FILE_ATTRIBUTE_NORMAL; - if ((flags & BDRV_O_NOCACHE)) - overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; - else if (!(flags & BDRV_O_CACHE_WB)) + if (flags & BDRV_O_NOCACHE) + overlapped |= FILE_FLAG_NO_BUFFERING; + if (!(flags & BDRV_O_CACHE_WB)) overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, @@ -349,9 +349,9 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) create_flags = OPEN_EXISTING; overlapped = FILE_ATTRIBUTE_NORMAL; - if ((flags & BDRV_O_NOCACHE)) - overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; - else if (!(flags & BDRV_O_CACHE_WB)) + if (flags & BDRV_O_NOCACHE) + overlapped |= FILE_FLAG_NO_BUFFERING; + if (!(flags & BDRV_O_CACHE_WB)) overlapped |= FILE_FLAG_WRITE_THROUGH; s->hfile = CreateFile(filename, access_flags, FILE_SHARE_READ, NULL, diff --git a/block/rbd.c b/block/rbd.c index 249a590c98..bdc448aa9f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -1,33 +1,39 @@ /* * QEMU Block driver for RADOS (Ceph) * - * Copyright (C) 2010 Christian Brunner <chb@muc.de> + * Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>, + * Josh Durgin <josh.durgin@dreamhost.com> * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. * */ +#include <inttypes.h> + #include "qemu-common.h" #include "qemu-error.h" -#include "rbd_types.h" #include "block_int.h" -#include <rados/librados.h> +#include <rbd/librbd.h> /* * When specifying the image filename use: * - * rbd:poolname/devicename + * rbd:poolname/devicename[@snapshotname][:option1=value1[:option2=value2...]] * * poolname must be the name of an existing rados pool * * devicename is the basename for all objects used to * emulate the raw device. * + * Each option given is used to configure rados, and may be + * any Ceph option, or "conf". The "conf" option specifies + * a Ceph configuration file to read. + * * Metadata information (image size, ...) is stored in an * object with the name "devicename.rbd". * @@ -40,6 +46,13 @@ #define OBJ_MAX_SIZE (1UL << OBJ_DEFAULT_OBJ_ORDER) +#define RBD_MAX_CONF_NAME_SIZE 128 +#define RBD_MAX_CONF_VAL_SIZE 512 +#define RBD_MAX_CONF_SIZE 1024 +#define RBD_MAX_POOL_NAME_SIZE 128 +#define RBD_MAX_SNAP_NAME_SIZE 128 +#define RBD_MAX_SNAPS 100 + typedef struct RBDAIOCB { BlockDriverAIOCB common; QEMUBH *bh; @@ -48,7 +61,6 @@ typedef struct RBDAIOCB { char *bounce; int write; int64_t sector_num; - int aiocnt; int error; struct BDRVRBDState *s; int cancelled; @@ -59,7 +71,7 @@ typedef struct RADOSCB { RBDAIOCB *acb; struct BDRVRBDState *s; int done; - int64_t segsize; + int64_t size; char *buf; int ret; } RADOSCB; @@ -69,25 +81,22 @@ typedef struct RADOSCB { typedef struct BDRVRBDState { int fds[2]; - rados_pool_t pool; - rados_pool_t header_pool; - char name[RBD_MAX_OBJ_NAME_SIZE]; - char block_name[RBD_MAX_BLOCK_NAME_SIZE]; - uint64_t size; - uint64_t objsize; + rados_t cluster; + rados_ioctx_t io_ctx; + rbd_image_t image; + char name[RBD_MAX_IMAGE_NAME_SIZE]; int qemu_aio_count; + char *snap; int event_reader_pos; RADOSCB *event_rcb; } BDRVRBDState; -typedef struct rbd_obj_header_ondisk RbdHeader1; - static void rbd_aio_bh_cb(void *opaque); -static int rbd_next_tok(char *dst, int dst_len, - char *src, char delim, - const char *name, - char **p) +static int qemu_rbd_next_tok(char *dst, int dst_len, + char *src, char delim, + const char *name, + char **p) { int l; char *end; @@ -115,10 +124,11 @@ static int rbd_next_tok(char *dst, int dst_len, return 0; } -static int rbd_parsename(const char *filename, - char *pool, int pool_len, - char *snap, int snap_len, - char *name, int name_len) +static int qemu_rbd_parsename(const char *filename, + char *pool, int pool_len, + char *snap, int snap_len, + char *name, int name_len, + char *conf, int conf_len) { const char *start; char *p, *buf; @@ -130,138 +140,108 @@ static int rbd_parsename(const char *filename, buf = qemu_strdup(start); p = buf; + *snap = '\0'; + *conf = '\0'; - ret = rbd_next_tok(pool, pool_len, p, '/', "pool name", &p); + ret = qemu_rbd_next_tok(pool, pool_len, p, '/', "pool name", &p); if (ret < 0 || !p) { ret = -EINVAL; goto done; } - ret = rbd_next_tok(name, name_len, p, '@', "object name", &p); - if (ret < 0) { - goto done; + + if (strchr(p, '@')) { + ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p); + if (ret < 0) { + goto done; + } + ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p); + } else { + ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p); } - if (!p) { - *snap = '\0'; + if (ret < 0 || !p) { goto done; } - ret = rbd_next_tok(snap, snap_len, p, '\0', "snap name", &p); + ret = qemu_rbd_next_tok(conf, conf_len, p, '\0', "configuration", &p); done: qemu_free(buf); return ret; } -static int create_tmap_op(uint8_t op, const char *name, char **tmap_desc) -{ - uint32_t len = strlen(name); - uint32_t len_le = cpu_to_le32(len); - /* total_len = encoding op + name + empty buffer */ - uint32_t total_len = 1 + (sizeof(uint32_t) + len) + sizeof(uint32_t); - uint8_t *desc = NULL; - - desc = qemu_malloc(total_len); - - *tmap_desc = (char *)desc; - - *desc = op; - desc++; - memcpy(desc, &len_le, sizeof(len_le)); - desc += sizeof(len_le); - memcpy(desc, name, len); - desc += len; - len = 0; /* no need for endian conversion for 0 */ - memcpy(desc, &len, sizeof(len)); - desc += sizeof(len); - - return (char *)desc - *tmap_desc; -} - -static void free_tmap_op(char *tmap_desc) +static int qemu_rbd_set_conf(rados_t cluster, const char *conf) { - qemu_free(tmap_desc); -} - -static int rbd_register_image(rados_pool_t pool, const char *name) -{ - char *tmap_desc; - const char *dir = RBD_DIRECTORY; - int ret; - - ret = create_tmap_op(CEPH_OSD_TMAP_SET, name, &tmap_desc); - if (ret < 0) { - return ret; - } - - ret = rados_tmap_update(pool, dir, tmap_desc, ret); - free_tmap_op(tmap_desc); - - return ret; -} + char *p, *buf; + char name[RBD_MAX_CONF_NAME_SIZE]; + char value[RBD_MAX_CONF_VAL_SIZE]; + int ret = 0; -static int touch_rbd_info(rados_pool_t pool, const char *info_oid) -{ - int r = rados_write(pool, info_oid, 0, NULL, 0); - if (r < 0) { - return r; - } - return 0; -} + buf = qemu_strdup(conf); + p = buf; -static int rbd_assign_bid(rados_pool_t pool, uint64_t *id) -{ - uint64_t out[1]; - const char *info_oid = RBD_INFO; + while (p) { + ret = qemu_rbd_next_tok(name, sizeof(name), p, + '=', "conf option name", &p); + if (ret < 0) { + break; + } - *id = 0; + if (!p) { + error_report("conf option %s has no value", name); + ret = -EINVAL; + break; + } - int r = touch_rbd_info(pool, info_oid); - if (r < 0) { - return r; - } + ret = qemu_rbd_next_tok(value, sizeof(value), p, + ':', "conf option value", &p); + if (ret < 0) { + break; + } - r = rados_exec(pool, info_oid, "rbd", "assign_bid", NULL, - 0, (char *)out, sizeof(out)); - if (r < 0) { - return r; + if (strcmp(name, "conf")) { + ret = rados_conf_set(cluster, name, value); + if (ret < 0) { + error_report("invalid conf option %s", name); + ret = -EINVAL; + break; + } + } else { + ret = rados_conf_read_file(cluster, value); + if (ret < 0) { + error_report("error reading conf file %s", value); + break; + } + } } - le64_to_cpus(out); - *id = out[0]; - - return 0; + qemu_free(buf); + return ret; } -static int rbd_create(const char *filename, QEMUOptionParameter *options) +static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) { int64_t bytes = 0; int64_t objsize; - uint64_t size; - time_t mtime; - uint8_t obj_order = RBD_DEFAULT_OBJ_ORDER; - char pool[RBD_MAX_SEG_NAME_SIZE]; - char n[RBD_MAX_SEG_NAME_SIZE]; - char name[RBD_MAX_OBJ_NAME_SIZE]; - char snap_buf[RBD_MAX_SEG_NAME_SIZE]; + int obj_order = 0; + char pool[RBD_MAX_POOL_NAME_SIZE]; + char name[RBD_MAX_IMAGE_NAME_SIZE]; + char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; + char conf[RBD_MAX_CONF_SIZE]; char *snap = NULL; - RbdHeader1 header; - rados_pool_t p; - uint64_t bid; - uint32_t hi, lo; + rados_t cluster; + rados_ioctx_t io_ctx; int ret; - if (rbd_parsename(filename, - pool, sizeof(pool), - snap_buf, sizeof(snap_buf), - name, sizeof(name)) < 0) { + if (qemu_rbd_parsename(filename, pool, sizeof(pool), + snap_buf, sizeof(snap_buf), + name, sizeof(name), + conf, sizeof(conf)) < 0) { return -EINVAL; } if (snap_buf[0] != '\0') { snap = snap_buf; } - snprintf(n, sizeof(n), "%s%s", name, RBD_SUFFIX); - /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { @@ -277,82 +257,64 @@ static int rbd_create(const char *filename, QEMUOptionParameter *options) error_report("obj size too small"); return -EINVAL; } - obj_order = ffs(objsize) - 1; + obj_order = ffs(objsize) - 1; } } options++; } - memset(&header, 0, sizeof(header)); - pstrcpy(header.text, sizeof(header.text), RBD_HEADER_TEXT); - pstrcpy(header.signature, sizeof(header.signature), RBD_HEADER_SIGNATURE); - pstrcpy(header.version, sizeof(header.version), RBD_HEADER_VERSION); - header.image_size = cpu_to_le64(bytes); - header.options.order = obj_order; - header.options.crypt_type = RBD_CRYPT_NONE; - header.options.comp_type = RBD_COMP_NONE; - header.snap_seq = 0; - header.snap_count = 0; - - if (rados_initialize(0, NULL) < 0) { + if (rados_create(&cluster, NULL) < 0) { error_report("error initializing"); return -EIO; } - if (rados_open_pool(pool, &p)) { - error_report("error opening pool %s", pool); - rados_deinitialize(); - return -EIO; + if (strstr(conf, "conf=") == NULL) { + if (rados_conf_read_file(cluster, NULL) < 0) { + error_report("error reading config file"); + rados_shutdown(cluster); + return -EIO; + } } - /* check for existing rbd header file */ - ret = rados_stat(p, n, &size, &mtime); - if (ret == 0) { - ret=-EEXIST; - goto done; + if (conf[0] != '\0' && + qemu_rbd_set_conf(cluster, conf) < 0) { + error_report("error setting config options"); + rados_shutdown(cluster); + return -EIO; } - ret = rbd_assign_bid(p, &bid); - if (ret < 0) { - error_report("failed assigning block id"); - rados_deinitialize(); + if (rados_connect(cluster) < 0) { + error_report("error connecting"); + rados_shutdown(cluster); return -EIO; } - hi = bid >> 32; - lo = bid & 0xFFFFFFFF; - snprintf(header.block_name, sizeof(header.block_name), "rb.%x.%x", hi, lo); - /* create header file */ - ret = rados_write(p, n, 0, (const char *)&header, sizeof(header)); - if (ret < 0) { - goto done; + if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) { + error_report("error opening pool %s", pool); + rados_shutdown(cluster); + return -EIO; } - ret = rbd_register_image(p, name); -done: - rados_close_pool(p); - rados_deinitialize(); + ret = rbd_create(io_ctx, name, bytes, &obj_order); + rados_ioctx_destroy(io_ctx); + rados_shutdown(cluster); return ret; } /* - * This aio completion is being called from rbd_aio_event_reader() and - * runs in qemu context. It schedules a bh, but just in case the aio + * This aio completion is being called from qemu_rbd_aio_event_reader() + * and runs in qemu context. It schedules a bh, but just in case the aio * was not cancelled before. */ -static void rbd_complete_aio(RADOSCB *rcb) +static void qemu_rbd_complete_aio(RADOSCB *rcb) { RBDAIOCB *acb = rcb->acb; int64_t r; - acb->aiocnt--; - if (acb->cancelled) { - if (!acb->aiocnt) { - qemu_vfree(acb->bounce); - qemu_aio_release(acb); - } + qemu_vfree(acb->bounce); + qemu_aio_release(acb); goto done; } @@ -363,32 +325,25 @@ static void rbd_complete_aio(RADOSCB *rcb) acb->ret = r; acb->error = 1; } else if (!acb->error) { - acb->ret += rcb->segsize; + acb->ret = rcb->size; } } else { - if (r == -ENOENT) { - memset(rcb->buf, 0, rcb->segsize); - if (!acb->error) { - acb->ret += rcb->segsize; - } - } else if (r < 0) { - memset(rcb->buf, 0, rcb->segsize); + if (r < 0) { + memset(rcb->buf, 0, rcb->size); acb->ret = r; acb->error = 1; - } else if (r < rcb->segsize) { - memset(rcb->buf + r, 0, rcb->segsize - r); + } else if (r < rcb->size) { + memset(rcb->buf + r, 0, rcb->size - r); if (!acb->error) { - acb->ret += rcb->segsize; + acb->ret = rcb->size; } } else if (!acb->error) { - acb->ret += r; + acb->ret = r; } } /* Note that acb->bh can be NULL in case where the aio was cancelled */ - if (!acb->aiocnt) { - acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb); - qemu_bh_schedule(acb->bh); - } + acb->bh = qemu_bh_new(rbd_aio_bh_cb, acb); + qemu_bh_schedule(acb->bh); done: qemu_free(rcb); } @@ -397,7 +352,7 @@ done: * aio fd read handler. It runs in the qemu context and calls the * completion handling of completed rados aio operations. */ -static void rbd_aio_event_reader(void *opaque) +static void qemu_rbd_aio_event_reader(void *opaque) { BDRVRBDState *s = opaque; @@ -413,176 +368,87 @@ static void rbd_aio_event_reader(void *opaque) s->event_reader_pos += ret; if (s->event_reader_pos == sizeof(s->event_rcb)) { s->event_reader_pos = 0; - rbd_complete_aio(s->event_rcb); - s->qemu_aio_count --; + qemu_rbd_complete_aio(s->event_rcb); + s->qemu_aio_count--; } } } } while (ret < 0 && errno == EINTR); } -static int rbd_aio_flush_cb(void *opaque) +static int qemu_rbd_aio_flush_cb(void *opaque) { BDRVRBDState *s = opaque; return (s->qemu_aio_count > 0); } - -static int rbd_set_snapc(rados_pool_t pool, const char *snap, RbdHeader1 *header) -{ - uint32_t snap_count = le32_to_cpu(header->snap_count); - rados_snap_t *snaps = NULL; - rados_snap_t seq; - uint32_t i; - uint64_t snap_names_len = le64_to_cpu(header->snap_names_len); - int r; - rados_snap_t snapid = 0; - - if (snap_count) { - const char *header_snap = (const char *)&header->snaps[snap_count]; - const char *end = header_snap + snap_names_len; - snaps = qemu_malloc(sizeof(rados_snap_t) * header->snap_count); - - for (i=0; i < snap_count; i++) { - snaps[i] = le64_to_cpu(header->snaps[i].id); - - if (snap && strcmp(snap, header_snap) == 0) { - snapid = snaps[i]; - } - - header_snap += strlen(header_snap) + 1; - if (header_snap > end) { - error_report("bad header, snapshot list broken"); - } - } - } - - if (snap && !snapid) { - error_report("snapshot not found"); - qemu_free(snaps); - return -ENOENT; - } - seq = le32_to_cpu(header->snap_seq); - - r = rados_set_snap_context(pool, seq, snaps, snap_count); - - rados_set_snap(pool, snapid); - - qemu_free(snaps); - - return r; -} - -#define BUF_READ_START_LEN 4096 - -static int rbd_read_header(BDRVRBDState *s, char **hbuf) -{ - char *buf = NULL; - char n[RBD_MAX_SEG_NAME_SIZE]; - uint64_t len = BUF_READ_START_LEN; - int r; - - snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX); - - buf = qemu_malloc(len); - - r = rados_read(s->header_pool, n, 0, buf, len); - if (r < 0) { - goto failed; - } - - if (r < len) { - goto done; - } - - qemu_free(buf); - buf = qemu_malloc(len); - - r = rados_stat(s->header_pool, n, &len, NULL); - if (r < 0) { - goto failed; - } - - r = rados_read(s->header_pool, n, 0, buf, len); - if (r < 0) { - goto failed; - } - -done: - *hbuf = buf; - return 0; - -failed: - qemu_free(buf); - return r; -} - -static int rbd_open(BlockDriverState *bs, const char *filename, int flags) +static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; - RbdHeader1 *header; - char pool[RBD_MAX_SEG_NAME_SIZE]; - char snap_buf[RBD_MAX_SEG_NAME_SIZE]; - char *snap = NULL; - char *hbuf = NULL; + char pool[RBD_MAX_POOL_NAME_SIZE]; + char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; + char conf[RBD_MAX_CONF_SIZE]; int r; - if (rbd_parsename(filename, pool, sizeof(pool), - snap_buf, sizeof(snap_buf), - s->name, sizeof(s->name)) < 0) { + if (qemu_rbd_parsename(filename, pool, sizeof(pool), + snap_buf, sizeof(snap_buf), + s->name, sizeof(s->name), + conf, sizeof(conf)) < 0) { return -EINVAL; } + s->snap = NULL; if (snap_buf[0] != '\0') { - snap = snap_buf; + s->snap = qemu_strdup(snap_buf); } - if ((r = rados_initialize(0, NULL)) < 0) { + r = rados_create(&s->cluster, NULL); + if (r < 0) { error_report("error initializing"); return r; } - if ((r = rados_open_pool(pool, &s->pool))) { - error_report("error opening pool %s", pool); - rados_deinitialize(); - return r; - } - - if ((r = rados_open_pool(pool, &s->header_pool))) { - error_report("error opening pool %s", pool); - rados_deinitialize(); - return r; + if (strstr(conf, "conf=") == NULL) { + r = rados_conf_read_file(s->cluster, NULL); + if (r < 0) { + error_report("error reading config file"); + rados_shutdown(s->cluster); + return r; + } } - if ((r = rbd_read_header(s, &hbuf)) < 0) { - error_report("error reading header from %s", s->name); - goto failed; + if (conf[0] != '\0') { + r = qemu_rbd_set_conf(s->cluster, conf); + if (r < 0) { + error_report("error setting config options"); + rados_shutdown(s->cluster); + return r; + } } - if (memcmp(hbuf + 64, RBD_HEADER_SIGNATURE, 4)) { - error_report("Invalid header signature"); - r = -EMEDIUMTYPE; - goto failed; + r = rados_connect(s->cluster); + if (r < 0) { + error_report("error connecting"); + rados_shutdown(s->cluster); + return r; } - if (memcmp(hbuf + 68, RBD_HEADER_VERSION, 8)) { - error_report("Unknown image version"); - r = -EMEDIUMTYPE; - goto failed; + r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); + if (r < 0) { + error_report("error opening pool %s", pool); + rados_shutdown(s->cluster); + return r; } - header = (RbdHeader1 *) hbuf; - s->size = le64_to_cpu(header->image_size); - s->objsize = 1ULL << header->options.order; - memcpy(s->block_name, header->block_name, sizeof(header->block_name)); - - r = rbd_set_snapc(s->pool, snap, header); + r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { - error_report("failed setting snap context: %s", strerror(-r)); - goto failed; + error_report("error reading header from %s", s->name); + rados_ioctx_destroy(s->io_ctx); + rados_shutdown(s->cluster); + return r; } - bs->read_only = (snap != NULL); + bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); @@ -592,23 +458,20 @@ static int rbd_open(BlockDriverState *bs, const char *filename, int flags) } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); - qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], rbd_aio_event_reader, NULL, - rbd_aio_flush_cb, NULL, s); + qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, + NULL, qemu_rbd_aio_flush_cb, NULL, s); - qemu_free(hbuf); return 0; failed: - qemu_free(hbuf); - - rados_close_pool(s->header_pool); - rados_close_pool(s->pool); - rados_deinitialize(); + rbd_close(s->image); + rados_ioctx_destroy(s->io_ctx); + rados_shutdown(s->cluster); return r; } -static void rbd_close(BlockDriverState *bs) +static void qemu_rbd_close(BlockDriverState *bs) { BDRVRBDState *s = bs->opaque; @@ -617,16 +480,17 @@ static void rbd_close(BlockDriverState *bs) qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL , NULL, NULL, NULL, NULL); - rados_close_pool(s->header_pool); - rados_close_pool(s->pool); - rados_deinitialize(); + rbd_close(s->image); + rados_ioctx_destroy(s->io_ctx); + qemu_free(s->snap); + rados_shutdown(s->cluster); } /* * Cancel aio. Since we don't reference acb in a non qemu threads, * it is safe to access it here. */ -static void rbd_aio_cancel(BlockDriverAIOCB *blockacb) +static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb) { RBDAIOCB *acb = (RBDAIOCB *) blockacb; acb->cancelled = 1; @@ -634,39 +498,28 @@ static void rbd_aio_cancel(BlockDriverAIOCB *blockacb) static AIOPool rbd_aio_pool = { .aiocb_size = sizeof(RBDAIOCB), - .cancel = rbd_aio_cancel, + .cancel = qemu_rbd_aio_cancel, }; -/* - * This is the callback function for rados_aio_read and _write - * - * Note: this function is being called from a non qemu thread so - * we need to be careful about what we do here. Generally we only - * write to the block notification pipe, and do the rest of the - * io completion handling from rbd_aio_event_reader() which - * runs in a qemu context. - */ -static void rbd_finish_aiocb(rados_completion_t c, RADOSCB *rcb) +static int qemu_rbd_send_pipe(BDRVRBDState *s, RADOSCB *rcb) { - int ret; - rcb->ret = rados_aio_get_return_value(c); - rados_aio_release(c); + int ret = 0; while (1) { fd_set wfd; - int fd = rcb->s->fds[RBD_FD_WRITE]; + int fd = s->fds[RBD_FD_WRITE]; - /* send the rcb pointer to the qemu thread that is responsible - for the aio completion. Must do it in a qemu thread context */ + /* send the op pointer to the qemu thread that is responsible + for the aio/op completion. Must do it in a qemu thread context */ ret = write(fd, (void *)&rcb, sizeof(rcb)); if (ret >= 0) { break; } if (errno == EINTR) { continue; - } + } if (errno != EAGAIN) { break; - } + } FD_ZERO(&wfd); FD_SET(fd, &wfd); @@ -675,13 +528,31 @@ static void rbd_finish_aiocb(rados_completion_t c, RADOSCB *rcb) } while (ret < 0 && errno == EINTR); } + return ret; +} + +/* + * This is the callback function for rbd_aio_read and _write + * + * Note: this function is being called from a non qemu thread so + * we need to be careful about what we do here. Generally we only + * write to the block notification pipe, and do the rest of the + * io completion handling from qemu_rbd_aio_event_reader() which + * runs in a qemu context. + */ +static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb) +{ + int ret; + rcb->ret = rbd_aio_get_return_value(c); + rbd_aio_release(c); + ret = qemu_rbd_send_pipe(rcb->s, rcb); if (ret < 0) { - error_report("failed writing to acb->s->fds\n"); + error_report("failed writing to acb->s->fds"); qemu_free(rcb); } } -/* Callback when all queued rados_aio requests are complete */ +/* Callback when all queued rbd_aio requests are complete */ static void rbd_aio_bh_cb(void *opaque) { @@ -707,19 +578,20 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs, { RBDAIOCB *acb; RADOSCB *rcb; - rados_completion_t c; - char n[RBD_MAX_SEG_NAME_SIZE]; - int64_t segnr, segoffs, segsize, last_segnr; + rbd_completion_t c; int64_t off, size; char *buf; + int r; BDRVRBDState *s = bs->opaque; acb = qemu_aio_get(&rbd_aio_pool, bs, cb, opaque); + if (!acb) { + return NULL; + } acb->write = write; acb->qiov = qiov; acb->bounce = qemu_blockalign(bs, qiov->size); - acb->aiocnt = 0; acb->ret = 0; acb->error = 0; acb->s = s; @@ -734,95 +606,106 @@ static BlockDriverAIOCB *rbd_aio_rw_vector(BlockDriverState *bs, off = sector_num * BDRV_SECTOR_SIZE; size = nb_sectors * BDRV_SECTOR_SIZE; - segnr = off / s->objsize; - segoffs = off % s->objsize; - segsize = s->objsize - segoffs; - - last_segnr = ((off + size - 1) / s->objsize); - acb->aiocnt = (last_segnr - segnr) + 1; - s->qemu_aio_count += acb->aiocnt; /* All the RADOSCB */ + s->qemu_aio_count++; /* All the RADOSCB */ - while (size > 0) { - if (size < segsize) { - segsize = size; - } + rcb = qemu_malloc(sizeof(RADOSCB)); + rcb->done = 0; + rcb->acb = acb; + rcb->buf = buf; + rcb->s = acb->s; + rcb->size = size; + r = rbd_aio_create_completion(rcb, (rbd_callback_t) rbd_finish_aiocb, &c); + if (r < 0) { + goto failed; + } - snprintf(n, sizeof(n), "%s.%012" PRIx64, s->block_name, - segnr); - - rcb = qemu_malloc(sizeof(RADOSCB)); - rcb->done = 0; - rcb->acb = acb; - rcb->segsize = segsize; - rcb->buf = buf; - rcb->s = acb->s; - - if (write) { - rados_aio_create_completion(rcb, NULL, - (rados_callback_t) rbd_finish_aiocb, - &c); - rados_aio_write(s->pool, n, segoffs, buf, segsize, c); - } else { - rados_aio_create_completion(rcb, - (rados_callback_t) rbd_finish_aiocb, - NULL, &c); - rados_aio_read(s->pool, n, segoffs, buf, segsize, c); - } + if (write) { + r = rbd_aio_write(s->image, off, size, buf, c); + } else { + r = rbd_aio_read(s->image, off, size, buf, c); + } - buf += segsize; - size -= segsize; - segoffs = 0; - segsize = s->objsize; - segnr++; + if (r < 0) { + goto failed; } return &acb->common; + +failed: + qemu_free(rcb); + s->qemu_aio_count--; + qemu_aio_release(acb); + return NULL; } -static BlockDriverAIOCB *rbd_aio_readv(BlockDriverState * bs, - int64_t sector_num, QEMUIOVector * qiov, - int nb_sectors, - BlockDriverCompletionFunc * cb, - void *opaque) +static BlockDriverAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque) { return rbd_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0); } -static BlockDriverAIOCB *rbd_aio_writev(BlockDriverState * bs, - int64_t sector_num, QEMUIOVector * qiov, - int nb_sectors, - BlockDriverCompletionFunc * cb, - void *opaque) +static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, + int nb_sectors, + BlockDriverCompletionFunc *cb, + void *opaque) { return rbd_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1); } -static int rbd_getinfo(BlockDriverState * bs, BlockDriverInfo * bdi) +static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVRBDState *s = bs->opaque; - bdi->cluster_size = s->objsize; + rbd_image_info_t info; + int r; + + r = rbd_stat(s->image, &info, sizeof(info)); + if (r < 0) { + return r; + } + + bdi->cluster_size = info.obj_size; return 0; } -static int64_t rbd_getlength(BlockDriverState * bs) +static int64_t qemu_rbd_getlength(BlockDriverState *bs) +{ + BDRVRBDState *s = bs->opaque; + rbd_image_info_t info; + int r; + + r = rbd_stat(s->image, &info, sizeof(info)); + if (r < 0) { + return r; + } + + return info.size; +} + +static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset) { BDRVRBDState *s = bs->opaque; + int r; - return s->size; + r = rbd_resize(s->image, offset); + if (r < 0) { + return r; + } + + return 0; } -static int rbd_snap_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) +static int qemu_rbd_snap_create(BlockDriverState *bs, + QEMUSnapshotInfo *sn_info) { BDRVRBDState *s = bs->opaque; - char inbuf[512], outbuf[128]; - uint64_t snap_id; int r; - char *p = inbuf; - char *end = inbuf + sizeof(inbuf); - char n[RBD_MAX_SEG_NAME_SIZE]; - char *hbuf = NULL; - RbdHeader1 *header; if (sn_info->name[0] == '\0') { return -EINVAL; /* we need a name for rbd snapshots */ @@ -841,185 +724,57 @@ static int rbd_snap_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) return -ERANGE; } - r = rados_selfmanaged_snap_create(s->header_pool, &snap_id); - if (r < 0) { - error_report("failed to create snap id: %s", strerror(-r)); - return r; - } - - *(uint32_t *)p = strlen(sn_info->name); - cpu_to_le32s((uint32_t *)p); - p += sizeof(uint32_t); - strncpy(p, sn_info->name, end - p); - p += strlen(p); - if (p + sizeof(snap_id) > end) { - error_report("invalid input parameter"); - return -EINVAL; - } - - *(uint64_t *)p = snap_id; - cpu_to_le64s((uint64_t *)p); - - snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX); - - r = rados_exec(s->header_pool, n, "rbd", "snap_add", inbuf, - sizeof(inbuf), outbuf, sizeof(outbuf)); - if (r < 0) { - error_report("rbd.snap_add execution failed failed: %s", strerror(-r)); - return r; - } - - sprintf(sn_info->id_str, "%s", sn_info->name); - - r = rbd_read_header(s, &hbuf); + r = rbd_snap_create(s->image, sn_info->name); if (r < 0) { - error_report("failed reading header: %s", strerror(-r)); + error_report("failed to create snap: %s", strerror(-r)); return r; } - header = (RbdHeader1 *) hbuf; - r = rbd_set_snapc(s->pool, sn_info->name, header); - if (r < 0) { - error_report("failed setting snap context: %s", strerror(-r)); - goto failed; - } - return 0; - -failed: - qemu_free(header); - return r; } -static int decode32(char **p, const char *end, uint32_t *v) -{ - if (*p + 4 > end) { - return -ERANGE; - } - - *v = *(uint32_t *)(*p); - le32_to_cpus(v); - *p += 4; - return 0; -} - -static int decode64(char **p, const char *end, uint64_t *v) -{ - if (*p + 8 > end) { - return -ERANGE; - } - - *v = *(uint64_t *)(*p); - le64_to_cpus(v); - *p += 8; - return 0; -} - -static int decode_str(char **p, const char *end, char **s) -{ - uint32_t len; - int r; - - if ((r = decode32(p, end, &len)) < 0) { - return r; - } - - *s = qemu_malloc(len + 1); - memcpy(*s, *p, len); - *p += len; - (*s)[len] = '\0'; - - return len; -} - -static int rbd_snap_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) +static int qemu_rbd_snap_list(BlockDriverState *bs, + QEMUSnapshotInfo **psn_tab) { BDRVRBDState *s = bs->opaque; - char n[RBD_MAX_SEG_NAME_SIZE]; QEMUSnapshotInfo *sn_info, *sn_tab = NULL; - RbdHeader1 *header; - char *hbuf = NULL; - char *outbuf = NULL, *end, *buf; - uint64_t len; - uint64_t snap_seq; - uint32_t snap_count; - int r, i; - - /* read header to estimate how much space we need to read the snap - * list */ - if ((r = rbd_read_header(s, &hbuf)) < 0) { - goto done_err; - } - header = (RbdHeader1 *)hbuf; - len = le64_to_cpu(header->snap_names_len); - len += 1024; /* should have already been enough, but new snapshots might - already been created since we read the header. just allocate - a bit more, so that in most cases it'll suffice anyway */ - qemu_free(hbuf); - - snprintf(n, sizeof(n), "%s%s", s->name, RBD_SUFFIX); - while (1) { - qemu_free(outbuf); - outbuf = qemu_malloc(len); + int i, snap_count; + rbd_snap_info_t *snaps; + int max_snaps = RBD_MAX_SNAPS; - r = rados_exec(s->header_pool, n, "rbd", "snap_list", NULL, 0, - outbuf, len); - if (r < 0) { - error_report("rbd.snap_list execution failed failed: %s", strerror(-r)); - goto done_err; + do { + snaps = qemu_malloc(sizeof(*snaps) * max_snaps); + snap_count = rbd_snap_list(s->image, snaps, &max_snaps); + if (snap_count < 0) { + qemu_free(snaps); } - if (r != len) { - break; - } - - /* if we're here, we probably raced with some snaps creation */ - len *= 2; - } - buf = outbuf; - end = buf + len; + } while (snap_count == -ERANGE); - if ((r = decode64(&buf, end, &snap_seq)) < 0) { - goto done_err; - } - if ((r = decode32(&buf, end, &snap_count)) < 0) { - goto done_err; + if (snap_count <= 0) { + return snap_count; } sn_tab = qemu_mallocz(snap_count * sizeof(QEMUSnapshotInfo)); - for (i = 0; i < snap_count; i++) { - uint64_t id, image_size; - char *snap_name; - if ((r = decode64(&buf, end, &id)) < 0) { - goto done_err; - } - if ((r = decode64(&buf, end, &image_size)) < 0) { - goto done_err; - } - if ((r = decode_str(&buf, end, &snap_name)) < 0) { - goto done_err; - } + for (i = 0; i < snap_count; i++) { + const char *snap_name = snaps[i].name; sn_info = sn_tab + i; pstrcpy(sn_info->id_str, sizeof(sn_info->id_str), snap_name); pstrcpy(sn_info->name, sizeof(sn_info->name), snap_name); - qemu_free(snap_name); - sn_info->vm_state_size = image_size; + sn_info->vm_state_size = snaps[i].size; sn_info->date_sec = 0; sn_info->date_nsec = 0; sn_info->vm_clock_nsec = 0; } + rbd_snap_list_end(snaps); + *psn_tab = sn_tab; - qemu_free(outbuf); return snap_count; -done_err: - qemu_free(sn_tab); - qemu_free(outbuf); - return r; } -static QEMUOptionParameter rbd_create_options[] = { +static QEMUOptionParameter qemu_rbd_create_options[] = { { .name = BLOCK_OPT_SIZE, .type = OPT_SIZE, @@ -1036,19 +791,20 @@ static QEMUOptionParameter rbd_create_options[] = { static BlockDriver bdrv_rbd = { .format_name = "rbd", .instance_size = sizeof(BDRVRBDState), - .bdrv_file_open = rbd_open, - .bdrv_close = rbd_close, - .bdrv_create = rbd_create, - .bdrv_get_info = rbd_getinfo, - .create_options = rbd_create_options, - .bdrv_getlength = rbd_getlength, + .bdrv_file_open = qemu_rbd_open, + .bdrv_close = qemu_rbd_close, + .bdrv_create = qemu_rbd_create, + .bdrv_get_info = qemu_rbd_getinfo, + .create_options = qemu_rbd_create_options, + .bdrv_getlength = qemu_rbd_getlength, + .bdrv_truncate = qemu_rbd_truncate, .protocol_name = "rbd", - .bdrv_aio_readv = rbd_aio_readv, - .bdrv_aio_writev = rbd_aio_writev, + .bdrv_aio_readv = qemu_rbd_aio_readv, + .bdrv_aio_writev = qemu_rbd_aio_writev, - .bdrv_snapshot_create = rbd_snap_create, - .bdrv_snapshot_list = rbd_snap_list, + .bdrv_snapshot_create = qemu_rbd_snap_create, + .bdrv_snapshot_list = qemu_rbd_snap_list, }; static void bdrv_rbd_init(void) diff --git a/block/rbd_types.h b/block/rbd_types.h deleted file mode 100644 index f4cca9970c..0000000000 --- a/block/rbd_types.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net> - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING.LIB. - * - */ - -#ifndef CEPH_RBD_TYPES_H -#define CEPH_RBD_TYPES_H - - -/* - * rbd image 'foo' consists of objects - * foo.rbd - image metadata - * foo.00000000 - * foo.00000001 - * ... - data - */ - -#define RBD_SUFFIX ".rbd" -#define RBD_DIRECTORY "rbd_directory" -#define RBD_INFO "rbd_info" - -#define RBD_DEFAULT_OBJ_ORDER 22 /* 4MB */ - -#define RBD_MAX_OBJ_NAME_SIZE 96 -#define RBD_MAX_BLOCK_NAME_SIZE 24 -#define RBD_MAX_SEG_NAME_SIZE 128 - -#define RBD_COMP_NONE 0 -#define RBD_CRYPT_NONE 0 - -#define RBD_HEADER_TEXT "<<< Rados Block Device Image >>>\n" -#define RBD_HEADER_SIGNATURE "RBD" -#define RBD_HEADER_VERSION "001.005" - -struct rbd_info { - uint64_t max_id; -} __attribute__ ((packed)); - -struct rbd_obj_snap_ondisk { - uint64_t id; - uint64_t image_size; -} __attribute__((packed)); - -struct rbd_obj_header_ondisk { - char text[40]; - char block_name[RBD_MAX_BLOCK_NAME_SIZE]; - char signature[4]; - char version[8]; - struct { - uint8_t order; - uint8_t crypt_type; - uint8_t comp_type; - uint8_t unused; - } __attribute__((packed)) options; - uint64_t image_size; - uint64_t snap_seq; - uint32_t snap_count; - uint32_t reserved; - uint64_t snap_names_len; - struct rbd_obj_snap_ondisk snaps[0]; -} __attribute__((packed)); - - -#endif diff --git a/block/vdi.c b/block/vdi.c index 701745bf8c..4c9e201c33 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -87,6 +87,7 @@ void uuid_unparse(const uuid_t uu, char *out); #define MiB (KiB * KiB) #define SECTOR_SIZE 512 +#define DEFAULT_CLUSTER_SIZE (1 * MiB) #if defined(CONFIG_VDI_DEBUG) #define logout(fmt, ...) \ @@ -803,7 +804,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) int result = 0; uint64_t bytes = 0; uint32_t blocks; - size_t block_size = 1 * MiB; + size_t block_size = DEFAULT_CLUSTER_SIZE; uint32_t image_type = VDI_TYPE_DYNAMIC; VdiHeader header; size_t i; @@ -921,7 +922,8 @@ static QEMUOptionParameter vdi_create_options[] = { { .name = BLOCK_OPT_CLUSTER_SIZE, .type = OPT_SIZE, - .help = "VDI cluster (block) size" + .help = "VDI cluster (block) size", + .value = { .n = DEFAULT_CLUSTER_SIZE }, }, #endif #if defined(CONFIG_VDI_STATIC_IMAGE) diff --git a/block/vmdk.c b/block/vmdk.c index 8fc9d67208..922b23d8f5 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -716,11 +716,11 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) return -errno; magic = cpu_to_be32(VMDK4_MAGIC); memset(&header, 0, sizeof(header)); - header.version = cpu_to_le32(1); - header.flags = cpu_to_le32(3); /* ?? */ - header.capacity = cpu_to_le64(total_size); - header.granularity = cpu_to_le64(128); - header.num_gtes_per_gte = cpu_to_le32(512); + header.version = 1; + header.flags = 3; /* ?? */ + header.capacity = total_size; + header.granularity = 128; + header.num_gtes_per_gte = 512; grains = (total_size + header.granularity - 1) / header.granularity; gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; @@ -736,6 +736,12 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) header.granularity - 1) / header.granularity) * header.granularity; + /* swap endianness for all header fields */ + header.version = cpu_to_le32(header.version); + header.flags = cpu_to_le32(header.flags); + header.capacity = cpu_to_le64(header.capacity); + header.granularity = cpu_to_le64(header.granularity); + header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte); header.desc_offset = cpu_to_le64(header.desc_offset); header.desc_size = cpu_to_le64(header.desc_size); header.rgd_offset = cpu_to_le64(header.rgd_offset); @@ -759,7 +765,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) goto exit; } - ret = ftruncate(fd, header.grain_offset << 9); + ret = ftruncate(fd, le64_to_cpu(header.grain_offset) << 9); if (ret < 0) { ret = -errno; goto exit; @@ -767,7 +773,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) /* write grain directory */ lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET); - for (i = 0, tmp = header.rgd_offset + gd_size; + for (i = 0, tmp = le64_to_cpu(header.rgd_offset) + gd_size; i < gt_count; i++, tmp += gt_size) { ret = qemu_write_full(fd, &tmp, sizeof(tmp)); if (ret != sizeof(tmp)) { @@ -778,7 +784,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options) /* write backup grain directory */ lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET); - for (i = 0, tmp = header.gd_offset + gd_size; + for (i = 0, tmp = le64_to_cpu(header.gd_offset) + gd_size; i < gt_count; i++, tmp += gt_size) { ret = qemu_write_full(fd, &tmp, sizeof(tmp)); if (ret != sizeof(tmp)) { diff --git a/blockdev.c b/blockdev.c index 6e0eb831c1..1502575acb 100644 --- a/blockdev.c +++ b/blockdev.c @@ -326,7 +326,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) if ((buf = qemu_opt_get(opts, "cache")) != NULL) { if (!strcmp(buf, "off") || !strcmp(buf, "none")) { - bdrv_flags |= BDRV_O_NOCACHE; + bdrv_flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; } else if (!strcmp(buf, "writeback")) { bdrv_flags |= BDRV_O_CACHE_WB; } else if (!strcmp(buf, "unsafe")) { diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index eb1cdf21ca..d4d039a2f6 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -31,7 +31,6 @@ #include <sys/syscall.h> #include <sys/param.h> #include <sys/sysctl.h> -#include <signal.h> #include <utime.h> #include "qemu.h" @@ -229,7 +229,7 @@ sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}" # default flags for all hosts QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS" CFLAGS="-g $CFLAGS" -QEMU_CFLAGS="-Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" +QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS" QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS" QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS" QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" @@ -1037,7 +1037,7 @@ fi gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits" gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags" gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags" -gcc_flags="-fstack-protector-all $gcc_flags" +gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags" cat > $TMPC << EOF int main(void) { return 0; } EOF @@ -1917,41 +1917,24 @@ fi if test "$rbd" != "no" ; then cat > $TMPC <<EOF #include <stdio.h> -#include <rados/librados.h> -int main(void) { rados_initialize(0, NULL); return 0; } -EOF - rbd_libs="-lrados" - if compile_prog "" "$rbd_libs" ; then - librados_too_old=no - cat > $TMPC <<EOF -#include <stdio.h> -#include <rados/librados.h> -#ifndef CEPH_OSD_TMAP_SET -#error missing CEPH_OSD_TMAP_SET -#endif +#include <rbd/librbd.h> int main(void) { - int (*func)(const rados_pool_t pool, uint64_t *snapid) = rados_selfmanaged_snap_create; - rados_initialize(0, NULL); + rados_t cluster; + rados_create(&cluster, NULL); return 0; } EOF - if compile_prog "" "$rbd_libs" ; then - rbd=yes - libs_tools="$rbd_libs $libs_tools" - libs_softmmu="$rbd_libs $libs_softmmu" - else - rbd=no - librados_too_old=yes - fi + rbd_libs="-lrbd -lrados" + if compile_prog "" "$rbd_libs" ; then + rbd=yes + libs_tools="$rbd_libs $libs_tools" + libs_softmmu="$rbd_libs $libs_softmmu" else if test "$rbd" = "yes" ; then feature_not_found "rados block device" fi rbd=no fi - if test "$librados_too_old" = "yes" ; then - echo "-> Your librados version is too old - upgrade needed to have rbd support" - fi fi ########################################## @@ -2431,7 +2414,7 @@ int main(void) { spice_server_new(); return 0; } EOF spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null) spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null) - if $pkg_config --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \ + if $pkg_config --atleast-version=0.6.0 spice-server >/dev/null 2>&1 && \ compile_prog "$spice_cflags" "$spice_libs" ; then spice="yes" libs_softmmu="$libs_softmmu $spice_libs" @@ -3385,8 +3368,6 @@ if test ! -z "$gdb_xml_files" ; then echo "TARGET_XML_FILES=$list" >> $config_target_mak fi -echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak - if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then echo "TARGET_HAS_BFLT=y" >> $config_target_mak fi @@ -180,7 +180,7 @@ void vga_hw_screen_dump(const char *filename) active_console = consoles[0]; /* There is currently no way of specifying which screen we want to dump, so always dump the first one. */ - if (consoles[0]->hw_screen_dump) + if (consoles[0] && consoles[0]->hw_screen_dump) consoles[0]->hw_screen_dump(consoles[0]->hw, filename); active_console = previous_active_console; } @@ -123,8 +123,7 @@ typedef union { endian ! */ typedef union { float64 d; -#if defined(HOST_WORDS_BIGENDIAN) \ - || (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT)) +#if defined(HOST_WORDS_BIGENDIAN) struct { uint32_t upper; uint32_t lower; @@ -138,7 +137,6 @@ typedef union { uint64_t ll; } CPU_DoubleU; -#if defined(FLOATX80) typedef union { floatx80 d; struct { @@ -146,9 +144,7 @@ typedef union { uint16_t upper; } l; } CPU_LDoubleU; -#endif -#if defined(CONFIG_SOFTFLOAT) typedef union { float128 q; #if defined(HOST_WORDS_BIGENDIAN) @@ -175,7 +171,6 @@ typedef union { } ll; #endif } CPU_QuadU; -#endif /* CPU memory access without any memory or io remapping */ diff --git a/cpu-common.h b/cpu-common.h index 151c32c1f2..9f5917224a 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -61,6 +61,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, ram_addr_t size, void *host); ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size); void qemu_ram_free(ram_addr_t addr); +void qemu_ram_free_from_ptr(ram_addr_t addr); void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); diff --git a/darwin-user/signal.c b/darwin-user/signal.c index 48620184ee..e2adca3918 100644 --- a/darwin-user/signal.c +++ b/darwin-user/signal.c @@ -21,7 +21,6 @@ #include <string.h> #include <stdarg.h> #include <unistd.h> -#include <signal.h> #include <errno.h> #include <sys/ucontext.h> @@ -32,8 +31,6 @@ #undef uc_link #endif -#include <signal.h> - #include "qemu.h" #include "qemu-common.h" diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt index 4bb2be8850..057c322090 100644 --- a/docs/qdev-device-use.txt +++ b/docs/qdev-device-use.txt @@ -8,20 +8,23 @@ more buses for children. You can specify a device's parent bus with A device typically has a device address on its parent bus. For buses where this address can be configured, devices provide a bus-specific -property. These are - - bus property name value format - PCI addr %x.%x (dev.fn, .fn optional) - I2C address %u - SCSI scsi-id %u +property. Examples: + + bus property name value format + PCI addr %x.%x (dev.fn, .fn optional) + I2C address %u + SCSI scsi-id %u + IDE unit %u + HDA cad %u + virtio-serial-bus nr %u + ccid-bus slot %u + USB port %d(.%d)* (port.port...) Example: device i440FX-pcihost is on the root bus, and provides a PCI bus named pci.0. To put a FOO device into its slot 4, use -device FOO,bus=/i440FX-pcihost/pci.0,addr=4. The abbreviated form bus=pci.0 also works as long as the bus name is unique. -Note: the USB device address can't be controlled at this time. - === Block Devices === A QEMU block device (drive) has a host and a guest part. @@ -44,28 +47,43 @@ The new way keeps the parts separate: you create the host part with The various old ways to define drives all boil down to the common form - -drive if=TYPE,index=IDX,bus=BUS,unit=UNIT,HOST-OPTS... + -drive if=TYPE,bus=BUS,unit=UNIT,OPTS... TYPE, BUS and UNIT identify the controller device, which of its buses to use, and the drive's address on that bus. Details depend on TYPE. -IDX is an alternative way to specify BUS and UNIT. + +Instead of bus=BUS,unit=UNIT, you can also say index=IDX. In the new way, this becomes something like -drive if=none,id=DRIVE-ID,HOST-OPTS... -device DEVNAME,drive=DRIVE-ID,DEV-OPTS... -The -device argument differs in detail for each kind of drive: +The old OPTS get split into HOST-OPTS and DEV-OPTS as follows: -* if=ide +* file, format, snapshot, cache, aio, readonly, rerror, werror go into + HOST-OPTS. + +* cyls, head, secs and trans go into HOST-OPTS. Future work: they + should go into DEV-OPTS instead. + +* serial goes into DEV-OPTS, for devices supporting serial numbers. + For other devices, it goes nowhere. - -device ide-drive,drive=DRIVE-ID,bus=IDE-BUS,unit=UNIT +* media is special. In the old way, it selects disk vs. CD-ROM with + if=ide, if=scsi and if=xen. The new way uses DEVNAME for that. + Additionally, readonly=on goes into HOST-OPTS. - where IDE-BUS identifies an IDE bus, normally either ide.0 or ide.1, - and UNIT is either 0 or 1. +* addr is special, see if=virtio below. - Bug: new way does not work for ide.1 unit 0 (in old terms: index=2) - unless you disable the default CD-ROM with -nodefaults. +The -device argument differs in detail for each type of drive: + +* if=ide + + -device DEVNAME,drive=DRIVE-ID,bus=IDE-BUS,unit=UNIT + + where DEVNAME is either ide-hd or ide-cd, IDE-BUS identifies an IDE + bus, normally either ide.0 or ide.1, and UNIT is either 0 or 1. * if=scsi @@ -77,27 +95,25 @@ The -device argument differs in detail for each kind of drive: As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI device address. - This SCSI controller a single SCSI bus, named ID.0. Put a disk on - it: + This SCSI controller provides a single SCSI bus, named ID.0. Put a + disk on it: - -device scsi-disk,drive=DRIVE-ID,bus=ID.0,scsi-id=SCSI-ID,removable=RMB + -device DEVNAME,drive=DRIVE-ID,bus=ID.0,scsi-id=UNIT - The (optional) removable parameter lets you override the SCSI INQUIRY - removable (RMB) bit for non CD-ROM devices. It is ignored for CD-ROM devices - which are always removable. RMB is "on" or "off". + where DEVNAME is either scsi-hd, scsi-cd or scsi-generic. * if=floppy - -global isa-fdc,driveA=DRIVE-ID,driveB=DRIVE-ID + -global isa-fdc.driveA=DRIVE-ID + -global isa-fdc.driveB=DRIVE-ID This is -global instead of -device, because the floppy controller is created automatically, and we want to configure that one, not create a second one (which isn't possible anyway). - Omitting a drive parameter makes that drive empty. - - Bug: driveA works only if you disable the default floppy drive with - -nodefaults. + Without any -global isa-fdc,... you get an empty driveA and no + driveB. You can use -nodefaults to suppress the default driveA, see + "Default Devices". * if=virtio @@ -105,11 +121,12 @@ The -device argument differs in detail for each kind of drive: This lets you control PCI device class and MSI-X vectors. - IOEVENTFD controls whether or not ioeventfd is used for virtqueue notify. It - can be set to on (default) or off. + IOEVENTFD controls whether or not ioeventfd is used for virtqueue + notify. It can be set to on (default) or off. As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to - control the PCI device address. + control the PCI device address. This replaces option addr available + with -drive if=virtio. * if=pflash, if=mtd, if=sd, if=xen are not yet available with -device @@ -117,15 +134,20 @@ For USB devices, the old way is actually different: -usbdevice disk:format=FMT:FILENAME -Provides much less control than -drive's HOST-OPTS... The new way -fixes that: +Provides much less control than -drive's OPTS... The new way fixes +that: -device usb-storage,drive=DRIVE-ID,removable=RMB -The removable parameter gives control over the SCSI INQUIRY removable (RMB) -bit. USB thumbdrives usually set removable=on, while USB hard disks set -removable=off. See the if=scsi description above for details on the removable -parameter, which applies only to scsi-disk devices and not to scsi-generic. +The removable parameter gives control over the SCSI INQUIRY removable +(RMB) bit. USB thumbdrives usually set removable=on, while USB hard +disks set removable=off. + +Bug: usb-storage pretends to be a block device, but it's really a SCSI +controller that can serve only a single device, which it creates +automatically. The automatic creation guesses what kind of guest part +to create from the host part, like -drive if=scsi. Host and guest +part are not cleanly separated. === Character Devices === @@ -170,7 +192,9 @@ The appropriate DEVNAME depends on the machine type. For type "pc": -device usb-braille,chardev=braille,vendorid=VID,productid=PRID -chardev braille,id=braille -* -virtioconsole is still being worked on +* -virtioconsole becomes + -device virtio-serial-pci,class=C,vectors=V,ioeventfd=IOEVENTFD,max_ports=N + -device virtconsole,is_console=NUM,nr=NR,name=NAME LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows: @@ -219,38 +243,29 @@ LEGACY-CHARDEV to refer to a host part defined with -chardev. === Network Devices === -A QEMU network device (NIC) has a host and a guest part. +Host and guest part of network devices have always been separate. -The old ways to define NICs define host and guest part together. It -looks like this: +The old way to define the guest part looks like this: - -net nic,vlan=VLAN,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V + -net nic,netdev=NET-ID,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V Except for USB it looks like this: - -usbdevice net:vlan=VLAN,macaddr=MACADDR,name=ID,addr=STR,vectors=V + -usbdevice net:netdev=NET-ID,macaddr=MACADDR,name=ID -The new way keeps the parts separate: you create the host part with --netdev, and the guest device with -device, like this: +The new way is -device: - -netdev type=TYPE,id=NET-ID -device DEVNAME,netdev=NET-ID,mac=MACADDR,DEV-OPTS... -Unlike the old way, this creates just a network device, not a VLAN. -If you really want a VLAN, create it the usual way, then create the -guest device like this: - - -device DEVNAME,vlan=VLAN,mac=MACADDR,DEV-OPTS... - DEVNAME equals MODEL, except for virtio you have to name the virtio device appropriate for the bus (virtio-net-pci for PCI), and for USB -NIC you have to use usb-net. +you have to use usb-net. The old name=ID parameter becomes the usual id=ID with -device. For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI device address, as usual. The old -net nic provides parameter addr -for that, it is silently ignored when the NIC is not a PCI device. +for that, which is silently ignored when the NIC is not a PCI device. For virtio-net-pci, you can control whether or not ioeventfd is used for virtqueue notify by setting ioeventfd= to on or off (default). @@ -264,20 +279,25 @@ devices and ne2k_isa are. Some PCI devices aren't available with -net nic, e.g. i82558a. -Bug: usb-net does not work, yet. Patch posted. +To connect to a VLAN instead of an ordinary host part, replace +netdev=NET-ID by vlan=VLAN. === Graphics Devices === Host and guest part of graphics devices have always been separate. -The old way to define the guest graphics device is -vga VGA. +The old way to define the guest graphics device is -vga VGA. Not all +machines support all -vga options. -The new way is -device. Map from -vga argument to -device: +The new way is -device. The mapping from -vga argument to -device +depends on the machine type. For machine "pc", it's: std -device VGA cirrus -device cirrus-vga vmware -device vmware-svga - xenfb not yet available with -device + qxl -device qxl-vga + none -nodefaults + disables more than just VGA, see "Default Devices" As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI device address. @@ -285,13 +305,16 @@ the PCI device address. -device VGA supports properties bios-offset and bios-size, but they aren't used with machine type "pc". -Bug: -device cirrus-vga and -device vmware-svga require -nodefaults. +For machine "isapc", it's -Bug: the new way requires PCI; ISA VGA is not yet available with --device. + std -device isa-vga + cirrus not yet available with -device + none -nodefaults + disables more than just VGA, see "Default Devices" -Bug: the new way doesn't work for machine type "pc", because it -violates obscure device initialization ordering constraints. +Bug: the new way doesn't work for machine types "pc" and "isapc", +because it violates obscure device initialization ordering +constraints. === Audio Devices === @@ -308,6 +331,7 @@ Map from -soundhw sound card name to -device: cs4231a -device cs4231a,iobase=IOADDR,irq=IRQ,dma=DMA es1370 -device ES1370 gus -device gus,iobase=IOADDR,irq=IRQ,dma=DMA,freq=F + hda -device intel-hda,msi=MSI -device hda-duplex sb16 -device sb16,iobase=IOADDR,irq=IRQ,dma=DMA,dma16=DMA16,version=V adlib not yet available with -device pcspk not yet available with -device @@ -321,9 +345,10 @@ The old way to define a virtual USB device is -usbdevice DRIVER:OPTS... The new way is -device DEVNAME,DEV-OPTS... Details depend on DRIVER: +* ccid -device usb-ccid +* keyboard -device usb-kbd * mouse -device usb-mouse * tablet -device usb-tablet -* keyboard -device usb-kdb * wacom-tablet -device usb-wacom-tablet * host:... See "Host Device Assignment" * disk:... See "Block Devices" @@ -353,7 +378,7 @@ The new way is -device pci-assign,host=ADDR,iommu=IOMMU,id=ID -The old dma=none becomes iommu=0 with -device. +The old dma=none becomes iommu=off with -device. The old way to assign a host USB device is @@ -365,4 +390,27 @@ The new way is -device usb-host,hostbus=BUS,hostaddr=ADDR,vendorid=VID,productid=PRID -where left out or zero BUS, ADDR, VID, PRID serve as wildcard. +Omitted options match anything, just like the old way's wildcard. + +=== Default Devices === + +QEMU creates a number of devices by default, depending on the machine +type. + +-device DEVNAME... and global DEVNAME... suppress default devices for +some DEVNAMEs: + + default device suppressing DEVNAMEs + CD-ROM ide-cd, ide-drive, scsi-cd + isa-fdc's driveA isa-fdc + parallel isa-parallel + serial isa-serial + VGA VGA, cirrus-vga, vmware-svga + virtioconsole virtio-serial-pci, virtio-serial-s390, virtio-serial + +The default NIC is connected to a default part created along with it. +It is *not* suppressed by configuring a NIC with -device (you may call +that a bug). -net and -netdev suppress the default NIC. + +-nodefaults suppresses all the default devices mentioned above, plus a +few other things such as default SD-Card drive and default monitor. diff --git a/error.c b/error.c new file mode 100644 index 0000000000..867eec2c1a --- /dev/null +++ b/error.c @@ -0,0 +1,140 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#include "error.h" +#include "error_int.h" +#include "qemu-objects.h" +#include "qerror.h" +#include <assert.h> + +struct Error +{ + QDict *obj; + const char *fmt; + char *msg; +}; + +void error_set(Error **errp, const char *fmt, ...) +{ + Error *err; + va_list ap; + + if (errp == NULL) { + return; + } + + err = qemu_mallocz(sizeof(*err)); + + va_start(ap, fmt); + err->obj = qobject_to_qdict(qobject_from_jsonv(fmt, &ap)); + va_end(ap); + err->fmt = fmt; + + *errp = err; +} + +bool error_is_set(Error **errp) +{ + return (errp && *errp); +} + +const char *error_get_pretty(Error *err) +{ + if (err->msg == NULL) { + QString *str; + str = qerror_format(err->fmt, err->obj); + err->msg = qemu_strdup(qstring_get_str(str)); + QDECREF(str); + } + + return err->msg; +} + +const char *error_get_field(Error *err, const char *field) +{ + if (strcmp(field, "class") == 0) { + return qdict_get_str(err->obj, field); + } else { + QDict *dict = qdict_get_qdict(err->obj, "data"); + return qdict_get_str(dict, field); + } +} + +QDict *error_get_data(Error *err) +{ + QDict *data = qdict_get_qdict(err->obj, "data"); + QINCREF(data); + return data; +} + +void error_set_field(Error *err, const char *field, const char *value) +{ + QDict *dict = qdict_get_qdict(err->obj, "data"); + return qdict_put(dict, field, qstring_from_str(value)); +} + +void error_free(Error *err) +{ + if (err) { + QDECREF(err->obj); + qemu_free(err->msg); + qemu_free(err); + } +} + +bool error_is_type(Error *err, const char *fmt) +{ + const char *error_class; + char *ptr; + char *end; + + ptr = strstr(fmt, "'class': '"); + assert(ptr != NULL); + ptr += strlen("'class': '"); + + end = strchr(ptr, '\''); + assert(end != NULL); + + error_class = error_get_field(err, "class"); + if (strlen(error_class) != end - ptr) { + return false; + } + + return strncmp(ptr, error_class, end - ptr) == 0; +} + +void error_propagate(Error **dst_err, Error *local_err) +{ + if (dst_err) { + *dst_err = local_err; + } else if (local_err) { + error_free(local_err); + } +} + +QObject *error_get_qobject(Error *err) +{ + QINCREF(err->obj); + return QOBJECT(err->obj); +} + +void error_set_qobject(Error **errp, QObject *obj) +{ + Error *err; + if (errp == NULL) { + return; + } + err = qemu_mallocz(sizeof(*err)); + err->obj = qobject_to_qdict(obj); + qobject_incref(obj); + + *errp = err; +} diff --git a/error.h b/error.h new file mode 100644 index 0000000000..003c855e65 --- /dev/null +++ b/error.h @@ -0,0 +1,70 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#ifndef ERROR_H +#define ERROR_H + +#include <stdbool.h> + +/** + * A class representing internal errors within QEMU. An error has a string + * typename and optionally a set of named string parameters. + */ +typedef struct Error Error; + +/** + * Set an indirect pointer to an error given a printf-style format parameter. + * Currently, qerror.h defines these error formats. This function is not + * meant to be used outside of QEMU. + */ +void error_set(Error **err, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +/** + * Returns true if an indirect pointer to an error is pointing to a valid + * error object. + */ +bool error_is_set(Error **err); + +/** + * Get a human readable representation of an error object. + */ +const char *error_get_pretty(Error *err); + +/** + * Get an individual named error field. + */ +const char *error_get_field(Error *err, const char *field); + +/** + * Get an individual named error field. + */ +void error_set_field(Error *err, const char *field, const char *value); + +/** + * Propagate an error to an indirect pointer to an error. This function will + * always transfer ownership of the error reference and handles the case where + * dst_err is NULL correctly. + */ +void error_propagate(Error **dst_err, Error *local_err); + +/** + * Free an error object. + */ +void error_free(Error *err); + +/** + * Determine if an error is of a speific type (based on the qerror format). + * Non-QEMU users should get the `class' field to identify the error type. + */ +bool error_is_type(Error *err, const char *fmt); + +#endif diff --git a/error_int.h b/error_int.h new file mode 100644 index 0000000000..5e3942405a --- /dev/null +++ b/error_int.h @@ -0,0 +1,29 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#ifndef QEMU_ERROR_INT_H +#define QEMU_ERROR_INT_H + +#include "qemu-common.h" +#include "qobject.h" +#include "qdict.h" +#include "error.h" + +/** + * Internal QEMU functions for working with Error. + * + * These are used to convert QErrors to Errors + */ +QDict *error_get_data(Error *err); +QObject *error_get_qobject(Error *err); +void error_set_qobject(Error **errp, QObject *obj); + +#endif @@ -36,7 +36,6 @@ #include "qemu-timer.h" #if defined(CONFIG_USER_ONLY) #include <qemu.h> -#include <signal.h> #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include <sys/param.h> #if __FreeBSD_version >= 700104 @@ -2952,6 +2951,19 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size) return qemu_ram_alloc_from_ptr(dev, name, size, NULL); } +void qemu_ram_free_from_ptr(ram_addr_t addr) +{ + RAMBlock *block; + + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (addr == block->offset) { + QLIST_REMOVE(block, next); + qemu_free(block); + return; + } + } +} + void qemu_ram_free(ram_addr_t addr) { RAMBlock *block; diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c deleted file mode 100644 index 88486511ee..0000000000 --- a/fpu/softfloat-native.c +++ /dev/null @@ -1,540 +0,0 @@ -/* Native implementation of soft float functions. Only a single status - context is supported */ -#include "softfloat.h" -#include <math.h> -#if defined(CONFIG_SOLARIS) -#include <fenv.h> -#endif - -void set_float_rounding_mode(int val STATUS_PARAM) -{ - STATUS(float_rounding_mode) = val; -#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \ - (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) - fpsetround(val); -#else - fesetround(val); -#endif -} - -#ifdef FLOATX80 -void set_floatx80_rounding_precision(int val STATUS_PARAM) -{ - STATUS(floatx80_rounding_precision) = val; -} -#endif - -#if defined(CONFIG_BSD) || \ - (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) -#define lrint(d) ((int32_t)rint(d)) -#define llrint(d) ((int64_t)rint(d)) -#define lrintf(f) ((int32_t)rint(f)) -#define llrintf(f) ((int64_t)rint(f)) -#define sqrtf(f) ((float)sqrt(f)) -#define remainderf(fa, fb) ((float)remainder(fa, fb)) -#define rintf(f) ((float)rint(f)) -#if !defined(__sparc__) && \ - (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) -extern long double rintl(long double); -extern long double scalbnl(long double, int); - -long long -llrintl(long double x) { - return ((long long) rintl(x)); -} - -long -lrintl(long double x) { - return ((long) rintl(x)); -} - -long double -ldexpl(long double x, int n) { - return (scalbnl(x, n)); -} -#endif -#endif - -#if defined(_ARCH_PPC) - -/* correct (but slow) PowerPC rint() (glibc version is incorrect) */ -static double qemu_rint(double x) -{ - double y = 4503599627370496.0; - if (fabs(x) >= y) - return x; - if (x < 0) - y = -y; - y = (x + y) - y; - if (y == 0.0) - y = copysign(y, x); - return y; -} - -#define rint qemu_rint -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32(int v STATUS_PARAM) -{ - return (float32)v; -} - -float32 uint32_to_float32(unsigned int v STATUS_PARAM) -{ - return (float32)v; -} - -float64 int32_to_float64(int v STATUS_PARAM) -{ - return (float64)v; -} - -float64 uint32_to_float64(unsigned int v STATUS_PARAM) -{ - return (float64)v; -} - -#ifdef FLOATX80 -floatx80 int32_to_floatx80(int v STATUS_PARAM) -{ - return (floatx80)v; -} -#endif -float32 int64_to_float32( int64_t v STATUS_PARAM) -{ - return (float32)v; -} -float32 uint64_to_float32( uint64_t v STATUS_PARAM) -{ - return (float32)v; -} -float64 int64_to_float64( int64_t v STATUS_PARAM) -{ - return (float64)v; -} -float64 uint64_to_float64( uint64_t v STATUS_PARAM) -{ - return (float64)v; -} -#ifdef FLOATX80 -floatx80 int64_to_floatx80( int64_t v STATUS_PARAM) -{ - return (floatx80)v; -} -#endif - -/* XXX: this code implements the x86 behaviour, not the IEEE one. */ -#if HOST_LONG_BITS == 32 -static inline int long_to_int32(long a) -{ - return a; -} -#else -static inline int long_to_int32(long a) -{ - if (a != (int32_t)a) - a = 0x80000000; - return a; -} -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float32_to_int32( float32 a STATUS_PARAM) -{ - return long_to_int32(lrintf(a)); -} -int float32_to_int32_round_to_zero( float32 a STATUS_PARAM) -{ - return (int)a; -} -int64_t float32_to_int64( float32 a STATUS_PARAM) -{ - return llrintf(a); -} - -int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM) -{ - return (int64_t)a; -} - -float64 float32_to_float64( float32 a STATUS_PARAM) -{ - return a; -} -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 a STATUS_PARAM) -{ - return a; -} -#endif - -unsigned int float32_to_uint32( float32 a STATUS_PARAM) -{ - int64_t v; - unsigned int res; - - v = llrintf(a); - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - res = v; - } - return res; -} -unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM) -{ - int64_t v; - unsigned int res; - - v = (int64_t)a; - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - res = v; - } - return res; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 a STATUS_PARAM) -{ - return rintf(a); -} - -float32 float32_rem( float32 a, float32 b STATUS_PARAM) -{ - return remainderf(a, b); -} - -float32 float32_sqrt( float32 a STATUS_PARAM) -{ - return sqrtf(a); -} -int float32_compare( float32 a, float32 b STATUS_PARAM ) -{ - if (a < b) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (a > b) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int float32_compare_quiet( float32 a, float32 b STATUS_PARAM ) -{ - if (isless(a, b)) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (isgreater(a, b)) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int float32_is_signaling_nan( float32 a1) -{ - float32u u; - uint32_t a; - u.f = a1; - a = u.i; - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); -} - -int float32_is_quiet_nan( float32 a1 ) -{ - float32u u; - uint64_t a; - u.f = a1; - a = u.i; - return ( 0xFF800000 < ( a<<1 ) ); -} - -int float32_is_any_nan( float32 a1 ) -{ - float32u u; - uint32_t a; - u.f = a1; - a = u.i; - return (a & ~(1 << 31)) > 0x7f800000U; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float64_to_int32( float64 a STATUS_PARAM) -{ - return long_to_int32(lrint(a)); -} -int float64_to_int32_round_to_zero( float64 a STATUS_PARAM) -{ - return (int)a; -} -int64_t float64_to_int64( float64 a STATUS_PARAM) -{ - return llrint(a); -} -int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM) -{ - return (int64_t)a; -} -float32 float64_to_float32( float64 a STATUS_PARAM) -{ - return a; -} -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 a STATUS_PARAM) -{ - return a; -} -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 a STATUS_PARAM) -{ - return a; -} -#endif - -unsigned int float64_to_uint32( float64 a STATUS_PARAM) -{ - int64_t v; - unsigned int res; - - v = llrint(a); - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - res = v; - } - return res; -} -unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM) -{ - int64_t v; - unsigned int res; - - v = (int64_t)a; - if (v < 0) { - res = 0; - } else if (v > 0xffffffff) { - res = 0xffffffff; - } else { - res = v; - } - return res; -} -uint64_t float64_to_uint64 (float64 a STATUS_PARAM) -{ - int64_t v; - - v = llrint(a + (float64)INT64_MIN); - - return v - INT64_MIN; -} -uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM) -{ - int64_t v; - - v = (int64_t)(a + (float64)INT64_MIN); - - return v - INT64_MIN; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -#if defined(__sun__) && \ - (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) -static inline float64 trunc(float64 x) -{ - return x < 0 ? -floor(-x) : floor(x); -} -#endif -float64 float64_trunc_to_int( float64 a STATUS_PARAM ) -{ - return trunc(a); -} - -float64 float64_round_to_int( float64 a STATUS_PARAM ) -{ - return rint(a); -} - -float64 float64_rem( float64 a, float64 b STATUS_PARAM) -{ - return remainder(a, b); -} - -float64 float64_sqrt( float64 a STATUS_PARAM) -{ - return sqrt(a); -} -int float64_compare( float64 a, float64 b STATUS_PARAM ) -{ - if (a < b) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (a > b) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int float64_compare_quiet( float64 a, float64 b STATUS_PARAM ) -{ - if (isless(a, b)) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (isgreater(a, b)) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int float64_is_signaling_nan( float64 a1) -{ - float64u u; - uint64_t a; - u.f = a1; - a = u.i; - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -int float64_is_quiet_nan( float64 a1 ) -{ - float64u u; - uint64_t a; - u.f = a1; - a = u.i; - - return ( LIT64( 0xFFF0000000000000 ) < (uint64_t) ( a<<1 ) ); - -} - -int float64_is_any_nan( float64 a1 ) -{ - float64u u; - uint64_t a; - u.f = a1; - a = u.i; - - return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 ); -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int floatx80_to_int32( floatx80 a STATUS_PARAM) -{ - return long_to_int32(lrintl(a)); -} -int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM) -{ - return (int)a; -} -int64_t floatx80_to_int64( floatx80 a STATUS_PARAM) -{ - return llrintl(a); -} -int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM) -{ - return (int64_t)a; -} -float32 floatx80_to_float32( floatx80 a STATUS_PARAM) -{ - return a; -} -float64 floatx80_to_float64( floatx80 a STATUS_PARAM) -{ - return a; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM) -{ - return rintl(a); -} -floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM) -{ - return remainderl(a, b); -} -floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) -{ - return sqrtl(a); -} -int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM ) -{ - if (a < b) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (a > b) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM ) -{ - if (isless(a, b)) { - return float_relation_less; - } else if (a == b) { - return float_relation_equal; - } else if (isgreater(a, b)) { - return float_relation_greater; - } else { - return float_relation_unordered; - } -} -int floatx80_is_signaling_nan( floatx80 a1) -{ - floatx80u u; - uint64_t aLow; - u.f = a1; - - aLow = u.i.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( u.i.high & 0x7FFF ) == 0x7FFF ) - && (uint64_t) ( aLow<<1 ) - && ( u.i.low == aLow ); -} - -int floatx80_is_quiet_nan( floatx80 a1 ) -{ - floatx80u u; - u.f = a1; - return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 ); -} - -int floatx80_is_any_nan( floatx80 a1 ) -{ - floatx80u u; - u.f = a1; - return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 ); -} - -#endif diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h deleted file mode 100644 index 6afb74a152..0000000000 --- a/fpu/softfloat-native.h +++ /dev/null @@ -1,531 +0,0 @@ -/* Native implementation of soft float functions */ -#include <math.h> - -#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ - || defined(CONFIG_SOLARIS) -#include <ieeefp.h> -#define fabsf(f) ((float)fabs(f)) -#else -#include <fenv.h> -#endif - -#if defined(__OpenBSD__) || defined(__NetBSD__) -#include <sys/param.h> -#endif - -/* - * Define some C99-7.12.3 classification macros and - * some C99-.12.4 for Solaris systems OS less than 10, - * or Solaris 10 systems running GCC 3.x or less. - * Solaris 10 with GCC4 does not need these macros as they - * are defined in <iso/math_c99.h> with a compiler directive - */ -#if defined(CONFIG_SOLARIS) && \ - ((CONFIG_SOLARIS_VERSION <= 9 ) || \ - ((CONFIG_SOLARIS_VERSION == 10) && (__GNUC__ < 4))) \ - || (defined(__OpenBSD__) && (OpenBSD < 200811)) -/* - * C99 7.12.3 classification macros - * and - * C99 7.12.14 comparison macros - * - * ... do not work on Solaris 10 using GNU CC 3.4.x. - * Try to workaround the missing / broken C99 math macros. - */ -#if defined(__OpenBSD__) -#define unordered(x, y) (isnan(x) || isnan(y)) -#endif - -#ifdef __NetBSD__ -#ifndef isgreater -#define isgreater(x, y) __builtin_isgreater(x, y) -#endif -#ifndef isgreaterequal -#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) -#endif -#ifndef isless -#define isless(x, y) __builtin_isless(x, y) -#endif -#ifndef islessequal -#define islessequal(x, y) __builtin_islessequal(x, y) -#endif -#ifndef isunordered -#define isunordered(x, y) __builtin_isunordered(x, y) -#endif -#endif - - -#define isnormal(x) (fpclass(x) >= FP_NZERO) -#define isgreater(x, y) ((!unordered(x, y)) && ((x) > (y))) -#define isgreaterequal(x, y) ((!unordered(x, y)) && ((x) >= (y))) -#define isless(x, y) ((!unordered(x, y)) && ((x) < (y))) -#define islessequal(x, y) ((!unordered(x, y)) && ((x) <= (y))) -#define isunordered(x,y) unordered(x, y) -#endif - -#if defined(__sun__) && !defined(CONFIG_NEEDS_LIBSUNMATH) - -#ifndef isnan -# define isnan(x) \ - (sizeof (x) == sizeof (long double) ? isnan_ld (x) \ - : sizeof (x) == sizeof (double) ? isnan_d (x) \ - : isnan_f (x)) -static inline int isnan_f (float x) { return x != x; } -static inline int isnan_d (double x) { return x != x; } -static inline int isnan_ld (long double x) { return x != x; } -#endif - -#ifndef isinf -# define isinf(x) \ - (sizeof (x) == sizeof (long double) ? isinf_ld (x) \ - : sizeof (x) == sizeof (double) ? isinf_d (x) \ - : isinf_f (x)) -static inline int isinf_f (float x) { return isnan (x - x); } -static inline int isinf_d (double x) { return isnan (x - x); } -static inline int isinf_ld (long double x) { return isnan (x - x); } -#endif -#endif - -typedef float float32; -typedef double float64; -#ifdef FLOATX80 -typedef long double floatx80; -#endif - -typedef union { - float32 f; - uint32_t i; -} float32u; -typedef union { - float64 f; - uint64_t i; -} float64u; -#ifdef FLOATX80 -typedef union { - floatx80 f; - struct { - uint64_t low; - uint16_t high; - } i; -} floatx80u; -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ - || defined(CONFIG_SOLARIS) -#if defined(__OpenBSD__) -#define FE_RM FP_RM -#define FE_RP FP_RP -#define FE_RZ FP_RZ -#endif -enum { - float_round_nearest_even = FP_RN, - float_round_down = FP_RM, - float_round_up = FP_RP, - float_round_to_zero = FP_RZ -}; -#else -enum { - float_round_nearest_even = FE_TONEAREST, - float_round_down = FE_DOWNWARD, - float_round_up = FE_UPWARD, - float_round_to_zero = FE_TOWARDZERO -}; -#endif - -typedef struct float_status { - int float_rounding_mode; -#ifdef FLOATX80 - int floatx80_rounding_precision; -#endif -} float_status; - -void set_float_rounding_mode(int val STATUS_PARAM); -#ifdef FLOATX80 -void set_floatx80_rounding_precision(int val STATUS_PARAM); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int STATUS_PARAM); -float32 uint32_to_float32( unsigned int STATUS_PARAM); -float64 int32_to_float64( int STATUS_PARAM); -float64 uint32_to_float64( unsigned int STATUS_PARAM); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int STATUS_PARAM); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int STATUS_PARAM); -#endif -float32 int64_to_float32( int64_t STATUS_PARAM); -float32 uint64_to_float32( uint64_t STATUS_PARAM); -float64 int64_to_float64( int64_t STATUS_PARAM); -float64 uint64_to_float64( uint64_t v STATUS_PARAM); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( int64_t STATUS_PARAM); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( int64_t STATUS_PARAM); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion constants. -*----------------------------------------------------------------------------*/ -#define float32_zero (0.0) -#define float32_one (1.0) -#define float32_ln2 (0.6931471) -#define float32_pi (3.1415926) -#define float32_half (0.5) - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float32_to_int32( float32 STATUS_PARAM); -int float32_to_int32_round_to_zero( float32 STATUS_PARAM); -unsigned int float32_to_uint32( float32 a STATUS_PARAM); -unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM); -int64_t float32_to_int64( float32 STATUS_PARAM); -int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM); -float64 float32_to_float64( float32 STATUS_PARAM); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 STATUS_PARAM); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 STATUS_PARAM); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 STATUS_PARAM); -INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM) -{ - return a + b; -} -INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM) -{ - return a - b; -} -INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM) -{ - return a * b; -} -INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM) -{ - return a / b; -} -float32 float32_rem( float32, float32 STATUS_PARAM); -float32 float32_sqrt( float32 STATUS_PARAM); -INLINE int float32_eq_quiet( float32 a, float32 b STATUS_PARAM) -{ - return a == b; -} -INLINE int float32_le( float32 a, float32 b STATUS_PARAM) -{ - return a <= b; -} -INLINE int float32_lt( float32 a, float32 b STATUS_PARAM) -{ - return a < b; -} -INLINE int float32_eq( float32 a, float32 b STATUS_PARAM) -{ - return a <= b && a >= b; -} -INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM) -{ - return islessequal(a, b); -} -INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM) -{ - return isless(a, b); -} -INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM) -{ - return isunordered(a, b); -} -INLINE int float32_unordered_quiet( float32 a, float32 b STATUS_PARAM) -{ - return isunordered(a, b); -} -int float32_compare( float32, float32 STATUS_PARAM ); -int float32_compare_quiet( float32, float32 STATUS_PARAM ); -int float32_is_signaling_nan( float32 ); -int float32_is_quiet_nan( float32 ); -int float32_is_any_nan( float32 ); - -INLINE float32 float32_abs(float32 a) -{ - return fabsf(a); -} - -INLINE float32 float32_chs(float32 a) -{ - return -a; -} - -INLINE float32 float32_is_infinity(float32 a) -{ - return fpclassify(a) == FP_INFINITE; -} - -INLINE float32 float32_is_neg(float32 a) -{ - float32u u; - u.f = a; - return u.i >> 31; -} - -INLINE float32 float32_is_zero(float32 a) -{ - return fpclassify(a) == FP_ZERO; -} - -INLINE float32 float32_scalbn(float32 a, int n STATUS_PARAM) -{ - return scalbnf(a, n); -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion constants. -*----------------------------------------------------------------------------*/ -#define float64_zero (0.0) -#define float64_one (1.0) -#define float64_ln2 (0.693147180559945) -#define float64_pi (3.141592653589793) -#define float64_half (0.5) - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float64_to_int32( float64 STATUS_PARAM ); -int float64_to_int32_round_to_zero( float64 STATUS_PARAM ); -unsigned int float64_to_uint32( float64 STATUS_PARAM ); -unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM ); -int64_t float64_to_int64( float64 STATUS_PARAM ); -int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); -uint64_t float64_to_uint64( float64 STATUS_PARAM ); -uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM ); -float32 float64_to_float32( float64 STATUS_PARAM ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 STATUS_PARAM ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 STATUS_PARAM ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 STATUS_PARAM ); -float64 float64_trunc_to_int( float64 STATUS_PARAM ); -INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM) -{ - return a + b; -} -INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM) -{ - return a - b; -} -INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM) -{ - return a * b; -} -INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM) -{ - return a / b; -} -float64 float64_rem( float64, float64 STATUS_PARAM ); -float64 float64_sqrt( float64 STATUS_PARAM ); -INLINE int float64_eq_quiet( float64 a, float64 b STATUS_PARAM) -{ - return a == b; -} -INLINE int float64_le( float64 a, float64 b STATUS_PARAM) -{ - return a <= b; -} -INLINE int float64_lt( float64 a, float64 b STATUS_PARAM) -{ - return a < b; -} -INLINE int float64_eq( float64 a, float64 b STATUS_PARAM) -{ - return a <= b && a >= b; -} -INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM) -{ - return islessequal(a, b); -} -INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM) -{ - return isless(a, b); - -} -INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM) -{ - return isunordered(a, b); -} -INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM) -{ - return isunordered(a, b); -} -int float64_compare( float64, float64 STATUS_PARAM ); -int float64_compare_quiet( float64, float64 STATUS_PARAM ); -int float64_is_signaling_nan( float64 ); -int float64_is_any_nan( float64 ); -int float64_is_quiet_nan( float64 ); - -INLINE float64 float64_abs(float64 a) -{ - return fabs(a); -} - -INLINE float64 float64_chs(float64 a) -{ - return -a; -} - -INLINE float64 float64_is_infinity(float64 a) -{ - return fpclassify(a) == FP_INFINITE; -} - -INLINE float64 float64_is_neg(float64 a) -{ - float64u u; - u.f = a; - return u.i >> 63; -} - -INLINE float64 float64_is_zero(float64 a) -{ - return fpclassify(a) == FP_ZERO; -} - -INLINE float64 float64_scalbn(float64 a, int n STATUS_PARAM) -{ - return scalbn(a, n); -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion constants. -*----------------------------------------------------------------------------*/ -#define floatx80_zero (0.0L) -#define floatx80_one (1.0L) -#define floatx80_ln2 (0.69314718055994530943L) -#define floatx80_pi (3.14159265358979323851L) -#define floatx80_half (0.5L) - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int floatx80_to_int32( floatx80 STATUS_PARAM ); -int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM ); -int64_t floatx80_to_int64( floatx80 STATUS_PARAM); -int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM); -float32 floatx80_to_float32( floatx80 STATUS_PARAM ); -float64 floatx80_to_float64( floatx80 STATUS_PARAM ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 STATUS_PARAM ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM ); -INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a + b; -} -INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a - b; -} -INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a * b; -} -INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a / b; -} -floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM ); -floatx80 floatx80_sqrt( floatx80 STATUS_PARAM ); -INLINE int floatx80_eq_quiet( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a == b; -} -INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a <= b; -} -INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a < b; -} -INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM) -{ - return a <= b && a >= b; -} -INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM) -{ - return islessequal(a, b); -} -INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM) -{ - return isless(a, b); - -} -INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM) -{ - return isunordered(a, b); -} -INLINE int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM) -{ - return isunordered(a, b); -} -int floatx80_compare( floatx80, floatx80 STATUS_PARAM ); -int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM ); -int floatx80_is_signaling_nan( floatx80 ); -int floatx80_is_quiet_nan( floatx80 ); -int floatx80_is_any_nan( floatx80 ); - -INLINE floatx80 floatx80_abs(floatx80 a) -{ - return fabsl(a); -} - -INLINE floatx80 floatx80_chs(floatx80 a) -{ - return -a; -} - -INLINE floatx80 floatx80_is_infinity(floatx80 a) -{ - return fpclassify(a) == FP_INFINITE; -} - -INLINE floatx80 floatx80_is_neg(floatx80 a) -{ - floatx80u u; - u.f = a; - return u.i.high >> 15; -} - -INLINE floatx80 floatx80_is_zero(floatx80 a) -{ - return fpclassify(a) == FP_ZERO; -} - -INLINE floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM) -{ - return scalbnl(a, n); -} - -#endif diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 9d68aae9d5..c7d35a161d 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -523,8 +523,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) } } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is a | quiet NaN; otherwise returns 0. This slightly differs from the same @@ -681,10 +679,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) } } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns 1 if the quadruple-precision floating-point value `a' is a quiet | NaN; otherwise returns 0. @@ -820,4 +814,3 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) } } -#endif diff --git a/fpu/softfloat.c b/fpu/softfloat.c index e3cd8a7296..7951a0e869 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -64,12 +64,10 @@ void set_float_exception_flags(int val STATUS_PARAM) STATUS(float_exception_flags) = val; } -#ifdef FLOATX80 void set_floatx80_rounding_precision(int val STATUS_PARAM) { STATUS(floatx80_rounding_precision) = val; } -#endif /*---------------------------------------------------------------------------- | Returns the fraction bits of the half-precision floating-point value `a'. @@ -564,8 +562,6 @@ static float64 } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the fraction bits of the extended double-precision floating-point | value `a'. @@ -851,10 +847,6 @@ static floatx80 } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the least-significant 64 fraction bits of the quadruple-precision | floating-point value `a'. @@ -1118,8 +1110,6 @@ static float128 } -#endif - /*---------------------------------------------------------------------------- | Returns the result of converting the 32-bit two's complement integer `a' | to the single-precision floating-point format. The conversion is performed @@ -1159,8 +1149,6 @@ float64 int32_to_float64( int32 a STATUS_PARAM ) } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the 32-bit two's complement integer `a' | to the extended double-precision floating-point format. The conversion @@ -1184,10 +1172,6 @@ floatx80 int32_to_floatx80( int32 a STATUS_PARAM ) } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the 32-bit two's complement integer `a' to | the quadruple-precision floating-point format. The conversion is performed @@ -1210,8 +1194,6 @@ float128 int32_to_float128( int32 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Returns the result of converting the 64-bit two's complement integer `a' | to the single-precision floating-point format. The conversion is performed @@ -1291,8 +1273,6 @@ float64 uint64_to_float64( uint64 a STATUS_PARAM ) } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the 64-bit two's complement integer `a' | to the extended double-precision floating-point format. The conversion @@ -1314,10 +1294,6 @@ floatx80 int64_to_floatx80( int64 a STATUS_PARAM ) } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the 64-bit two's complement integer `a' to | the quadruple-precision floating-point format. The conversion is performed @@ -1351,8 +1327,6 @@ float128 int64_to_float128( int64 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the 32-bit two's complement integer format. The conversion is @@ -1590,8 +1564,6 @@ float64 float32_to_float64( float32 a STATUS_PARAM ) } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion @@ -1622,10 +1594,6 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM ) } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point value | `a' to the double-precision floating-point format. The conversion is @@ -1656,8 +1624,6 @@ float128 float32_to_float128( float32 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Rounds the single-precision floating-point value `a' to an integer, and | returns the result as a single-precision floating-point value. The @@ -2939,8 +2905,6 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM) return packFloat16(aSign, aExp + 14, aSig >> 13); } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the extended double-precision floating-point format. The conversion @@ -2972,10 +2936,6 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM ) } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point value | `a' to the quadruple-precision floating-point format. The conversion is @@ -3007,8 +2967,6 @@ float128 float64_to_float128( float64 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Rounds the double-precision floating-point value `a' to an integer, and | returns the result as a double-precision floating-point value. The @@ -3816,8 +3774,6 @@ int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM ) return 0; } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the 32-bit two's complement integer format. The @@ -4030,8 +3986,6 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM ) } -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the quadruple-precision floating-point format. The @@ -4056,8 +4010,6 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Rounds the extended double-precision floating-point value `a' to an integer, | and returns the result as an extended quadruple-precision floating-point @@ -4849,10 +4801,6 @@ int floatx80_unordered_quiet( floatx80 a, floatx80 b STATUS_PARAM ) return 0; } -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the 32-bit two's complement integer format. The conversion @@ -5102,8 +5050,6 @@ float64 float128_to_float64( float128 a STATUS_PARAM ) } -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the extended double-precision floating-point format. The @@ -5139,8 +5085,6 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM ) } -#endif - /*---------------------------------------------------------------------------- | Rounds the quadruple-precision floating-point value `a' to an integer, and | returns the result as a quadruple-precision floating-point value. The @@ -6020,8 +5964,6 @@ int float128_unordered_quiet( float128 a, float128 b STATUS_PARAM ) return 0; } -#endif - /* misc functions */ float32 uint32_to_float32( unsigned int a STATUS_PARAM ) { @@ -6423,7 +6365,6 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM ) return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR ); } -#ifdef FLOATX80 floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM ) { flag aSign; @@ -6454,9 +6395,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM ) return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision), aSign, aExp, aSig, 0 STATUS_VAR ); } -#endif -#ifdef FLOAT128 float128 float128_scalbn( float128 a, int n STATUS_PARAM ) { flag aSign; @@ -6489,4 +6428,3 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM ) STATUS_VAR ); } -#endif diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 58c9b7b40c..bde250087b 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -74,24 +74,6 @@ typedef int64_t int64; #define SNAN_BIT_IS_ONE 0 #endif -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#ifdef CONFIG_SOFTFLOAT -/* bit exact soft float support */ -#define FLOATX80 -#define FLOAT128 -#else -/* native float support */ -#if (defined(__i386__) || defined(__x86_64__)) && !defined(CONFIG_BSD) -#define FLOATX80 -#endif -#endif /* !CONFIG_SOFTFLOAT */ - #define STATUS_PARAM , float_status *status #define STATUS(field) status->field #define STATUS_VAR , status @@ -106,7 +88,6 @@ enum { float_relation_unordered = 2 }; -#ifdef CONFIG_SOFTFLOAT /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point types. *----------------------------------------------------------------------------*/ @@ -149,14 +130,11 @@ typedef uint64_t float64; #define const_float32(x) (x) #define const_float64(x) (x) #endif -#ifdef FLOATX80 typedef struct { uint64_t low; uint16_t high; } floatx80; #define make_floatx80(exp, mant) ((floatx80) { mant, exp }) -#endif -#ifdef FLOAT128 typedef struct { #ifdef HOST_WORDS_BIGENDIAN uint64_t high, low; @@ -164,7 +142,6 @@ typedef struct { uint64_t low, high; #endif } float128; -#endif /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point underflow tininess-detection mode. @@ -201,9 +178,7 @@ typedef struct float_status { signed char float_detect_tininess; signed char float_rounding_mode; signed char float_exception_flags; -#ifdef FLOATX80 signed char floatx80_rounding_precision; -#endif /* should denormalised results go to zero and set the inexact flag? */ flag flush_to_zero; /* should denormalised inputs go to zero and set the input_denormal flag? */ @@ -233,9 +208,7 @@ INLINE int get_float_exception_flags(float_status *status) { return STATUS(float_exception_flags); } -#ifdef FLOATX80 void set_floatx80_rounding_precision(int val STATUS_PARAM); -#endif /*---------------------------------------------------------------------------- | Routine to raise any or all of the software IEC/IEEE floating-point @@ -250,22 +223,14 @@ float32 int32_to_float32( int32 STATUS_PARAM ); float64 int32_to_float64( int32 STATUS_PARAM ); float32 uint32_to_float32( unsigned int STATUS_PARAM ); float64 uint32_to_float64( unsigned int STATUS_PARAM ); -#ifdef FLOATX80 floatx80 int32_to_floatx80( int32 STATUS_PARAM ); -#endif -#ifdef FLOAT128 float128 int32_to_float128( int32 STATUS_PARAM ); -#endif float32 int64_to_float32( int64 STATUS_PARAM ); float32 uint64_to_float32( uint64 STATUS_PARAM ); float64 int64_to_float64( int64 STATUS_PARAM ); float64 uint64_to_float64( uint64 STATUS_PARAM ); -#ifdef FLOATX80 floatx80 int64_to_floatx80( int64 STATUS_PARAM ); -#endif -#ifdef FLOAT128 float128 int64_to_float128( int64 STATUS_PARAM ); -#endif /*---------------------------------------------------------------------------- | Software half-precision conversion routines. @@ -303,12 +268,8 @@ uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM ); int64 float32_to_int64( float32 STATUS_PARAM ); int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM ); float64 float32_to_float64( float32 STATUS_PARAM ); -#ifdef FLOATX80 floatx80 float32_to_floatx80( float32 STATUS_PARAM ); -#endif -#ifdef FLOAT128 float128 float32_to_float128( float32 STATUS_PARAM ); -#endif /*---------------------------------------------------------------------------- | Software IEC/IEEE single-precision operations. @@ -420,12 +381,8 @@ int64 float64_to_int64_round_to_zero( float64 STATUS_PARAM ); uint64 float64_to_uint64 (float64 a STATUS_PARAM); uint64 float64_to_uint64_round_to_zero (float64 a STATUS_PARAM); float32 float64_to_float32( float64 STATUS_PARAM ); -#ifdef FLOATX80 floatx80 float64_to_floatx80( float64 STATUS_PARAM ); -#endif -#ifdef FLOAT128 float128 float64_to_float128( float64 STATUS_PARAM ); -#endif /*---------------------------------------------------------------------------- | Software IEC/IEEE double-precision operations. @@ -492,6 +449,11 @@ INLINE int float64_is_any_nan(float64 a) return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL); } +INLINE int float64_is_zero_or_denormal(float64 a) +{ + return (float64_val(a) & 0x7ff0000000000000LL) == 0; +} + INLINE float64 float64_set_sign(float64 a, int sign) { return make_float64((float64_val(a) & 0x7fffffffffffffffULL) @@ -518,8 +480,6 @@ INLINE float64 float64_set_sign(float64 a, int sign) #define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 )) #endif -#ifdef FLOATX80 - /*---------------------------------------------------------------------------- | Software IEC/IEEE extended double-precision conversion routines. *----------------------------------------------------------------------------*/ @@ -529,9 +489,7 @@ int64 floatx80_to_int64( floatx80 STATUS_PARAM ); int64 floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM ); float32 floatx80_to_float32( floatx80 STATUS_PARAM ); float64 floatx80_to_float64( floatx80 STATUS_PARAM ); -#ifdef FLOAT128 float128 floatx80_to_float128( floatx80 STATUS_PARAM ); -#endif /*---------------------------------------------------------------------------- | Software IEC/IEEE extended double-precision operations. @@ -585,6 +543,11 @@ INLINE int floatx80_is_zero(floatx80 a) return (a.high & 0x7fff) == 0 && a.low == 0; } +INLINE int floatx80_is_zero_or_denormal(floatx80 a) +{ + return (a.high & 0x7fff) == 0; +} + INLINE int floatx80_is_any_nan(floatx80 a) { return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1); @@ -610,10 +573,6 @@ INLINE int floatx80_is_any_nan(floatx80 a) #define floatx80_default_nan_low LIT64( 0xC000000000000000 ) #endif -#endif - -#ifdef FLOAT128 - /*---------------------------------------------------------------------------- | Software IEC/IEEE quadruple-precision conversion routines. *----------------------------------------------------------------------------*/ @@ -623,9 +582,7 @@ int64 float128_to_int64( float128 STATUS_PARAM ); int64 float128_to_int64_round_to_zero( float128 STATUS_PARAM ); float32 float128_to_float32( float128 STATUS_PARAM ); float64 float128_to_float64( float128 STATUS_PARAM ); -#ifdef FLOATX80 floatx80 float128_to_floatx80( float128 STATUS_PARAM ); -#endif /*---------------------------------------------------------------------------- | Software IEC/IEEE quadruple-precision operations. @@ -679,6 +636,11 @@ INLINE int float128_is_zero(float128 a) return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0; } +INLINE int float128_is_zero_or_denormal(float128 a) +{ + return (a.high & 0x7fff000000000000LL) == 0; +} + INLINE int float128_is_any_nan(float128 a) { return ((a.high >> 48) & 0x7fff) == 0x7fff && @@ -697,12 +659,4 @@ INLINE int float128_is_any_nan(float128 a) #define float128_default_nan_low LIT64( 0x0000000000000000 ) #endif -#endif - -#else /* CONFIG_SOFTFLOAT */ - -#include "softfloat-native.h" - -#endif /* !CONFIG_SOFTFLOAT */ - #endif /* !SOFTFLOAT_H */ diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index 126e60e276..af9daf797f 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -97,11 +97,4 @@ typedef struct FileOperations void *opaque; } FileOperations; -static inline const char *rpath(FsContext *ctx, const char *path) -{ - /* FIXME: so wrong... */ - static char buffer[4096]; - snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path); - return buffer; -} #endif diff --git a/fsdev/qemu-fsdev-dummy.c b/fsdev/qemu-fsdev-dummy.c new file mode 100644 index 0000000000..619e163a46 --- /dev/null +++ b/fsdev/qemu-fsdev-dummy.c @@ -0,0 +1,20 @@ +/* + * Virtio 9p + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Gautham R Shenoy <ego@in.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ +#include <stdio.h> +#include <string.h> +#include "qemu-fsdev.h" + +int qemu_fsdev_add(QemuOpts *opts) +{ + return 0; +} @@ -1105,10 +1105,6 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n) env->active_fpu.fcr31 = tmp & 0xFF83FFFF; /* set rounding mode */ RESTORE_ROUNDING_MODE; -#ifndef CONFIG_SOFTFLOAT - /* no floating point exception for native float */ - SET_FP_ENABLE(env->active_fpu.fcr31, 0); -#endif break; case 71: env->active_fpu.fcr0 = tmp; break; } diff --git a/hw/9pfs/virtio-9p-debug.c b/hw/9pfs/virtio-9p-debug.c index 6b18842fd4..4636ad51f0 100644 --- a/hw/9pfs/virtio-9p-debug.c +++ b/hw/9pfs/virtio-9p-debug.c @@ -10,8 +10,9 @@ * the COPYING file in the top-level directory. * */ -#include "virtio.h" -#include "pc.h" + +#include "hw/virtio.h" +#include "hw/pc.h" #include "virtio-9p.h" #include "virtio-9p-debug.h" diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c new file mode 100644 index 0000000000..a2b6acc408 --- /dev/null +++ b/hw/9pfs/virtio-9p-device.c @@ -0,0 +1,173 @@ +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "hw/virtio.h" +#include "hw/pc.h" +#include "qemu_socket.h" +#include "hw/virtio-pci.h" +#include "virtio-9p.h" +#include "fsdev/qemu-fsdev.h" +#include "virtio-9p-xattr.h" + +static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) +{ + features |= 1 << VIRTIO_9P_MOUNT_TAG; + return features; +} + +static V9fsState *to_virtio_9p(VirtIODevice *vdev) +{ + return (V9fsState *)vdev; +} + +static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) +{ + struct virtio_9p_config *cfg; + V9fsState *s = to_virtio_9p(vdev); + + cfg = qemu_mallocz(sizeof(struct virtio_9p_config) + + s->tag_len); + stw_raw(&cfg->tag_len, s->tag_len); + memcpy(cfg->tag, s->tag, s->tag_len); + memcpy(config, cfg, s->config_size); + qemu_free(cfg); +} + +VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) + { + V9fsState *s; + int i, len; + struct stat stat; + FsTypeEntry *fse; + + + s = (V9fsState *)virtio_common_init("virtio-9p", + VIRTIO_ID_9P, + sizeof(struct virtio_9p_config)+ + MAX_TAG_LEN, + sizeof(V9fsState)); + + /* initialize pdu allocator */ + QLIST_INIT(&s->free_list); + for (i = 0; i < (MAX_REQ - 1); i++) { + QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); + } + + s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output); + + fse = get_fsdev_fsentry(conf->fsdev_id); + + if (!fse) { + /* We don't have a fsdev identified by fsdev_id */ + fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " + "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL"); + exit(1); + } + + if (!fse->path || !conf->tag) { + /* we haven't specified a mount_tag or the path */ + fprintf(stderr, "fsdev with id %s needs path " + "and Virtio-9p device needs mount_tag arguments\n", + conf->fsdev_id); + exit(1); + } + + if (!strcmp(fse->security_model, "passthrough")) { + /* Files on the Fileserver set to client user credentials */ + s->ctx.fs_sm = SM_PASSTHROUGH; + s->ctx.xops = passthrough_xattr_ops; + } else if (!strcmp(fse->security_model, "mapped")) { + /* Files on the fileserver are set to QEMU credentials. + * Client user credentials are saved in extended attributes. + */ + s->ctx.fs_sm = SM_MAPPED; + s->ctx.xops = mapped_xattr_ops; + } else if (!strcmp(fse->security_model, "none")) { + /* + * Files on the fileserver are set to QEMU credentials. + */ + s->ctx.fs_sm = SM_NONE; + s->ctx.xops = none_xattr_ops; + } else { + fprintf(stderr, "Default to security_model=none. You may want" + " enable advanced security model using " + "security option:\n\t security_model=passthrough\n\t " + "security_model=mapped\n"); + s->ctx.fs_sm = SM_NONE; + s->ctx.xops = none_xattr_ops; + } + + if (lstat(fse->path, &stat)) { + fprintf(stderr, "share path %s does not exist\n", fse->path); + exit(1); + } else if (!S_ISDIR(stat.st_mode)) { + fprintf(stderr, "share path %s is not a directory\n", fse->path); + exit(1); + } + + s->ctx.fs_root = qemu_strdup(fse->path); + len = strlen(conf->tag); + if (len > MAX_TAG_LEN) { + len = MAX_TAG_LEN; + } + /* s->tag is non-NULL terminated string */ + s->tag = qemu_malloc(len); + memcpy(s->tag, conf->tag, len); + s->tag_len = len; + s->ctx.uid = -1; + + s->ops = fse->ops; + s->vdev.get_features = virtio_9p_get_features; + s->config_size = sizeof(struct virtio_9p_config) + + s->tag_len; + s->vdev.get_config = virtio_9p_get_config; + + return &s->vdev; +} + +static int virtio_9p_init_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + VirtIODevice *vdev; + + vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf); + vdev->nvectors = proxy->nvectors; + virtio_init_pci(proxy, vdev, + PCI_VENDOR_ID_REDHAT_QUMRANET, + 0x1009, + 0x2, + 0x00); + /* make the actual value visible */ + proxy->nvectors = vdev->nvectors; + return 0; +} + +static PCIDeviceInfo virtio_9p_info = { + .qdev.name = "virtio-9p-pci", + .qdev.size = sizeof(VirtIOPCIProxy), + .init = virtio_9p_init_pci, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), + DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), + DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), + DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void virtio_9p_register_devices(void) +{ + pci_qdev_register(&virtio_9p_info); +} + +device_init(virtio_9p_register_devices) diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 0a015de9a5..77904c37bd 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -10,7 +10,8 @@ * the COPYING file in the top-level directory. * */ -#include "virtio.h" + +#include "hw/virtio.h" #include "virtio-9p.h" #include "virtio-9p-xattr.h" #include <arpa/inet.h> @@ -24,7 +25,8 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf) { int err; - err = lstat(rpath(fs_ctx, path), stbuf); + char buffer[PATH_MAX]; + err = lstat(rpath(fs_ctx, path, buffer), stbuf); if (err) { return err; } @@ -34,19 +36,19 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf) gid_t tmp_gid; mode_t tmp_mode; dev_t tmp_dev; - if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid, + if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { stbuf->st_uid = tmp_uid; } - if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid, + if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { stbuf->st_gid = tmp_gid; } - if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode, - sizeof(mode_t)) > 0) { + if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode", + &tmp_mode, sizeof(mode_t)) > 0) { stbuf->st_mode = tmp_mode; } - if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev, + if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { stbuf->st_rdev = tmp_dev; } @@ -91,10 +93,12 @@ static int local_set_xattr(const char *path, FsCred *credp) static int local_post_create_passthrough(FsContext *fs_ctx, const char *path, FsCred *credp) { - if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) { + char buffer[PATH_MAX]; + if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) { return -1; } - if (lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) { + if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid, + credp->fc_gid) < 0) { /* * If we fail to change ownership and if we are * using security model none. Ignore the error @@ -110,9 +114,10 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path, char *buf, size_t bufsz) { ssize_t tsize = -1; + char buffer[PATH_MAX]; if (fs_ctx->fs_sm == SM_MAPPED) { int fd; - fd = open(rpath(fs_ctx, path), O_RDONLY); + fd = open(rpath(fs_ctx, path, buffer), O_RDONLY); if (fd == -1) { return -1; } @@ -123,7 +128,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path, return tsize; } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - tsize = readlink(rpath(fs_ctx, path), buf, bufsz); + tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz); } return tsize; } @@ -140,12 +145,14 @@ static int local_closedir(FsContext *ctx, DIR *dir) static int local_open(FsContext *ctx, const char *path, int flags) { - return open(rpath(ctx, path), flags); + char buffer[PATH_MAX]; + return open(rpath(ctx, path, buffer), flags); } static DIR *local_opendir(FsContext *ctx, const char *path) { - return opendir(rpath(ctx, path)); + char buffer[PATH_MAX]; + return opendir(rpath(ctx, path, buffer)); } static void local_rewinddir(FsContext *ctx, DIR *dir) @@ -200,11 +207,12 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp) { + char buffer[PATH_MAX]; if (fs_ctx->fs_sm == SM_MAPPED) { - return local_set_xattr(rpath(fs_ctx, path), credp); + return local_set_xattr(rpath(fs_ctx, path, buffer), credp); } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - return chmod(rpath(fs_ctx, path), credp->fc_mode); + return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode); } return -1; } @@ -213,21 +221,24 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp) { int err = -1; int serrno = 0; + char buffer[PATH_MAX]; /* Determine the security model */ if (fs_ctx->fs_sm == SM_MAPPED) { - err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0); + err = mknod(rpath(fs_ctx, path, buffer), + SM_LOCAL_MODE_BITS|S_IFREG, 0); if (err == -1) { return err; } - local_set_xattr(rpath(fs_ctx, path), credp); + local_set_xattr(rpath(fs_ctx, path, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev); + err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode, + credp->fc_rdev); if (err == -1) { return err; } @@ -240,7 +251,7 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp) return err; err_end: - remove(rpath(fs_ctx, path)); + remove(rpath(fs_ctx, path, buffer)); errno = serrno; return err; } @@ -249,22 +260,23 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp) { int err = -1; int serrno = 0; + char buffer[PATH_MAX]; /* Determine the security model */ if (fs_ctx->fs_sm == SM_MAPPED) { - err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS); + err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS); if (err == -1) { return err; } credp->fc_mode = credp->fc_mode|S_IFDIR; - err = local_set_xattr(rpath(fs_ctx, path), credp); + err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - err = mkdir(rpath(fs_ctx, path), credp->fc_mode); + err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode); if (err == -1) { return err; } @@ -277,7 +289,7 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp) return err; err_end: - remove(rpath(fs_ctx, path)); + remove(rpath(fs_ctx, path, buffer)); errno = serrno; return err; } @@ -318,23 +330,24 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags, int fd = -1; int err = -1; int serrno = 0; + char buffer[PATH_MAX]; /* Determine the security model */ if (fs_ctx->fs_sm == SM_MAPPED) { - fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS); + fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS); if (fd == -1) { return fd; } credp->fc_mode = credp->fc_mode|S_IFREG; /* Set cleint credentials in xattr */ - err = local_set_xattr(rpath(fs_ctx, path), credp); + err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - fd = open(rpath(fs_ctx, path), flags, credp->fc_mode); + fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode); if (fd == -1) { return fd; } @@ -348,7 +361,7 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags, err_end: close(fd); - remove(rpath(fs_ctx, path)); + remove(rpath(fs_ctx, path, buffer)); errno = serrno; return err; } @@ -359,12 +372,13 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, { int err = -1; int serrno = 0; + char buffer[PATH_MAX]; /* Determine the security model */ if (fs_ctx->fs_sm == SM_MAPPED) { int fd; ssize_t oldpath_size, write_size; - fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR, + fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR, SM_LOCAL_MODE_BITS); if (fd == -1) { return fd; @@ -384,18 +398,19 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, close(fd); /* Set cleint credentials in symlink's xattr */ credp->fc_mode = credp->fc_mode|S_IFLNK; - err = local_set_xattr(rpath(fs_ctx, newpath), credp); + err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp); if (err == -1) { serrno = errno; goto err_end; } } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - err = symlink(oldpath, rpath(fs_ctx, newpath)); + err = symlink(oldpath, rpath(fs_ctx, newpath, buffer)); if (err) { return err; } - err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid); + err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid, + credp->fc_gid); if (err == -1) { /* * If we fail to change ownership and if we are @@ -411,70 +426,45 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, return err; err_end: - remove(rpath(fs_ctx, newpath)); + remove(rpath(fs_ctx, newpath, buffer)); errno = serrno; return err; } static int local_link(FsContext *ctx, const char *oldpath, const char *newpath) { - char *tmp = qemu_strdup(rpath(ctx, oldpath)); - int err, serrno = 0; - - if (tmp == NULL) { - return -ENOMEM; - } - - err = link(tmp, rpath(ctx, newpath)); - if (err == -1) { - serrno = errno; - } - - qemu_free(tmp); - - if (err == -1) { - errno = serrno; - } + char buffer[PATH_MAX], buffer1[PATH_MAX]; - return err; + return link(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1)); } static int local_truncate(FsContext *ctx, const char *path, off_t size) { - return truncate(rpath(ctx, path), size); + char buffer[PATH_MAX]; + return truncate(rpath(ctx, path, buffer), size); } static int local_rename(FsContext *ctx, const char *oldpath, const char *newpath) { - char *tmp; - int err; - - tmp = qemu_strdup(rpath(ctx, oldpath)); - - err = rename(tmp, rpath(ctx, newpath)); - if (err == -1) { - int serrno = errno; - qemu_free(tmp); - errno = serrno; - } else { - qemu_free(tmp); - } - - return err; + char buffer[PATH_MAX], buffer1[PATH_MAX]; + return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1)); } static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp) { + char buffer[PATH_MAX]; if ((credp->fc_uid == -1 && credp->fc_gid == -1) || (fs_ctx->fs_sm == SM_PASSTHROUGH)) { - return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid); + return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid, + credp->fc_gid); } else if (fs_ctx->fs_sm == SM_MAPPED) { - return local_set_xattr(rpath(fs_ctx, path), credp); + return local_set_xattr(rpath(fs_ctx, path, buffer), credp); } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || (fs_ctx->fs_sm == SM_NONE)) { - return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid); + return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid, + credp->fc_gid); } return -1; } @@ -482,12 +472,15 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp) static int local_utimensat(FsContext *s, const char *path, const struct timespec *buf) { - return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW); + char buffer[PATH_MAX]; + return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf, + AT_SYMLINK_NOFOLLOW); } static int local_remove(FsContext *ctx, const char *path) { - return remove(rpath(ctx, path)); + char buffer[PATH_MAX]; + return remove(rpath(ctx, path, buffer)); } static int local_fsync(FsContext *ctx, int fd, int datasync) @@ -501,7 +494,8 @@ static int local_fsync(FsContext *ctx, int fd, int datasync) static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf) { - return statfs(rpath(s, path), stbuf); + char buffer[PATH_MAX]; + return statfs(rpath(s, path, buffer), stbuf); } static ssize_t local_lgetxattr(FsContext *ctx, const char *path, diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/virtio-9p-posix-acl.c index 575abe86b0..f5b392e180 100644 --- a/hw/9pfs/virtio-9p-posix-acl.c +++ b/hw/9pfs/virtio-9p-posix-acl.c @@ -13,7 +13,7 @@ #include <sys/types.h> #include <attr/xattr.h> -#include "virtio.h" +#include "hw/virtio.h" #include "virtio-9p.h" #include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" @@ -26,7 +26,8 @@ static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size) { - return lgetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size); + char buffer[PATH_MAX]; + return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, size); } static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path, @@ -50,14 +51,17 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path, static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size, int flags) { - return lsetxattr(rpath(ctx, path), MAP_ACL_ACCESS, value, size, flags); + char buffer[PATH_MAX]; + return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS, value, + size, flags); } static int mp_pacl_removexattr(FsContext *ctx, const char *path, const char *name) { int ret; - ret = lremovexattr(rpath(ctx, path), MAP_ACL_ACCESS); + char buffer[PATH_MAX]; + ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_ACCESS); if (ret == -1 && errno == ENODATA) { /* * We don't get ENODATA error when trying to remove a @@ -73,7 +77,8 @@ static int mp_pacl_removexattr(FsContext *ctx, static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size) { - return lgetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size); + char buffer[PATH_MAX]; + return lgetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, size); } static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path, @@ -97,14 +102,17 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path, static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size, int flags) { - return lsetxattr(rpath(ctx, path), MAP_ACL_DEFAULT, value, size, flags); + char buffer[PATH_MAX]; + return lsetxattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT, value, + size, flags); } static int mp_dacl_removexattr(FsContext *ctx, const char *path, const char *name) { int ret; - ret = lremovexattr(rpath(ctx, path), MAP_ACL_DEFAULT); + char buffer[PATH_MAX]; + ret = lremovexattr(rpath(ctx, path, buffer), MAP_ACL_DEFAULT); if (ret == -1 && errno == ENODATA) { /* * We don't get ENODATA error when trying to remove a diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/virtio-9p-xattr-user.c index bba13ce643..5044a3e5ab 100644 --- a/hw/9pfs/virtio-9p-xattr-user.c +++ b/hw/9pfs/virtio-9p-xattr-user.c @@ -12,7 +12,7 @@ */ #include <sys/types.h> -#include "virtio.h" +#include "hw/virtio.h" #include "virtio-9p.h" #include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" @@ -21,6 +21,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size) { + char buffer[PATH_MAX]; if (strncmp(name, "user.virtfs.", 12) == 0) { /* * Don't allow fetch of user.virtfs namesapce @@ -29,7 +30,7 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, errno = ENOATTR; return -1; } - return lgetxattr(rpath(ctx, path), name, value, size); + return lgetxattr(rpath(ctx, path, buffer), name, value, size); } static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, @@ -67,6 +68,7 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path, static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size, int flags) { + char buffer[PATH_MAX]; if (strncmp(name, "user.virtfs.", 12) == 0) { /* * Don't allow fetch of user.virtfs namesapce @@ -75,12 +77,13 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name, errno = EACCES; return -1; } - return lsetxattr(rpath(ctx, path), name, value, size, flags); + return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags); } static int mp_user_removexattr(FsContext *ctx, const char *path, const char *name) { + char buffer[PATH_MAX]; if (strncmp(name, "user.virtfs.", 12) == 0) { /* * Don't allow fetch of user.virtfs namesapce @@ -89,7 +92,7 @@ static int mp_user_removexattr(FsContext *ctx, errno = EACCES; return -1; } - return lremovexattr(rpath(ctx, path), name); + return lremovexattr(rpath(ctx, path, buffer), name); } XattrOperations mapped_user_xattr = { diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c index 03c3d3f6bb..bde0b7fb4f 100644 --- a/hw/9pfs/virtio-9p-xattr.c +++ b/hw/9pfs/virtio-9p-xattr.c @@ -11,7 +11,7 @@ * */ -#include "virtio.h" +#include "hw/virtio.h" #include "virtio-9p.h" #include "fsdev/file-op-9p.h" #include "virtio-9p-xattr.h" @@ -66,20 +66,21 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, void *value, size_t vsize) { ssize_t size = 0; + char buffer[PATH_MAX]; void *ovalue = value; XattrOperations *xops; char *orig_value, *orig_value_start; ssize_t xattr_len, parsed_len = 0, attr_len; /* Get the actual len */ - xattr_len = llistxattr(rpath(ctx, path), value, 0); + xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0); if (xattr_len <= 0) { return xattr_len; } /* Now fetch the xattr and find the actual size */ orig_value = qemu_malloc(xattr_len); - xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len); + xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len); /* store the orig pointer */ orig_value_start = orig_value; diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/virtio-9p-xattr.h index 2bbae2dcb5..247e414ebd 100644 --- a/hw/9pfs/virtio-9p-xattr.h +++ b/hw/9pfs/virtio-9p-xattr.h @@ -54,20 +54,23 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value, static inline ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size) { - return lgetxattr(rpath(ctx, path), name, value, size); + char buffer[PATH_MAX]; + return lgetxattr(rpath(ctx, path, buffer), name, value, size); } static inline int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, size_t size, int flags) { - return lsetxattr(rpath(ctx, path), name, value, size, flags); + char buffer[PATH_MAX]; + return lsetxattr(rpath(ctx, path, buffer), name, value, size, flags); } static inline int pt_removexattr(FsContext *ctx, const char *path, const char *name) { - return lremovexattr(rpath(ctx, path), name); + char buffer[PATH_MAX]; + return lremovexattr(rpath(ctx, path, buffer), name); } static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path, diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index b5fc52b3eb..4890df6f75 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -11,9 +11,10 @@ * */ -#include "virtio.h" -#include "pc.h" +#include "hw/virtio.h" +#include "hw/pc.h" #include "qemu_socket.h" +#include "hw/virtio-pci.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" #include "virtio-9p-debug.h" @@ -194,7 +195,6 @@ static int v9fs_do_open2(V9fsState *s, char *fullname, uid_t uid, gid_t gid, cred.fc_uid = uid; cred.fc_gid = gid; cred.fc_mode = mode & 07777; - flags = flags; return s->ops->open2(&s->ctx, fullname, flags, &cred); } @@ -423,6 +423,22 @@ static void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs) v9fs_string_sprintf(lhs, "%s", rhs->data); } +/* + * Return TRUE if s1 is an ancestor of s2. + * + * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d". + * As a special case, We treat s1 as ancestor of s2 if they are same! + */ +static int v9fs_path_is_ancestor(V9fsString *s1, V9fsString *s2) +{ + if (!strncmp(s1->data, s2->data, s1->size)) { + if (s2->data[s1->size] == '\0' || s2->data[s1->size] == '/') { + return 1; + } + } + return 0; +} + static size_t v9fs_string_size(V9fsString *str) { return str->size; @@ -2805,13 +2821,13 @@ static int v9fs_complete_rename(V9fsState *s, V9fsRenameState *vs) for (fidp = s->fid_list; fidp; fidp = fidp->next) { if (vs->fidp == fidp) { /* - * we replace name of this fid towards the end - * so that our below strcmp will work + * we replace name of this fid towards the end so + * that our below v9fs_path_is_ancestor check will + * work */ continue; } - if (!strncmp(vs->fidp->path.data, fidp->path.data, - strlen(vs->fidp->path.data))) { + if (v9fs_path_is_ancestor(&vs->fidp->path, &fidp->path)) { /* replace the name */ v9fs_fix_path(&fidp->path, &vs->name, strlen(vs->fidp->path.data)); @@ -3589,6 +3605,11 @@ static pdu_handler_t *pdu_handlers[] = { [P9_TREMOVE] = v9fs_remove, }; +static void v9fs_op_not_supp(V9fsState *s, V9fsPDU *pdu) +{ + complete_pdu(s, pdu, -EOPNOTSUPP); +} + static void submit_pdu(V9fsState *s, V9fsPDU *pdu) { pdu_handler_t *handler; @@ -3596,16 +3617,16 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu) if (debug_9p_pdu) { pprint_pdu(pdu); } - - BUG_ON(pdu->id >= ARRAY_SIZE(pdu_handlers)); - - handler = pdu_handlers[pdu->id]; - BUG_ON(handler == NULL); - + if (pdu->id >= ARRAY_SIZE(pdu_handlers) || + (pdu_handlers[pdu->id] == NULL)) { + handler = v9fs_op_not_supp; + } else { + handler = pdu_handlers[pdu->id]; + } handler(s, pdu); } -static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) +void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) { V9fsState *s = (V9fsState *)vdev; V9fsPDU *pdu; @@ -3629,119 +3650,3 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) free_pdu(s, pdu); } - -static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) -{ - features |= 1 << VIRTIO_9P_MOUNT_TAG; - return features; -} - -static V9fsState *to_virtio_9p(VirtIODevice *vdev) -{ - return (V9fsState *)vdev; -} - -static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) -{ - struct virtio_9p_config *cfg; - V9fsState *s = to_virtio_9p(vdev); - - cfg = qemu_mallocz(sizeof(struct virtio_9p_config) + - s->tag_len); - stw_raw(&cfg->tag_len, s->tag_len); - memcpy(cfg->tag, s->tag, s->tag_len); - memcpy(config, cfg, s->config_size); - qemu_free(cfg); -} - -VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) - { - V9fsState *s; - int i, len; - struct stat stat; - FsTypeEntry *fse; - - - s = (V9fsState *)virtio_common_init("virtio-9p", - VIRTIO_ID_9P, - sizeof(struct virtio_9p_config)+ - MAX_TAG_LEN, - sizeof(V9fsState)); - - /* initialize pdu allocator */ - QLIST_INIT(&s->free_list); - for (i = 0; i < (MAX_REQ - 1); i++) { - QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); - } - - s->vq = virtio_add_queue(&s->vdev, MAX_REQ, handle_9p_output); - - fse = get_fsdev_fsentry(conf->fsdev_id); - - if (!fse) { - /* We don't have a fsdev identified by fsdev_id */ - fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " - "id = %s\n", conf->fsdev_id ? conf->fsdev_id : "NULL"); - exit(1); - } - - if (!fse->path || !conf->tag) { - /* we haven't specified a mount_tag or the path */ - fprintf(stderr, "fsdev with id %s needs path " - "and Virtio-9p device needs mount_tag arguments\n", - conf->fsdev_id); - exit(1); - } - - if (!strcmp(fse->security_model, "passthrough")) { - /* Files on the Fileserver set to client user credentials */ - s->ctx.fs_sm = SM_PASSTHROUGH; - s->ctx.xops = passthrough_xattr_ops; - } else if (!strcmp(fse->security_model, "mapped")) { - /* Files on the fileserver are set to QEMU credentials. - * Client user credentials are saved in extended attributes. - */ - s->ctx.fs_sm = SM_MAPPED; - s->ctx.xops = mapped_xattr_ops; - } else if (!strcmp(fse->security_model, "none")) { - /* - * Files on the fileserver are set to QEMU credentials. - */ - s->ctx.fs_sm = SM_NONE; - s->ctx.xops = none_xattr_ops; - } else { - fprintf(stderr, "Default to security_model=none. You may want" - " enable advanced security model using " - "security option:\n\t security_model=passthrough \n\t " - "security_model=mapped\n"); - s->ctx.fs_sm = SM_NONE; - s->ctx.xops = none_xattr_ops; - } - - if (lstat(fse->path, &stat)) { - fprintf(stderr, "share path %s does not exist\n", fse->path); - exit(1); - } else if (!S_ISDIR(stat.st_mode)) { - fprintf(stderr, "share path %s is not a directory \n", fse->path); - exit(1); - } - - s->ctx.fs_root = qemu_strdup(fse->path); - len = strlen(conf->tag); - if (len > MAX_TAG_LEN) { - len = MAX_TAG_LEN; - } - /* s->tag is non-NULL terminated string */ - s->tag = qemu_malloc(len); - memcpy(s->tag, conf->tag, len); - s->tag_len = len; - s->ctx.uid = -1; - - s->ops = fse->ops; - s->vdev.get_features = virtio_9p_get_features; - s->config_size = sizeof(struct virtio_9p_config) + - s->tag_len; - s->vdev.get_config = virtio_9p_get_config; - - return &s->vdev; -} diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 622928fce5..2bfbe622af 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -101,6 +101,11 @@ enum p9_proto_version { #define P9_NOTAG (u16)(~0) #define P9_NOFID (u32)(~0) #define P9_MAXWELEM 16 +static inline const char *rpath(FsContext *ctx, const char *path, char *buffer) +{ + snprintf(buffer, PATH_MAX, "%s/%s", ctx->fs_root, path); + return buffer; +} /* * ample room for Twrite/Rread header @@ -504,4 +509,6 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, return pdu_packunpack(dst, sg, sg_count, offset, size, 0); } +extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); + #endif diff --git a/hw/ide/core.c b/hw/ide/core.c index 45410e81a2..95beb175b3 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -430,7 +430,6 @@ void ide_dma_error(IDEState *s) s->error = ABRT_ERR; s->status = READY_STAT | ERR_STAT; ide_set_inactive(s); - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); ide_set_irq(s->bus); } @@ -500,8 +499,11 @@ handle_rw_error: n = s->nsector; s->io_buffer_index = 0; s->io_buffer_size = n * 512; - if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0) + if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0) { + /* The PRDs were too short. Reset the Active bit, but don't raise an + * interrupt. */ goto eot; + } #ifdef DEBUG_AIO printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n", @@ -523,7 +525,6 @@ handle_rw_error: return; eot: - s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT); ide_set_inactive(s); } diff --git a/hw/multiboot.c b/hw/multiboot.c index 394ed0136e..6e6cfb9531 100644 --- a/hw/multiboot.c +++ b/hw/multiboot.c @@ -307,7 +307,7 @@ int load_multiboot(void *fw_cfg, | MULTIBOOT_FLAGS_MMAP); stl_p(bootinfo + MBI_MEM_LOWER, 640); stl_p(bootinfo + MBI_MEM_UPPER, (ram_size / 1024) - 1024); - stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */ + stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8000ffff); /* XXX: use the -boot switch? */ stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP); mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr); @@ -1070,6 +1070,15 @@ void pc_vga_init(PCIBus *pci_bus) isa_vga_init(); } } + + /* + * sga does not suppress normal vga output. So a machine can have both a + * vga card and sga manually enabled. Output will be seen on both. + * For nographic case, sga is enabled at all times + */ + if (display_type == DT_NOGRAPHIC) { + isa_create_simple("sga"); + } } static void cpu_request_exit(void *opaque, int irq, int level) diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c index 17b0165533..6b57fbf597 100644 --- a/hw/ppce500_mpc8544ds.c +++ b/hw/ppce500_mpc8544ds.c @@ -275,7 +275,7 @@ static void mpc8544ds_init(ram_addr_t ram_size, mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]], mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]], NULL); - pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); + pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); if (!pci_bus) printf("couldn't create PCI controller!\n"); @@ -357,7 +357,9 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) ret = true; } qemu_mutex_unlock(&qxl->ssd.lock); - qxl_log_command(qxl, "vga", ext); + if (ret) { + qxl_log_command(qxl, "vga", ext); + } return ret; case QXL_MODE_COMPAT: case QXL_MODE_NATIVE: diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 837f24e212..ad6a730be0 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -413,7 +413,11 @@ int scsi_req_parse(SCSIRequest *req, uint8_t *buf) scsi_req_xfer_mode(req); req->cmd.lba = scsi_req_lba(req); trace_scsi_req_parsed(req->dev->id, req->lun, req->tag, buf[0], - req->cmd.mode, req->cmd.xfer, req->cmd.lba); + req->cmd.mode, req->cmd.xfer); + if (req->cmd.lba != -1) { + trace_scsi_req_parsed_lba(req->dev->id, req->lun, req->tag, buf[0], + req->cmd.lba); + } return 0; } diff --git a/hw/sga.c b/hw/sga.c new file mode 100644 index 0000000000..7ef750adf6 --- /dev/null +++ b/hw/sga.c @@ -0,0 +1,56 @@ +/* + * QEMU dummy ISA device for loading sgabios option rom. + * + * Copyright (c) 2011 Glauber Costa, Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * sgabios code originally available at code.google.com/p/sgabios + * + */ +#include "pci.h" +#include "pc.h" +#include "loader.h" +#include "sysemu.h" + +#define SGABIOS_FILENAME "sgabios.bin" + +typedef struct ISAGAState { + ISADevice dev; +} ISASGAState; + +static int isa_cirrus_vga_initfn(ISADevice *dev) +{ + rom_add_vga(SGABIOS_FILENAME); + return 0; +} + +static ISADeviceInfo sga_info = { + .qdev.name = "sga", + .qdev.desc = "Serial Graphics Adapter", + .qdev.size = sizeof(ISASGAState), + .init = isa_cirrus_vga_initfn, +}; + +static void sga_register(void) +{ + isa_qdev_register(&sga_info); +} + +device_init(sga_register); diff --git a/hw/vga-isa.c b/hw/vga-isa.c index fde0d56fd3..245841f18b 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -77,7 +77,6 @@ static ISADeviceInfo vga_info = { .qdev.size = sizeof(ISAVGAState), .qdev.vmsd = &vmstate_vga_common, .qdev.reset = vga_reset_isa, - .qdev.no_user = 1, .init = vga_initfn, }; diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index c19629d507..c018351095 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -26,6 +26,7 @@ #include "loader.h" #include "kvm.h" #include "blockdev.h" +#include "virtio-pci.h" /* from Linux's linux/virtio_pci.h */ @@ -95,27 +96,6 @@ */ #define wmb() do { } while (0) -/* PCI bindings. */ - -typedef struct { - PCIDevice pci_dev; - VirtIODevice *vdev; - uint32_t flags; - uint32_t addr; - uint32_t class_code; - uint32_t nvectors; - BlockConf block; - NICConf nic; - uint32_t host_features; -#ifdef CONFIG_LINUX - V9fsConf fsconf; -#endif - virtio_serial_conf serial; - virtio_net_conf net; - bool ioeventfd_disabled; - bool ioeventfd_started; -} VirtIOPCIProxy; - /* virtio device */ static void virtio_pci_notify(void *opaque, uint16_t vector) @@ -669,7 +649,7 @@ static const VirtIOBindings virtio_pci_bindings = { .vmstate_change = virtio_pci_vmstate_change, }; -static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, +void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, uint16_t vendor, uint16_t device, uint16_t class_code, uint8_t pif) { @@ -835,25 +815,6 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev) return 0; } -#ifdef CONFIG_VIRTFS -static int virtio_9p_init_pci(PCIDevice *pci_dev) -{ - VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); - VirtIODevice *vdev; - - vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf); - vdev->nvectors = proxy->nvectors; - virtio_init_pci(proxy, vdev, - PCI_VENDOR_ID_REDHAT_QUMRANET, - 0x1009, - 0x2, - 0x00); - /* make the actual value visible */ - proxy->nvectors = vdev->nvectors; - return 0; -} -#endif - static PCIDeviceInfo virtio_info[] = { { .qdev.name = "virtio-blk-pci", @@ -922,20 +883,6 @@ static PCIDeviceInfo virtio_info[] = { }, .qdev.reset = virtio_pci_reset, },{ -#ifdef CONFIG_VIRTFS - .qdev.name = "virtio-9p-pci", - .qdev.alias = "virtio-9p", - .qdev.size = sizeof(VirtIOPCIProxy), - .init = virtio_9p_init_pci, - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), - DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), - DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), - DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), - DEFINE_PROP_END_OF_LIST(), - }, - }, { -#endif /* end of list */ } }; diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h new file mode 100644 index 0000000000..a4b5fd30e1 --- /dev/null +++ b/hw/virtio-pci.h @@ -0,0 +1,43 @@ +/* + * Virtio PCI Bindings + * + * Copyright IBM, Corp. 2007 + * Copyright (c) 2009 CodeSourcery + * + * Authors: + * Anthony Liguori <aliguori@us.ibm.com> + * Paul Brook <paul@codesourcery.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef QEMU_VIRTIO_PCI_H +#define QEMU_VIRTIO_PCI_H + +#include "virtio-net.h" +#include "virtio-serial.h" + +typedef struct { + PCIDevice pci_dev; + VirtIODevice *vdev; + uint32_t flags; + uint32_t addr; + uint32_t class_code; + uint32_t nvectors; + BlockConf block; + NICConf nic; + uint32_t host_features; +#ifdef CONFIG_LINUX + V9fsConf fsconf; +#endif + virtio_serial_conf serial; + virtio_net_conf net; + bool ioeventfd_disabled; + bool ioeventfd_started; +} VirtIOPCIProxy; + +extern void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, + uint16_t vendor, uint16_t device, + uint16_t class_code, uint8_t pif); +#endif diff --git a/json-lexer.c b/json-lexer.c index 65c9720d65..c21338f66d 100644 --- a/json-lexer.c +++ b/json-lexer.c @@ -18,6 +18,8 @@ #include "qemu-common.h" #include "json-lexer.h" +#define MAX_TOKEN_SIZE (64ULL << 20) + /* * \"([^\\\"]|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*\" * '([^\\']|(\\\"\\'\\\\\\/\\b\\f\\n\\r\\t\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))*' @@ -103,7 +105,8 @@ static const uint8_t json_lexer[][256] = { ['u'] = IN_DQ_UCODE0, }, [IN_DQ_STRING] = { - [1 ... 0xFF] = IN_DQ_STRING, + [1 ... 0xBF] = IN_DQ_STRING, + [0xC2 ... 0xF4] = IN_DQ_STRING, ['\\'] = IN_DQ_STRING_ESCAPE, ['"'] = JSON_STRING, }, @@ -142,7 +145,8 @@ static const uint8_t json_lexer[][256] = { ['u'] = IN_SQ_UCODE0, }, [IN_SQ_STRING] = { - [1 ... 0xFF] = IN_SQ_STRING, + [1 ... 0xBF] = IN_SQ_STRING, + [0xC2 ... 0xF4] = IN_SQ_STRING, ['\\'] = IN_SQ_STRING_ESCAPE, ['\''] = JSON_STRING, }, @@ -272,7 +276,7 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func) lexer->x = lexer->y = 0; } -static int json_lexer_feed_char(JSONLexer *lexer, char ch) +static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) { int char_consumed, new_state; @@ -303,12 +307,41 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch) new_state = IN_START; break; case IN_ERROR: - return -EINVAL; + /* XXX: To avoid having previous bad input leaving the parser in an + * unresponsive state where we consume unpredictable amounts of + * subsequent "good" input, percolate this error state up to the + * tokenizer/parser by forcing a NULL object to be emitted, then + * reset state. + * + * Also note that this handling is required for reliable channel + * negotiation between QMP and the guest agent, since chr(0xFF) + * is placed at the beginning of certain events to ensure proper + * delivery when the channel is in an unknown state. chr(0xFF) is + * never a valid ASCII/UTF-8 sequence, so this should reliably + * induce an error/flush state. + */ + lexer->emit(lexer, lexer->token, JSON_ERROR, lexer->x, lexer->y); + QDECREF(lexer->token); + lexer->token = qstring_new(); + new_state = IN_START; + lexer->state = new_state; + return 0; default: break; } lexer->state = new_state; - } while (!char_consumed); + } while (!char_consumed && !flush); + + /* Do not let a single token grow to an arbitrarily large size, + * this is a security consideration. + */ + if (lexer->token->length > MAX_TOKEN_SIZE) { + lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y); + QDECREF(lexer->token); + lexer->token = qstring_new(); + lexer->state = IN_START; + } + return 0; } @@ -319,7 +352,7 @@ int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) for (i = 0; i < size; i++) { int err; - err = json_lexer_feed_char(lexer, buffer[i]); + err = json_lexer_feed_char(lexer, buffer[i], false); if (err < 0) { return err; } @@ -330,7 +363,7 @@ int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) int json_lexer_flush(JSONLexer *lexer) { - return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0); + return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true); } void json_lexer_destroy(JSONLexer *lexer) diff --git a/json-lexer.h b/json-lexer.h index 3b50c4634b..10bc0a7798 100644 --- a/json-lexer.h +++ b/json-lexer.h @@ -25,6 +25,7 @@ typedef enum json_token_type { JSON_STRING, JSON_ESCAPE, JSON_SKIP, + JSON_ERROR, } JSONTokenType; typedef struct JSONLexer JSONLexer; diff --git a/json-parser.c b/json-parser.c index 6c06ef91a6..849e2156da 100644 --- a/json-parser.c +++ b/json-parser.c @@ -22,9 +22,11 @@ #include "qbool.h" #include "json-parser.h" #include "json-lexer.h" +#include "qerror.h" typedef struct JSONParserContext { + Error *err; } JSONParserContext; #define BUG_ON(cond) assert(!(cond)) @@ -95,11 +97,15 @@ static void GCC_FMT_ATTR(3, 4) parse_error(JSONParserContext *ctxt, QObject *token, const char *msg, ...) { va_list ap; + char message[1024]; va_start(ap, msg); - fprintf(stderr, "parse error: "); - vfprintf(stderr, msg, ap); - fprintf(stderr, "\n"); + vsnprintf(message, sizeof(message), msg, ap); va_end(ap); + if (ctxt->err) { + error_free(ctxt->err); + ctxt->err = NULL; + } + error_set(&ctxt->err, QERR_JSON_PARSE_ERROR, message); } /** @@ -269,10 +275,15 @@ out: */ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_list *ap) { - QObject *key, *token = NULL, *value, *peek; + QObject *key = NULL, *token = NULL, *value, *peek; QList *working = qlist_copy(*tokens); peek = qlist_peek(working); + if (peek == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + key = parse_value(ctxt, &working, ap); if (!key || qobject_type(key) != QTYPE_QSTRING) { parse_error(ctxt, peek, "key is not a string in object"); @@ -280,6 +291,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict, QList **tokens, va_l } token = qlist_pop(working); + if (token == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + if (!token_is_operator(token, ':')) { parse_error(ctxt, token, "missing : in object pair"); goto out; @@ -315,6 +331,10 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a QList *working = qlist_copy(*tokens); token = qlist_pop(working); + if (token == NULL) { + goto out; + } + if (!token_is_operator(token, '{')) { goto out; } @@ -324,12 +344,22 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a dict = qdict_new(); peek = qlist_peek(working); + if (peek == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + if (!token_is_operator(peek, '}')) { if (parse_pair(ctxt, dict, &working, ap) == -1) { goto out; } token = qlist_pop(working); + if (token == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + while (!token_is_operator(token, '}')) { if (!token_is_operator(token, ',')) { parse_error(ctxt, token, "expected separator in dict"); @@ -343,6 +373,10 @@ static QObject *parse_object(JSONParserContext *ctxt, QList **tokens, va_list *a } token = qlist_pop(working); + if (token == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } } qobject_decref(token); token = NULL; @@ -371,6 +405,10 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap QList *working = qlist_copy(*tokens); token = qlist_pop(working); + if (token == NULL) { + goto out; + } + if (!token_is_operator(token, '[')) { goto out; } @@ -380,6 +418,11 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap list = qlist_new(); peek = qlist_peek(working); + if (peek == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + if (!token_is_operator(peek, ']')) { QObject *obj; @@ -392,6 +435,11 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); token = qlist_pop(working); + if (token == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } + while (!token_is_operator(token, ']')) { if (!token_is_operator(token, ',')) { parse_error(ctxt, token, "expected separator in list"); @@ -410,6 +458,10 @@ static QObject *parse_array(JSONParserContext *ctxt, QList **tokens, va_list *ap qlist_append_obj(list, obj); token = qlist_pop(working); + if (token == NULL) { + parse_error(ctxt, NULL, "premature EOI"); + goto out; + } } qobject_decref(token); @@ -438,6 +490,9 @@ static QObject *parse_keyword(JSONParserContext *ctxt, QList **tokens) QList *working = qlist_copy(*tokens); token = qlist_pop(working); + if (token == NULL) { + goto out; + } if (token_get_type(token) != JSON_KEYWORD) { goto out; @@ -475,6 +530,9 @@ static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *a } token = qlist_pop(working); + if (token == NULL) { + goto out; + } if (token_is_escape(token, "%p")) { obj = va_arg(*ap, QObject *); @@ -514,6 +572,10 @@ static QObject *parse_literal(JSONParserContext *ctxt, QList **tokens) QList *working = qlist_copy(*tokens); token = qlist_pop(working); + if (token == NULL) { + goto out; + } + switch (token_get_type(token)) { case JSON_STRING: obj = QOBJECT(qstring_from_escaped_str(ctxt, token)); @@ -565,13 +627,24 @@ static QObject *parse_value(JSONParserContext *ctxt, QList **tokens, va_list *ap QObject *json_parser_parse(QList *tokens, va_list *ap) { + return json_parser_parse_err(tokens, ap, NULL); +} + +QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp) +{ JSONParserContext ctxt = {}; - QList *working = qlist_copy(tokens); + QList *working; QObject *result; + if (!tokens) { + return NULL; + } + working = qlist_copy(tokens); result = parse_value(&ctxt, &working, ap); QDECREF(working); + error_propagate(errp, ctxt.err); + return result; } diff --git a/json-parser.h b/json-parser.h index 97f43f67d4..8f2b5ec4bc 100644 --- a/json-parser.h +++ b/json-parser.h @@ -16,7 +16,9 @@ #include "qemu-common.h" #include "qlist.h" +#include "error.h" QObject *json_parser_parse(QList *tokens, va_list *ap); +QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp); #endif diff --git a/json-streamer.c b/json-streamer.c index f7e7a68d40..c255c7818f 100644 --- a/json-streamer.c +++ b/json-streamer.c @@ -18,6 +18,9 @@ #include "json-lexer.h" #include "json-streamer.h" +#define MAX_TOKEN_SIZE (64ULL << 20) +#define MAX_NESTING (1ULL << 10) + static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTokenType type, int x, int y) { JSONMessageParser *parser = container_of(lexer, JSONMessageParser, lexer); @@ -49,14 +52,44 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok qdict_put(dict, "x", qint_from_int(x)); qdict_put(dict, "y", qint_from_int(y)); + parser->token_size += token->length; + qlist_append(parser->tokens, dict); - if (parser->brace_count == 0 && - parser->bracket_count == 0) { - parser->emit(parser, parser->tokens); + if (type == JSON_ERROR) { + goto out_emit_bad; + } else if (parser->brace_count < 0 || + parser->bracket_count < 0 || + (parser->brace_count == 0 && + parser->bracket_count == 0)) { + goto out_emit; + } else if (parser->token_size > MAX_TOKEN_SIZE || + parser->bracket_count > MAX_NESTING || + parser->brace_count > MAX_NESTING) { + /* Security consideration, we limit total memory allocated per object + * and the maximum recursion depth that a message can force. + */ + goto out_emit; + } + + return; + +out_emit_bad: + /* clear out token list and tell the parser to emit and error + * indication by passing it a NULL list + */ + QDECREF(parser->tokens); + parser->tokens = NULL; +out_emit: + /* send current list of tokens to parser and reset tokenizer */ + parser->brace_count = 0; + parser->bracket_count = 0; + parser->emit(parser, parser->tokens); + if (parser->tokens) { QDECREF(parser->tokens); - parser->tokens = qlist_new(); } + parser->tokens = qlist_new(); + parser->token_size = 0; } void json_message_parser_init(JSONMessageParser *parser, @@ -66,6 +99,7 @@ void json_message_parser_init(JSONMessageParser *parser, parser->brace_count = 0; parser->bracket_count = 0; parser->tokens = qlist_new(); + parser->token_size = 0; json_lexer_init(&parser->lexer, json_message_process_token); } diff --git a/json-streamer.h b/json-streamer.h index 09f3bd70e4..f09bc4daec 100644 --- a/json-streamer.h +++ b/json-streamer.h @@ -24,6 +24,7 @@ typedef struct JSONMessageParser int brace_count; int bracket_count; QList *tokens; + uint64_t token_size; } JSONMessageParser; void json_message_parser_init(JSONMessageParser *parser, diff --git a/linux-user/signal.c b/linux-user/signal.c index c7a375fe0e..11b25be7b8 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -21,7 +21,6 @@ #include <string.h> #include <stdarg.h> #include <unistd.h> -#include <signal.h> #include <errno.h> #include <assert.h> #include <sys/ucontext.h> diff --git a/net/slirp.c b/net/slirp.c index e387a116ad..e057a14ce9 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -614,7 +614,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, } fwd = qemu_malloc(sizeof(struct GuestFwd)); - snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port); + snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port); fwd->hd = qemu_chr_open(buf, p, NULL); if (!fwd->hd) { error_report("could not open guest forwarding device '%s'", buf); @@ -27,7 +27,6 @@ #include "config-host.h" -#include <signal.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/wait.h> diff --git a/pc-bios/s390-zipl.rom b/pc-bios/s390-zipl.rom Binary files differindex f7af9b155d..3115128efe 100644 --- a/pc-bios/s390-zipl.rom +++ b/pc-bios/s390-zipl.rom diff --git a/posix-aio-compat.c b/posix-aio-compat.c index f3cc8687ce..c4116e30f2 100644 --- a/posix-aio-compat.c +++ b/posix-aio-compat.c @@ -17,7 +17,6 @@ #include <unistd.h> #include <errno.h> #include <time.h> -#include <signal.h> #include <string.h> #include <stdlib.h> #include <stdio.h> diff --git a/qemu-char.c b/qemu-char.c index 5e04a20b8c..fb13b28454 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -35,7 +35,6 @@ #include <unistd.h> #include <fcntl.h> -#include <signal.h> #include <time.h> #include <errno.h> #include <sys/time.h> diff --git a/qemu-common.h b/qemu-common.h index b851b20c51..39fabc9e0f 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -39,6 +39,7 @@ typedef struct Monitor Monitor; #include <sys/stat.h> #include <sys/time.h> #include <assert.h> +#include <signal.h> #ifdef _WIN32 #include "qemu-os-win32.h" diff --git a/qemu-config.c b/qemu-config.c index 5d7ffa2f23..c63741c6b1 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -306,7 +306,7 @@ static QemuOptsList qemu_trace_opts = { .name = "file", .type = QEMU_OPT_STRING, }, - { /* end if list */ } + { /* end of list */ } }, }; #endif @@ -385,6 +385,12 @@ QemuOptsList qemu_spice_opts = { .name = "disable-ticketing", .type = QEMU_OPT_BOOL, },{ + .name = "disable-copy-paste", + .type = QEMU_OPT_BOOL, + },{ + .name = "sasl", + .type = QEMU_OPT_BOOL, + },{ .name = "x509-dir", .type = QEMU_OPT_STRING, },{ @@ -430,7 +436,7 @@ QemuOptsList qemu_spice_opts = { .name = "playback-compression", .type = QEMU_OPT_BOOL, }, - { /* end if list */ } + { /* end of list */ } }, }; @@ -446,7 +452,7 @@ QemuOptsList qemu_option_rom_opts = { .name = "romfile", .type = QEMU_OPT_STRING, }, - { /* end if list */ } + { /* end of list */ } }, }; @@ -1655,7 +1655,7 @@ open_f(int argc, char **argv) flags |= BDRV_O_SNAPSHOT; break; case 'n': - flags |= BDRV_O_NOCACHE; + flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; break; case 'r': readonly = 1; @@ -1751,7 +1751,7 @@ int main(int argc, char **argv) flags |= BDRV_O_SNAPSHOT; break; case 'n': - flags |= BDRV_O_NOCACHE; + flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; break; case 'c': add_user_command(optarg); diff --git a/qemu-nbd.c b/qemu-nbd.c index e858033e06..110d78e6a4 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -238,7 +238,7 @@ int main(int argc, char **argv) flags |= BDRV_O_SNAPSHOT; break; case 'n': - flags |= BDRV_O_NOCACHE; + flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB; break; case 'b': bindto = optarg; diff --git a/qemu-options.hx b/qemu-options.hx index 82e085a229..d9edff7d35 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -714,9 +714,25 @@ Force using the specified IP version. @item password=<secret> Set the password you need to authenticate. +@item sasl +Require that the client use SASL to authenticate with the spice. +The exact choice of authentication method used is controlled from the +system / user's SASL configuration file for the 'qemu' service. This +is typically found in /etc/sasl2/qemu.conf. If running QEMU as an +unprivileged user, an environment variable SASL_CONF_PATH can be used +to make it search alternate locations for the service config. +While some SASL auth methods can also provide data encryption (eg GSSAPI), +it is recommended that SASL always be combined with the 'tls' and +'x509' settings to enable use of SSL and server certificates. This +ensures a data encryption preventing compromise of authentication +credentials. + @item disable-ticketing Allow client connects without authentication. +@item disable-copy-paste +Disable copy paste between the client and the guest. + @item tls-port=<nr> Set the TCP port spice is listening on for encrypted channels. diff --git a/qemu-progress.c b/qemu-progress.c index 8ebe8efa99..5f1b8dfb97 100644 --- a/qemu-progress.c +++ b/qemu-progress.c @@ -26,7 +26,6 @@ #include "osdep.h" #include "sysemu.h" #include <stdio.h> -#include <signal.h> struct progress_state { float current; diff --git a/qemu-timer.c b/qemu-timer.c index 4141b6edbe..72066c7c50 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -39,15 +39,6 @@ #include <sys/param.h> #endif -#ifdef __linux__ -#include <sys/ioctl.h> -#include <linux/rtc.h> -/* For the benefit of older linux systems which don't supply it, - we use a local copy of hpet.h. */ -/* #include <linux/hpet.h> */ -#include "hpet.h" -#endif - #ifdef _WIN32 #include <windows.h> #include <mmsystem.h> @@ -234,12 +225,6 @@ static int dynticks_start_timer(struct qemu_alarm_timer *t); static void dynticks_stop_timer(struct qemu_alarm_timer *t); static void dynticks_rearm_timer(struct qemu_alarm_timer *t); -static int hpet_start_timer(struct qemu_alarm_timer *t); -static void hpet_stop_timer(struct qemu_alarm_timer *t); - -static int rtc_start_timer(struct qemu_alarm_timer *t); -static void rtc_stop_timer(struct qemu_alarm_timer *t); - #endif /* __linux__ */ #endif /* _WIN32 */ @@ -304,10 +289,6 @@ static struct qemu_alarm_timer alarm_timers[] = { #ifdef __linux__ {"dynticks", dynticks_start_timer, dynticks_stop_timer, dynticks_rearm_timer}, - /* HPET - if available - is preferred */ - {"hpet", hpet_start_timer, hpet_stop_timer, NULL}, - /* ...otherwise try RTC */ - {"rtc", rtc_start_timer, rtc_stop_timer, NULL}, #endif {"unix", unix_start_timer, unix_stop_timer, NULL}, #else @@ -822,107 +803,6 @@ static int64_t qemu_next_alarm_deadline(void) #if defined(__linux__) -#define RTC_FREQ 1024 - -static void enable_sigio_timer(int fd) -{ - struct sigaction act; - - /* timer signal */ - sigfillset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = host_alarm_handler; - - sigaction(SIGIO, &act, NULL); - fcntl_setfl(fd, O_ASYNC); - fcntl(fd, F_SETOWN, getpid()); -} - -static int hpet_start_timer(struct qemu_alarm_timer *t) -{ - struct hpet_info info; - int r, fd; - - fd = qemu_open("/dev/hpet", O_RDONLY); - if (fd < 0) - return -1; - - /* Set frequency */ - r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ); - if (r < 0) { - fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n" - "error, but for better emulation accuracy type:\n" - "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n"); - goto fail; - } - - /* Check capabilities */ - r = ioctl(fd, HPET_INFO, &info); - if (r < 0) - goto fail; - - /* Enable periodic mode */ - r = ioctl(fd, HPET_EPI, 0); - if (info.hi_flags && (r < 0)) - goto fail; - - /* Enable interrupt */ - r = ioctl(fd, HPET_IE_ON, 0); - if (r < 0) - goto fail; - - enable_sigio_timer(fd); - t->fd = fd; - - return 0; -fail: - close(fd); - return -1; -} - -static void hpet_stop_timer(struct qemu_alarm_timer *t) -{ - int fd = t->fd; - - close(fd); -} - -static int rtc_start_timer(struct qemu_alarm_timer *t) -{ - int rtc_fd; - unsigned long current_rtc_freq = 0; - - TFR(rtc_fd = qemu_open("/dev/rtc", O_RDONLY)); - if (rtc_fd < 0) - return -1; - ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq); - if (current_rtc_freq != RTC_FREQ && - ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { - fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n" - "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n" - "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n"); - goto fail; - } - if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) { - fail: - close(rtc_fd); - return -1; - } - - enable_sigio_timer(rtc_fd); - - t->fd = rtc_fd; - - return 0; -} - -static void rtc_stop_timer(struct qemu_alarm_timer *t) -{ - int rtc_fd = t->fd; - - close(rtc_fd); -} - static int dynticks_start_timer(struct qemu_alarm_timer *t) { struct sigevent ev; @@ -330,12 +330,14 @@ QError *qerror_from_info(const char *file, int linenr, const char *func, return qerr; } -static void parse_error(const QError *qerror, int c) +static void parse_error(const QErrorStringTable *entry, int c) { - qerror_abort(qerror, "expected '%c' in '%s'", c, qerror->entry->desc); + fprintf(stderr, "expected '%c' in '%s'", c, entry->desc); + abort(); } -static const char *append_field(QString *outstr, const QError *qerror, +static const char *append_field(QDict *error, QString *outstr, + const QErrorStringTable *entry, const char *start) { QObject *obj; @@ -344,23 +346,23 @@ static const char *append_field(QString *outstr, const QError *qerror, const char *end, *key; if (*start != '%') - parse_error(qerror, '%'); + parse_error(entry, '%'); start++; if (*start != '(') - parse_error(qerror, '('); + parse_error(entry, '('); start++; end = strchr(start, ')'); if (!end) - parse_error(qerror, ')'); + parse_error(entry, ')'); key_qs = qstring_from_substr(start, 0, end - start - 1); key = qstring_get_str(key_qs); - qdict = qobject_to_qdict(qdict_get(qerror->error, "data")); + qdict = qobject_to_qdict(qdict_get(error, "data")); obj = qdict_get(qdict, key); if (!obj) { - qerror_abort(qerror, "key '%s' not found in QDict", key); + abort(); } switch (qobject_type(obj)) { @@ -371,41 +373,60 @@ static const char *append_field(QString *outstr, const QError *qerror, qstring_append_int(outstr, qdict_get_int(qdict, key)); break; default: - qerror_abort(qerror, "invalid type '%c'", qobject_type(obj)); + abort(); } QDECREF(key_qs); return ++end; } -/** - * qerror_human(): Format QError data into human-readable string. - * - * Formats according to member 'desc' of the specified QError object. - */ -QString *qerror_human(const QError *qerror) +static QString *qerror_format_desc(QDict *error, + const QErrorStringTable *entry) { - const char *p; QString *qstring; + const char *p; - assert(qerror->entry != NULL); + assert(entry != NULL); qstring = qstring_new(); - for (p = qerror->entry->desc; *p != '\0';) { + for (p = entry->desc; *p != '\0';) { if (*p != '%') { qstring_append_chr(qstring, *p++); } else if (*(p + 1) == '%') { qstring_append_chr(qstring, '%'); p += 2; } else { - p = append_field(qstring, qerror, p); + p = append_field(error, qstring, entry, p); } } return qstring; } +QString *qerror_format(const char *fmt, QDict *error) +{ + const QErrorStringTable *entry = NULL; + int i; + + for (i = 0; qerror_table[i].error_fmt; i++) { + if (strcmp(qerror_table[i].error_fmt, fmt) == 0) { + entry = &qerror_table[i]; + break; + } + } + + return qerror_format_desc(error, entry); +} + +/** + * qerror_human(): Format QError data into human-readable string. + */ +QString *qerror_human(const QError *qerror) +{ + return qerror_format_desc(qerror->error, qerror->entry); +} + /** * qerror_print(): Print QError data * @@ -39,6 +39,7 @@ QString *qerror_human(const QError *qerror); void qerror_print(QError *qerror); void qerror_report_internal(const char *file, int linenr, const char *func, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +QString *qerror_format(const char *fmt, QDict *error); #define qerror_report(fmt, ...) \ qerror_report_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__) QError *qobject_to_qerror(const QObject *obj); @@ -120,6 +121,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_JSON_PARSING \ "{ 'class': 'JSONParsing', 'data': {} }" +#define QERR_JSON_PARSE_ERROR \ + "{ 'class': 'JSONParseError', 'data': { 'message': %s } }" + #define QERR_KVM_MISSING_CAP \ "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }" @@ -23,7 +23,6 @@ */ #include <unistd.h> #include <fcntl.h> -#include <signal.h> #include <time.h> #include <errno.h> #include <sys/time.h> diff --git a/spice-qemu-char.c b/spice-qemu-char.c index fa15a71e14..605c241239 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -36,14 +36,13 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) while (len > 0) { last_out = MIN(len, VMC_MAX_HOST_WRITE); - qemu_chr_read(scd->chr, p, last_out); - if (last_out > 0) { - out += last_out; - len -= last_out; - p += last_out; - } else { + if (qemu_chr_can_read(scd->chr) < last_out) { break; } + qemu_chr_read(scd->chr, p, last_out); + out += last_out; + len -= last_out; + p += last_out; } dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out); diff --git a/target-arm/helper.c b/target-arm/helper.c index 1cc492d8a3..12084167d6 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -848,6 +848,7 @@ void do_interrupt(CPUARMState *env) return; } } + env->cp15.c5_insn = 2; /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: new_mode = ARM_CPU_MODE_ABT; diff --git a/target-arm/translate.c b/target-arm/translate.c index 1501db1b1f..f5507ec3b6 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -980,20 +980,20 @@ static inline void gen_vfp_F1_ld0(int dp) #define VFP_GEN_ITOF(name) \ static inline void gen_vfp_##name(int dp, int neon) \ { \ - TCGv statusptr = tcg_temp_new_i32(); \ + TCGv_ptr statusptr = tcg_temp_new_ptr(); \ int offset; \ if (neon) { \ offset = offsetof(CPUState, vfp.standard_fp_status); \ } else { \ offset = offsetof(CPUState, vfp.fp_status); \ } \ - tcg_gen_addi_i32(statusptr, cpu_env, offset); \ + tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ if (dp) { \ gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \ } else { \ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ } \ - tcg_temp_free_i32(statusptr); \ + tcg_temp_free_ptr(statusptr); \ } VFP_GEN_ITOF(uito) @@ -1003,20 +1003,20 @@ VFP_GEN_ITOF(sito) #define VFP_GEN_FTOI(name) \ static inline void gen_vfp_##name(int dp, int neon) \ { \ - TCGv statusptr = tcg_temp_new_i32(); \ + TCGv_ptr statusptr = tcg_temp_new_ptr(); \ int offset; \ if (neon) { \ offset = offsetof(CPUState, vfp.standard_fp_status); \ } else { \ offset = offsetof(CPUState, vfp.fp_status); \ } \ - tcg_gen_addi_i32(statusptr, cpu_env, offset); \ + tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ if (dp) { \ gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \ } else { \ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ } \ - tcg_temp_free_i32(statusptr); \ + tcg_temp_free_ptr(statusptr); \ } VFP_GEN_FTOI(toui) @@ -1029,21 +1029,21 @@ VFP_GEN_FTOI(tosiz) static inline void gen_vfp_##name(int dp, int shift, int neon) \ { \ TCGv tmp_shift = tcg_const_i32(shift); \ - TCGv statusptr = tcg_temp_new_i32(); \ + TCGv_ptr statusptr = tcg_temp_new_ptr(); \ int offset; \ if (neon) { \ offset = offsetof(CPUState, vfp.standard_fp_status); \ } else { \ offset = offsetof(CPUState, vfp.fp_status); \ } \ - tcg_gen_addi_i32(statusptr, cpu_env, offset); \ + tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ if (dp) { \ gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ } else { \ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \ } \ tcg_temp_free_i32(tmp_shift); \ - tcg_temp_free_i32(statusptr); \ + tcg_temp_free_ptr(statusptr); \ } VFP_GEN_FIX(tosh) VFP_GEN_FIX(tosl) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 715828f2df..fe658862c2 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -532,16 +532,6 @@ enum { CC_OP_NB, }; -#ifdef FLOATX80 -#define USE_X86LDOUBLE -#endif - -#ifdef USE_X86LDOUBLE -typedef floatx80 CPU86_LDouble; -#else -typedef float64 CPU86_LDouble; -#endif - typedef struct SegmentCache { uint32_t selector; target_ulong base; @@ -594,11 +584,7 @@ typedef union { #define MMX_Q(n) q typedef union { -#ifdef USE_X86LDOUBLE - CPU86_LDouble d __attribute__((aligned(16))); -#else - CPU86_LDouble d; -#endif + floatx80 d __attribute__((aligned(16))); MMXReg mmx; } FPReg; @@ -654,7 +640,7 @@ typedef struct CPUX86State { /* emulator internal variables */ float_status fp_status; - CPU86_LDouble ft0; + floatx80 ft0; float_status mmx_status; /* for 3DNow! float ops */ float_status sse_status; @@ -865,8 +851,8 @@ static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) /* op_helper.c */ /* used for debug or cpu save/restore */ -void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f); -CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper); +void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f); +floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper); /* cpu-exec.c */ /* the following helpers are only usable in user mode simulation as diff --git a/target-i386/exec.h b/target-i386/exec.h index ee36a7181a..9bd080e3a8 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -98,67 +98,6 @@ static inline void svm_check_intercept(uint32_t type) #endif /* !defined(CONFIG_USER_ONLY) */ -#ifdef USE_X86LDOUBLE -/* use long double functions */ -#define floatx_to_int32 floatx80_to_int32 -#define floatx_to_int64 floatx80_to_int64 -#define floatx_to_int32_round_to_zero floatx80_to_int32_round_to_zero -#define floatx_to_int64_round_to_zero floatx80_to_int64_round_to_zero -#define int32_to_floatx int32_to_floatx80 -#define int64_to_floatx int64_to_floatx80 -#define float32_to_floatx float32_to_floatx80 -#define float64_to_floatx float64_to_floatx80 -#define floatx_to_float32 floatx80_to_float32 -#define floatx_to_float64 floatx80_to_float64 -#define floatx_add floatx80_add -#define floatx_div floatx80_div -#define floatx_mul floatx80_mul -#define floatx_sub floatx80_sub -#define floatx_sqrt floatx80_sqrt -#define floatx_abs floatx80_abs -#define floatx_chs floatx80_chs -#define floatx_scalbn floatx80_scalbn -#define floatx_round_to_int floatx80_round_to_int -#define floatx_compare floatx80_compare -#define floatx_compare_quiet floatx80_compare_quiet -#define floatx_is_any_nan floatx80_is_any_nan -#define floatx_is_neg floatx80_is_neg -#define floatx_is_zero floatx80_is_zero -#define floatx_zero floatx80_zero -#define floatx_one floatx80_one -#define floatx_ln2 floatx80_ln2 -#define floatx_pi floatx80_pi -#else -#define floatx_to_int32 float64_to_int32 -#define floatx_to_int64 float64_to_int64 -#define floatx_to_int32_round_to_zero float64_to_int32_round_to_zero -#define floatx_to_int64_round_to_zero float64_to_int64_round_to_zero -#define int32_to_floatx int32_to_float64 -#define int64_to_floatx int64_to_float64 -#define float32_to_floatx float32_to_float64 -#define float64_to_floatx(x, e) (x) -#define floatx_to_float32 float64_to_float32 -#define floatx_to_float64(x, e) (x) -#define floatx_add float64_add -#define floatx_div float64_div -#define floatx_mul float64_mul -#define floatx_sub float64_sub -#define floatx_sqrt float64_sqrt -#define floatx_abs float64_abs -#define floatx_chs float64_chs -#define floatx_scalbn float64_scalbn -#define floatx_round_to_int float64_round_to_int -#define floatx_compare float64_compare -#define floatx_compare_quiet float64_compare_quiet -#define floatx_is_any_nan float64_is_any_nan -#define floatx_is_neg float64_is_neg -#define floatx_is_zero float64_is_zero -#define floatx_zero float64_zero -#define floatx_one float64_one -#define floatx_ln2 float64_ln2 -#define floatx_pi float64_pi -#endif - #define RC_MASK 0xc00 #define RC_NEAR 0x000 #define RC_DOWN 0x400 @@ -167,11 +106,6 @@ static inline void svm_check_intercept(uint32_t type) #define MAXTAN 9223372036854775808.0 -#ifdef USE_X86LDOUBLE - -/* only for x86 */ -typedef CPU_LDoubleU CPU86_LDoubleU; - /* the following deal with x86 long double-precision numbers */ #define MAXEXPD 0x7fff #define EXPBIAS 16383 @@ -180,23 +114,6 @@ typedef CPU_LDoubleU CPU86_LDoubleU; #define MANTD(fp) (fp.l.lower) #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS -#else - -typedef CPU_DoubleU CPU86_LDoubleU; - -/* the following deal with IEEE double-precision numbers */ -#define MAXEXPD 0x7ff -#define EXPBIAS 1023 -#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) -#define SIGND(fp) ((fp.l.upper) & 0x80000000) -#ifdef __arm__ -#define MANTD(fp) (fp.l.lower | ((uint64_t)(fp.l.upper & ((1 << 20) - 1)) << 32)) -#else -#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) -#endif -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) -#endif - static inline void fpush(void) { env->fpstt = (env->fpstt - 1) & 7; @@ -209,65 +126,24 @@ static inline void fpop(void) env->fpstt = (env->fpstt + 1) & 7; } -#ifndef USE_X86LDOUBLE -static inline CPU86_LDouble helper_fldt(target_ulong ptr) -{ - CPU86_LDoubleU temp; - int upper, e; - uint64_t ll; - - /* mantissa */ - upper = lduw(ptr + 8); - /* XXX: handle overflow ? */ - e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ - e |= (upper >> 4) & 0x800; /* sign */ - ll = (ldq(ptr) >> 11) & ((1LL << 52) - 1); -#ifdef __arm__ - temp.l.upper = (e << 20) | (ll >> 32); - temp.l.lower = ll; -#else - temp.ll = ll | ((uint64_t)e << 52); -#endif - return temp.d; -} - -static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) +static inline floatx80 helper_fldt(target_ulong ptr) { - CPU86_LDoubleU temp; - int e; - - temp.d = f; - /* mantissa */ - stq(ptr, (MANTD(temp) << 11) | (1LL << 63)); - /* exponent + sign */ - e = EXPD(temp) - EXPBIAS + 16383; - e |= SIGND(temp) >> 16; - stw(ptr + 8, e); -} -#else - -/* we use memory access macros */ - -static inline CPU86_LDouble helper_fldt(target_ulong ptr) -{ - CPU86_LDoubleU temp; + CPU_LDoubleU temp; temp.l.lower = ldq(ptr); temp.l.upper = lduw(ptr + 8); return temp.d; } -static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) +static inline void helper_fstt(floatx80 f, target_ulong ptr) { - CPU86_LDoubleU temp; + CPU_LDoubleU temp; temp.d = f; stq(ptr, temp.l.lower); stw(ptr + 8, temp.l.upper); } -#endif /* USE_X86LDOUBLE */ - #define FPUS_IE (1 << 0) #define FPUS_DE (1 << 1) #define FPUS_ZE (1 << 2) diff --git a/target-i386/helper.c b/target-i386/helper.c index 89df997436..509d68ca0f 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -21,7 +21,6 @@ #include <stdio.h> #include <string.h> #include <inttypes.h> -#include <signal.h> #include "cpu.h" #include "exec-all.h" @@ -403,15 +402,10 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf, fptag, env->mxcsr); for(i=0;i<8;i++) { -#if defined(USE_X86LDOUBLE) CPU_LDoubleU u; u.d = env->fpregs[i].d; cpu_fprintf(f, "FPR%d=%016" PRIx64 " %04x", i, u.l.lower, u.l.upper); -#else - cpu_fprintf(f, "FPR%d=%016" PRIx64, - i, env->fpregs[i].mmx.q); -#endif if ((i & 1) == 1) cpu_fprintf(f, "\n"); else diff --git a/target-i386/machine.c b/target-i386/machine.c index d78eceb779..bbeae8852c 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -84,7 +84,6 @@ static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) exit(0); } -#ifdef USE_X86LDOUBLE /* XXX: add that in a FPU generic layer */ union x86_longdouble { uint64_t mant; @@ -202,102 +201,6 @@ static bool fpregs_is_1_no_mmx(void *opaque, int version_id) VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_mmx, vmstate_fpreg_1_mmx, FPReg), \ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_no_mmx, vmstate_fpreg_1_no_mmx, FPReg) -#else -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) -{ - FPReg *fp_reg = opaque; - - qemu_get_be64s(f, &fp_reg->mmx.MMX_Q(0)); - return 0; -} - -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) -{ - FPReg *fp_reg = opaque; - /* if we use doubles for float emulation, we save the doubles to - avoid losing information in case of MMX usage. It can give - problems if the image is restored on a CPU where long - doubles are used instead. */ - qemu_put_be64s(f, &fp_reg->mmx.MMX_Q(0)); -} - -const VMStateInfo vmstate_fpreg = { - .name = "fpreg", - .get = get_fpreg, - .put = put_fpreg, -}; - -static int get_fpreg_0_mmx(QEMUFile *f, void *opaque, size_t size) -{ - FPReg *fp_reg = opaque; - uint64_t mant; - uint16_t exp; - - qemu_get_be64s(f, &mant); - qemu_get_be16s(f, &exp); - fp_reg->mmx.MMX_Q(0) = mant; - return 0; -} - -const VMStateInfo vmstate_fpreg_0_mmx = { - .name = "fpreg_0_mmx", - .get = get_fpreg_0_mmx, - .put = put_fpreg_error, -}; - -static int get_fpreg_0_no_mmx(QEMUFile *f, void *opaque, size_t size) -{ - FPReg *fp_reg = opaque; - uint64_t mant; - uint16_t exp; - - qemu_get_be64s(f, &mant); - qemu_get_be16s(f, &exp); - - fp_reg->d = cpu_set_fp80(mant, exp); - return 0; -} - -const VMStateInfo vmstate_fpreg_0_no_mmx = { - .name = "fpreg_0_no_mmx", - .get = get_fpreg_0_no_mmx, - .put = put_fpreg_error, -}; - -static bool fpregs_is_1(void *opaque, int version_id) -{ - CPUState *env = opaque; - - return env->fpregs_format_vmstate == 1; -} - -static bool fpregs_is_0_mmx(void *opaque, int version_id) -{ - CPUState *env = opaque; - int guess_mmx; - - guess_mmx = ((env->fptag_vmstate == 0xff) && - (env->fpus_vmstate & 0x3800) == 0); - return guess_mmx && env->fpregs_format_vmstate == 0; -} - -static bool fpregs_is_0_no_mmx(void *opaque, int version_id) -{ - CPUState *env = opaque; - int guess_mmx; - - guess_mmx = ((env->fptag_vmstate == 0xff) && - (env->fpus_vmstate & 0x3800) == 0); - return !guess_mmx && env->fpregs_format_vmstate == 0; -} - -#define VMSTATE_FP_REGS(_field, _state, _n) \ - VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1, vmstate_fpreg, FPReg), \ - VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0_mmx, vmstate_fpreg_0_mmx, FPReg), \ - VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0_no_mmx, vmstate_fpreg_0_no_mmx, FPReg) - -#endif /* USE_X86LDOUBLE */ - static bool version_is_5(void *opaque, int version_id) { return version_id == 5; @@ -344,11 +247,7 @@ static void cpu_pre_save(void *opaque) env->fptag_vmstate |= ((!env->fptags[i]) << i); } -#ifdef USE_X86LDOUBLE env->fpregs_format_vmstate = 0; -#else - env->fpregs_format_vmstate = 1; -#endif } static int cpu_post_load(void *opaque, int version_id) diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c index 3c539f37cf..cec0c7686f 100644 --- a/target-i386/op_helper.c +++ b/target-i386/op_helper.c @@ -95,26 +95,9 @@ static const uint8_t rclb_table[32] = { 6, 7, 8, 0, 1, 2, 3, 4, }; -#if defined(CONFIG_SOFTFLOAT) -# define floatx_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL ) -# define floatx_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL ) -# define floatx_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL ) -#else -# define floatx_lg2 (0.30102999566398119523L) -# define floatx_l2e (1.44269504088896340739L) -# define floatx_l2t (3.32192809488736234781L) -#endif - -static const CPU86_LDouble f15rk[7] = -{ - floatx_zero, - floatx_one, - floatx_pi, - floatx_lg2, - floatx_ln2, - floatx_l2e, - floatx_l2t, -}; +#define floatx80_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL ) +#define floatx80_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL ) +#define floatx80_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL ) /* broken thread support */ @@ -3442,18 +3425,18 @@ void helper_verw(target_ulong selector1) /* x87 FPU helpers */ -static inline double CPU86_LDouble_to_double(CPU86_LDouble a) +static inline double floatx80_to_double(floatx80 a) { union { float64 f64; double d; } u; - u.f64 = floatx_to_float64(a, &env->fp_status); + u.f64 = floatx80_to_float64(a, &env->fp_status); return u.d; } -static inline CPU86_LDouble double_to_CPU86_LDouble(double a) +static inline floatx80 double_to_floatx80(double a) { union { float64 f64; @@ -3461,7 +3444,7 @@ static inline CPU86_LDouble double_to_CPU86_LDouble(double a) } u; u.d = a; - return float64_to_floatx(u.f64, &env->fp_status); + return float64_to_floatx80(u.f64, &env->fp_status); } static void fpu_set_exception(int mask) @@ -3471,12 +3454,12 @@ static void fpu_set_exception(int mask) env->fpus |= FPUS_SE | FPUS_B; } -static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b) +static inline floatx80 helper_fdiv(floatx80 a, floatx80 b) { - if (floatx_is_zero(b)) { + if (floatx80_is_zero(b)) { fpu_set_exception(FPUS_ZE); } - return floatx_div(a, b, &env->fp_status); + return floatx80_div(a, b, &env->fp_status); } static void fpu_raise_exception(void) @@ -3498,7 +3481,7 @@ void helper_flds_FT0(uint32_t val) uint32_t i; } u; u.i = val; - FT0 = float32_to_floatx(u.f, &env->fp_status); + FT0 = float32_to_floatx80(u.f, &env->fp_status); } void helper_fldl_FT0(uint64_t val) @@ -3508,12 +3491,12 @@ void helper_fldl_FT0(uint64_t val) uint64_t i; } u; u.i = val; - FT0 = float64_to_floatx(u.f, &env->fp_status); + FT0 = float64_to_floatx80(u.f, &env->fp_status); } void helper_fildl_FT0(int32_t val) { - FT0 = int32_to_floatx(val, &env->fp_status); + FT0 = int32_to_floatx80(val, &env->fp_status); } void helper_flds_ST0(uint32_t val) @@ -3525,7 +3508,7 @@ void helper_flds_ST0(uint32_t val) } u; new_fpstt = (env->fpstt - 1) & 7; u.i = val; - env->fpregs[new_fpstt].d = float32_to_floatx(u.f, &env->fp_status); + env->fpregs[new_fpstt].d = float32_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ } @@ -3539,7 +3522,7 @@ void helper_fldl_ST0(uint64_t val) } u; new_fpstt = (env->fpstt - 1) & 7; u.i = val; - env->fpregs[new_fpstt].d = float64_to_floatx(u.f, &env->fp_status); + env->fpregs[new_fpstt].d = float64_to_floatx80(u.f, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ } @@ -3548,7 +3531,7 @@ void helper_fildl_ST0(int32_t val) { int new_fpstt; new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = int32_to_floatx(val, &env->fp_status); + env->fpregs[new_fpstt].d = int32_to_floatx80(val, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ } @@ -3557,7 +3540,7 @@ void helper_fildll_ST0(int64_t val) { int new_fpstt; new_fpstt = (env->fpstt - 1) & 7; - env->fpregs[new_fpstt].d = int64_to_floatx(val, &env->fp_status); + env->fpregs[new_fpstt].d = int64_to_floatx80(val, &env->fp_status); env->fpstt = new_fpstt; env->fptags[new_fpstt] = 0; /* validate stack entry */ } @@ -3568,7 +3551,7 @@ uint32_t helper_fsts_ST0(void) float32 f; uint32_t i; } u; - u.f = floatx_to_float32(ST0, &env->fp_status); + u.f = floatx80_to_float32(ST0, &env->fp_status); return u.i; } @@ -3578,14 +3561,14 @@ uint64_t helper_fstl_ST0(void) float64 f; uint64_t i; } u; - u.f = floatx_to_float64(ST0, &env->fp_status); + u.f = floatx80_to_float64(ST0, &env->fp_status); return u.i; } int32_t helper_fist_ST0(void) { int32_t val; - val = floatx_to_int32(ST0, &env->fp_status); + val = floatx80_to_int32(ST0, &env->fp_status); if (val != (int16_t)val) val = -32768; return val; @@ -3594,21 +3577,21 @@ int32_t helper_fist_ST0(void) int32_t helper_fistl_ST0(void) { int32_t val; - val = floatx_to_int32(ST0, &env->fp_status); + val = floatx80_to_int32(ST0, &env->fp_status); return val; } int64_t helper_fistll_ST0(void) { int64_t val; - val = floatx_to_int64(ST0, &env->fp_status); + val = floatx80_to_int64(ST0, &env->fp_status); return val; } int32_t helper_fistt_ST0(void) { int32_t val; - val = floatx_to_int32_round_to_zero(ST0, &env->fp_status); + val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); if (val != (int16_t)val) val = -32768; return val; @@ -3617,14 +3600,14 @@ int32_t helper_fistt_ST0(void) int32_t helper_fisttl_ST0(void) { int32_t val; - val = floatx_to_int32_round_to_zero(ST0, &env->fp_status); + val = floatx80_to_int32_round_to_zero(ST0, &env->fp_status); return val; } int64_t helper_fisttll_ST0(void) { int64_t val; - val = floatx_to_int64_round_to_zero(ST0, &env->fp_status); + val = floatx80_to_int64_round_to_zero(ST0, &env->fp_status); return val; } @@ -3693,7 +3676,7 @@ void helper_fmov_STN_ST0(int st_index) void helper_fxchg_ST0_STN(int st_index) { - CPU86_LDouble tmp; + floatx80 tmp; tmp = ST(st_index); ST(st_index) = ST0; ST0 = tmp; @@ -3707,7 +3690,7 @@ void helper_fcom_ST0_FT0(void) { int ret; - ret = floatx_compare(ST0, FT0, &env->fp_status); + ret = floatx80_compare(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1]; } @@ -3715,7 +3698,7 @@ void helper_fucom_ST0_FT0(void) { int ret; - ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); + ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret+ 1]; } @@ -3726,7 +3709,7 @@ void helper_fcomi_ST0_FT0(void) int eflags; int ret; - ret = floatx_compare(ST0, FT0, &env->fp_status); + ret = floatx80_compare(ST0, FT0, &env->fp_status); eflags = helper_cc_compute_all(CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; @@ -3737,7 +3720,7 @@ void helper_fucomi_ST0_FT0(void) int eflags; int ret; - ret = floatx_compare_quiet(ST0, FT0, &env->fp_status); + ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status); eflags = helper_cc_compute_all(CC_OP); eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1]; CC_SRC = eflags; @@ -3745,22 +3728,22 @@ void helper_fucomi_ST0_FT0(void) void helper_fadd_ST0_FT0(void) { - ST0 = floatx_add(ST0, FT0, &env->fp_status); + ST0 = floatx80_add(ST0, FT0, &env->fp_status); } void helper_fmul_ST0_FT0(void) { - ST0 = floatx_mul(ST0, FT0, &env->fp_status); + ST0 = floatx80_mul(ST0, FT0, &env->fp_status); } void helper_fsub_ST0_FT0(void) { - ST0 = floatx_sub(ST0, FT0, &env->fp_status); + ST0 = floatx80_sub(ST0, FT0, &env->fp_status); } void helper_fsubr_ST0_FT0(void) { - ST0 = floatx_sub(FT0, ST0, &env->fp_status); + ST0 = floatx80_sub(FT0, ST0, &env->fp_status); } void helper_fdiv_ST0_FT0(void) @@ -3777,34 +3760,34 @@ void helper_fdivr_ST0_FT0(void) void helper_fadd_STN_ST0(int st_index) { - ST(st_index) = floatx_add(ST(st_index), ST0, &env->fp_status); + ST(st_index) = floatx80_add(ST(st_index), ST0, &env->fp_status); } void helper_fmul_STN_ST0(int st_index) { - ST(st_index) = floatx_mul(ST(st_index), ST0, &env->fp_status); + ST(st_index) = floatx80_mul(ST(st_index), ST0, &env->fp_status); } void helper_fsub_STN_ST0(int st_index) { - ST(st_index) = floatx_sub(ST(st_index), ST0, &env->fp_status); + ST(st_index) = floatx80_sub(ST(st_index), ST0, &env->fp_status); } void helper_fsubr_STN_ST0(int st_index) { - ST(st_index) = floatx_sub(ST0, ST(st_index), &env->fp_status); + ST(st_index) = floatx80_sub(ST0, ST(st_index), &env->fp_status); } void helper_fdiv_STN_ST0(int st_index) { - CPU86_LDouble *p; + floatx80 *p; p = &ST(st_index); *p = helper_fdiv(*p, ST0); } void helper_fdivr_STN_ST0(int st_index) { - CPU86_LDouble *p; + floatx80 *p; p = &ST(st_index); *p = helper_fdiv(ST0, *p); } @@ -3812,52 +3795,52 @@ void helper_fdivr_STN_ST0(int st_index) /* misc FPU operations */ void helper_fchs_ST0(void) { - ST0 = floatx_chs(ST0); + ST0 = floatx80_chs(ST0); } void helper_fabs_ST0(void) { - ST0 = floatx_abs(ST0); + ST0 = floatx80_abs(ST0); } void helper_fld1_ST0(void) { - ST0 = f15rk[1]; + ST0 = floatx80_one; } void helper_fldl2t_ST0(void) { - ST0 = f15rk[6]; + ST0 = floatx80_l2t; } void helper_fldl2e_ST0(void) { - ST0 = f15rk[5]; + ST0 = floatx80_l2e; } void helper_fldpi_ST0(void) { - ST0 = f15rk[2]; + ST0 = floatx80_pi; } void helper_fldlg2_ST0(void) { - ST0 = f15rk[3]; + ST0 = floatx80_lg2; } void helper_fldln2_ST0(void) { - ST0 = f15rk[4]; + ST0 = floatx80_ln2; } void helper_fldz_ST0(void) { - ST0 = f15rk[0]; + ST0 = floatx80_zero; } void helper_fldz_FT0(void) { - FT0 = f15rk[0]; + FT0 = floatx80_zero; } uint32_t helper_fnstsw(void) @@ -3891,7 +3874,6 @@ static void update_fp_status(void) break; } set_float_rounding_mode(rnd_type, &env->fp_status); -#ifdef FLOATX80 switch((env->fpuc >> 8) & 3) { case 0: rnd_type = 32; @@ -3905,7 +3887,6 @@ static void update_fp_status(void) break; } set_floatx80_rounding_precision(rnd_type, &env->fp_status); -#endif } void helper_fldcw(uint32_t val) @@ -3944,7 +3925,7 @@ void helper_fninit(void) void helper_fbld_ST0(target_ulong ptr) { - CPU86_LDouble tmp; + floatx80 tmp; uint64_t val; unsigned int v; int i; @@ -3954,9 +3935,9 @@ void helper_fbld_ST0(target_ulong ptr) v = ldub(ptr + i); val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); } - tmp = int64_to_floatx(val, &env->fp_status); + tmp = int64_to_floatx80(val, &env->fp_status); if (ldub(ptr + 9) & 0x80) { - floatx_chs(tmp); + floatx80_chs(tmp); } fpush(); ST0 = tmp; @@ -3968,7 +3949,7 @@ void helper_fbst_ST0(target_ulong ptr) target_ulong mem_ref, mem_end; int64_t val; - val = floatx_to_int64(ST0, &env->fp_status); + val = floatx80_to_int64(ST0, &env->fp_status); mem_ref = ptr; mem_end = mem_ref + 9; if (val < 0) { @@ -3992,19 +3973,19 @@ void helper_fbst_ST0(target_ulong ptr) void helper_f2xm1(void) { - double val = CPU86_LDouble_to_double(ST0); + double val = floatx80_to_double(ST0); val = pow(2.0, val) - 1.0; - ST0 = double_to_CPU86_LDouble(val); + ST0 = double_to_floatx80(val); } void helper_fyl2x(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if (fptemp>0.0){ fptemp = log(fptemp)/log(2.0); /* log2(ST) */ - fptemp *= CPU86_LDouble_to_double(ST1); - ST1 = double_to_CPU86_LDouble(fptemp); + fptemp *= floatx80_to_double(ST1); + ST1 = double_to_floatx80(fptemp); fpop(); } else { env->fpus &= (~0x4700); @@ -4014,15 +3995,15 @@ void helper_fyl2x(void) void helper_fptan(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { fptemp = tan(fptemp); - ST0 = double_to_CPU86_LDouble(fptemp); + ST0 = double_to_floatx80(fptemp); fpush(); - ST0 = floatx_one; + ST0 = floatx80_one; env->fpus &= (~0x400); /* C2 <-- 0 */ /* the above code is for |arg| < 2**52 only */ } @@ -4032,21 +4013,21 @@ void helper_fpatan(void) { double fptemp, fpsrcop; - fpsrcop = CPU86_LDouble_to_double(ST1); - fptemp = CPU86_LDouble_to_double(ST0); - ST1 = double_to_CPU86_LDouble(atan2(fpsrcop, fptemp)); + fpsrcop = floatx80_to_double(ST1); + fptemp = floatx80_to_double(ST0); + ST1 = double_to_floatx80(atan2(fpsrcop, fptemp)); fpop(); } void helper_fxtract(void) { - CPU86_LDoubleU temp; + CPU_LDoubleU temp; temp.d = ST0; - if (floatx_is_zero(ST0)) { + if (floatx80_is_zero(ST0)) { /* Easy way to generate -inf and raising division by 0 exception */ - ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status); + ST0 = floatx80_div(floatx80_chs(floatx80_one), floatx80_zero, &env->fp_status); fpush(); ST0 = temp.d; } else { @@ -4054,7 +4035,7 @@ void helper_fxtract(void) expdif = EXPD(temp) - EXPBIAS; /*DP exponent bias*/ - ST0 = int32_to_floatx(expdif, &env->fp_status); + ST0 = int32_to_floatx80(expdif, &env->fp_status); fpush(); BIASEXPONENT(temp); ST0 = temp.d; @@ -4064,15 +4045,15 @@ void helper_fxtract(void) void helper_fprem1(void) { double st0, st1, dblq, fpsrcop, fptemp; - CPU86_LDoubleU fpsrcop1, fptemp1; + CPU_LDoubleU fpsrcop1, fptemp1; int expdif; signed long long int q; - st0 = CPU86_LDouble_to_double(ST0); - st1 = CPU86_LDouble_to_double(ST1); + st0 = floatx80_to_double(ST0); + st1 = floatx80_to_double(ST1); if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */ + ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ return; } @@ -4116,21 +4097,21 @@ void helper_fprem1(void) -(floor(fabs(fpsrcop))) : floor(fpsrcop); st0 -= (st1 * fpsrcop * fptemp); } - ST0 = double_to_CPU86_LDouble(st0); + ST0 = double_to_floatx80(st0); } void helper_fprem(void) { double st0, st1, dblq, fpsrcop, fptemp; - CPU86_LDoubleU fpsrcop1, fptemp1; + CPU_LDoubleU fpsrcop1, fptemp1; int expdif; signed long long int q; - st0 = CPU86_LDouble_to_double(ST0); - st1 = CPU86_LDouble_to_double(ST1); + st0 = floatx80_to_double(ST0); + st1 = floatx80_to_double(ST1); if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) { - ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */ + ST0 = double_to_floatx80(0.0 / 0.0); /* NaN */ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ return; } @@ -4175,17 +4156,17 @@ void helper_fprem(void) -(floor(fabs(fpsrcop))) : floor(fpsrcop); st0 -= (st1 * fpsrcop * fptemp); } - ST0 = double_to_CPU86_LDouble(st0); + ST0 = double_to_floatx80(st0); } void helper_fyl2xp1(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if ((fptemp+1.0)>0.0) { fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */ - fptemp *= CPU86_LDouble_to_double(ST1); - ST1 = double_to_CPU86_LDouble(fptemp); + fptemp *= floatx80_to_double(ST1); + ST1 = double_to_floatx80(fptemp); fpop(); } else { env->fpus &= (~0x4700); @@ -4195,23 +4176,23 @@ void helper_fyl2xp1(void) void helper_fsqrt(void) { - if (floatx_is_neg(ST0)) { + if (floatx80_is_neg(ST0)) { env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ env->fpus |= 0x400; } - ST0 = floatx_sqrt(ST0, &env->fp_status); + ST0 = floatx80_sqrt(ST0, &env->fp_status); } void helper_fsincos(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_CPU86_LDouble(sin(fptemp)); + ST0 = double_to_floatx80(sin(fptemp)); fpush(); - ST0 = double_to_CPU86_LDouble(cos(fptemp)); + ST0 = double_to_floatx80(cos(fptemp)); env->fpus &= (~0x400); /* C2 <-- 0 */ /* the above code is for |arg| < 2**63 only */ } @@ -4219,27 +4200,27 @@ void helper_fsincos(void) void helper_frndint(void) { - ST0 = floatx_round_to_int(ST0, &env->fp_status); + ST0 = floatx80_round_to_int(ST0, &env->fp_status); } void helper_fscale(void) { - if (floatx_is_any_nan(ST1)) { + if (floatx80_is_any_nan(ST1)) { ST0 = ST1; } else { - int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status); - ST0 = floatx_scalbn(ST0, n, &env->fp_status); + int n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status); + ST0 = floatx80_scalbn(ST0, n, &env->fp_status); } } void helper_fsin(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_CPU86_LDouble(sin(fptemp)); + ST0 = double_to_floatx80(sin(fptemp)); env->fpus &= (~0x400); /* C2 <-- 0 */ /* the above code is for |arg| < 2**53 only */ } @@ -4247,12 +4228,12 @@ void helper_fsin(void) void helper_fcos(void) { - double fptemp = CPU86_LDouble_to_double(ST0); + double fptemp = floatx80_to_double(ST0); if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { env->fpus |= 0x400; } else { - ST0 = double_to_CPU86_LDouble(cos(fptemp)); + ST0 = double_to_floatx80(cos(fptemp)); env->fpus &= (~0x400); /* C2 <-- 0 */ /* the above code is for |arg5 < 2**63 only */ } @@ -4260,7 +4241,7 @@ void helper_fcos(void) void helper_fxam_ST0(void) { - CPU86_LDoubleU temp; + CPU_LDoubleU temp; int expdif; temp.d = ST0; @@ -4272,11 +4253,7 @@ void helper_fxam_ST0(void) /* XXX: test fptags too */ expdif = EXPD(temp); if (expdif == MAXEXPD) { -#ifdef USE_X86LDOUBLE if (MANTD(temp) == 0x8000000000000000ULL) -#else - if (MANTD(temp) == 0) -#endif env->fpus |= 0x500 /*Infinity*/; else env->fpus |= 0x100 /*NaN*/; @@ -4294,7 +4271,7 @@ void helper_fstenv(target_ulong ptr, int data32) { int fpus, fptag, exp, i; uint64_t mant; - CPU86_LDoubleU tmp; + CPU_LDoubleU tmp; fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; fptag = 0; @@ -4310,9 +4287,7 @@ void helper_fstenv(target_ulong ptr, int data32) /* zero */ fptag |= 1; } else if (exp == 0 || exp == MAXEXPD -#ifdef USE_X86LDOUBLE || (mant & (1LL << 63)) == 0 -#endif ) { /* NaNs, infinity, denormal */ fptag |= 2; @@ -4364,7 +4339,7 @@ void helper_fldenv(target_ulong ptr, int data32) void helper_fsave(target_ulong ptr, int data32) { - CPU86_LDouble tmp; + floatx80 tmp; int i; helper_fstenv(ptr, data32); @@ -4392,7 +4367,7 @@ void helper_fsave(target_ulong ptr, int data32) void helper_frstor(target_ulong ptr, int data32) { - CPU86_LDouble tmp; + floatx80 tmp; int i; helper_fldenv(ptr, data32); @@ -4408,7 +4383,7 @@ void helper_frstor(target_ulong ptr, int data32) void helper_fxsave(target_ulong ptr, int data64) { int fpus, fptag, i, nb_xmm_regs; - CPU86_LDouble tmp; + floatx80 tmp; target_ulong addr; /* The operand must be 16 byte aligned */ @@ -4469,7 +4444,7 @@ void helper_fxsave(target_ulong ptr, int data64) void helper_fxrstor(target_ulong ptr, int data64) { int i, fpus, fptag, nb_xmm_regs; - CPU86_LDouble tmp; + floatx80 tmp; target_ulong addr; /* The operand must be 16 byte aligned */ @@ -4516,61 +4491,23 @@ void helper_fxrstor(target_ulong ptr, int data64) } } -#ifndef USE_X86LDOUBLE - -void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f) -{ - CPU86_LDoubleU temp; - int e; - - temp.d = f; - /* mantissa */ - *pmant = (MANTD(temp) << 11) | (1LL << 63); - /* exponent + sign */ - e = EXPD(temp) - EXPBIAS + 16383; - e |= SIGND(temp) >> 16; - *pexp = e; -} - -CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper) -{ - CPU86_LDoubleU temp; - int e; - uint64_t ll; - - /* XXX: handle overflow ? */ - e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ - e |= (upper >> 4) & 0x800; /* sign */ - ll = (mant >> 11) & ((1LL << 52) - 1); -#ifdef __arm__ - temp.l.upper = (e << 20) | (ll >> 32); - temp.l.lower = ll; -#else - temp.ll = ll | ((uint64_t)e << 52); -#endif - return temp.d; -} - -#else - -void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f) +void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f) { - CPU86_LDoubleU temp; + CPU_LDoubleU temp; temp.d = f; *pmant = temp.l.lower; *pexp = temp.l.upper; } -CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper) +floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper) { - CPU86_LDoubleU temp; + CPU_LDoubleU temp; temp.l.upper = upper; temp.l.lower = mant; return temp.d; } -#endif #ifdef TARGET_X86_64 diff --git a/target-i386/translate.c b/target-i386/translate.c index 199302e517..10bd72a0e2 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7538,7 +7538,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; case 5: /* lfence */ case 6: /* mfence */ - if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) + if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2)) goto illegal_op; break; case 7: /* sfence / clflush */ diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 9e5578d455..26f0ee42e9 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -171,9 +171,6 @@ typedef void (*disas_proc)(DisasContext *, uint16_t); static void disas_##name (DisasContext *s, uint16_t insn) #endif -/* FIXME: Remove this. */ -#define gen_im32(val) tcg_const_i32(val) - /* Generate a load from the specified address. Narrow values are sign extended to full register width. */ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign) @@ -339,7 +336,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) if ((ext & 0x80) == 0) { /* base not suppressed */ if (IS_NULL_QREG(base)) { - base = gen_im32(offset + bd); + base = tcg_const_i32(offset + bd); bd = 0; } if (!IS_NULL_QREG(add)) { @@ -355,7 +352,7 @@ static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base) add = tmp; } } else { - add = gen_im32(bd); + add = tcg_const_i32(bd); } if ((ext & 3) != 0) { /* memory indirect */ @@ -536,15 +533,15 @@ static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize) case 0: /* Absolute short. */ offset = ldsw_code(s->pc); s->pc += 2; - return gen_im32(offset); + return tcg_const_i32(offset); case 1: /* Absolute long. */ offset = read_im32(s); - return gen_im32(offset); + return tcg_const_i32(offset); case 2: /* pc displacement */ offset = s->pc; offset += ldsw_code(s->pc); s->pc += 2; - return gen_im32(offset); + return tcg_const_i32(offset); case 3: /* pc index+displacement. */ return gen_lea_indexed(s, opsize, NULL_QREG); case 4: /* Immediate. */ @@ -1209,16 +1206,16 @@ DISAS_INSN(arith_im) break; case 2: /* subi */ tcg_gen_mov_i32(dest, src1); - gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im)); + gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); tcg_gen_subi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); s->cc_op = CC_OP_SUB; break; case 3: /* addi */ tcg_gen_mov_i32(dest, src1); tcg_gen_addi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); - gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); + gen_helper_xflag_lt(QREG_CC_X, dest, tcg_const_i32(im)); s->cc_op = CC_OP_ADD; break; case 5: /* eori */ @@ -1228,7 +1225,7 @@ DISAS_INSN(arith_im) case 6: /* cmpi */ tcg_gen_mov_i32(dest, src1); tcg_gen_subi_i32(dest, dest, im); - gen_update_cc_add(dest, gen_im32(im)); + gen_update_cc_add(dest, tcg_const_i32(im)); s->cc_op = CC_OP_SUB; break; default: @@ -1324,8 +1321,8 @@ DISAS_INSN(clr) default: abort(); } - DEST_EA(insn, opsize, gen_im32(0), NULL); - gen_logic_cc(s, gen_im32(0)); + DEST_EA(insn, opsize, tcg_const_i32(0), NULL); + gen_logic_cc(s, tcg_const_i32(0)); } static TCGv gen_get_ccr(DisasContext *s) @@ -1589,7 +1586,7 @@ DISAS_INSN(jump) } if ((insn & 0x40) == 0) { /* jsr */ - gen_push(s, gen_im32(s->pc)); + gen_push(s, tcg_const_i32(s->pc)); } gen_jmp(s, tmp); } @@ -1617,7 +1614,7 @@ DISAS_INSN(addsubq) tcg_gen_addi_i32(dest, dest, val); } } else { - src2 = gen_im32(val); + src2 = tcg_const_i32(val); if (insn & 0x0100) { gen_helper_xflag_lt(QREG_CC_X, dest, src2); tcg_gen_subi_i32(dest, dest, val); @@ -1666,7 +1663,7 @@ DISAS_INSN(branch) } if (op == 1) { /* bsr */ - gen_push(s, gen_im32(s->pc)); + gen_push(s, tcg_const_i32(s->pc)); } gen_flush_cc_op(s); if (op > 1) { @@ -1757,7 +1754,7 @@ DISAS_INSN(mov3q) val = (insn >> 9) & 7; if (val == 0) val = -1; - src = gen_im32(val); + src = tcg_const_i32(val); gen_logic_cc(s, src); DEST_EA(insn, OS_LONG, src, NULL); } @@ -1883,7 +1880,7 @@ DISAS_INSN(shift_im) tmp = (insn >> 9) & 7; if (tmp == 0) tmp = 8; - shift = gen_im32(tmp); + shift = tcg_const_i32(tmp); /* No need to flush flags becuse we know we will set C flag. */ if (insn & 0x100) { gen_helper_shl_cc(reg, cpu_env, reg, shift); @@ -2191,7 +2188,7 @@ DISAS_INSN(fpu) switch ((ext >> 10) & 7) { case 4: /* FPCR */ /* Not implemented. Always return zero. */ - tmp32 = gen_im32(0); + tmp32 = tcg_const_i32(0); break; case 1: /* FPIAR */ case 2: /* FPSR */ @@ -2592,7 +2589,7 @@ DISAS_INSN(mac) /* Skip the accumulate if the value is already saturated. */ l1 = gen_new_label(); tmp = tcg_temp_new(); - gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); gen_op_jmp_nz32(tmp, l1); } #endif @@ -2626,7 +2623,7 @@ DISAS_INSN(mac) /* Skip the accumulate if the value is already saturated. */ l1 = gen_new_label(); tmp = tcg_temp_new(); - gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc)); + gen_op_and32(tmp, QREG_MACSR, tcg_const_i32(MACSR_PAV0 << acc)); gen_op_jmp_nz32(tmp, l1); } #endif diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 4700632931..cf2a368b57 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -21,7 +21,6 @@ #include <stdio.h> #include <string.h> #include <inttypes.h> -#include <signal.h> #include "cpu.h" #include "exec-all.h" diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 51c99c816f..470e42f676 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -51,9 +51,7 @@ DEF_HELPER_FLAGS_1(cntlzw32, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32) DEF_HELPER_FLAGS_2(brinc, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl) DEF_HELPER_0(float_check_status, void) -#ifdef CONFIG_SOFTFLOAT DEF_HELPER_0(reset_fpstatus, void) -#endif DEF_HELPER_2(compute_fprf, i32, i64, i32) DEF_HELPER_2(store_fpscr, void, i64, i32) DEF_HELPER_1(fpscr_clrbit, void, i32) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index ccf4668f28..e7b1b10c69 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -45,9 +45,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static int cap_interrupt_unset = false; static int cap_interrupt_level = false; static int cap_segstate; -#ifdef KVM_CAP_PPC_BOOKE_SREGS static int cap_booke_sregs; -#endif /* XXX We have a race condition where we actually have a level triggered * interrupt, but the infrastructure can't expose that yet, so the guest @@ -222,13 +220,13 @@ int kvm_arch_get_registers(CPUState *env) for (i = 0;i < 32; i++) env->gpr[i] = regs.gpr[i]; -#ifdef KVM_CAP_PPC_BOOKE_SREGS if (cap_booke_sregs) { ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } +#ifdef KVM_CAP_PPC_BOOKE_SREGS if (sregs.u.e.features & KVM_SREGS_E_BASE) { env->spr[SPR_BOOKE_CSRR0] = sregs.u.e.csrr0; env->spr[SPR_BOOKE_CSRR1] = sregs.u.e.csrr1; @@ -325,16 +323,16 @@ int kvm_arch_get_registers(CPUState *env) env->spr[SPR_BOOKE_PID2] = sregs.u.e.impl.fsl.pid2; } } - } #endif + } -#ifdef KVM_CAP_PPC_SEGSTATE if (cap_segstate) { ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } +#ifdef KVM_CAP_PPC_SEGSTATE ppc_store_sdr1(env, sregs.u.s.sdr1); /* Sync SLB */ @@ -357,8 +355,8 @@ int kvm_arch_get_registers(CPUState *env) env->IBAT[0][i] = sregs.u.s.ppc32.ibat[i] & 0xffffffff; env->IBAT[1][i] = sregs.u.s.ppc32.ibat[i] >> 32; } - } #endif + } return 0; } diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index c52a37173b..15d9222c72 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -971,7 +971,6 @@ void helper_store_fpscr (uint64_t arg, uint32_t mask) void helper_float_check_status (void) { -#ifdef CONFIG_SOFTFLOAT if (env->exception_index == POWERPC_EXCP_PROGRAM && (env->error_code & POWERPC_EXCP_FP)) { /* Differred floating-point exception after target FPR update */ @@ -989,22 +988,12 @@ void helper_float_check_status (void) float_inexact_excp(); } } -#else - if (env->exception_index == POWERPC_EXCP_PROGRAM && - (env->error_code & POWERPC_EXCP_FP)) { - /* Differred floating-point exception after target FPR update */ - if (msr_fe0 != 0 || msr_fe1 != 0) - helper_raise_exception_err(env->exception_index, env->error_code); - } -#endif } -#ifdef CONFIG_SOFTFLOAT void helper_reset_fpstatus (void) { set_float_exception_flags(0, &env->fp_status); } -#endif /* fadd - fadd. */ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 9b3f90c858..59aef855d4 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -215,9 +215,7 @@ struct opc_handler_t { static inline void gen_reset_fpstatus(void) { -#ifdef CONFIG_SOFTFLOAT gen_helper_reset_fpstatus(); -#endif } static inline void gen_compute_fprf(TCGv_i64 arg, int set_fprf, int set_rc) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index b511afaaca..fc50ae3cd2 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -73,7 +73,7 @@ static void spr_read_generic (void *opaque, int gprn, int sprn) gen_load_spr(cpu_gpr[gprn], sprn); #ifdef PPC_DUMP_SPR_ACCESSES { - TCGv t0 = tcg_const_i32(sprn); + TCGv_i32 t0 = tcg_const_i32(sprn); gen_helper_load_dump_spr(t0); tcg_temp_free_i32(t0); } @@ -85,7 +85,7 @@ static void spr_write_generic (void *opaque, int sprn, int gprn) gen_store_spr(sprn, cpu_gpr[gprn]); #ifdef PPC_DUMP_SPR_ACCESSES { - TCGv t0 = tcg_const_i32(sprn); + TCGv_i32 t0 = tcg_const_i32(sprn); gen_helper_store_dump_spr(t0); tcg_temp_free_i32(t0); } @@ -1367,16 +1367,16 @@ static void spr_write_e500_l1csr0 (void *opaque, int sprn, int gprn) static void spr_write_booke206_mmucsr0 (void *opaque, int sprn, int gprn) { - TCGv t0 = tcg_const_i32(sprn); + TCGv_i32 t0 = tcg_const_i32(sprn); gen_helper_booke206_tlbflush(t0); - tcg_temp_free(t0); + tcg_temp_free_i32(t0); } static void spr_write_booke_pid (void *opaque, int sprn, int gprn) { - TCGv t0 = tcg_const_i32(sprn); + TCGv_i32 t0 = tcg_const_i32(sprn); gen_helper_booke_setpid(t0, cpu_gpr[gprn]); - tcg_temp_free(t0); + tcg_temp_free_i32(t0); } #endif diff --git a/target-s390x/helper.c b/target-s390x/helper.c index c79af46693..745d8c52bb 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -28,11 +28,6 @@ #include "qemu-common.h" #include "qemu-timer.h" -#if !defined(CONFIG_USER_ONLY) -#include <linux/kvm.h> -#include "kvm.h" -#endif - //#define DEBUG_S390 //#define DEBUG_S390_PTE //#define DEBUG_S390_STDOUT diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 49760a40a2..db03a7971f 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -1731,25 +1731,15 @@ void HELPER(sqdbr)(uint32_t f1, uint32_t f2) env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status); } -static inline uint64_t cksm_overflow(uint64_t cksm) -{ - if (cksm > 0xffffffffULL) { - cksm &= 0xffffffffULL; - cksm++; - } - return cksm; -} - /* checksum */ void HELPER(cksm)(uint32_t r1, uint32_t r2) { uint64_t src = get_address_31fix(r2); uint64_t src_len = env->regs[(r2 + 1) & 15]; - uint64_t cksm = 0; + uint64_t cksm = (uint32_t)env->regs[r1]; while (src_len >= 4) { cksm += ldl(src); - cksm = cksm_overflow(cksm); /* move to next word */ src_len -= 4; @@ -1760,26 +1750,24 @@ void HELPER(cksm)(uint32_t r1, uint32_t r2) case 0: break; case 1: - cksm += ldub(src); - cksm = cksm_overflow(cksm); + cksm += ldub(src) << 24; break; case 2: - cksm += lduw(src); - cksm = cksm_overflow(cksm); + cksm += lduw(src) << 16; break; case 3: - /* XXX check if this really is correct */ - cksm += lduw(src) << 8; - cksm += ldub(src + 2); - cksm = cksm_overflow(cksm); + cksm += lduw(src) << 16; + cksm += ldub(src + 2) << 8; break; } /* indicate we've processed everything */ + env->regs[r2] = src + src_len; env->regs[(r2 + 1) & 15] = 0; /* store result */ - env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | (uint32_t)cksm; + env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) | + ((uint32_t)cksm + (cksm >> 32)); } static inline uint32_t cc_calc_ltgt_32(CPUState *env, int32_t src, diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 8e71df3d26..eda4624d11 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -1078,9 +1078,12 @@ static void gen_jcc(DisasContext *s, uint32_t mask, int skip) tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, skip); break; default: + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); goto do_dynamic; } tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); account_inline_branch(s); break; case CC_OP_TM_64: @@ -1095,6 +1098,7 @@ static void gen_jcc(DisasContext *s, uint32_t mask, int skip) tcg_gen_brcondi_i64(TCG_COND_EQ, tmp64, 0, skip); break; default: + tcg_temp_free_i64(tmp64); goto do_dynamic; } tcg_temp_free_i64(tmp64); @@ -2056,7 +2060,7 @@ do_mh: even for very long ones... */ tmp = get_address(s, 0, b2, d2); tmp3 = tcg_const_i64(stm_len); - tmp4 = tcg_const_i64(32); + tmp4 = tcg_const_i64(op == 0x26 ? 32 : 4); for (i = r1;; i = (i + 1) % 16) { switch (op) { case 0x4: @@ -2068,9 +2072,8 @@ do_mh: tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s)); tcg_gen_trunc_i64_i32(TCGV_HIGH(regs[i]), tmp2); #else - tmp2 = tcg_temp_new_i64(); tcg_gen_qemu_ld32u(tmp2, tmp, get_mem_index(s)); - tcg_gen_shl_i64(tmp2, tmp2, 4); + tcg_gen_shl_i64(tmp2, tmp2, tmp4); tcg_gen_ext32u_i64(regs[i], regs[i]); tcg_gen_or_i64(regs[i], regs[i], tmp2); #endif @@ -2094,6 +2097,7 @@ do_mh: tcg_gen_add_i64(tmp, tmp, tmp3); } tcg_temp_free_i64(tmp); + tcg_temp_free_i64(tmp3); tcg_temp_free_i64(tmp4); break; case 0x2c: /* STCMH R1,M3,D2(B2) [RSY] */ @@ -2330,18 +2334,22 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) case 0x0: /* IIHH R1,I2 [RI] */ tmp = tcg_const_i64(i2); tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 48, 16); + tcg_temp_free_i64(tmp); break; case 0x1: /* IIHL R1,I2 [RI] */ tmp = tcg_const_i64(i2); tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 32, 16); + tcg_temp_free_i64(tmp); break; case 0x2: /* IILH R1,I2 [RI] */ tmp = tcg_const_i64(i2); tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 16, 16); + tcg_temp_free_i64(tmp); break; case 0x3: /* IILL R1,I2 [RI] */ tmp = tcg_const_i64(i2); tcg_gen_deposit_i64(regs[r1], regs[r1], tmp, 0, 16); + tcg_temp_free_i64(tmp); break; case 0x4: /* NIHH R1,I2 [RI] */ case 0x8: /* OIHH R1,I2 [RI] */ @@ -2366,6 +2374,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) set_cc_nz_u32(s, tmp32); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32); + tcg_temp_free_i64(tmp); break; case 0x5: /* NIHL R1,I2 [RI] */ case 0x9: /* OIHL R1,I2 [RI] */ @@ -2391,6 +2400,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) set_cc_nz_u32(s, tmp32); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32); + tcg_temp_free_i64(tmp); break; case 0x6: /* NILH R1,I2 [RI] */ case 0xa: /* OILH R1,I2 [RI] */ @@ -2416,6 +2426,7 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) set_cc_nz_u32(s, tmp32); tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32); + tcg_temp_free_i64(tmp); break; case 0x7: /* NILL R1,I2 [RI] */ case 0xb: /* OILL R1,I2 [RI] */ @@ -2439,29 +2450,33 @@ static void disas_a5(DisasContext *s, int op, int r1, int i2) set_cc_nz_u32(s, tmp32); /* signedness should not matter here */ tcg_temp_free_i64(tmp2); tcg_temp_free_i32(tmp32); + tcg_temp_free_i64(tmp); break; case 0xc: /* LLIHH R1,I2 [RI] */ tmp = tcg_const_i64( ((uint64_t)i2) << 48 ); store_reg(r1, tmp); + tcg_temp_free_i64(tmp); break; case 0xd: /* LLIHL R1,I2 [RI] */ tmp = tcg_const_i64( ((uint64_t)i2) << 32 ); store_reg(r1, tmp); + tcg_temp_free_i64(tmp); break; case 0xe: /* LLILH R1,I2 [RI] */ tmp = tcg_const_i64( ((uint64_t)i2) << 16 ); store_reg(r1, tmp); + tcg_temp_free_i64(tmp); break; case 0xf: /* LLILL R1,I2 [RI] */ tmp = tcg_const_i64(i2); store_reg(r1, tmp); + tcg_temp_free_i64(tmp); break; default: LOG_DISAS("illegal a5 operation 0x%x\n", op); gen_illegal_opcode(s, 2); return; } - tcg_temp_free_i64(tmp); } static void disas_a7(DisasContext *s, int op, int r1, int i2) @@ -2963,6 +2978,8 @@ static void disas_b2(DisasContext *s, int op, uint32_t insn) /* we need to keep cc_op intact */ s->is_jmp = DISAS_JUMP; tcg_temp_free_i64(tmp); + tcg_temp_free_i64(tmp2); + tcg_temp_free_i64(tmp3); break; case 0x20: /* SERVC R1,R2 [RRE] */ /* SCLP Service call (PV hypercall) */ @@ -3456,6 +3473,9 @@ static void disas_b9(DisasContext *s, int op, int r1, int r2) tcg_temp_free_i64(tmp2); tcg_temp_free_i64(tmp3); break; + case 0x0f: /* LRVGR R1,R2 [RRE] */ + tcg_gen_bswap64_i64(regs[r1], regs[r2]); + break; case 0x1f: /* LRVR R1,R2 [RRE] */ tmp32_1 = load_reg32(r2); tcg_gen_bswap32_i32(tmp32_1, tmp32_1); @@ -4593,6 +4613,8 @@ static void disas_s390_insn(DisasContext *s) store_reg32(r1, tmp32_1); tcg_gen_trunc_i64_i32(tmp32_2, tmp2); store_reg32(r1 + 1, tmp32_2); + tcg_temp_free_i64(tmp); + tcg_temp_free_i64(tmp2); break; case 0x98: /* LM R1,R3,D2(B2) [RS] */ case 0x90: /* STM R1,R3,D2(B2) [RS] */ @@ -4616,6 +4638,7 @@ static void disas_s390_insn(DisasContext *s) } tcg_gen_add_i64(tmp, tmp, tmp3); } + tcg_temp_free_i64(tmp); tcg_temp_free_i64(tmp2); tcg_temp_free_i64(tmp3); tcg_temp_free_i64(tmp4); diff --git a/target-sparc/helper.c b/target-sparc/helper.c index b2d4d70a11..e9b42d03a9 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -21,7 +21,6 @@ #include <stdio.h> #include <string.h> #include <inttypes.h> -#include <signal.h> #include "cpu.h" #include "exec-all.h" diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 0028bfa562..8cb7d88eb6 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -102,7 +102,11 @@ enum { /* guest base is supported */ #define TCG_TARGET_HAS_GUEST_BASE +#ifdef __OpenBSD__ +#include <machine/sysarch.h> +#else #include <sys/cachectl.h> +#endif static inline void flush_icache_range(unsigned long start, unsigned long stop) { diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 207a89fd97..ebf5e1389d 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -1063,66 +1063,66 @@ static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg) tcg_gen_op2i_i64(INDEX_op_movi_i64, ret, arg); } -static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld8u_i64, ret, arg2, offset); } -static inline void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld8s_i64, ret, arg2, offset); } -static inline void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld16u_i64, ret, arg2, offset); } -static inline void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld16s_i64, ret, arg2, offset); } -static inline void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld32u_i64, ret, arg2, offset); } -static inline void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_i64 arg2, +static inline void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld32s_i64, ret, arg2, offset); } -static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_i64 arg2, tcg_target_long offset) +static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_ld_i64, ret, arg2, offset); } -static inline void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_i64 arg2, +static inline void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_st8_i64, arg1, arg2, offset); } -static inline void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_i64 arg2, +static inline void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_st16_i64, arg1, arg2, offset); } -static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_i64 arg2, +static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_st32_i64, arg1, arg2, offset); } -static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_i64 arg2, tcg_target_long offset) +static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) { tcg_gen_ldst_op_i64(INDEX_op_st_i64, arg1, arg2, offset); } @@ -2304,8 +2304,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #endif } -#define tcg_gen_ld_ptr tcg_gen_ld_i32 -#define tcg_gen_discard_ptr tcg_gen_discard_i32 +#define tcg_gen_ld_ptr(R, A, O) tcg_gen_ld_i32(TCGV_PTR_TO_NAT(R), (A), (O)) +#define tcg_gen_discard_ptr(A) tcg_gen_discard_i32(TCGV_PTR_TO_NAT(A)) #else /* TCG_TARGET_REG_BITS == 32 */ @@ -2372,8 +2372,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) tcg_gen_qemu_ldst_op_i64(INDEX_op_qemu_st64, arg, addr, mem_index); } -#define tcg_gen_ld_ptr tcg_gen_ld_i64 -#define tcg_gen_discard_ptr tcg_gen_discard_i64 +#define tcg_gen_ld_ptr(R, A, O) tcg_gen_ld_i64(TCGV_PTR_TO_NAT(R), (A), (O)) +#define tcg_gen_discard_ptr(A) tcg_gen_discard_i64(TCGV_PTR_TO_NAT(A)) #endif /* TCG_TARGET_REG_BITS != 32 */ @@ -2523,11 +2523,17 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) #endif #if TCG_TARGET_REG_BITS == 32 -#define tcg_gen_add_ptr tcg_gen_add_i32 -#define tcg_gen_addi_ptr tcg_gen_addi_i32 -#define tcg_gen_ext_i32_ptr tcg_gen_mov_i32 +#define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i32(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), \ + TCGV_PTR_TO_NAT(B)) +#define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i32(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), (B)) +#define tcg_gen_ext_i32_ptr(R, A) tcg_gen_mov_i32(TCGV_PTR_TO_NAT(R), (A)) #else /* TCG_TARGET_REG_BITS == 32 */ -#define tcg_gen_add_ptr tcg_gen_add_i64 -#define tcg_gen_addi_ptr tcg_gen_addi_i64 -#define tcg_gen_ext_i32_ptr tcg_gen_ext_i32_i64 +#define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i64(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), \ + TCGV_PTR_TO_NAT(B)) +#define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), (B)) +#define tcg_gen_ext_i32_ptr(R, A) tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A)) #endif /* TCG_TARGET_REG_BITS != 32 */ @@ -585,7 +585,7 @@ void tcg_register_helper(void *func, const char *name) void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, int sizemask, TCGArg ret, int nargs, TCGArg *args) { -#ifdef TCG_TARGET_I386 +#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64 int call_type; #endif int i; @@ -612,7 +612,7 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, *gen_opc_ptr++ = INDEX_op_call; nparam = gen_opparam_ptr++; -#ifdef TCG_TARGET_I386 +#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64 call_type = (flags & TCG_CALL_TYPE_MASK); #endif if (ret != TCG_CALL_DUMMY_ARG) { @@ -150,12 +150,19 @@ typedef struct int i64; } TCGv_i64; +typedef struct { + int iptr; +} TCGv_ptr; + #define MAKE_TCGV_I32(i) __extension__ \ ({ TCGv_i32 make_tcgv_tmp = {i}; make_tcgv_tmp;}) #define MAKE_TCGV_I64(i) __extension__ \ ({ TCGv_i64 make_tcgv_tmp = {i}; make_tcgv_tmp;}) +#define MAKE_TCGV_PTR(i) __extension__ \ + ({ TCGv_ptr make_tcgv_tmp = {i}; make_tcgv_tmp; }) #define GET_TCGV_I32(t) ((t).i32) #define GET_TCGV_I64(t) ((t).i64) +#define GET_TCGV_PTR(t) ((t).iptr) #if TCG_TARGET_REG_BITS == 32 #define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t)) #define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1) @@ -165,10 +172,17 @@ typedef struct typedef int TCGv_i32; typedef int TCGv_i64; +#if TCG_TARGET_REG_BITS == 32 +#define TCGv_ptr TCGv_i32 +#else +#define TCGv_ptr TCGv_i64 +#endif #define MAKE_TCGV_I32(x) (x) #define MAKE_TCGV_I64(x) (x) +#define MAKE_TCGV_PTR(x) (x) #define GET_TCGV_I32(t) (t) #define GET_TCGV_I64(t) (t) +#define GET_TCGV_PTR(t) (t) #if TCG_TARGET_REG_BITS == 32 #define TCGV_LOW(t) (t) @@ -459,25 +473,27 @@ do {\ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); #if TCG_TARGET_REG_BITS == 32 -#define tcg_const_ptr tcg_const_i32 -#define tcg_add_ptr tcg_add_i32 -#define tcg_sub_ptr tcg_sub_i32 -#define TCGv_ptr TCGv_i32 -#define GET_TCGV_PTR GET_TCGV_I32 -#define tcg_global_reg_new_ptr tcg_global_reg_new_i32 -#define tcg_global_mem_new_ptr tcg_global_mem_new_i32 -#define tcg_temp_new_ptr tcg_temp_new_i32 -#define tcg_temp_free_ptr tcg_temp_free_i32 +#define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n)) +#define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n)) + +#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32(V)) +#define tcg_global_reg_new_ptr(R, N) \ + TCGV_NAT_TO_PTR(tcg_global_reg_new_i32((R), (N))) +#define tcg_global_mem_new_ptr(R, O, N) \ + TCGV_NAT_TO_PTR(tcg_global_mem_new_i32((R), (O), (N))) +#define tcg_temp_new_ptr() TCGV_NAT_TO_PTR(tcg_temp_new_i32()) +#define tcg_temp_free_ptr(T) tcg_temp_free_i32(TCGV_PTR_TO_NAT(T)) #else -#define tcg_const_ptr tcg_const_i64 -#define tcg_add_ptr tcg_add_i64 -#define tcg_sub_ptr tcg_sub_i64 -#define TCGv_ptr TCGv_i64 -#define GET_TCGV_PTR GET_TCGV_I64 -#define tcg_global_reg_new_ptr tcg_global_reg_new_i64 -#define tcg_global_mem_new_ptr tcg_global_mem_new_i64 -#define tcg_temp_new_ptr tcg_temp_new_i64 -#define tcg_temp_free_ptr tcg_temp_free_i64 +#define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I64(n)) +#define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I64(GET_TCGV_PTR(n)) + +#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64(V)) +#define tcg_global_reg_new_ptr(R, N) \ + TCGV_NAT_TO_PTR(tcg_global_reg_new_i64((R), (N))) +#define tcg_global_mem_new_ptr(R, O, N) \ + TCGV_NAT_TO_PTR(tcg_global_mem_new_i64((R), (O), (N))) +#define tcg_temp_new_ptr() TCGV_NAT_TO_PTR(tcg_temp_new_i64()) +#define tcg_temp_free_ptr(T) tcg_temp_free_i64(TCGV_PTR_TO_NAT(T)) #endif void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, diff --git a/trace-events b/trace-events index 3137a1518f..e0e9574d21 100644 --- a/trace-events +++ b/trace-events @@ -210,7 +210,8 @@ disable scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d" disable scsi_req_data(int target, int lun, int tag, int len) "target %d lun %d tag %d len %d" disable scsi_req_dequeue(int target, int lun, int tag) "target %d lun %d tag %d" disable scsi_req_continue(int target, int lun, int tag) "target %d lun %d tag %d" -disable scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer, uint64_t lba) "target %d lun %d tag %d command %d dir %d length %d lba %"PRIu64"" +disable scsi_req_parsed(int target, int lun, int tag, int cmd, int mode, int xfer) "target %d lun %d tag %d command %d dir %d length %d" +disable scsi_req_parsed_lba(int target, int lun, int tag, int cmd, uint64_t lba) "target %d lun %d tag %d command %d lba %"PRIu64"" disable scsi_req_parse_bad(int target, int lun, int tag, int cmd) "target %d lun %d tag %d command %d" # vl.c diff --git a/ui/curses.c b/ui/curses.c index 82bc614040..d29b6cf874 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -24,7 +24,6 @@ #include <curses.h> #ifndef _WIN32 -#include <signal.h> #include <sys/ioctl.h> #include <termios.h> #endif @@ -28,10 +28,6 @@ #include <SDL.h> #include <SDL_syswm.h> -#ifndef _WIN32 -#include <signal.h> -#endif - #include "qemu-common.h" #include "console.h" #include "sysemu.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index ef56ed61a9..dd9905be36 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -299,8 +299,6 @@ static int parse_name(const char *string, const char *optname, exit(1); } -#if SPICE_SERVER_VERSION >= 0x000600 /* 0.6.0 */ - static const char *stream_video_names[] = { [ SPICE_STREAM_VIDEO_OFF ] = "off", [ SPICE_STREAM_VIDEO_ALL ] = "all", @@ -309,8 +307,6 @@ static const char *stream_video_names[] = { #define parse_stream_video(_name) \ name2enum(_name, stream_video_names, ARRAY_SIZE(stream_video_names)) -#endif /* >= 0.6.0 */ - static const char *compression_names[] = { [ SPICE_IMAGE_COMPRESS_OFF ] = "off", [ SPICE_IMAGE_COMPRESS_AUTO_GLZ ] = "auto_glz", @@ -549,11 +545,29 @@ void qemu_spice_init(void) if (password) { spice_server_set_ticket(spice_server, password, 0, 0, 0); } + if (qemu_opt_get_bool(opts, "sasl", 0)) { +#if SPICE_SERVER_VERSION >= 0x000900 /* 0.9.0 */ + if (spice_server_set_sasl_appname(spice_server, "qemu") == -1 || + spice_server_set_sasl(spice_server, 1) == -1) { + fprintf(stderr, "spice: failed to enable sasl\n"); + exit(1); + } +#else + fprintf(stderr, "spice: sasl is not available (spice >= 0.9 required)\n"); + exit(1); +#endif + } if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) { auth = "none"; spice_server_set_noauth(spice_server); } +#if SPICE_SERVER_VERSION >= 0x000801 + if (qemu_opt_get_bool(opts, "disable-copy-paste", 0)) { + spice_server_set_agent_copypaste(spice_server, false); + } +#endif + compression = SPICE_IMAGE_COMPRESS_AUTO_GLZ; str = qemu_opt_get(opts, "image-compression"); if (str) { @@ -575,8 +589,6 @@ void qemu_spice_init(void) } spice_server_set_zlib_glz_compression(spice_server, wan_compr); -#if SPICE_SERVER_VERSION >= 0x000600 /* 0.6.0 */ - str = qemu_opt_get(opts, "streaming-video"); if (str) { int streaming_video = parse_stream_video(str); @@ -588,8 +600,6 @@ void qemu_spice_init(void) spice_server_set_playback_compression (spice_server, qemu_opt_get_bool(opts, "playback-compression", 1)); -#endif /* >= 0.6.0 */ - qemu_opt_foreach(opts, add_channel, NULL, 0); spice_server_init(spice_server, &core_interface); @@ -39,7 +39,6 @@ #else #include <bus/usb/usb.h> #endif -#include <signal.h> /* This value has maximum potential at 16. * You should also set hw.usb.debug to gain diff --git a/usb-linux.c b/usb-linux.c index baa6574ef5..fcfa09e4b8 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -37,7 +37,6 @@ #include <dirent.h> #include <sys/ioctl.h> -#include <signal.h> #include <linux/usbdevice_fs.h> #include <linux/version.h> @@ -289,6 +289,8 @@ static struct { { .driver = "VGA", .flag = &default_vga }, { .driver = "cirrus-vga", .flag = &default_vga }, { .driver = "vmware-svga", .flag = &default_vga }, + { .driver = "isa-vga", .flag = &default_vga }, + { .driver = "qxl-vga", .flag = &default_vga }, }; static int default_driver_check(QemuOpts *opts, void *opaque) @@ -1933,6 +1935,7 @@ static int configure_accelerator(void) p = get_opt_name(buf, sizeof (buf), p, ':'); for (i = 0; i < ARRAY_SIZE(accel_list); i++) { if (strcmp(accel_list[i].opt_name, buf) == 0) { + *(accel_list[i].allowed) = 1; ret = accel_list[i].init(); if (ret < 0) { init_failed = 1; @@ -1944,9 +1947,9 @@ static int configure_accelerator(void) accel_list[i].name, strerror(-ret)); } + *(accel_list[i].allowed) = 0; } else { accel_initalised = 1; - *(accel_list[i].allowed) = 1; } break; } |