Miscellaenous bugfixes, including crash fixes from Alexey, Peter M. and

Thomas.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJauOmSAAoJEL/70l94x66DwA4IAIfXUyWSDzAMTc19N/gY4eKB
 cptfJas1CmfrMU+EBIVZoiVdYF1H5qvctxVSaCXL3y7XNfwrjfDoiplfbi9rTSKb
 pW59bqIf7Y+ViOYDYHdbxKMcvWxIaiWKfpzWkncy+aeqObs620VSCbVmqVsQsKQu
 1OHWrTlgNAP4aqPy9gZ6O1YXBDxTCIKW9N+QIdho5RqB1uPFkjBJcxlF04ydF9S7
 kIgblBsosljTOk03I2hf6KKtfXfRXctgE/RYyE8SW3dy+CQWfiGjkE/z17ABBjK2
 g7Rex6S9NA/+fDXO+2MAYnx6iBA9Dkxt2CcWWDjGwg+nXS4+B/OoF4MhRwV6N2g=
 =5hGp
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

Miscellaenous bugfixes, including crash fixes from Alexey, Peter M. and
Thomas.

# gpg: Signature made Mon 26 Mar 2018 13:37:38 BST
# gpg:                using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream:
  qemu-pr-helper: Actually allow users to specify pidfile
  chardev/char-fe: Allow NULL chardev in qemu_chr_fe_init()
  iothread: fix breakage on windows
  scsi: turn "is this a SCSI device?" into a conditional hint
  chardev-socket: remove useless if
  tcg: Really fix cpu_io_recompile
  vhost-user-test: add back memfd check
  vhost-user-test: do not hang if chardev creation failed
  scripts/device-crash-test: Remove fixed isapc-with-iommu entry
  hw/audio: Fix crashes when devices are used on ISA bus without DMA
  fdc: Exit if ISA controller does not support DMA
  hw/net/can: Fix segfaults when using the devices without bus
  WHPX improve vcpu_post_run perf
  WHPX fix WHvSetPartitionProperty in PropertyCode
  WHPX fix WHvGetCapability out WrittenSizeInBytes
  scripts/get_maintainer.pl: Print proper error message for missing $file

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-03-26 15:17:25 +01:00
commit 7b93d78a04
18 changed files with 159 additions and 124 deletions

View file

@ -1728,8 +1728,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
CPUArchState *env = cpu->env_ptr; CPUArchState *env = cpu->env_ptr;
#endif #endif
TranslationBlock *tb; TranslationBlock *tb;
uint32_t n, flags; uint32_t n;
target_ulong pc, cs_base;
tb_lock(); tb_lock();
tb = tb_find_pc(retaddr); 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", cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p",
(void *)retaddr); (void *)retaddr);
} }
n = cpu->icount_decr.u16.low + tb->icount;
cpu_restore_state_from_tb(cpu, tb, retaddr); 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 /* 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 they were already the first instruction in the TB. If this is not
the first instruction in a TB then re-execute the preceding the first instruction in a TB then re-execute the preceding
branch. */ branch. */
n = 1;
#if defined(TARGET_MIPS) #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); env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
cpu->icount_decr.u16.low++; cpu->icount_decr.u16.low++;
env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags &= ~MIPS_HFLAG_BMASK;
n = 2;
} }
#elif defined(TARGET_SH4) #elif defined(TARGET_SH4)
if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0
&& n > 1) { && env->pc != tb->pc) {
env->pc -= 2; env->pc -= 2;
cpu->icount_decr.u16.low++; cpu->icount_decr.u16.low++;
env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
n = 2;
} }
#endif #endif
/* This should never happen. */
if (n > CF_COUNT_MASK) {
cpu_abort(cpu, "TB too big during recompile");
}
pc = tb->pc; /* Generate a new TB executing the I/O insn. */
cs_base = tb->cs_base; cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | n;
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;
if (tb->cflags & CF_NOCACHE) { if (tb->cflags & CF_NOCACHE) {
if (tb->orig_tb) { if (tb->orig_tb) {
@ -1785,11 +1773,6 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
tb_remove(tb); 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 /* 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 * the first in the TB) then we end up generating a whole new TB and
* repeating the fault, which is horribly inefficient. * repeating the fault, which is horribly inefficient.

View file

@ -198,19 +198,21 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp)
{ {
int tag = 0; int tag = 0;
if (CHARDEV_IS_MUX(s)) { if (s) {
MuxChardev *d = MUX_CHARDEV(s); if (CHARDEV_IS_MUX(s)) {
MuxChardev *d = MUX_CHARDEV(s);
if (d->mux_cnt >= MAX_MUX) { if (d->mux_cnt >= MAX_MUX) {
goto unavailable;
}
d->backends[d->mux_cnt] = b;
tag = d->mux_cnt++;
} else if (s->be) {
goto unavailable; 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; b->fe_open = false;

View file

@ -550,12 +550,10 @@ static void tcp_chr_connect(void *opaque)
s->is_listen, s->is_telnet); s->is_listen, s->is_telnet);
s->connected = 1; s->connected = 1;
if (s->ioc) { chr->gsource = io_add_watch_poll(chr, s->ioc,
chr->gsource = io_add_watch_poll(chr, s->ioc, tcp_chr_read_poll,
tcp_chr_read_poll, tcp_chr_read,
tcp_chr_read, chr, chr->gcontext);
chr, chr->gcontext);
}
s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,

4
configure vendored
View file

@ -2496,7 +2496,9 @@ if test "$whpx" != "no" ; then
#include <WinHvEmulation.h> #include <WinHvEmulation.h>
int main(void) { int main(void) {
WHV_CAPABILITY whpx_cap; WHV_CAPABILITY whpx_cap;
WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap)); UINT32 writtenSize;
WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap),
&writtenSize);
return 0; return 0;
} }
EOF EOF

View file

@ -28,6 +28,7 @@
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/qdev.h" #include "hw/qdev.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qapi/error.h"
/* /*
Missing features: Missing features:
@ -663,8 +664,13 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
CSState *s = CS4231A (dev); CSState *s = CS4231A (dev);
IsaDmaClass *k; IsaDmaClass *k;
isa_init_irq (d, &s->pic, s->irq);
s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma); 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 = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->dma, cs_dma_read, s); k->register_channel(s->isa_dma, s->dma, cs_dma_read, s);

View file

@ -241,6 +241,12 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
IsaDmaClass *k; IsaDmaClass *k;
struct audsettings as; 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); AUD_register_card ("gus", &s->card);
as.freq = s->freq; 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, isa_register_portio_list(d, &s->portio_list2, (s->port + 0x100) & 0xf00,
gus_portio_list2, s, "gus"); 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 = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s); k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s);
s->emu.himemaddr = s->himem; s->emu.himemaddr = s->himem;

View file

@ -1371,6 +1371,13 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
SB16State *s = SB16 (dev); SB16State *s = SB16 (dev);
IsaDmaClass *k; 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); isa_init_irq (isadev, &s->pic, s->irq);
s->mixer_regs[0x80] = magic_of_irq (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, isa_register_portio_list(isadev, &s->portio_list, s->port,
sb16_ioport_list, s, "sb16"); 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 = ISADMA_GET_CLASS(s->isa_hdma);
k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s); 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 = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s); k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);

View file

@ -2695,7 +2695,10 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
fdctrl->dma_chann = isa->dma; fdctrl->dma_chann = isa->dma;
if (fdctrl->dma_chann != -1) { if (fdctrl->dma_chann != -1) {
fdctrl->dma = isa_get_dma(isa_bus_from_device(isadev), isa->dma); 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); qdev_set_legacy_instance_id(dev, isa->iobase, 2);

View file

@ -866,6 +866,10 @@ int can_sja_connect_to_bus(CanSJA1000State *s, CanBusState *bus)
{ {
s->bus_client.info = &can_sja_bus_client_info; s->bus_client.info = &can_sja_bus_client_info;
if (!bus) {
return -EINVAL;
}
if (can_bus_insert_client(bus, &s->bus_client) < 0) { if (can_bus_insert_client(bus, &s->bus_client) < 0) {
return -1; return -1;
} }

View file

@ -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) */ /* 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); rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version);
if (rc < 0) { if (rc < 0) {
error_setg(errp, "cannot get SG_IO version number: %s. " error_setg_errno(errp, -rc, "cannot get SG_IO version number");
"Is this a SCSI device?", if (rc != -EPERM) {
strerror(-rc)); error_append_hint(errp, "Is this a SCSI device?\n");
}
return; return;
} }
if (sg_version < 30000) { if (sg_version < 30000) {

View file

@ -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 */ /* 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); rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
if (rc < 0) { if (rc < 0) {
error_setg(errp, "cannot get SG_IO version number: %s. " error_setg_errno(errp, -rc, "cannot get SG_IO version number");
"Is this a SCSI device?", if (rc != -EPERM) {
strerror(-rc)); error_append_hint(errp, "Is this a SCSI device?\n");
}
return; return;
} }
if (sg_version < 30000) { if (sg_version < 30000) {

View file

@ -31,11 +31,15 @@ typedef ObjectClass IOThreadClass;
#define IOTHREAD_CLASS(klass) \ #define IOTHREAD_CLASS(klass) \
OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD) OBJECT_CLASS_CHECK(IOThreadClass, klass, TYPE_IOTHREAD)
#ifdef CONFIG_POSIX
/* Benchmark results from 2016 on NVMe SSD drives show max polling times around /* 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 * 16-32 microseconds yield IOPS improvements for both iodepth=1 and iodepth=32
* workloads. * workloads.
*/ */
#define IOTHREAD_POLL_MAX_NS_DEFAULT 32768ULL #define IOTHREAD_POLL_MAX_NS_DEFAULT 32768ULL
#else
#define IOTHREAD_POLL_MAX_NS_DEFAULT 0ULL
#endif
static __thread IOThread *my_iothread; static __thread IOThread *my_iothread;

View file

@ -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"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, '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':-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':'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':'mioe3680_pci', 'loglevel':logging.ERROR, 'expected':True},
{'exitcode':-11, 'device':'pcm3680_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}, {'exitcode':-11, 'device':'kvaser_pci', 'loglevel':logging.ERROR, 'expected':True},

View file

@ -381,8 +381,8 @@ foreach my $file (@ARGV) {
##if $file is a directory and it lacks a trailing slash, add one ##if $file is a directory and it lacks a trailing slash, add one
if ((-d $file)) { if ((-d $file)) {
$file =~ s@([^/])$@$1/@; $file =~ s@([^/])$@$1/@;
} elsif (!(-f $file)) { } elsif (!(stat $file)) {
die "$P: file '${file}' not found\n"; die "$P: file '${file}' not found: $!\n";
} }
} }
if ($from_filename) { if ($from_filename) {

View file

@ -903,12 +903,12 @@ static int drop_privileges(void)
int main(int argc, char **argv) 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[] = { struct option lopt[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "socket", required_argument, NULL, 'k' }, { "socket", required_argument, NULL, 'k' },
{ "pidfile", no_argument, NULL, 'f' }, { "pidfile", required_argument, NULL, 'f' },
{ "daemon", no_argument, NULL, 'd' }, { "daemon", no_argument, NULL, 'd' },
{ "trace", required_argument, NULL, 'T' }, { "trace", required_argument, NULL, 'T' },
{ "user", required_argument, NULL, 'u' }, { "user", required_argument, NULL, 'u' },
@ -952,7 +952,8 @@ int main(int argc, char **argv)
} }
break; break;
case 'f': case 'f':
pidfile = optarg; g_free(pidfile);
pidfile = g_strdup(optarg);
break; break;
#ifdef CONFIG_LIBCAP #ifdef CONFIG_LIBCAP
case 'u': { case 'u': {

View file

@ -153,7 +153,7 @@ struct whpx_vcpu {
bool interruptable; bool interruptable;
uint64_t tpr; uint64_t tpr;
uint64_t apic_base; 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 */ /* Must be the last field as it may have a tail */
WHV_RUN_VP_EXIT_CONTEXT exit_ctx; WHV_RUN_VP_EXIT_CONTEXT exit_ctx;
@ -695,7 +695,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
/* Inject NMI */ /* Inject NMI */
if (!vcpu->interrupt_in_flight.InterruptionPending && if (!vcpu->interruption_pending &&
cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) { cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
if (cpu->interrupt_request & CPU_INTERRUPT_NMI) { if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
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 */ /* 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)) { vcpu->interruptable && (env->eflags & IF_MASK)) {
assert(!new_int.InterruptionPending); assert(!new_int.InterruptionPending);
if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { 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) 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 whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
X86CPU *x86_cpu = X86_CPU(cpu); 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, env->eflags = vcpu->exit_ctx.VpContext.Rflags;
reg_names, 4, reg_values);
if (FAILED(hr)) {
error_report("WHPX: Failed to get interrupt state regusters,"
" hr=%08lx", hr);
vcpu->interruptable = false;
return;
}
assert(reg_names[0] == WHvX64RegisterRflags); uint64_t tpr = vcpu->exit_ctx.VpContext.Cr8;
env->eflags = reg_values[0].Reg64; if (vcpu->tpr != tpr) {
vcpu->tpr = tpr;
assert(reg_names[1] == WHvX64RegisterCr8);
if (vcpu->tpr != reg_values[1].Reg64) {
vcpu->tpr = reg_values[1].Reg64;
qemu_mutex_lock_iothread(); qemu_mutex_lock_iothread();
cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr); cpu_set_apic_tpr(x86_cpu->apic_state, vcpu->tpr);
qemu_mutex_unlock_iothread(); qemu_mutex_unlock_iothread();
} }
assert(reg_names[2] == WHvRegisterPendingInterruption); vcpu->interruption_pending =
vcpu->interrupt_in_flight = reg_values[2].PendingInterruption; vcpu->exit_ctx.VpContext.ExecutionState.InterruptionPending;
assert(reg_names[3] == WHvRegisterInterruptState); vcpu->interruptable =
vcpu->interruptable = !reg_values[3].InterruptState.InterruptShadow; !vcpu->exit_ctx.VpContext.ExecutionState.InterruptShadow;
return; return;
} }
@ -1254,6 +1235,7 @@ static int whpx_accel_init(MachineState *ms)
int ret; int ret;
HRESULT hr; HRESULT hr;
WHV_CAPABILITY whpx_cap; WHV_CAPABILITY whpx_cap;
UINT32 whpx_cap_size;
WHV_PARTITION_PROPERTY prop; WHV_PARTITION_PROPERTY prop;
whpx = &whpx_global; whpx = &whpx_global;
@ -1262,7 +1244,7 @@ static int whpx_accel_init(MachineState *ms)
whpx->mem_quota = ms->ram_size; whpx->mem_quota = ms->ram_size;
hr = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &whpx_cap, hr = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &whpx_cap,
sizeof(whpx_cap)); sizeof(whpx_cap), &whpx_cap_size);
if (FAILED(hr) || !whpx_cap.HypervisorPresent) { if (FAILED(hr) || !whpx_cap.HypervisorPresent) {
error_report("WHPX: No accelerator found, hr=%08lx", hr); error_report("WHPX: No accelerator found, hr=%08lx", hr);
ret = -ENOSPC; ret = -ENOSPC;
@ -1277,9 +1259,9 @@ static int whpx_accel_init(MachineState *ms)
} }
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
prop.PropertyCode = WHvPartitionPropertyCodeProcessorCount;
prop.ProcessorCount = smp_cpus; prop.ProcessorCount = smp_cpus;
hr = WHvSetPartitionProperty(whpx->partition, hr = WHvSetPartitionProperty(whpx->partition,
WHvPartitionPropertyCodeProcessorCount,
&prop, &prop,
sizeof(WHV_PARTITION_PROPERTY)); sizeof(WHV_PARTITION_PROPERTY));

View file

@ -18,6 +18,7 @@
#include "qemu/range.h" #include "qemu/range.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "chardev/char-fe.h" #include "chardev/char-fe.h"
#include "qemu/memfd.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "libqos/libqos.h" #include "libqos/libqos.h"
#include "libqos/pci-pc.h" #include "libqos/pci-pc.h"
@ -40,23 +41,14 @@
#define HAVE_MONOTONIC_TIME #define HAVE_MONOTONIC_TIME
#endif #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" "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_CHR " -chardev socket,id=%s,path=%s%s"
#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce" #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_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 #define HUGETLBFS_MAGIC 0x958458f6
/*********** FROM hw/virtio/vhost-user.c *************************************/ /*********** FROM hw/virtio/vhost-user.c *************************************/
@ -175,6 +167,33 @@ static void test_server_listen(TestServer *server);
static const char *tmpfs; static const char *tmpfs;
static const char *root; 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) static void init_virtio_dev(TestServer *s, uint32_t features_mask)
{ {
uint32_t features; 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); chr = qemu_chr_new(server->chr_name, chr_path);
g_free(chr_path); g_free(chr_path);
g_assert_nonnull(chr);
qemu_chr_fe_init(&server->chr, chr, &error_abort); qemu_chr_fe_init(&server->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read, qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
chr_event, NULL, server, NULL, true); chr_event, NULL, server, NULL, true);
@ -640,16 +660,18 @@ GSourceFuncs test_migrate_source_funcs = {
.check = test_migrate_source_check, .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; TestServer *server = NULL;
char *qemu_cmd = NULL; char *qemu_cmd = NULL;
QTestState *s = 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); test_server_listen(server);
qemu_cmd = GET_QEMU_CMD(server); qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
s = qtest_start(qemu_cmd); s = qtest_start(qemu_cmd);
g_free(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); char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
QTestState *global = global_qtest, *from, *to; QTestState *global = global_qtest, *from, *to;
GSource *source; GSource *source;
gchar *cmd; gchar *cmd, *tmp;
QDict *rsp; QDict *rsp;
guint8 *log; guint8 *log;
guint64 size; guint64 size;
@ -679,7 +701,7 @@ static void test_migrate(void)
test_server_listen(s); test_server_listen(s);
test_server_listen(dest); test_server_listen(dest);
cmd = GET_QEMU_CMDE(s, 2, "", ""); cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
from = qtest_start(cmd); from = qtest_start(cmd);
g_free(cmd); g_free(cmd);
@ -688,7 +710,9 @@ static void test_migrate(void)
size = get_log_size(s); size = get_log_size(s);
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8)); 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); to = qtest_init(cmd);
g_free(cmd); g_free(cmd);
@ -801,7 +825,7 @@ static void test_reconnect_subprocess(void)
char *cmd; char *cmd;
g_thread_new("connect", connect_thread, s); 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); qtest_start(cmd);
g_free(cmd); g_free(cmd);
@ -839,7 +863,7 @@ static void test_connect_fail_subprocess(void)
s->test_fail = true; s->test_fail = true;
g_thread_new("connect", connect_thread, s); 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); qtest_start(cmd);
g_free(cmd); g_free(cmd);
@ -869,7 +893,7 @@ static void test_flags_mismatch_subprocess(void)
s->test_flags = TEST_FLAGS_DISCONNECT; s->test_flags = TEST_FLAGS_DISCONNECT;
g_thread_new("connect", connect_thread, s); 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); qtest_start(cmd);
g_free(cmd); g_free(cmd);
@ -904,11 +928,21 @@ static void test_multiqueue(void)
s->queues = 2; s->queues = 2;
test_server_listen(s); test_server_listen(s);
cmd = g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d " if (qemu_memfd_check()) {
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d", cmd = g_strdup_printf(
512, 512, root, s->chr_name, QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
s->socket_path, "", s->chr_name, "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
s->queues, s->queues * 2 + 2); 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); qtest_start(cmd);
g_free(cmd); g_free(cmd);
@ -954,7 +988,13 @@ int main(int argc, char **argv)
/* run the main loop thread so the chardev may operate */ /* run the main loop thread so the chardev may operate */
thread = g_thread_new(NULL, thread_function, loop); 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/migrate", test_migrate);
qtest_add_func("/vhost-user/multiqueue", test_multiqueue); qtest_add_func("/vhost-user/multiqueue", test_multiqueue);

View file

@ -410,5 +410,7 @@ void aio_context_setup(AioContext *ctx)
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
int64_t grow, int64_t shrink, Error **errp) 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");
}
} }