diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 5ad1b919bc9d3daec17592869d9b93515ae13c6d..d4190602d18506f03b8f741bfd7757fa75209798 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1728,8 +1728,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) CPUArchState *env = cpu->env_ptr; #endif TranslationBlock *tb; - uint32_t n, flags; - target_ulong pc, cs_base; + uint32_t n; tb_lock(); tb = tb_find_pc(retaddr); @@ -1737,44 +1736,33 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p", (void *)retaddr); } - n = cpu->icount_decr.u16.low + tb->icount; cpu_restore_state_from_tb(cpu, tb, retaddr); - /* Calculate how many instructions had been executed before the fault - occurred. */ - n = n - cpu->icount_decr.u16.low; - /* Generate a new TB ending on the I/O insn. */ - n++; + /* On MIPS and SH, delay slot instructions can only be restarted if they were already the first instruction in the TB. If this is not the first instruction in a TB then re-execute the preceding branch. */ + n = 1; #if defined(TARGET_MIPS) - if ((env->hflags & MIPS_HFLAG_BMASK) != 0 && n > 1) { + if ((env->hflags & MIPS_HFLAG_BMASK) != 0 + && env->active_tc.PC != tb->pc) { env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4); cpu->icount_decr.u16.low++; env->hflags &= ~MIPS_HFLAG_BMASK; + n = 2; } #elif defined(TARGET_SH4) if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 - && n > 1) { + && env->pc != tb->pc) { env->pc -= 2; cpu->icount_decr.u16.low++; env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); + n = 2; } #endif - /* This should never happen. */ - if (n > CF_COUNT_MASK) { - cpu_abort(cpu, "TB too big during recompile"); - } - pc = tb->pc; - cs_base = tb->cs_base; - flags = tb->flags; - tb_phys_invalidate(tb, -1); - - /* Execute one IO instruction without caching - instead of creating large TB. */ - cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | CF_NOCACHE | 1; + /* Generate a new TB executing the I/O insn. */ + cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | n; if (tb->cflags & CF_NOCACHE) { if (tb->orig_tb) { @@ -1785,11 +1773,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) tb_remove(tb); } - /* Generate new TB instead of the current one. */ - /* FIXME: In theory this could raise an exception. In practice - we have already translated the block once so it's probably ok. */ - tb_gen_code(cpu, pc, cs_base, flags, curr_cflags() | CF_LAST_IO | n); - /* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not * the first in the TB) then we end up generating a whole new TB and * repeating the fault, which is horribly inefficient. diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 392db78b13df0b1be0c0507d62c7dce04d7c4f0b..b1f228e8b573dc465d2f3d09fb9c8445304fcaf9 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -198,19 +198,21 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) { int tag = 0; - if (CHARDEV_IS_MUX(s)) { - MuxChardev *d = MUX_CHARDEV(s); + if (s) { + if (CHARDEV_IS_MUX(s)) { + MuxChardev *d = MUX_CHARDEV(s); + + if (d->mux_cnt >= MAX_MUX) { + goto unavailable; + } - if (d->mux_cnt >= MAX_MUX) { + d->backends[d->mux_cnt] = b; + tag = d->mux_cnt++; + } else if (s->be) { goto unavailable; + } else { + s->be = b; } - - d->backends[d->mux_cnt] = b; - tag = d->mux_cnt++; - } else if (s->be) { - goto unavailable; - } else { - s->be = b; } b->fe_open = false; diff --git a/chardev/char-socket.c b/chardev/char-socket.c index d057192ced0acb82f030f1f00ce58b7c41c02f36..159e69c3b15a58f9593374853a36cd752c69f31b 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -550,12 +550,10 @@ static void tcp_chr_connect(void *opaque) s->is_listen, s->is_telnet); s->connected = 1; - if (s->ioc) { - chr->gsource = io_add_watch_poll(chr, s->ioc, - tcp_chr_read_poll, - tcp_chr_read, - chr, chr->gcontext); - } + chr->gsource = io_add_watch_poll(chr, s->ioc, + tcp_chr_read_poll, + tcp_chr_read, + chr, chr->gcontext); s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, diff --git a/configure b/configure index 8376cb151a05b90543b65b7165a45092616ff250..4d0e92c96cd0108fd98408a2d88ee0fa0b01ba42 100755 --- a/configure +++ b/configure @@ -2496,7 +2496,9 @@ if test "$whpx" != "no" ; then #include int main(void) { WHV_CAPABILITY whpx_cap; - WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap)); + UINT32 writtenSize; + WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap), + &writtenSize); return 0; } EOF diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 096e8e98d73dca80d225b37c523beacdf8544d30..aaebec18393a6aa20d0a2812282d5e95cbd86668 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -28,6 +28,7 @@ #include "hw/isa/isa.h" #include "hw/qdev.h" #include "qemu/timer.h" +#include "qapi/error.h" /* Missing features: @@ -663,8 +664,13 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp) CSState *s = CS4231A (dev); IsaDmaClass *k; - isa_init_irq (d, &s->pic, s->irq); s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma); + if (!s->isa_dma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + + isa_init_irq(d, &s->pic, s->irq); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->dma, cs_dma_read, s); diff --git a/hw/audio/gus.c b/hw/audio/gus.c index 3e864cd36d4758252f8cfd3aa78d4da0bce2785c..8e0b27e0f23760c23c6442fc24a3f98547785568 100644 --- a/hw/audio/gus.c +++ b/hw/audio/gus.c @@ -241,6 +241,12 @@ static void gus_realizefn (DeviceState *dev, Error **errp) IsaDmaClass *k; struct audsettings as; + s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); + if (!s->isa_dma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + AUD_register_card ("gus", &s->card); as.freq = s->freq; @@ -272,7 +278,6 @@ static void gus_realizefn (DeviceState *dev, Error **errp) isa_register_portio_list(d, &s->portio_list2, (s->port + 0x100) & 0xf00, gus_portio_list2, s, "gus"); - s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s); s->emu.himemaddr = s->himem; diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 31de264ab7bc37d02c128d84f479bd45beba5314..5a4d32364ef534fe304f3e79003cc497fae65102 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -1371,6 +1371,13 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) SB16State *s = SB16 (dev); IsaDmaClass *k; + s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); + s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); + if (!s->isa_dma || !s->isa_hdma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } + isa_init_irq (isadev, &s->pic, s->irq); s->mixer_regs[0x80] = magic_of_irq (s->irq); @@ -1389,11 +1396,9 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) isa_register_portio_list(isadev, &s->portio_list, s->port, sb16_ioport_list, s, "sb16"); - s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma); k = ISADMA_GET_CLASS(s->isa_hdma); k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s); - s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma); k = ISADMA_GET_CLASS(s->isa_dma); k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s); diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 7b7dd41296d006657e5429d9a0b0b8ab495d86dd..cd29e27d8f594338463d4b858eeda12253e32b17 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2695,7 +2695,10 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp) fdctrl->dma_chann = isa->dma; if (fdctrl->dma_chann != -1) { fdctrl->dma = isa_get_dma(isa_bus_from_device(isadev), isa->dma); - assert(fdctrl->dma); + if (!fdctrl->dma) { + error_setg(errp, "ISA controller does not support DMA"); + return; + } } qdev_set_legacy_instance_id(dev, isa->iobase, 2); diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c index 629323312cfa2758737fa8cc1fdc771177ff26af..9a85038c8ad0095472bc6db39554d4bce53cd593 100644 --- a/hw/net/can/can_sja1000.c +++ b/hw/net/can/can_sja1000.c @@ -866,6 +866,10 @@ int can_sja_connect_to_bus(CanSJA1000State *s, CanBusState *bus) { s->bus_client.info = &can_sja_bus_client_info; + if (!bus) { + return -EINVAL; + } + if (can_bus_insert_client(bus, &s->bus_client) < 0) { return -1; } diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 5b7a48f5a5daec0773da20ea0994d2db870db003..f5ab767ab5d1a09e895b9bf1534d5cb07dec1e23 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2607,9 +2607,10 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) /* check we are using a driver managing SG_IO (version 3 and after) */ rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_setg(errp, "cannot get SG_IO version number: %s. " - "Is this a SCSI device?", - strerror(-rc)); + error_setg_errno(errp, -rc, "cannot get SG_IO version number"); + if (rc != -EPERM) { + error_append_hint(errp, "Is this a SCSI device?\n"); + } return; } if (sg_version < 30000) { diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 7414fe2d675ccf61985207317ae816319cf61158..4753f8738f74669240ec78e98efe567eb50795ea 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -500,9 +500,10 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp) /* check we are using a driver managing SG_IO (version 3 and after */ rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { - error_setg(errp, "cannot get SG_IO version number: %s. " - "Is this a SCSI device?", - strerror(-rc)); + error_setg_errno(errp, -rc, "cannot get SG_IO version number"); + if (rc != -EPERM) { + error_append_hint(errp, "Is this a SCSI device?\n"); + } return; } if (sg_version < 30000) { diff --git a/iothread.c b/iothread.c index 1b3463cb004aebc698eb9fab88e40ff899034159..e675c38442235120d1d0e911e7c0caedd00353f1 100644 --- a/iothread.c +++ b/iothread.c @@ -31,11 +31,15 @@ typedef ObjectClass IOThreadClass; #define IOTHREAD_CLASS(klass) \ OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD) +#ifdef CONFIG_POSIX /* Benchmark results from 2016 on NVMe SSD drives show max polling times around * 16-32 microseconds yield IOPS improvements for both iodepth=1 and iodepth=32 * workloads. */ #define IOTHREAD_POLL_MAX_NS_DEFAULT 32768ULL +#else +#define IOTHREAD_POLL_MAX_NS_DEFAULT 0ULL +#endif static __thread IOThread *my_iothread; diff --git a/scripts/device-crash-test b/scripts/device-crash-test index f04f34924e62ecf6d953690abd99a422dde61168..24c7bf5a165a801b4e1e331a7c52228b34ef3226 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -218,11 +218,7 @@ ERROR_WHITELIST = [ {'exitcode':-6, 'log':r"Object .* is not an instance of type e500-ccsr", 'loglevel':logging.ERROR}, {'exitcode':-6, 'log':r"vmstate_register_with_alias_id: Assertion `!se->compat \|\| se->instance_id == 0' failed", 'loglevel':logging.ERROR}, {'exitcode':-6, 'device':'isa-fdc', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'device':'gus', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'isa-serial', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'device':'sb16', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'device':'cs4231a', 'loglevel':logging.ERROR, 'expected':True}, - {'exitcode':-11, 'machine':'isapc', 'device':'.*-iommu', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'mioe3680_pci', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'pcm3680_pci', 'loglevel':logging.ERROR, 'expected':True}, {'exitcode':-11, 'device':'kvaser_pci', 'loglevel':logging.ERROR, 'expected':True}, diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 07369aa8ea9b219d9d072b263d4dfab1bed0055e..43fb5f512f70d8f7b32681393b564dcee51c1e67 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -381,8 +381,8 @@ foreach my $file (@ARGV) { ##if $file is a directory and it lacks a trailing slash, add one if ((-d $file)) { $file =~ s@([^/])$@$1/@; - } elsif (!(-f $file)) { - die "$P: file '${file}' not found\n"; + } elsif (!(stat $file)) { + die "$P: file '${file}' not found: $!\n"; } } if ($from_filename) { diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c index 3facbba17080e63b4554214a405542d038a39792..21e1b8ea601c1891e3ea3fec04c0e5442d7803f9 100644 --- a/scsi/qemu-pr-helper.c +++ b/scsi/qemu-pr-helper.c @@ -903,12 +903,12 @@ static int drop_privileges(void) int main(int argc, char **argv) { - const char *sopt = "hVk:fdT:u:g:vq"; + const char *sopt = "hVk:f:dT:u:g:vq"; struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "socket", required_argument, NULL, 'k' }, - { "pidfile", no_argument, NULL, 'f' }, + { "pidfile", required_argument, NULL, 'f' }, { "daemon", no_argument, NULL, 'd' }, { "trace", required_argument, NULL, 'T' }, { "user", required_argument, NULL, 'u' }, @@ -952,7 +952,8 @@ int main(int argc, char **argv) } break; case 'f': - pidfile = optarg; + g_free(pidfile); + pidfile = g_strdup(optarg); break; #ifdef CONFIG_LIBCAP case 'u': { diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 940bbe590d3375281fca9a562a4e2eb47e640117..bf33d320bf68a7793141d799b2495189fb819ce7 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -153,7 +153,7 @@ struct whpx_vcpu { bool interruptable; uint64_t tpr; uint64_t apic_base; - WHV_X64_PENDING_INTERRUPTION_REGISTER interrupt_in_flight; + bool interruption_pending; /* Must be the last field as it may have a tail */ WHV_RUN_VP_EXIT_CONTEXT exit_ctx; @@ -695,7 +695,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu) qemu_mutex_lock_iothread(); /* Inject NMI */ - if (!vcpu->interrupt_in_flight.InterruptionPending && + if (!vcpu->interruption_pending && cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) { if (cpu->interrupt_request & CPU_INTERRUPT_NMI) { cpu->interrupt_request &= ~CPU_INTERRUPT_NMI; @@ -724,7 +724,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu) } /* Get pending hard interruption or replay one that was overwritten */ - if (!vcpu->interrupt_in_flight.InterruptionPending && + if (!vcpu->interruption_pending && vcpu->interruptable && (env->eflags & IF_MASK)) { assert(!new_int.InterruptionPending); if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { @@ -781,44 +781,25 @@ static void whpx_vcpu_pre_run(CPUState *cpu) static void whpx_vcpu_post_run(CPUState *cpu) { - HRESULT hr; - struct whpx_state *whpx = &whpx_global; struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu); struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); X86CPU *x86_cpu = X86_CPU(cpu); - WHV_REGISTER_VALUE reg_values[4]; - const WHV_REGISTER_NAME reg_names[4] = { - WHvX64RegisterRflags, - WHvX64RegisterCr8, - WHvRegisterPendingInterruption, - WHvRegisterInterruptState, - }; - hr = WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, - reg_names, 4, reg_values); - if (FAILED(hr)) { - error_report("WHPX: Failed to get interrupt state regusters," - " hr=%08lx", hr); - vcpu->interruptable = false; - return; - } + env->eflags = vcpu->exit_ctx.VpContext.Rflags; - assert(reg_names[0] == WHvX64RegisterRflags); - env->eflags = reg_values[0].Reg64; - - assert(reg_names[1] == WHvX64RegisterCr8); - if (vcpu->tpr != reg_values[1].Reg64) { - vcpu->tpr = reg_values[1].Reg64; + uint64_t tpr = vcpu->exit_ctx.VpContext.Cr8; + if (vcpu->tpr != tpr) { + vcpu->tpr = tpr; qemu_mutex_lock_iothread(); cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr); qemu_mutex_unlock_iothread(); } - assert(reg_names[2] == WHvRegisterPendingInterruption); - vcpu->interrupt_in_flight = reg_values[2].PendingInterruption; + vcpu->interruption_pending = + vcpu->exit_ctx.VpContext.ExecutionState.InterruptionPending; - assert(reg_names[3] == WHvRegisterInterruptState); - vcpu->interruptable = !reg_values[3].InterruptState.InterruptShadow; + vcpu->interruptable = + !vcpu->exit_ctx.VpContext.ExecutionState.InterruptShadow; return; } @@ -1254,6 +1235,7 @@ static int whpx_accel_init(MachineState *ms) int ret; HRESULT hr; WHV_CAPABILITY whpx_cap; + UINT32 whpx_cap_size; WHV_PARTITION_PROPERTY prop; whpx = &whpx_global; @@ -1262,7 +1244,7 @@ static int whpx_accel_init(MachineState *ms) whpx->mem_quota = ms->ram_size; hr = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &whpx_cap, - sizeof(whpx_cap)); + sizeof(whpx_cap), &whpx_cap_size); if (FAILED(hr) || !whpx_cap.HypervisorPresent) { error_report("WHPX: No accelerator found, hr=%08lx", hr); ret = -ENOSPC; @@ -1277,9 +1259,9 @@ static int whpx_accel_init(MachineState *ms) } memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); - prop.PropertyCode = WHvPartitionPropertyCodeProcessorCount; prop.ProcessorCount = smp_cpus; hr = WHvSetPartitionProperty(whpx->partition, + WHvPartitionPropertyCodeProcessorCount, &prop, sizeof(WHV_PARTITION_PROPERTY)); diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index 22e9202b8dff46beca20e46a2d33ab6166257370..61d997253cae9df6e2164b850c653f42037ab62e 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -18,6 +18,7 @@ #include "qemu/range.h" #include "qemu/sockets.h" #include "chardev/char-fe.h" +#include "qemu/memfd.h" #include "sysemu/sysemu.h" #include "libqos/libqos.h" #include "libqos/pci-pc.h" @@ -40,23 +41,14 @@ #define HAVE_MONOTONIC_TIME #endif -#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM,"\ +#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM," \ "mem-path=%s,share=on -numa node,memdev=mem" +#define QEMU_CMD_MEMFD " -m %d -object memory-backend-memfd,id=mem,size=%dM," \ + " -numa node,memdev=mem" #define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s" #define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce" #define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0" -#define QEMU_CMD QEMU_CMD_MEM QEMU_CMD_CHR \ - QEMU_CMD_NETDEV QEMU_CMD_NET - -#define GET_QEMU_CMD(s) \ - g_strdup_printf(QEMU_CMD, 512, 512, (root), (s)->chr_name, \ - (s)->socket_path, "", (s)->chr_name) - -#define GET_QEMU_CMDE(s, mem, chr_opts, extra, ...) \ - g_strdup_printf(QEMU_CMD extra, (mem), (mem), (root), (s)->chr_name, \ - (s)->socket_path, (chr_opts), (s)->chr_name, ##__VA_ARGS__) - #define HUGETLBFS_MAGIC 0x958458f6 /*********** FROM hw/virtio/vhost-user.c *************************************/ @@ -175,6 +167,33 @@ static void test_server_listen(TestServer *server); static const char *tmpfs; static const char *root; +enum test_memfd { + TEST_MEMFD_AUTO, + TEST_MEMFD_YES, + TEST_MEMFD_NO, +}; + +static char *get_qemu_cmd(TestServer *s, + int mem, enum test_memfd memfd, const char *mem_path, + const char *chr_opts, const char *extra) +{ + if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check()) { + memfd = TEST_MEMFD_YES; + } + + if (memfd == TEST_MEMFD_YES) { + return g_strdup_printf(QEMU_CMD_MEMFD QEMU_CMD_CHR + QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem, + s->chr_name, s->socket_path, + chr_opts, s->chr_name, extra); + } else { + return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR + QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem, + mem_path, s->chr_name, s->socket_path, + chr_opts, s->chr_name, extra); + } +} + static void init_virtio_dev(TestServer *s, uint32_t features_mask) { uint32_t features; @@ -494,6 +513,7 @@ static void test_server_create_chr(TestServer *server, const gchar *opt) chr = qemu_chr_new(server->chr_name, chr_path); g_free(chr_path); + g_assert_nonnull(chr); qemu_chr_fe_init(&server->chr, chr, &error_abort); qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read, chr_event, NULL, server, NULL, true); @@ -640,16 +660,18 @@ GSourceFuncs test_migrate_source_funcs = { .check = test_migrate_source_check, }; -static void test_read_guest_mem(void) +static void test_read_guest_mem(const void *arg) { + enum test_memfd memfd = GPOINTER_TO_INT(arg); TestServer *server = NULL; char *qemu_cmd = NULL; QTestState *s = NULL; - server = test_server_new("test"); + server = test_server_new(memfd == TEST_MEMFD_YES ? + "read-guest-memfd" : "read-guest-mem"); test_server_listen(server); - qemu_cmd = GET_QEMU_CMD(server); + qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", ""); s = qtest_start(qemu_cmd); g_free(qemu_cmd); @@ -671,7 +693,7 @@ static void test_migrate(void) char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path); QTestState *global = global_qtest, *from, *to; GSource *source; - gchar *cmd; + gchar *cmd, *tmp; QDict *rsp; guint8 *log; guint64 size; @@ -679,7 +701,7 @@ static void test_migrate(void) test_server_listen(s); test_server_listen(dest); - cmd = GET_QEMU_CMDE(s, 2, "", ""); + cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", ""); from = qtest_start(cmd); g_free(cmd); @@ -688,7 +710,9 @@ static void test_migrate(void) size = get_log_size(s); g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8)); - cmd = GET_QEMU_CMDE(dest, 2, "", " -incoming %s", uri); + tmp = g_strdup_printf(" -incoming %s", uri); + cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp); + g_free(tmp); to = qtest_init(cmd); g_free(cmd); @@ -801,7 +825,7 @@ static void test_reconnect_subprocess(void) char *cmd; g_thread_new("connect", connect_thread, s); - cmd = GET_QEMU_CMDE(s, 2, ",server", ""); + cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", ""); qtest_start(cmd); g_free(cmd); @@ -839,7 +863,7 @@ static void test_connect_fail_subprocess(void) s->test_fail = true; g_thread_new("connect", connect_thread, s); - cmd = GET_QEMU_CMDE(s, 2, ",server", ""); + cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", ""); qtest_start(cmd); g_free(cmd); @@ -869,7 +893,7 @@ static void test_flags_mismatch_subprocess(void) s->test_flags = TEST_FLAGS_DISCONNECT; g_thread_new("connect", connect_thread, s); - cmd = GET_QEMU_CMDE(s, 2, ",server", ""); + cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", ""); qtest_start(cmd); g_free(cmd); @@ -904,11 +928,21 @@ static void test_multiqueue(void) s->queues = 2; test_server_listen(s); - cmd = g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " - "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", - 512, 512, root, s->chr_name, - s->socket_path, "", s->chr_name, - s->queues, s->queues * 2 + 2); + if (qemu_memfd_check()) { + cmd = g_strdup_printf( + QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " + "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", + 512, 512, s->chr_name, + s->socket_path, "", s->chr_name, + s->queues, s->queues * 2 + 2); + } else { + cmd = g_strdup_printf( + QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " + "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", + 512, 512, root, s->chr_name, + s->socket_path, "", s->chr_name, + s->queues, s->queues * 2 + 2); + } qtest_start(cmd); g_free(cmd); @@ -954,7 +988,13 @@ int main(int argc, char **argv) /* run the main loop thread so the chardev may operate */ thread = g_thread_new(NULL, thread_function, loop); - qtest_add_func("/vhost-user/read-guest-mem", test_read_guest_mem); + if (qemu_memfd_check()) { + qtest_add_data_func("/vhost-user/read-guest-mem/memfd", + GINT_TO_POINTER(TEST_MEMFD_YES), + test_read_guest_mem); + } + qtest_add_data_func("/vhost-user/read-guest-mem/memfile", + GINT_TO_POINTER(TEST_MEMFD_NO), test_read_guest_mem); qtest_add_func("/vhost-user/migrate", test_migrate); qtest_add_func("/vhost-user/multiqueue", test_multiqueue); diff --git a/util/aio-win32.c b/util/aio-win32.c index d6d5e02f0095da81c6fe72a035cca2b883d12035..a67b00c6ad80c21ba56af974d4be5f740178dda4 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -410,5 +410,7 @@ void aio_context_setup(AioContext *ctx) void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, int64_t grow, int64_t shrink, Error **errp) { - error_setg(errp, "AioContext polling is not implemented on Windows"); + if (max_ns) { + error_setg(errp, "AioContext polling is not implemented on Windows"); + } }