diff options
| -rw-r--r-- | backends/hostmem-file.c | 5 | ||||
| -rw-r--r-- | docs/memory.txt | 8 | ||||
| -rw-r--r-- | hw/input/ps2.c | 2 | ||||
| -rw-r--r-- | hw/net/opencores_eth.c | 2 | ||||
| -rw-r--r-- | hw/net/rtl8139.c | 2 | ||||
| -rw-r--r-- | hw/ppc/spapr.c | 4 | ||||
| -rw-r--r-- | hw/ppc/spapr_rtas.c | 7 | ||||
| -rw-r--r-- | hw/timer/hpet.c | 14 | ||||
| -rw-r--r-- | nbd/client.c | 63 | ||||
| -rw-r--r-- | nbd/common.c | 5 | ||||
| -rw-r--r-- | nbd/nbd-internal.h | 15 | ||||
| -rw-r--r-- | nbd/server.c | 11 | ||||
| -rw-r--r-- | net/filter.c | 2 | ||||
| -rw-r--r-- | net/net.c | 44 | ||||
| -rw-r--r-- | qemu-nbd.c | 1 | ||||
| -rw-r--r-- | qga/commands.c | 4 | ||||
| -rw-r--r-- | qga/installer/qemu-ga.wxs | 4 | ||||
| -rw-r--r-- | slirp/slirp.c | 12 | ||||
| -rw-r--r-- | slirp/socket.c | 34 | ||||
| -rw-r--r-- | slirp/socket.h | 2 | ||||
| -rw-r--r-- | slirp/tcp_input.c | 6 | ||||
| -rw-r--r-- | slirp/tcp_subr.c | 7 | ||||
| -rw-r--r-- | target-i386/helper.c | 18 | ||||
| -rw-r--r-- | tci.c | 41 | ||||
| -rw-r--r-- | tests/.gitignore | 1 | ||||
| -rw-r--r-- | translate-all.c | 3 | ||||
| -rw-r--r-- | util/hexdump.c | 33 |
27 files changed, 218 insertions, 132 deletions
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c index c70f268d6f..b17a1f10a2 100644 --- a/backends/hostmem-file.c +++ b/backends/hostmem-file.c @@ -52,11 +52,14 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) error_setg(errp, "-mem-path not supported on this host"); #else if (!memory_region_size(&backend->mr)) { + gchar *path; backend->force_prealloc = mem_prealloc; + path = object_get_canonical_path(OBJECT(backend)); memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), - object_get_canonical_path(OBJECT(backend)), + path, backend->size, fb->share, fb->mem_path, errp); + g_free(path); } #endif } diff --git a/docs/memory.txt b/docs/memory.txt index f9272ca969..431d9ca88f 100644 --- a/docs/memory.txt +++ b/docs/memory.txt @@ -185,9 +185,9 @@ an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at offset 0x2000. As a diagram: - 0 1000 2000 3000 4000 5000 6000 7000 8000 - |------|------|------|------|------|------|------|-------| - A: [ ] + 0 1000 2000 3000 4000 5000 6000 7000 8000 + |------|------|------|------|------|------|------|------| + A: [ ] C: [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC] B: [ ] D: [DDDDD] @@ -247,7 +247,7 @@ system_memory: container@0-2^48-1 | +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff) | - +---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff) + +---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff) | (prio 1) | +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 58892d5ecd..a8aa36f5c0 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -628,7 +628,7 @@ static void ps2_kbd_reset(void *opaque) ps2_common_reset(&s->common); s->scan_enabled = 0; s->translate = 0; - s->scancode_set = 0; + s->scancode_set = 2; } static void ps2_mouse_reset(void *opaque) diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 09e239a65a..c6094fbb56 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -85,7 +85,7 @@ static void mii_reset(Mii *s) { memset(s->regs, 0, sizeof(s->regs)); s->regs[MII_BMCR] = 0x1000; - s->regs[MII_BMSR] = 0x7848; /* no ext regs */ + s->regs[MII_BMSR] = 0x7868; /* no ext regs */ s->regs[MII_PHYIDR1] = 0x2000; s->regs[MII_PHYIDR2] = 0x5c90; s->regs[MII_ANAR] = 0x01e1; diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index fee97bf607..1e5ec149fa 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -2046,7 +2046,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } /* transfer ownership to target */ - txdw0 &= ~CP_RX_OWN; + txdw0 &= ~CP_TX_OWN; /* reset error indicator bits */ txdw0 &= ~CP_TX_STATUS_UNF; diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e7be21e678..feaab08c3d 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2208,6 +2208,10 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, if (*errp) { return; } + if (node < 0 || node >= MAX_NODES) { + error_setg(errp, "Invaild node %d", node); + return; + } /* * Currently PowerPC kernel doesn't allow hot-adding memory to diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 2db229272e..f07325831c 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -684,6 +684,9 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, int i; uint32_t lrdr_capacity[5]; MachineState *machine = MACHINE(qdev_get_machine()); + sPAPRMachineState *spapr = SPAPR_MACHINE(machine); + uint64_t max_hotplug_addr = spapr->hotplug_memory.base + + memory_region_size(&spapr->hotplug_memory.mr); ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size); if (ret < 0) { @@ -733,8 +736,8 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, } - lrdr_capacity[0] = cpu_to_be32(((uint64_t)machine->maxram_size) >> 32); - lrdr_capacity[1] = cpu_to_be32(machine->maxram_size & 0xffffffff); + lrdr_capacity[0] = cpu_to_be32(max_hotplug_addr >> 32); + lrdr_capacity[1] = cpu_to_be32(max_hotplug_addr & 0xffffffff); lrdr_capacity[2] = 0; lrdr_capacity[3] = cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE); lrdr_capacity[4] = cpu_to_be32(max_cpus/smp_threads); diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 78140e6092..a2c18b30c3 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -201,12 +201,7 @@ static void update_irq(struct HPETTimer *timer, int set) if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) { s->isr &= ~mask; if (!timer_fsb_route(timer)) { - /* fold the ICH PIRQ# pin's internal inversion logic into hpet */ - if (route >= ISA_NUM_IRQS) { - qemu_irq_raise(s->irqs[route]); - } else { - qemu_irq_lower(s->irqs[route]); - } + qemu_irq_lower(s->irqs[route]); } } else if (timer_fsb_route(timer)) { address_space_stl_le(&address_space_memory, timer->fsb >> 32, @@ -214,12 +209,7 @@ static void update_irq(struct HPETTimer *timer, int set) NULL); } else if (timer->config & HPET_TN_TYPE_LEVEL) { s->isr |= mask; - /* fold the ICH PIRQ# pin's internal inversion logic into hpet */ - if (route >= ISA_NUM_IRQS) { - qemu_irq_lower(s->irqs[route]); - } else { - qemu_irq_raise(s->irqs[route]); - } + qemu_irq_raise(s->irqs[route]); } else { s->isr &= ~mask; qemu_irq_pulse(s->irqs[route]); diff --git a/nbd/client.c b/nbd/client.c index d9b7a9b07e..6777e589d1 100644 --- a/nbd/client.c +++ b/nbd/client.c @@ -73,16 +73,46 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); */ -static int nbd_handle_reply_err(uint32_t opt, uint32_t type, Error **errp) +/* If type represents success, return 1 without further action. + * If type represents an error reply, consume the rest of the packet on ioc. + * Then return 0 for unsupported (so the client can fall back to + * other approaches), or -1 with errp set for other errors. + */ +static int nbd_handle_reply_err(QIOChannel *ioc, uint32_t opt, uint32_t type, + Error **errp) { + uint32_t len; + char *msg = NULL; + int result = -1; + if (!(type & (1 << 31))) { - return 0; + return 1; + } + + if (read_sync(ioc, &len, sizeof(len)) != sizeof(len)) { + error_setg(errp, "failed to read option length"); + return -1; + } + len = be32_to_cpu(len); + if (len) { + if (len > NBD_MAX_BUFFER_SIZE) { + error_setg(errp, "server's error message is too long"); + goto cleanup; + } + msg = g_malloc(len + 1); + if (read_sync(ioc, msg, len) != len) { + error_setg(errp, "failed to read option error message"); + goto cleanup; + } + msg[len] = '\0'; } switch (type) { case NBD_REP_ERR_UNSUP: - error_setg(errp, "Unsupported option type %x", opt); - break; + TRACE("server doesn't understand request %d, attempting fallback", + opt); + result = 0; + goto cleanup; case NBD_REP_ERR_POLICY: error_setg(errp, "Denied by server for option %x", opt); @@ -101,7 +131,13 @@ static int nbd_handle_reply_err(uint32_t opt, uint32_t type, Error **errp) break; } - return -1; + if (msg) { + error_append_hint(errp, "%s\n", msg); + } + + cleanup: + g_free(msg); + return result; } static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp) @@ -111,6 +147,7 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp) uint32_t type; uint32_t len; uint32_t namelen; + int error; *name = NULL; if (read_sync(ioc, &magic, sizeof(magic)) != sizeof(magic)) { @@ -138,11 +175,9 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp) return -1; } type = be32_to_cpu(type); - if (type == NBD_REP_ERR_UNSUP) { - return 0; - } - if (nbd_handle_reply_err(opt, type, errp) < 0) { - return -1; + error = nbd_handle_reply_err(ioc, opt, type, errp); + if (error <= 0) { + return error; } if (read_sync(ioc, &len, sizeof(len)) != sizeof(len)) { @@ -628,16 +663,16 @@ ssize_t nbd_send_request(QIOChannel *ioc, struct nbd_request *request) uint8_t buf[NBD_REQUEST_SIZE]; ssize_t ret; + TRACE("Sending request to server: " + "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}", + request->from, request->len, request->handle, request->type); + cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); cpu_to_be32w((uint32_t*)(buf + 4), request->type); cpu_to_be64w((uint64_t*)(buf + 8), request->handle); cpu_to_be64w((uint64_t*)(buf + 16), request->from); cpu_to_be32w((uint32_t*)(buf + 24), request->len); - TRACE("Sending request to server: " - "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}", - request->from, request->len, request->handle, request->type); - ret = write_sync(ioc, buf, sizeof(buf)); if (ret < 0) { return ret; diff --git a/nbd/common.c b/nbd/common.c index a44718ce58..8ddb2dd2f0 100644 --- a/nbd/common.c +++ b/nbd/common.c @@ -50,9 +50,12 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc, * qio_channel_yield() that works with AIO contexts * and consider using that in this branch */ qemu_coroutine_yield(); - } else { + } else if (done) { + /* XXX this is needed by nbd_reply_ready. */ qio_channel_wait(ioc, do_read ? G_IO_IN : G_IO_OUT); + } else { + return -EAGAIN; } continue; } diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h index d09b4ee308..379153561d 100644 --- a/nbd/nbd-internal.h +++ b/nbd/nbd-internal.h @@ -33,18 +33,21 @@ /* #define DEBUG_NBD */ #ifdef DEBUG_NBD -#define TRACE(msg, ...) do { \ - LOG(msg, ## __VA_ARGS__); \ -} while(0) +#define DEBUG_NBD_PRINT 1 #else -#define TRACE(msg, ...) \ - do { } while (0) +#define DEBUG_NBD_PRINT 0 #endif +#define TRACE(msg, ...) do { \ + if (DEBUG_NBD_PRINT) { \ + LOG(msg, ## __VA_ARGS__); \ + } \ +} while (0) + #define LOG(msg, ...) do { \ fprintf(stderr, "%s:%s():L%d: " msg "\n", \ __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \ -} while(0) +} while (0) /* This is all part of the "official" NBD API. * diff --git a/nbd/server.c b/nbd/server.c index b95571bdf5..2a4dd10f52 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -26,6 +26,7 @@ static int system_errno_to_nbd_errno(int err) case 0: return NBD_SUCCESS; case EPERM: + case EROFS: return NBD_EPERM; case EIO: return NBD_EIO; @@ -482,9 +483,12 @@ static int nbd_negotiate_options(NBDClient *client) return -EINVAL; default: TRACE("Unsupported option 0x%x", clientflags); + if (nbd_negotiate_drop_sync(client->ioc, length) != length) { + return -EIO; + } nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP, clientflags); - return -EINVAL; + break; } } else { /* @@ -655,6 +659,9 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, struct nbd_reply *reply) reply->error = system_errno_to_nbd_errno(reply->error); + TRACE("Sending response to client: { .error = %d, handle = %" PRIu64 " }", + reply->error, reply->handle); + /* Reply [ 0 .. 3] magic (NBD_REPLY_MAGIC) [ 4 .. 7] error (0 == no error) @@ -664,8 +671,6 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, struct nbd_reply *reply) stl_be_p(buf + 4, reply->error); stq_be_p(buf + 8, reply->handle); - TRACE("Sending response to client"); - ret = write_sync(ioc, buf, sizeof(buf)); if (ret < 0) { return ret; diff --git a/net/filter.c b/net/filter.c index 1c4fc5a2c7..8ac79f3b7b 100644 --- a/net/filter.c +++ b/net/filter.c @@ -164,7 +164,7 @@ static void netfilter_set_status(Object *obj, const char *str, Error **errp) return; } nf->on = !nf->on; - if (nfc->status_changed) { + if (nf->netdev && nfc->status_changed) { nfc->status_changed(nf, errp); } } diff --git a/net/net.c b/net/net.c index 594c3b8b5d..0ad6217cb9 100644 --- a/net/net.c +++ b/net/net.c @@ -81,34 +81,6 @@ int default_net = 1; /***********************************************************/ /* network device redirectors */ -#if defined(DEBUG_NET) -static void hex_dump(FILE *f, const uint8_t *buf, int size) -{ - int len, i, j, c; - - for(i=0;i<size;i+=16) { - len = size - i; - if (len > 16) - len = 16; - fprintf(f, "%08x ", i); - for(j=0;j<16;j++) { - if (j < len) - fprintf(f, " %02x", buf[i+j]); - else - fprintf(f, " "); - } - fprintf(f, " "); - for(j=0;j<len;j++) { - c = buf[i+j]; - if (c < ' ' || c > '~') - c = '.'; - fprintf(f, "%c", c); - } - fprintf(f, "\n"); - } -} -#endif - static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { const char *p, *p1; @@ -664,7 +636,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, #ifdef DEBUG_NET printf("qemu_send_packet_async:\n"); - hex_dump(stdout, buf, size); + qemu_hexdump((const char *)buf, stdout, "net", size); #endif if (sender->link_down || !sender->peer) { @@ -711,23 +683,28 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov, int iovcnt, unsigned flags) { - uint8_t buf[NET_BUFSIZE]; + uint8_t *buf = NULL; uint8_t *buffer; size_t offset; + ssize_t ret; if (iovcnt == 1) { buffer = iov[0].iov_base; offset = iov[0].iov_len; } else { + buf = g_new(uint8_t, NET_BUFSIZE); buffer = buf; - offset = iov_to_buf(iov, iovcnt, 0, buf, sizeof(buf)); + offset = iov_to_buf(iov, iovcnt, 0, buf, NET_BUFSIZE); } if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) { - return nc->info->receive_raw(nc, buffer, offset); + ret = nc->info->receive_raw(nc, buffer, offset); } else { - return nc->info->receive(nc, buffer, offset); + ret = nc->info->receive(nc, buffer, offset); } + + g_free(buf); + return ret; } ssize_t qemu_deliver_packet_iov(NetClientState *sender, @@ -1100,6 +1077,7 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) } error_propagate(errp, err); + opts_visitor_cleanup(ov); return ret; } diff --git a/qemu-nbd.c b/qemu-nbd.c index ca4a724d25..c2e4d3f64c 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -75,6 +75,7 @@ static void usage(const char *name) " -e, --shared=NUM device can be shared by NUM clients (default '1')\n" " -t, --persistent don't exit on the last connection\n" " -v, --verbose display extra debugging information\n" +" -x, --export-name=NAME expose export by name\n" "\n" "Exposing part of the image:\n" " -o, --offset=OFFSET offset into the image\n" diff --git a/qga/commands.c b/qga/commands.c index 95d8b04a16..b653a460b9 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -373,6 +373,7 @@ static gboolean guest_exec_output_watch(GIOChannel *ch, return true; close: + g_io_channel_shutdown(ch, true, NULL); g_io_channel_unref(ch); g_atomic_int_set(&p->closed, 1); return false; @@ -447,6 +448,7 @@ GuestExec *qmp_guest_exec(const char *path, g_io_channel_set_encoding(in_ch, NULL, NULL); g_io_channel_set_buffered(in_ch, false); g_io_channel_set_flags(in_ch, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_close_on_unref(in_ch, true); g_io_add_watch(in_ch, G_IO_OUT, guest_exec_input_watch, &gei->in); } @@ -462,6 +464,8 @@ GuestExec *qmp_guest_exec(const char *path, g_io_channel_set_encoding(err_ch, NULL, NULL); g_io_channel_set_buffered(out_ch, false); g_io_channel_set_buffered(err_ch, false); + g_io_channel_set_close_on_unref(out_ch, true); + g_io_channel_set_close_on_unref(err_ch, true); g_io_add_watch(out_ch, G_IO_IN | G_IO_HUP, guest_exec_output_watch, &gei->out); g_io_add_watch(err_ch, G_IO_IN | G_IO_HUP, diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs index 7f9289122f..fa2260cafa 100644 --- a/qga/installer/qemu-ga.wxs +++ b/qga/installer/qemu-ga.wxs @@ -96,7 +96,7 @@ <File Id="gspawn-win32-helper-console.exe" Name="gspawn-win32-helper-console.exe" Source="$(var.Mingw_bin)/gspawn-win32-helper-console.exe" KeyPath="yes" DiskId="1"/> </Component> <Component Id="gspawn-helper" Guid="{CD67A5A3-2DB1-4DA1-A67A-8D71E797B466}"> - <File Id="gspawn-win32-helper.exe" Name="gspawn-win32-helper.exe" Source="$(var.Mingw_bin)/gspawn-win32-helper.exe" KeyPath="yes" DiskId="1"/> + <File Id="gspawn-win32-helper.exe" Name="gspawn-win32-helper.exe" Source="$(var.Mingw_bin)/gspawn-win32-helper-console.exe" KeyPath="yes" DiskId="1"/> </Component> <?endif?> <?if $(var.Arch) = "64"?> @@ -104,7 +104,7 @@ <File Id="gspawn-win64-helper-console.exe" Name="gspawn-win64-helper-console.exe" Source="$(var.Mingw_bin)/gspawn-win64-helper-console.exe" KeyPath="yes" DiskId="1"/> </Component> <Component Id="gspawn-helper" Guid="{D201AD22-1846-4E4F-B6E1-C7A908ED2457}"> - <File Id="gspawn-win64-helper.exe" Name="gspawn-win64-helper.exe" Source="$(var.Mingw_bin)/gspawn-win64-helper.exe" KeyPath="yes" DiskId="1"/> + <File Id="gspawn-win64-helper.exe" Name="gspawn-win64-helper.exe" Source="$(var.Mingw_bin)/gspawn-win64-helper-console.exe" KeyPath="yes" DiskId="1"/> </Component> <?endif?> <Component Id="iconv" Guid="{35EE3558-D34B-4F0A-B8BD-430FF0775246}"> diff --git a/slirp/slirp.c b/slirp/slirp.c index fef526c5ad..9f4bea3d3b 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -534,7 +534,12 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) * test for G_IO_IN below if this succeeds */ if (revents & G_IO_PRI) { - sorecvoob(so); + ret = sorecvoob(so); + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ + continue; + } } /* * Check sockets for reading @@ -553,6 +558,11 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) if (ret > 0) { tcp_output(sototcpcb(so)); } + if (ret < 0) { + /* Socket error might have resulted in the socket being + * removed, do not try to do anything more with it. */ + continue; + } } /* diff --git a/slirp/socket.c b/slirp/socket.c index b836c42b8e..bd97b2d682 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -176,9 +176,24 @@ soread(struct socket *so) if (nn < 0 && (errno == EINTR || errno == EAGAIN)) return 0; else { + int err; + socklen_t slen = sizeof err; + + err = errno; + if (nn == 0) { + getsockopt(so->s, SOL_SOCKET, SO_ERROR, + &err, &slen); + } + DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); sofcantrcvmore(so); - tcp_sockclosed(sototcpcb(so)); + + if (err == ECONNRESET || err == ECONNREFUSED + || err == ENOTCONN || err == EPIPE) { + tcp_drop(sototcpcb(so), err); + } else { + tcp_sockclosed(sototcpcb(so)); + } return -1; } } @@ -260,10 +275,11 @@ err: * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data */ -void +int sorecvoob(struct socket *so) { struct tcpcb *tp = sototcpcb(so); + int ret; DEBUG_CALL("sorecvoob"); DEBUG_ARG("so = %p", so); @@ -276,11 +292,15 @@ sorecvoob(struct socket *so) * urgent data, or the read() doesn't return all the * urgent data. */ - soread(so); - tp->snd_up = tp->snd_una + so->so_snd.sb_cc; - tp->t_force = 1; - tcp_output(tp); - tp->t_force = 0; + ret = soread(so); + if (ret > 0) { + tp->snd_up = tp->snd_una + so->so_snd.sb_cc; + tp->t_force = 1; + tcp_output(tp); + tp->t_force = 0; + } + + return ret; } /* diff --git a/slirp/socket.h b/slirp/socket.h index e9c9b053dc..7dca506973 100644 --- a/slirp/socket.h +++ b/slirp/socket.h @@ -127,7 +127,7 @@ struct socket *solookup(struct socket **, struct socket *, struct socket *socreate(Slirp *); void sofree(struct socket *); int soread(struct socket *); -void sorecvoob(struct socket *); +int sorecvoob(struct socket *); int sosendoob(struct socket *); int sowrite(struct socket *); void sorecvfrom(struct socket *); diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c index 1fcca3040e..5433e7fe9c 100644 --- a/slirp/tcp_input.c +++ b/slirp/tcp_input.c @@ -725,6 +725,12 @@ findso: so->so_ti = ti; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; tp->t_state = TCPS_SYN_RECEIVED; + /* + * Initialize receive sequence numbers now so that we can send a + * valid RST if the remote end rejects our connection. + */ + tp->irs = ti->ti_seq; + tcp_rcvseqinit(tp); tcp_template(tp); } return; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index dbfd2c673b..32ff452e93 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -356,6 +356,10 @@ tcp_sockclosed(struct tcpcb *tp) DEBUG_CALL("tcp_sockclosed"); DEBUG_ARG("tp = %p", tp); + if (!tp) { + return; + } + switch (tp->t_state) { case TCPS_CLOSED: @@ -374,8 +378,7 @@ tcp_sockclosed(struct tcpcb *tp) tp->t_state = TCPS_LAST_ACK; break; } - if (tp) - tcp_output(tp); + tcp_output(tp); } /* diff --git a/target-i386/helper.c b/target-i386/helper.c index 575583942a..bf3e76207e 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -919,29 +919,31 @@ do_check_protect_pse36: !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) { prot |= PAGE_EXEC; } - - if ((prot & (1 << is_write1)) == 0) { - goto do_fault_protect; - } - if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) && (ptep & PG_USER_MASK) && env->pkru) { uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT; uint32_t pkru_ad = (env->pkru >> pk * 2) & 1; uint32_t pkru_wd = (env->pkru >> pk * 2) & 2; + uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; if (pkru_ad) { - prot &= ~(PAGE_READ | PAGE_WRITE); + pkru_prot &= ~(PAGE_READ | PAGE_WRITE); } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) { - prot &= ~PAGE_WRITE; + pkru_prot &= ~PAGE_WRITE; } - if ((prot & (1 << is_write1)) == 0) { + + prot &= pkru_prot; + if ((pkru_prot & (1 << is_write1)) == 0) { assert(is_write1 != 2); error_code |= PG_ERROR_PK_MASK; goto do_fault_protect; } } + if ((prot & (1 << is_write1)) == 0) { + goto do_fault_protect; + } + /* yes, it can! */ is_dirty = is_write && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || is_dirty) { diff --git a/tci.c b/tci.c index 7cbb39ed4b..82705fe772 100644 --- a/tci.c +++ b/tci.c @@ -1,7 +1,7 @@ /* * Tiny Code Interpreter for QEMU * - * Copyright (c) 2009, 2011 Stefan Weil + * Copyright (c) 2009, 2011, 2016 Stefan Weil * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,9 +19,12 @@ #include "qemu/osdep.h" -/* Defining NDEBUG disables assertions (which makes the code faster). */ -#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG) -# define NDEBUG +/* Enable TCI assertions only when debugging TCG (and without NDEBUG defined). + * Without assertions, the interpreter runs much faster. */ +#if defined(CONFIG_DEBUG_TCG) +# define tci_assert(cond) assert(cond) +#else +# define tci_assert(cond) ((void)0) #endif #include "qemu-common.h" @@ -56,7 +59,7 @@ static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS]; static tcg_target_ulong tci_read_reg(TCGReg index) { - assert(index < ARRAY_SIZE(tci_reg)); + tci_assert(index < ARRAY_SIZE(tci_reg)); return tci_reg[index]; } @@ -105,9 +108,9 @@ static uint64_t tci_read_reg64(TCGReg index) static void tci_write_reg(TCGReg index, tcg_target_ulong value) { - assert(index < ARRAY_SIZE(tci_reg)); - assert(index != TCG_AREG0); - assert(index != TCG_REG_CALL_STACK); + tci_assert(index < ARRAY_SIZE(tci_reg)); + tci_assert(index != TCG_AREG0); + tci_assert(index != TCG_REG_CALL_STACK); tci_reg[index] = value; } @@ -325,7 +328,7 @@ static uint64_t tci_read_ri64(uint8_t **tb_ptr) static tcg_target_ulong tci_read_label(uint8_t **tb_ptr) { tcg_target_ulong label = tci_read_i(tb_ptr); - assert(label != 0); + tci_assert(label != 0); return label; } @@ -468,11 +471,11 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) tci_reg[TCG_AREG0] = (tcg_target_ulong)env; tci_reg[TCG_REG_CALL_STACK] = sp_value; - assert(tb_ptr); + tci_assert(tb_ptr); for (;;) { TCGOpcode opc = tb_ptr[0]; -#if !defined(NDEBUG) +#if defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG) uint8_t op_size = tb_ptr[1]; uint8_t *old_code_ptr = tb_ptr; #endif @@ -525,7 +528,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) break; case INDEX_op_br: label = tci_read_label(&tb_ptr); - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; case INDEX_op_setcond_i32: @@ -600,7 +603,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) t0 = tci_read_r32(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); - assert(t1 != sp_value || (int32_t)t2 < 0); + tci_assert(t1 != sp_value || (int32_t)t2 < 0); *(uint32_t *)(t1 + t2) = t0; break; @@ -725,7 +728,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare32(t0, t1, condition)) { - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } @@ -751,7 +754,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(tmp64, v64, condition)) { - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } @@ -885,7 +888,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) t0 = tci_read_r64(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); - assert(t1 != sp_value || (int32_t)t2 < 0); + tci_assert(t1 != sp_value || (int32_t)t2 < 0); *(uint64_t *)(t1 + t2) = t0; break; @@ -992,7 +995,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(t0, t1, condition)) { - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } @@ -1087,7 +1090,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) break; case INDEX_op_goto_tb: t0 = tci_read_i32(&tb_ptr); - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); tb_ptr += (int32_t)t0; continue; case INDEX_op_qemu_ld_i32: @@ -1234,7 +1237,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) TODO(); break; } - assert(tb_ptr == old_code_ptr + op_size); + tci_assert(tb_ptr == old_code_ptr + op_size); } exit: return next_tb; diff --git a/tests/.gitignore b/tests/.gitignore index b7bf13ed27..9eed22988b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -39,6 +39,7 @@ test-io-channel-file.txt test-io-channel-socket test-io-channel-tls test-io-task +test-logging test-mul64 test-opts-visitor test-qapi-event.[ch] diff --git a/translate-all.c b/translate-all.c index b4df1ec68f..8329ea60ee 100644 --- a/translate-all.c +++ b/translate-all.c @@ -861,7 +861,8 @@ static void tb_invalidate_check(target_ulong address) address &= TARGET_PAGE_MASK; for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { - for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL; + tb = tb->phys_hash_next) { if (!(address + TARGET_PAGE_SIZE <= tb->pc || address >= tb->pc + tb->size)) { printf("ERROR invalidate: address=" TARGET_FMT_lx diff --git a/util/hexdump.c b/util/hexdump.c index 1d9c12967b..f879ff0ad6 100644 --- a/util/hexdump.c +++ b/util/hexdump.c @@ -18,21 +18,32 @@ void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size) { - unsigned int b; + unsigned int b, len, i, c; - for (b = 0; b < size; b++) { - if ((b % 16) == 0) { - fprintf(fp, "%s: %04x:", prefix, b); + for (b = 0; b < size; b += 16) { + len = size - b; + if (len > 16) { + len = 16; } - if ((b % 4) == 0) { - fprintf(fp, " "); + fprintf(fp, "%s: %04x:", prefix, b); + for (i = 0; i < 16; i++) { + if ((i % 4) == 0) { + fprintf(fp, " "); + } + if (i < len) { + fprintf(fp, " %02x", (unsigned char)buf[b + i]); + } else { + fprintf(fp, " "); + } } - fprintf(fp, " %02x", (unsigned char)buf[b]); - if ((b % 16) == 15) { - fprintf(fp, "\n"); + fprintf(fp, " "); + for (i = 0; i < len; i++) { + c = buf[b + i]; + if (c < ' ' || c > '~') { + c = '.'; + } + fprintf(fp, "%c", c); } - } - if ((b % 16) != 0) { fprintf(fp, "\n"); } } |