diff options
51 files changed, 528 insertions, 417 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 5c3c70c89b..fbe1fd9489 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -50,8 +50,7 @@ Descriptions of section entries: General Project Administration ------------------------------ -M: Anthony Liguori <anthony@codemonkey.ws> -M: Paul Brook <paul@codesourcery.com> +M: Anthony Liguori <aliguori@amazon.com> Guest CPU cores (TCG): ---------------------- @@ -62,7 +61,6 @@ F: target-alpha/ F: hw/alpha/ ARM -M: Paul Brook <paul@codesourcery.com> M: Peter Maydell <peter.maydell@linaro.org> S: Maintained F: target-arm/ @@ -83,8 +81,7 @@ F: hw/lm32/ F: hw/char/lm32_* M68K -M: Paul Brook <paul@codesourcery.com> -S: Odd Fixes +S: Orphan F: target-m68k/ F: hw/m68k/ @@ -248,7 +245,6 @@ F: hw/*/imx* F: hw/arm/kzm.c Integrator CP -M: Paul Brook <paul@codesourcery.com> M: Peter Maydell <peter.maydell@linaro.org> S: Maintained F: hw/arm/integratorcp.c @@ -274,7 +270,6 @@ S: Maintained F: hw/arm/palm.c Real View -M: Paul Brook <paul@codesourcery.com> M: Peter Maydell <peter.maydell@linaro.org> S: Maintained F: hw/arm/realview* @@ -285,13 +280,11 @@ S: Maintained F: hw/arm/spitz.c Stellaris -M: Paul Brook <paul@codesourcery.com> M: Peter Maydell <peter.maydell@linaro.org> S: Maintained F: hw/*/stellaris* Versatile PB -M: Paul Brook <paul@codesourcery.com> M: Peter Maydell <peter.maydell@linaro.org> S: Maintained F: hw/*/versatile* @@ -327,18 +320,15 @@ F: hw/lm32/milkymist.c M68K Machines ------------- an5206 -M: Paul Brook <paul@codesourcery.com> -S: Maintained +S: Orphan F: hw/m68k/an5206.c dummy_m68k -M: Paul Brook <paul@codesourcery.com> -S: Maintained +S: Orphan F: hw/m68k/dummy_m68k.c mcf5208 -M: Paul Brook <paul@codesourcery.com> -S: Maintained +S: Orphan F: hw/m68k/mcf5208.c MicroBlaze Machines @@ -509,7 +499,7 @@ F: hw/unicore32/ X86 Machines ------------ PC -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> S: Supported F: hw/i386/pc.[ch] F: hw/i386/pc_piix.c @@ -567,8 +557,7 @@ F: hw/scsi/* T: git git://github.com/bonzini/qemu.git scsi-next LSI53C895A -M: Paul Brook <paul@codesourcery.com> -S: Odd Fixes +S: Orphan F: hw/scsi/lsi53c895a.c SSI @@ -593,7 +582,7 @@ S: Supported F: hw/*/*vhost* virtio -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> S: Supported F: hw/*/virtio* @@ -652,7 +641,7 @@ F: block/ F: hw/block/ Character Devices -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> S: Maintained F: qemu-char.c @@ -690,7 +679,7 @@ F: audio/spiceaudio.c F: hw/display/qxl* Graphics -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> S: Maintained F: ui/ @@ -700,7 +689,7 @@ S: Odd Fixes F: ui/cocoa.m Main loop -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> S: Supported F: vl.c @@ -712,7 +701,7 @@ F: hmp.c F: hmp-commands.hx Network device layer -M: Anthony Liguori <anthony@codemonkey.ws> +M: Anthony Liguori <aliguori@amazon.com> M: Stefan Hajnoczi <stefanha@redhat.com> S: Maintained F: net/ @@ -808,8 +808,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, if (ret < 0) { if (error_is_set(&local_err)) { error_propagate(errp, local_err); - } else if (filename) { - error_setg_errno(errp, -ret, "Could not open '%s'", filename); + } else if (bs->filename[0]) { + error_setg_errno(errp, -ret, "Could not open '%s'", bs->filename); } else { error_setg_errno(errp, -ret, "Could not open image"); } @@ -824,8 +824,8 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, #ifndef _WIN32 if (bs->is_temporary) { - assert(filename != NULL); - unlink(filename); + assert(bs->filename[0] != '\0'); + unlink(bs->filename); } #endif return 0; diff --git a/block/iscsi.c b/block/iscsi.c index 6152ef1891..a2a961e163 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -811,7 +811,7 @@ iscsi_getlength(BlockDriverState *bs) return len; } -#if defined(SCSI_PROVISIONING_TYPE_DEALLOCATED) +#if defined(LIBISCSI_FEATURE_IOVECTOR) static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs, int64_t sector_num, @@ -903,7 +903,7 @@ out: return ret; } -#endif /* SCSI_PROVISIONING_TYPE_DEALLOCATED */ +#endif /* LIBISCSI_FEATURE_IOVECTOR */ static int coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num, @@ -1529,7 +1529,7 @@ static BlockDriver bdrv_iscsi = { .bdrv_getlength = iscsi_getlength, .bdrv_truncate = iscsi_truncate, -#if defined(SCSI_PROVISIONING_TYPE_DEALLOCATED) +#if defined(LIBISCSI_FEATURE_IOVECTOR) .bdrv_co_get_block_status = iscsi_co_get_block_status, #endif .bdrv_co_discard = iscsi_co_discard, diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 39323ace38..0fd26bb4cc 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -35,6 +35,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, BDRVQcowState *s = bs->opaque; int new_l1_size2, ret, i; uint64_t *new_l1_table; + int64_t old_l1_table_offset, old_l1_size; int64_t new_l1_table_offset, new_l1_size; uint8_t data[12]; @@ -106,11 +107,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, goto fail; } g_free(s->l1_table); - qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t), - QCOW2_DISCARD_OTHER); + old_l1_table_offset = s->l1_table_offset; s->l1_table_offset = new_l1_table_offset; s->l1_table = new_l1_table; + old_l1_size = s->l1_size; s->l1_size = new_l1_size; + qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * sizeof(uint64_t), + QCOW2_DISCARD_OTHER); return 0; fail: g_free(new_l1_table); @@ -270,6 +273,10 @@ fail: qcow2_cache_put(bs, s->l2_table_cache, (void**) table); } s->l1_table[l1_index] = old_l2_offset; + if (l2_offset > 0) { + qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), + QCOW2_DISCARD_ALWAYS); + } return ret; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index d2b7064a02..2d67885850 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1034,7 +1034,6 @@ static void inc_refcounts(BlockDriverState *bs, /* Flags for check_refcounts_l1() and check_refcounts_l2() */ enum { - CHECK_OFLAG_COPIED = 0x1, /* check QCOW_OFLAG_COPIED matches refcount */ CHECK_FRAG_INFO = 0x2, /* update BlockFragInfo counters */ }; @@ -1481,8 +1480,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, /* current L1 table */ ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, - s->l1_table_offset, s->l1_size, - CHECK_OFLAG_COPIED | CHECK_FRAG_INFO); + s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); if (ret < 0) { goto fail; } @@ -1733,8 +1731,8 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, } for (j = 0; j < l1_sz; j++) { - if ((l1[j] & L1E_OFFSET_MASK) && - overlaps_with(l1[j] & L1E_OFFSET_MASK, s->cluster_size)) { + uint64_t l2_ofs = be64_to_cpu(l1[j]) & L1E_OFFSET_MASK; + if (l2_ofs && overlaps_with(l2_ofs, s->cluster_size)) { g_free(l1); return QCOW2_OL_INACTIVE_L2; } diff --git a/block/vhdx.c b/block/vhdx.c index b8aa49ce4e..6cb04122bb 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -20,6 +20,7 @@ #include "qemu/module.h" #include "qemu/crc32c.h" #include "block/vhdx.h" +#include "migration/migration.h" /* Several metadata and region table data entries are identified by @@ -159,6 +160,7 @@ typedef struct BDRVVHDXState { VHDXParentLocatorHeader parent_header; VHDXParentLocatorEntry *parent_entries; + Error *migration_blocker; } BDRVVHDXState; uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size, @@ -806,6 +808,12 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, /* TODO: differencing files, write */ + /* Disable migration when VHDX images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vhdx", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + return 0; fail: qemu_vfree(s->headers[0]); @@ -952,6 +960,8 @@ static void vhdx_close(BlockDriverState *bs) qemu_vfree(s->headers[1]); qemu_vfree(s->bat); qemu_vfree(s->parent_entries); + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static BlockDriver bdrv_vhdx = { diff --git a/blockdev.c b/blockdev.c index 8aa66a949c..8c83f6f1ca 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1926,7 +1926,6 @@ void qmp_drive_mirror(const char *device, const char *target, } else { switch (mode) { case NEW_IMAGE_MODE_EXISTING: - ret = 0; break; case NEW_IMAGE_MODE_ABSOLUTE_PATHS: /* create new image with backing file */ @@ -1541,7 +1541,7 @@ static uint64_t subpage_read(void *opaque, hwaddr addr, uint8_t buf[4]; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p len %d addr " TARGET_FMT_plx "\n", __func__, + printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__, subpage, len, addr); #endif address_space_read(subpage->as, addr + subpage->base, buf, len); @@ -1564,7 +1564,7 @@ static void subpage_write(void *opaque, hwaddr addr, uint8_t buf[4]; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p len %d addr " TARGET_FMT_plx + printf("%s: subpage %p len %u addr " TARGET_FMT_plx " value %"PRIx64"\n", __func__, subpage, len, addr, value); #endif @@ -1585,16 +1585,16 @@ static void subpage_write(void *opaque, hwaddr addr, } static bool subpage_accepts(void *opaque, hwaddr addr, - unsigned size, bool is_write) + unsigned len, bool is_write) { subpage_t *subpage = opaque; #if defined(DEBUG_SUBPAGE) - printf("%s: subpage %p %c len %d addr " TARGET_FMT_plx "\n", + printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n", __func__, subpage, is_write ? 'w' : 'r', len, addr); #endif return address_space_access_valid(subpage->as, addr + subpage->base, - size, is_write); + len, is_write); } static const MemoryRegionOps subpage_ops = { @@ -1614,8 +1614,8 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, idx = SUBPAGE_IDX(start); eidx = SUBPAGE_IDX(end); #if defined(DEBUG_SUBPAGE) - printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__, - mmio, start, end, idx, eidx, memory); + printf("%s: %p start %08x end %08x idx %08x eidx %08x section %d\n", + __func__, mmio, start, end, idx, eidx, section); #endif for (; idx <= eidx; idx++) { mmio->sub_section[idx] = section; @@ -1636,8 +1636,8 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base) "subpage", TARGET_PAGE_SIZE); mmio->iomem.subpage = true; #if defined(DEBUG_SUBPAGE) - printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, - mmio, base, TARGET_PAGE_SIZE, subpage_memory); + printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__, + mmio, base, TARGET_PAGE_SIZE); #endif subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED); @@ -1553,7 +1553,7 @@ static void gdb_accept(void) static int gdbserver_open(int port) { struct sockaddr_in sockaddr; - int fd, val, ret; + int fd, ret; fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { @@ -1564,9 +1564,7 @@ static int gdbserver_open(int port) fcntl(fd, F_SETFD, FD_CLOEXEC); #endif - /* allow fast reuse */ - val = 1; - qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + socket_set_fast_reuse(fd); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(port); diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/virtio-9p-xattr.c index 90ae565c19..3fae557a84 100644 --- a/hw/9pfs/virtio-9p-xattr.c +++ b/hw/9pfs/virtio-9p-xattr.c @@ -36,7 +36,7 @@ ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, if (xops) { return xops->getxattr(ctx, path, name, value, size); } - errno = -EOPNOTSUPP; + errno = EOPNOTSUPP; return -1; } @@ -123,7 +123,7 @@ int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, if (xops) { return xops->setxattr(ctx, path, name, value, size, flags); } - errno = -EOPNOTSUPP; + errno = EOPNOTSUPP; return -1; } @@ -135,7 +135,7 @@ int v9fs_remove_xattr(FsContext *ctx, if (xops) { return xops->removexattr(ctx, path, name); } - errno = -EOPNOTSUPP; + errno = EOPNOTSUPP; return -1; } diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index aac9a32e0c..59e1bb8388 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -700,7 +700,7 @@ static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr) } } - if (addr >= 0x80000000000 && addr <= 0xfffffffffff) { + if (addr >= 0x80000000000ull && addr <= 0xfffffffffffull) { /* Check the fourth window for DAC enable and window enable. */ if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) { uint64_t pte_addr; diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index f35fc5944a..8742294dfb 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -405,6 +405,7 @@ static int ioreq_map(struct ioreq *ioreq) xen_be_printf(&ioreq->blkdev->xendev, 0, "can't map grant ref %d (%s, %d maps)\n", refs[i], strerror(errno), ioreq->blkdev->cnt_map); + ioreq->mapped = 1; ioreq_unmap(ioreq); return -1; } diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 6223a557b2..9328dd1b57 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -248,11 +248,9 @@ static uint64_t sh_serial_read(void *opaque, hwaddr offs, s->flags &= ~SH_SERIAL_FLAG_RDF; } break; -#if 0 case 0x18: ret = s->fcr; break; -#endif case 0x1c: ret = s->rx_cnt; break; diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 4d36841d40..24ec52f8f9 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -11,6 +11,8 @@ static char *scsibus_get_dev_path(DeviceState *dev); static char *scsibus_get_fw_dev_path(DeviceState *dev); static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf); static void scsi_req_dequeue(SCSIRequest *req); +static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len); +static void scsi_target_free_buf(SCSIRequest *req); static Property scsi_props[] = { DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), @@ -317,7 +319,8 @@ typedef struct SCSITargetReq SCSITargetReq; struct SCSITargetReq { SCSIRequest req; int len; - uint8_t buf[2056]; + uint8_t *buf; + int buf_len; }; static void store_lun(uint8_t *outbuf, int lun) @@ -361,14 +364,12 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) if (!found_lun0) { n += 8; } - len = MIN(n + 8, r->req.cmd.xfer & ~7); - if (len > sizeof(r->buf)) { - /* TODO: > 256 LUNs? */ - return false; - } + scsi_target_alloc_buf(&r->req, n + 8); + + len = MIN(n + 8, r->req.cmd.xfer & ~7); memset(r->buf, 0, len); - stl_be_p(&r->buf, n); + stl_be_p(&r->buf[0], n); i = found_lun0 ? 8 : 16; QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { DeviceState *qdev = kid->child; @@ -387,6 +388,9 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) static bool scsi_target_emulate_inquiry(SCSITargetReq *r) { assert(r->req.dev->lun != r->req.lun); + + scsi_target_alloc_buf(&r->req, SCSI_INQUIRY_LEN); + if (r->req.cmd.buf[1] & 0x2) { /* Command support data - optional, not implemented */ return false; @@ -411,7 +415,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r) return false; } /* done with EVPD */ - assert(r->len < sizeof(r->buf)); + assert(r->len < r->buf_len); r->len = MIN(r->req.cmd.xfer, r->len); return true; } @@ -422,7 +426,7 @@ static bool scsi_target_emulate_inquiry(SCSITargetReq *r) } /* PAGE CODE == 0 */ - r->len = MIN(r->req.cmd.xfer, 36); + r->len = MIN(r->req.cmd.xfer, SCSI_INQUIRY_LEN); memset(r->buf, 0, r->len); if (r->req.lun != 0) { r->buf[0] = TYPE_NO_LUN; @@ -455,8 +459,9 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf) } break; case REQUEST_SENSE: + scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN); r->len = scsi_device_get_sense(r->req.dev, r->buf, - MIN(req->cmd.xfer, sizeof r->buf), + MIN(req->cmd.xfer, r->buf_len), (req->cmd.buf[1] & 1) == 0); if (r->req.dev->sense_is_ua) { scsi_device_unit_attention_reported(req->dev); @@ -501,11 +506,29 @@ static uint8_t *scsi_target_get_buf(SCSIRequest *req) return r->buf; } +static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len) +{ + SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); + + r->buf = g_malloc(len); + r->buf_len = len; + + return r->buf; +} + +static void scsi_target_free_buf(SCSIRequest *req) +{ + SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); + + g_free(r->buf); +} + static const struct SCSIReqOps reqops_target_command = { .size = sizeof(SCSITargetReq), .send_command = scsi_target_send_command, .read_data = scsi_target_read_data, .get_buf = scsi_target_get_buf, + .free_req = scsi_target_free_buf, }; @@ -1365,7 +1388,7 @@ int scsi_build_sense(uint8_t *in_buf, int in_len, buf[7] = 10; buf[12] = sense.asc; buf[13] = sense.ascq; - return MIN(len, 18); + return MIN(len, SCSI_SENSE_LEN); } else { /* Return descriptor format sense buffer */ buf[0] = 0x72; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 35f0878409..0396e334ed 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1143,7 +1143,9 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) switch (ret) { case USB_RET_IOERROR: case USB_RET_NODEV: + DPRINTF("usb-ohci: got DEV ERROR\n"); OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); + break; case USB_RET_NAK: DPRINTF("usb-ohci: got NAK\n"); return 1; diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index d82ce5d8a6..197795ffe1 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -205,7 +205,6 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, struct XenDevOps *ops) { struct XenDevice *xendev; - char *dom0; xendev = xen_be_find_xendev(type, dom, dev); if (xendev) { @@ -219,12 +218,10 @@ static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev, xendev->dev = dev; xendev->ops = ops; - dom0 = xs_get_domain_path(xenstore, 0); - snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d", - dom0, xendev->type, xendev->dom, xendev->dev); + snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d", + xendev->type, xendev->dom, xendev->dev); snprintf(xendev->name, sizeof(xendev->name), "%s-%d", xendev->type, xendev->dev); - free(dom0); xendev->debug = debug; xendev->local_port = -1; @@ -570,14 +567,12 @@ static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops) { struct XenDevice *xendev; char path[XEN_BUFSIZE], token[XEN_BUFSIZE]; - char **dev = NULL, *dom0; + char **dev = NULL; unsigned int cdev, j; /* setup watch */ - dom0 = xs_get_domain_path(xenstore, 0); snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops); - snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom); - free(dom0); + snprintf(path, sizeof(path), "backend/%s/%d", type, dom); if (!xs_watch(xenstore, path, token)) { xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path); return -1; @@ -603,12 +598,10 @@ static void xenstore_update_be(char *watch, char *type, int dom, struct XenDevOps *ops) { struct XenDevice *xendev; - char path[XEN_BUFSIZE], *dom0, *bepath; + char path[XEN_BUFSIZE], *bepath; unsigned int len, dev; - dom0 = xs_get_domain_path(xenstore, 0); - len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom); - free(dom0); + len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom); if (strncmp(path, watch, len) != 0) { return; } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index dc27f33152..8dd15948d8 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -324,21 +324,7 @@ extern uintptr_t tci_tb_ptr; In some implementations, we pass the "logical" return address manually; in others, we must infer the logical return from the true return. */ #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) -# if defined(__arm__) -/* We define two insns between the return address and the branch back to - straight-line. Find and decode that branch insn. */ -# define GETRA_LDST(RA) tcg_getra_ldst(RA) -static inline uintptr_t tcg_getra_ldst(uintptr_t ra) -{ - int32_t b; - ra += 8; /* skip the two insns */ - b = *(int32_t *)ra; /* load the branch insn */ - b = (b << 8) >> (8 - 2); /* extract the displacement */ - ra += 8; /* branches are relative to pc+8 */ - ra += b; /* apply the displacement */ - return ra; -} -# elif defined(__aarch64__) +# if defined(__aarch64__) # define GETRA_LDST(RA) tcg_getra_ldst(RA) static inline uintptr_t tcg_getra_ldst(uintptr_t ra) { diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 1b6651054a..76f6ac24a7 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -9,6 +9,8 @@ #define MAX_SCSI_DEVS 255 #define SCSI_CMD_BUF_SIZE 16 +#define SCSI_SENSE_LEN 18 +#define SCSI_INQUIRY_LEN 36 typedef struct SCSIBus SCSIBus; typedef struct SCSIBusInfo SCSIBusInfo; diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index 06e2e6f0ee..304c90c2b4 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -184,6 +184,86 @@ static inline unsigned long hweight_long(unsigned long w) } /** + * rol8 - rotate an 8-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint8_t rol8(uint8_t word, unsigned int shift) +{ + return (word << shift) | (word >> (8 - shift)); +} + +/** + * ror8 - rotate an 8-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint8_t ror8(uint8_t word, unsigned int shift) +{ + return (word >> shift) | (word << (8 - shift)); +} + +/** + * rol16 - rotate a 16-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint16_t rol16(uint16_t word, unsigned int shift) +{ + return (word << shift) | (word >> (16 - shift)); +} + +/** + * ror16 - rotate a 16-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint16_t ror16(uint16_t word, unsigned int shift) +{ + return (word >> shift) | (word << (16 - shift)); +} + +/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint32_t rol32(uint32_t word, unsigned int shift) +{ + return (word << shift) | (word >> (32 - shift)); +} + +/** + * ror32 - rotate a 32-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint32_t ror32(uint32_t word, unsigned int shift) +{ + return (word >> shift) | (word << (32 - shift)); +} + +/** + * rol64 - rotate a 64-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint64_t rol64(uint64_t word, unsigned int shift) +{ + return (word << shift) | (word >> (64 - shift)); +} + +/** + * ror64 - rotate a 64-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint64_t ror64(uint64_t word, unsigned int shift) +{ + return (word >> shift) | (word << (64 - shift)); +} + +/** * extract32: * @value: the value to extract the bit field from * @start: the lowest bit in the bit field (numbered from 0) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index c5174d76a7..45588d7d58 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -39,6 +39,7 @@ int socket_set_cork(int fd, int v); int socket_set_nodelay(int fd); void qemu_set_block(int fd); void qemu_set_nonblock(int fd); +int socket_set_fast_reuse(int fd); int send_all(int fd, const void *buf, int len1); int recv_all(int fd, void *buf, int len1, bool single_read); diff --git a/include/sysemu/char.h b/include/sysemu/char.h index 8053130a97..ad101d9258 100644 --- a/include/sysemu/char.h +++ b/include/sysemu/char.h @@ -78,6 +78,7 @@ struct CharDriverState { int explicit_be_open; int avail_connections; int is_mux; + guint fd_in_tag; QemuOpts *opts; QTAILQ_ENTRY(CharDriverState) next; }; diff --git a/migration.c b/migration.c index b4f8462ae4..2b1ab20c54 100644 --- a/migration.c +++ b/migration.c @@ -150,6 +150,7 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) MigrationState *s = migrate_get_current(); int i; + caps = NULL; /* silence compiler warning */ for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) { if (head == NULL) { head = g_malloc0(sizeof(*caps)); diff --git a/net/socket.c b/net/socket.c index e61309d8d5..fb21e20a54 100644 --- a/net/socket.c +++ b/net/socket.c @@ -262,6 +262,11 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr return -1; } + /* Allow multiple sockets to bind the same multicast ip and port by setting + * SO_REUSEADDR. This is the only situation where SO_REUSEADDR should be set + * on windows. Use socket_set_fast_reuse otherwise as it sets SO_REUSEADDR + * only on posix systems. + */ val = 1; ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if (ret < 0) { @@ -510,7 +515,7 @@ static int net_socket_listen_init(NetClientState *peer, NetClientState *nc; NetSocketState *s; struct sockaddr_in saddr; - int fd, val, ret; + int fd, ret; if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -522,9 +527,7 @@ static int net_socket_listen_init(NetClientState *peer, } qemu_set_nonblock(fd); - /* allow fast reuse */ - val = 1; - qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + socket_set_fast_reuse(fd); ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { @@ -645,7 +648,7 @@ static int net_socket_udp_init(NetClientState *peer, const char *lhost) { NetSocketState *s; - int fd, val, ret; + int fd, ret; struct sockaddr_in laddr, raddr; if (parse_host_port(&laddr, lhost) < 0) { @@ -661,11 +664,9 @@ static int net_socket_udp_init(NetClientState *peer, perror("socket(PF_INET, SOCK_DGRAM)"); return -1; } - val = 1; - ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - &val, sizeof(val)); + + ret = socket_set_fast_reuse(fd); if (ret < 0) { - perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); closesocket(fd); return -1; } diff --git a/pc-bios/README b/pc-bios/README index e404a228a4..d70be16888 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32 and Sparc64 are built from OpenBIOS SVN revision - 1198. + 1229. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex c6b3319fab..550273a5ef 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex 2aa400cfd9..01105fc904 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex f6ee286034..62c9e77983 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/qemu-char.c b/qemu-char.c index f7f5464b67..e00f84c8e9 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -193,6 +193,8 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...) va_end(ap); } +static void remove_fd_in_watch(CharDriverState *chr); + void qemu_chr_add_handlers(CharDriverState *s, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, @@ -203,6 +205,7 @@ void qemu_chr_add_handlers(CharDriverState *s, if (!opaque && !fd_can_read && !fd_read && !fd_event) { fe_open = 0; + remove_fd_in_watch(s); } else { fe_open = 1; } @@ -725,6 +728,14 @@ static void io_remove_watch_poll(guint tag) g_source_destroy(&iwp->parent); } +static void remove_fd_in_watch(CharDriverState *chr) +{ + if (chr->fd_in_tag) { + io_remove_watch_poll(chr->fd_in_tag); + chr->fd_in_tag = 0; + } +} + #ifndef _WIN32 static GIOChannel *io_channel_from_fd(int fd) { @@ -798,7 +809,6 @@ static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) typedef struct FDCharDriver { CharDriverState *chr; GIOChannel *fd_in, *fd_out; - guint fd_in_tag; int max_size; QTAILQ_ENTRY(FDCharDriver) node; } FDCharDriver; @@ -830,10 +840,7 @@ static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) status = g_io_channel_read_chars(chan, (gchar *)buf, len, &bytes_read, NULL); if (status == G_IO_STATUS_EOF) { - if (s->fd_in_tag) { - io_remove_watch_poll(s->fd_in_tag); - s->fd_in_tag = 0; - } + remove_fd_in_watch(chr); qemu_chr_be_event(chr, CHR_EVENT_CLOSED); return FALSE; } @@ -863,13 +870,10 @@ static void fd_chr_update_read_handler(CharDriverState *chr) { FDCharDriver *s = chr->opaque; - if (s->fd_in_tag) { - io_remove_watch_poll(s->fd_in_tag); - s->fd_in_tag = 0; - } - + remove_fd_in_watch(chr); if (s->fd_in) { - s->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, fd_chr_read, chr); + chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, + fd_chr_read, chr); } } @@ -877,11 +881,7 @@ static void fd_chr_close(struct CharDriverState *chr) { FDCharDriver *s = chr->opaque; - if (s->fd_in_tag) { - io_remove_watch_poll(s->fd_in_tag); - s->fd_in_tag = 0; - } - + remove_fd_in_watch(chr); if (s->fd_in) { g_io_channel_unref(s->fd_in); } @@ -1012,7 +1012,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) typedef struct { GIOChannel *fd; - guint fd_tag; int connected; int read_bytes; guint timer_tag; @@ -1123,10 +1122,7 @@ static void pty_chr_state(CharDriverState *chr, int connected) PtyCharDriver *s = chr->opaque; if (!connected) { - if (s->fd_tag) { - io_remove_watch_poll(s->fd_tag); - s->fd_tag = 0; - } + remove_fd_in_watch(chr); s->connected = 0; /* (re-)connect poll interval for idle guests: once per second. * We check more frequently in case the guests sends data to @@ -1140,7 +1136,8 @@ static void pty_chr_state(CharDriverState *chr, int connected) if (!s->connected) { s->connected = 1; qemu_chr_be_generic_open(chr); - s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr); + chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, + pty_chr_read, chr); } } } @@ -1151,10 +1148,7 @@ static void pty_chr_close(struct CharDriverState *chr) PtyCharDriver *s = chr->opaque; int fd; - if (s->fd_tag) { - io_remove_watch_poll(s->fd_tag); - s->fd_tag = 0; - } + remove_fd_in_watch(chr); fd = g_io_channel_unix_get_fd(s->fd); g_io_channel_unref(s->fd); close(fd); @@ -2161,7 +2155,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) typedef struct { int fd; GIOChannel *chan; - guint tag; uint8_t buf[READ_BUF_LEN]; int bufcnt; int bufptr; @@ -2217,10 +2210,7 @@ static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) s->bufcnt = bytes_read; s->bufptr = s->bufcnt; if (status != G_IO_STATUS_NORMAL) { - if (s->tag) { - io_remove_watch_poll(s->tag); - s->tag = 0; - } + remove_fd_in_watch(chr); return FALSE; } @@ -2238,23 +2228,18 @@ static void udp_chr_update_read_handler(CharDriverState *chr) { NetCharDriver *s = chr->opaque; - if (s->tag) { - io_remove_watch_poll(s->tag); - s->tag = 0; - } - + remove_fd_in_watch(chr); if (s->chan) { - s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr); + chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll, + udp_chr_read, chr); } } static void udp_chr_close(CharDriverState *chr) { NetCharDriver *s = chr->opaque; - if (s->tag) { - io_remove_watch_poll(s->tag); - s->tag = 0; - } + + remove_fd_in_watch(chr); if (s->chan) { g_io_channel_unref(s->chan); closesocket(s->fd); @@ -2304,7 +2289,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) typedef struct { GIOChannel *chan, *listen_chan; - guint tag, listen_tag; + guint listen_tag; int fd, listen_fd; int connected; int max_size; @@ -2489,10 +2474,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) if (s->listen_chan) { s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); } - if (s->tag) { - io_remove_watch_poll(s->tag); - s->tag = 0; - } + remove_fd_in_watch(chr); g_io_channel_unref(s->chan); s->chan = NULL; closesocket(s->fd); @@ -2522,7 +2504,8 @@ static void tcp_chr_connect(void *opaque) s->connected = 1; if (s->chan) { - s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr); + chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, + tcp_chr_read, chr); } qemu_chr_be_generic_open(chr); } @@ -2605,10 +2588,7 @@ static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; if (s->fd >= 0) { - if (s->tag) { - io_remove_watch_poll(s->tag); - s->tag = 0; - } + remove_fd_in_watch(chr); if (s->chan) { g_io_channel_unref(s->chan); } @@ -2989,11 +2969,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) if (strstart(filename, "vc", &p)) { qemu_opt_set(opts, "backend", "vc"); if (*p == ':') { - if (sscanf(p+1, "%8[0-9]x%8[0-9]", width, height) == 2) { + if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) { /* pixels */ qemu_opt_set(opts, "width", width); qemu_opt_set(opts, "height", height); - } else if (sscanf(p+1, "%8[0-9]Cx%8[0-9]C", width, height) == 2) { + } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) { /* chars */ qemu_opt_set(opts, "cols", width); qemu_opt_set(opts, "rows", height); @@ -3271,7 +3251,12 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, backend->kind = CHARDEV_BACKEND_KIND_MUX; backend->mux->chardev = g_strdup(bid); ret = qmp_chardev_add(id, backend, errp); - assert(!error_is_set(errp)); + if (error_is_set(errp)) { + chr = qemu_chr_find(bid); + qemu_chr_delete(chr); + chr = NULL; + goto qapi_out; + } } chr = qemu_chr_find(id); diff --git a/qemu-seccomp.c b/qemu-seccomp.c index 37d38f881c..69cee443af 100644 --- a/qemu-seccomp.c +++ b/qemu-seccomp.c @@ -90,6 +90,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { { SCMP_SYS(getuid), 245 }, { SCMP_SYS(geteuid), 245 }, { SCMP_SYS(timer_create), 245 }, + { SCMP_SYS(times), 245 }, { SCMP_SYS(exit), 245 }, { SCMP_SYS(clock_gettime), 245 }, { SCMP_SYS(time), 245 }, diff --git a/roms/openbios b/roms/openbios -Subproject 0f3d51ef22ec9166beb3ed434d253029ed7cfe8 +Subproject d363cf50c50c268da7e6d0bf707adde1893d1ab diff --git a/slirp/misc.c b/slirp/misc.c index c0d489950a..6c1636f7b6 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -212,8 +212,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty) so->s = accept(s, (struct sockaddr *)&addr, &addrlen); } while (so->s < 0 && errno == EINTR); closesocket(s); - opt = 1; - qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); + socket_set_fast_reuse(so->s); opt = 1; qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); qemu_set_nonblock(so->s); diff --git a/slirp/socket.c b/slirp/socket.c index 25d60e7a89..37ac5cf2fb 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -627,9 +627,7 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, addr.sin_port = hport; if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || -#ifndef _WIN32 - (qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) || -#endif + (socket_set_fast_reuse(s) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (listen(s,1) < 0)) { int tmperrno = errno; /* Don't clobber the real reason we failed */ diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 043f28fcae..7571c5a282 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -337,8 +337,7 @@ int tcp_fconnect(struct socket *so) struct sockaddr_in addr; qemu_set_nonblock(s); - opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + socket_set_fast_reuse(s); opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); @@ -426,8 +425,7 @@ void tcp_connect(struct socket *inso) return; } qemu_set_nonblock(s); - opt = 1; - qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); + socket_set_fast_reuse(s); opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); socket_set_nodelay(s); diff --git a/slirp/udp.c b/slirp/udp.c index b105f871f3..8cc6cb66da 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -354,7 +354,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, { struct sockaddr_in addr; struct socket *so; - socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1; + socklen_t addrlen = sizeof(struct sockaddr_in); so = socreate(slirp); if (!so) { @@ -372,7 +372,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, udp_detach(so); return NULL; } - qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); + socket_set_fast_reuse(so->s); getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; diff --git a/target-arm/iwmmxt_helper.c b/target-arm/iwmmxt_helper.c index 7953b53f7e..e6cfa62da8 100644 --- a/target-arm/iwmmxt_helper.c +++ b/target-arm/iwmmxt_helper.c @@ -577,7 +577,7 @@ uint64_t HELPER(iwmmxt_rorl)(CPUARMState *env, uint64_t x, uint32_t n) uint64_t HELPER(iwmmxt_rorq)(CPUARMState *env, uint64_t x, uint32_t n) { - x = (x >> n) | (x << (64 - n)); + x = ror64(x, n); env->iwmmxt.cregs[ARM_IWMMXT_wCASF] = NZBIT64(x); return x; } diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c index 2566a040a6..462f984a26 100644 --- a/target-i386/arch_memory_mapping.c +++ b/target-i386/arch_memory_mapping.c @@ -75,7 +75,7 @@ static void walk_pte2(MemoryMappingList *list, } /* PAE Paging or IA-32e Paging */ -#define PLM4_ADDR_MASK 0xffffffffff000 /* selects bits 51:12 */ +#define PLM4_ADDR_MASK 0xffffffffff000ULL /* selects bits 51:12 */ static void walk_pde(MemoryMappingList *list, hwaddr pde_start_addr, int32_t a20_mask, target_ulong start_line_addr) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index eb0e84ce44..622cc49aa7 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -175,20 +175,12 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) ct->ct |= TCG_CT_REG; tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); #ifdef CONFIG_SOFTMMU - /* r0-r2 will be overwritten when reading the tlb entry, + /* r0-r2,lr will be overwritten when reading the tlb entry, so don't use these. */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2); -#endif - break; - case 'L': - ct->ct |= TCG_CT_REG; - tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1); -#ifdef CONFIG_SOFTMMU - /* r1 is still needed to load data_reg or data_reg2, - so don't use it. */ - tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1); + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14); #endif break; @@ -207,6 +199,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) /* Avoid clashes with registers being used for helper args */ tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3); #endif + tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14); #endif break; @@ -320,6 +313,9 @@ typedef enum { INSN_STRB_REG = 0x06400000, INSN_LDRD_IMM = 0x004000d0, + INSN_LDRD_REG = 0x000000d0, + INSN_STRD_IMM = 0x004000f0, + INSN_STRD_REG = 0x000000f0, } ARMInsn; #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00) @@ -379,13 +375,17 @@ static inline void tcg_out_b_noaddr(TCGContext *s, int cond) /* We pay attention here to not modify the branch target by skipping the corresponding bytes. This ensure that caches and memory are kept coherent during retranslation. */ -#ifdef HOST_WORDS_BIGENDIAN - tcg_out8(s, (cond << 4) | 0x0a); - s->code_ptr += 3; -#else s->code_ptr += 3; tcg_out8(s, (cond << 4) | 0x0a); -#endif +} + +static inline void tcg_out_bl_noaddr(TCGContext *s, int cond) +{ + /* We pay attention here to not modify the branch target by skipping + the corresponding bytes. This ensure that caches and memory are + kept coherent during retranslation. */ + s->code_ptr += 3; + tcg_out8(s, (cond << 4) | 0x0b); } static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset) @@ -810,6 +810,30 @@ static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt, tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0); } +static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt, + TCGReg rn, int imm8) +{ + tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0); +} + +static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt, + TCGReg rn, TCGReg rm) +{ + tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0); +} + +static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt, + TCGReg rn, int imm8) +{ + tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0); +} + +static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt, + TCGReg rn, TCGReg rm) +{ + tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0); +} + /* Register pre-increment with base writeback. */ static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt, TCGReg rn, TCGReg rm) @@ -975,34 +999,27 @@ static inline void tcg_out_st8(TCGContext *s, int cond, tcg_out_st8_12(s, cond, rd, rn, offset); } -/* The _goto case is normally between TBs within the same code buffer, - * and with the code buffer limited to 16MB we shouldn't need the long - * case. - * - * .... except to the prologue that is in its own buffer. +/* The _goto case is normally between TBs within the same code buffer, and + * with the code buffer limited to 16MB we wouldn't need the long case. + * But we also use it for the tail-call to the qemu_ld/st helpers, which does. */ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr) { - int32_t val; + int32_t disp = addr - (tcg_target_long) s->code_ptr; - if (addr & 1) { - /* goto to a Thumb destination isn't supported */ - tcg_abort(); + if ((addr & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) { + tcg_out_b(s, cond, disp); + return; } - val = addr - (tcg_target_long) s->code_ptr; - if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd) - tcg_out_b(s, cond, val); - else { - if (cond == COND_AL) { - tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4); - tcg_out32(s, addr); - } else { - tcg_out_movi32(s, cond, TCG_REG_TMP, val - 8); - tcg_out_dat_reg(s, cond, ARITH_ADD, - TCG_REG_PC, TCG_REG_PC, - TCG_REG_TMP, SHIFT_IMM_LSL(0)); + tcg_out_movi32(s, cond, TCG_REG_TMP, addr); + if (use_armv5t_instructions) { + tcg_out_bx(s, cond, TCG_REG_TMP); + } else { + if (addr & 1) { + tcg_abort(); } + tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP); } } @@ -1057,23 +1074,29 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index) } #ifdef CONFIG_SOFTMMU - -/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, - int mmu_idx) */ -static const void * const qemu_ld_helpers[4] = { - helper_ldb_mmu, - helper_ldw_mmu, - helper_ldl_mmu, - helper_ldq_mmu, +/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, + * int mmu_idx, uintptr_t ra) + */ +static const void * const qemu_ld_helpers[8] = { + helper_ret_ldub_mmu, + helper_ret_lduw_mmu, + helper_ret_ldul_mmu, + helper_ret_ldq_mmu, + + helper_ret_ldsb_mmu, + helper_ret_ldsw_mmu, + helper_ret_ldul_mmu, + helper_ret_ldq_mmu, }; -/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, - uintxx_t val, int mmu_idx) */ +/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, + * uintxx_t val, int mmu_idx, uintptr_t ra) + */ static const void * const qemu_st_helpers[4] = { - helper_stb_mmu, - helper_stw_mmu, - helper_stl_mmu, - helper_stq_mmu, + helper_ret_stb_mmu, + helper_ret_stw_mmu, + helper_ret_stl_mmu, + helper_ret_stq_mmu, }; /* Helper routines for marshalling helper function arguments into @@ -1117,53 +1140,62 @@ static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg, if (argreg & 1) { argreg++; } - argreg = tcg_out_arg_reg32(s, argreg, arglo); - argreg = tcg_out_arg_reg32(s, argreg, arghi); - return argreg; + if (use_armv6_instructions && argreg >= 4 + && (arglo & 1) == 0 && arghi == arglo + 1) { + tcg_out_strd_8(s, COND_AL, arglo, + TCG_REG_CALL_STACK, (argreg - 4) * 4); + return argreg + 2; + } else { + argreg = tcg_out_arg_reg32(s, argreg, arglo); + argreg = tcg_out_arg_reg32(s, argreg, arghi); + return argreg; + } } #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS) -/* Load and compare a TLB entry, leaving the flags set. Leaves R2 pointing - to the tlb entry. Clobbers R1 and TMP. */ +/* We're expecting to use an 8-bit immediate and to mask. */ +QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8); -static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, - int s_bits, int tlb_offset) +/* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset. + Using the offset of the second entry in the last tlb table ensures + that we can index all of the elements of the first entry. */ +QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) + > 0xffff); + +/* Load and compare a TLB entry, leaving the flags set. Returns the register + containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */ + +static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, + int s_bits, int mem_index, bool is_load) { TCGReg base = TCG_AREG0; + int cmp_off = + (is_load + ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read) + : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); + int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); /* Should generate something like the following: - * pre-v7: * shr tmp, addr_reg, #TARGET_PAGE_BITS (1) - * add r2, env, #off & 0xff00 + * add r2, env, #high * and r0, tmp, #(CPU_TLB_SIZE - 1) (2) * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3) - * ldr r0, [r2, #off & 0xff]! (4) + * ldr r0, [r2, #cmp] (4) * tst addr_reg, #s_mask - * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS (5) - * - * v7 (not implemented yet): - * ubfx r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS (1) - * movw tmp, #~TARGET_PAGE_MASK & ~s_mask - * movw r0, #off - * add r2, env, r2, lsl #CPU_TLB_ENTRY_BITS (2) - * bic tmp, addr_reg, tmp - * ldr r0, [r2, r0]! (3) - * cmp r0, tmp (4) + * ldr r1, [r2, #add] (5) + * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS */ -# if CPU_TLB_BITS > 8 -# error -# endif tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP, 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS)); - /* We assume that the offset is contained within 16 bits. */ - assert((tlb_offset & ~0xffff) == 0); - if (tlb_offset > 0xff) { + /* We checked that the offset is contained within 16 bits above. */ + if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) { tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base, - (24 << 7) | (tlb_offset >> 8)); - tlb_offset &= 0xff; + (24 << 7) | (cmp_off >> 8)); base = TCG_REG_R2; + add_off -= cmp_off & 0xff00; + cmp_off &= 0xff; } tcg_out_dat_imm(s, COND_AL, ARITH_AND, @@ -1175,14 +1207,11 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, but due to how the pointer needs setting up, ldm isn't useful. Base arm5 doesn't have ldrd, but armv5te does. */ if (use_armv6_instructions && TARGET_LONG_BITS == 64) { - tcg_out_memop_8(s, COND_AL, INSN_LDRD_IMM, TCG_REG_R0, - TCG_REG_R2, tlb_offset, 1, 1); + tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off); } else { - tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0, - TCG_REG_R2, tlb_offset, 1, 1); + tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off); if (TARGET_LONG_BITS == 64) { - tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R1, - TCG_REG_R2, 4, 1, 0); + tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4); } } @@ -1192,6 +1221,9 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, 0, addrlo, (1 << s_bits) - 1); } + /* Load the tlb addend. */ + tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off); + tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0, TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS)); @@ -1199,6 +1231,8 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi, tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0, TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0)); } + + return TCG_REG_R2; } /* Record the context of a call to the out of line helper code for the slow @@ -1232,7 +1266,8 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc, static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) { TCGReg argreg, data_reg, data_reg2; - uint8_t *start; + int opc = lb->opc; + uintptr_t func; reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr); @@ -1243,46 +1278,46 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg); } argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index); - tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[lb->opc & 3]); + argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14); + + /* For armv6 we can use the canonical unsigned helpers and minimize + icache usage. For pre-armv6, use the signed helpers since we do + not have a single insn sign-extend. */ + if (use_armv6_instructions) { + func = (uintptr_t)qemu_ld_helpers[opc & 3]; + } else { + func = (uintptr_t)qemu_ld_helpers[opc]; + if (opc & 4) { + opc = 2; + } + } + tcg_out_call(s, func); data_reg = lb->datalo_reg; data_reg2 = lb->datahi_reg; - - start = s->code_ptr; - switch (lb->opc) { + switch (opc) { case 0 | 4: tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0); break; case 1 | 4: tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0); break; - case 0: - case 1: - case 2: default: tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); break; case 3: - tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); - tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1); - break; - } - - /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between - the call and the branch back to straight-line code. Note that the - moves above could be elided by register allocation, nor do we know - which code alternative we chose for extension. */ - switch (s->code_ptr - start) { - case 0: - tcg_out_nop(s); - /* FALLTHRU */ - case 4: - tcg_out_nop(s); - /* FALLTHRU */ - case 8: + if (data_reg != TCG_REG_R1) { + tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); + tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1); + } else if (data_reg2 != TCG_REG_R0) { + tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1); + tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0); + } else { + tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0); + tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1); + tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_TMP); + } break; - default: - abort(); } tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr); @@ -1320,13 +1355,10 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) } argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index); - tcg_out_call(s, (tcg_target_long) qemu_st_helpers[lb->opc & 3]); + argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14); - /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between - the call and the branch back to straight-line code. */ - tcg_out_nop(s); - tcg_out_nop(s); - tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr); + /* Tail-call to the helper, which will return to the fast path. */ + tcg_out_goto(s, COND_AL, (tcg_target_long) qemu_st_helpers[lb->opc & 3]); } #endif /* SOFTMMU */ @@ -1336,7 +1368,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) bool bswap; #ifdef CONFIG_SOFTMMU int mem_index, s_bits; - TCGReg addr_reg2; + TCGReg addr_reg2, addend; uint8_t *label_ptr; #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -1353,53 +1385,63 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) mem_index = *args; s_bits = opc & 3; - tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, - offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)); + addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 1); + /* This a conditional BL only to load a pointer within this opcode into LR + for the slow path. We will not be using the value for a tail call. */ label_ptr = s->code_ptr; - tcg_out_b_noaddr(s, COND_NE); - - tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, - offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_read)); + tcg_out_bl_noaddr(s, COND_NE); switch (opc) { case 0: - tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, addend); break; case 0 | 4: - tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, addend); break; case 1: - tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend); if (bswap) { tcg_out_bswap16(s, COND_AL, data_reg, data_reg); } break; case 1 | 4: if (bswap) { - tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, addend); tcg_out_bswap16s(s, COND_AL, data_reg, data_reg); } else { - tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, addend); } break; case 2: default: - tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, addend); if (bswap) { tcg_out_bswap32(s, COND_AL, data_reg, data_reg); } break; case 3: - if (bswap) { - tcg_out_ld32_rwb(s, COND_AL, data_reg2, TCG_REG_R1, addr_reg); - tcg_out_ld32_12(s, COND_AL, data_reg, TCG_REG_R1, 4); - tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2); - tcg_out_bswap32(s, COND_AL, data_reg, data_reg); - } else { - tcg_out_ld32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg); - tcg_out_ld32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4); + { + /* Be careful not to modify data_reg and data_reg2 + for the slow path below. */ + TCGReg dl = (bswap ? data_reg2 : data_reg); + TCGReg dh = (bswap ? data_reg : data_reg2); + + if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) { + tcg_out_ldrd_r(s, COND_AL, dl, addr_reg, addend); + } else if (dl != addend) { + tcg_out_ld32_rwb(s, COND_AL, dl, addend, addr_reg); + tcg_out_ld32_12(s, COND_AL, dh, addend, 4); + } else { + tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP, + addend, addr_reg, SHIFT_IMM_LSL(0)); + tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0); + tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4); + } + if (bswap) { + tcg_out_bswap32(s, COND_AL, dh, dh); + tcg_out_bswap32(s, COND_AL, dl, dl); + } } break; } @@ -1450,9 +1492,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) } break; case 3: - /* TODO: use block load - - * check that data_reg2 > data_reg or the other way */ - if (data_reg == addr_reg) { + if (use_armv6_instructions && !bswap + && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) { + tcg_out_ldrd_8(s, COND_AL, data_reg, addr_reg, 0); + } else if (use_armv6_instructions && bswap + && (data_reg2 & 1) == 0 && data_reg == data_reg2 + 1) { + tcg_out_ldrd_8(s, COND_AL, data_reg2, addr_reg, 0); + } else if (data_reg == addr_reg) { tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4); tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0); } else { @@ -1474,7 +1520,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) bool bswap; #ifdef CONFIG_SOFTMMU int mem_index, s_bits; - TCGReg addr_reg2; + TCGReg addr_reg2, addend; uint8_t *label_ptr; #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -1491,51 +1537,49 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) mem_index = *args; s_bits = opc & 3; - tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, - offsetof(CPUArchState, - tlb_table[mem_index][0].addr_write)); - - label_ptr = s->code_ptr; - tcg_out_b_noaddr(s, COND_NE); - - tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, - offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_write)); + addend = tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits, mem_index, 0); switch (opc) { case 0: - tcg_out_st8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, addend); break; case 1: if (bswap) { - tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg); - tcg_out_st16_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1); + tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg); + tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend); } else { - tcg_out_st16_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, addend); } break; case 2: default: if (bswap) { - tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg); - tcg_out_st32_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1); + tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg); + tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, addend); } else { - tcg_out_st32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1); + tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, addend); } break; case 3: if (bswap) { - tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2); - tcg_out_st32_rwb(s, COND_AL, TCG_REG_R0, TCG_REG_R1, addr_reg); - tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg); - tcg_out_st32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R1, 4); + tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2); + tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, addend, addr_reg); + tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg); + tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, addend, 4); + } else if (use_armv6_instructions + && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) { + tcg_out_strd_r(s, COND_EQ, data_reg, addr_reg, addend); } else { - tcg_out_st32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg); - tcg_out_st32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4); + tcg_out_st32_rwb(s, COND_EQ, data_reg, addend, addr_reg); + tcg_out_st32_12(s, COND_EQ, data_reg2, addend, 4); } break; } + /* The conditional call must come last, as we're going to return here. */ + label_ptr = s->code_ptr; + tcg_out_bl_noaddr(s, COND_NE); + add_qemu_ldst_label(s, 0, opc, data_reg, data_reg2, addr_reg, addr_reg2, mem_index, s->code_ptr, label_ptr); #else /* !CONFIG_SOFTMMU */ @@ -1576,13 +1620,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) } break; case 3: - /* TODO: use block store - - * check that data_reg2 > data_reg or the other way */ if (bswap) { tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2); tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0); tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg); tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4); + } else if (use_armv6_instructions + && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) { + tcg_out_strd_8(s, COND_AL, data_reg, addr_reg, 0); } else { tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0); tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4); @@ -1991,7 +2036,7 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_qemu_ld16u, { "r", "l" } }, { INDEX_op_qemu_ld16s, { "r", "l" } }, { INDEX_op_qemu_ld32, { "r", "l" } }, - { INDEX_op_qemu_ld64, { "L", "L", "l" } }, + { INDEX_op_qemu_ld64, { "r", "r", "l" } }, { INDEX_op_qemu_st8, { "s", "s" } }, { INDEX_op_qemu_st16, { "s", "s" } }, @@ -2003,7 +2048,7 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_qemu_ld16u, { "r", "l", "l" } }, { INDEX_op_qemu_ld16s, { "r", "l", "l" } }, { INDEX_op_qemu_ld32, { "r", "l", "l" } }, - { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } }, + { INDEX_op_qemu_ld64, { "r", "r", "l", "l" } }, { INDEX_op_qemu_st8, { "s", "s", "s" } }, { INDEX_op_qemu_st16, { "s", "s", "s" } }, diff --git a/tcg/optimize.c b/tcg/optimize.c index b29bf25b67..89e2d6a3b3 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -238,20 +238,16 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) return (int64_t)x >> (int64_t)y; case INDEX_op_rotr_i32: - x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y); - return x; + return ror32(x, y); case INDEX_op_rotr_i64: - x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y); - return x; + return ror64(x, y); case INDEX_op_rotl_i32: - x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y)); - return x; + return rol32(x, y); case INDEX_op_rotl_i64: - x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y)); - return x; + return rol64(x, y); CASE_OP_32_64(not): return ~x; diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index 233ab3bf35..4976becbe7 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -670,7 +670,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_shl_i64: case INDEX_op_shr_i64: case INDEX_op_sar_i64: - /* TODO: Implementation of rotl_i64, rotr_i64 missing in tci.c. */ case INDEX_op_rotl_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ case INDEX_op_rotr_i64: /* Optional (TCG_TARGET_HAS_rot_i64). */ tcg_out_r(s, args[0]); @@ -688,13 +688,13 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); - tci_write_reg32(t0, (t1 << t2) | (t1 >> (32 - t2))); + tci_write_reg32(t0, rol32(t1, t2)); break; case INDEX_op_rotr_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); - tci_write_reg32(t0, (t1 >> t2) | (t1 << (32 - t2))); + tci_write_reg32(t0, ror32(t1, t2)); break; #endif #if TCG_TARGET_HAS_deposit_i32 @@ -952,8 +952,16 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) break; #if TCG_TARGET_HAS_rot_i64 case INDEX_op_rotl_i64: + t0 = *tb_ptr++; + t1 = tci_read_ri64(&tb_ptr); + t2 = tci_read_ri64(&tb_ptr); + tci_write_reg64(t0, rol64(t1, t2)); + break; case INDEX_op_rotr_i64: - TODO(); + t0 = *tb_ptr++; + t1 = tci_read_ri64(&tb_ptr); + t2 = tci_read_ri64(&tb_ptr); + tci_write_reg64(t0, ror64(t1, t2)); break; #endif #if TCG_TARGET_HAS_deposit_i64 diff --git a/tests/.gitignore b/tests/.gitignore index ae5280ef68..425757cfe1 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -5,9 +5,11 @@ check-qjson check-qlist check-qstring test-aio +test-bitops test-throttle test-cutils test-hbitmap +test-int128 test-iov test-mul64 test-qapi-types.[ch] @@ -21,3 +23,4 @@ test-thread-pool test-x86-cpuid test-xbzrle *-test +qapi-schema/*.test.* diff --git a/tests/Makefile b/tests/Makefile index 994fef1839..915ae5e2d1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -261,10 +261,10 @@ check-tests/test-qapi.py: tests/test-qapi.py .PHONY: $(patsubst %, check-%, $(check-qapi-schema-y)) $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json - $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, " TEST $*.out") - @diff -q $(SRC_PATH)/$*.out $*.out - @diff -q $(SRC_PATH)/$*.err $*.err - @diff -q $(SRC_PATH)/$*.exit $*.exit + $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.test.out 2>$*.test.err; echo $$? >$*.test.exit, " TEST $*.out") + @diff -q $(SRC_PATH)/$*.out $*.test.out + @diff -q $(SRC_PATH)/$*.err $*.test.err + @diff -q $(SRC_PATH)/$*.exit $*.test.exit # Consolidated targets diff --git a/tests/qemu-iotests/.gitignore b/tests/qemu-iotests/.gitignore index 62b4002995..0541f80daa 100644 --- a/tests/qemu-iotests/.gitignore +++ b/tests/qemu-iotests/.gitignore @@ -2,6 +2,7 @@ check.log check.time *.out.bad *.notrun +socket_scm_helper # ignore everything in the scratch directory scratch/ diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out index 0764389f8e..15045799a2 100644 --- a/tests/qemu-iotests/026.out +++ b/tests/qemu-iotests/026.out @@ -5,16 +5,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: on; write write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: on; write -b write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write @@ -33,16 +29,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: on; write write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: on; write -b write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write @@ -181,16 +173,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: on; write write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: off; write @@ -207,16 +195,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: on; write write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: off; write diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache index 33bad0d6ae..c9d242e9ec 100644 --- a/tests/qemu-iotests/026.out.nocache +++ b/tests/qemu-iotests/026.out.nocache @@ -5,16 +5,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: on; write write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: on; write -b write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 5; imm: off; once: off; write @@ -33,16 +29,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: on; write write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: on; write -b write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l1_update; errno: 28; imm: off; once: off; write @@ -189,16 +181,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: on; write write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b write failed: Input/output error - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 5; imm: off; once: off; write @@ -215,16 +203,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: on; write write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b write failed: No space left on device - -1 leaked clusters were found on the image. -This means waste of disk space, but no harm to data. +No errors were found on the image. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Event: l2_alloc.write; errno: 28; imm: off; once: off; write diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 253bc3df2e..e00a44c86f 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -157,6 +157,18 @@ void qemu_set_nonblock(int fd) fcntl(fd, F_SETFL, f | O_NONBLOCK); } +int socket_set_fast_reuse(int fd) +{ + int val = 1, ret; + + ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&val, sizeof(val)); + + assert(ret == 0); + + return ret; +} + void qemu_set_cloexec(int fd) { int f; diff --git a/util/oslib-win32.c b/util/oslib-win32.c index 983b7a2375..776ccfaaf0 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -124,6 +124,16 @@ void qemu_set_nonblock(int fd) qemu_fd_register(fd); } +int socket_set_fast_reuse(int fd) +{ + /* Enabling the reuse of an endpoint that was used by a socket still in + * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows + * fast reuse is the default and SO_REUSEADDR does strange things. So we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ + return 0; +} + int inet_aton(const char *cp, struct in_addr *ia) { uint32_t addr = inet_addr(cp); diff --git a/util/path.c b/util/path.c index f0c69627c7..623219e4c5 100644 --- a/util/path.c +++ b/util/path.c @@ -39,7 +39,7 @@ static int strneq(const char *s1, unsigned int n, const char *s2) } static struct pathelem *add_entry(struct pathelem *root, const char *name, - unsigned char type); + unsigned type); static struct pathelem *new_entry(const char *root, struct pathelem *parent, @@ -82,7 +82,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path) } static struct pathelem *add_entry(struct pathelem *root, const char *name, - unsigned char type) + unsigned type) { struct pathelem **e; diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 095716ecdb..6b97dc11f9 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -155,7 +155,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) continue; } - qemu_setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + socket_set_fast_reuse(slisten); #ifdef IPV6_V6ONLY if (e->ai_family == PF_INET6) { /* listen on both ipv4 and ipv6 */ @@ -274,7 +274,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); return -1; } - qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + socket_set_fast_reuse(sock); if (connect_state != NULL) { qemu_set_nonblock(sock); } @@ -455,7 +455,7 @@ int inet_dgram_opts(QemuOpts *opts, Error **errp) error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); goto err; } - qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + socket_set_fast_reuse(sock); /* bind socket */ if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { @@ -2825,7 +2825,7 @@ int main(int argc, char **argv, char **envp) const char *icount_option = NULL; const char *initrd_filename; const char *kernel_filename, *kernel_cmdline; - const char *boot_order = NULL; + const char *boot_order; DisplayState *ds; int cyls, heads, secs, translation; QemuOpts *hda_opts = NULL, *opts, *machine_opts; @@ -4050,9 +4050,7 @@ int main(int argc, char **argv, char **envp) initrd_filename = qemu_opt_get(machine_opts, "initrd"); kernel_cmdline = qemu_opt_get(machine_opts, "append"); - if (!boot_order) { - boot_order = machine->default_boot_order; - } + boot_order = machine->default_boot_order; opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); if (opts) { char *normal_boot_order; @@ -949,7 +949,7 @@ static void xenstore_record_dm_state(struct xs_handle *xs, const char *state) exit(1); } - snprintf(path, sizeof (path), "/local/domain/0/device-model/%u/state", xen_domid); + snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { fprintf(stderr, "error recording dm state\n"); exit(1); |