mirror of https://github.com/xemu-project/xemu.git
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:
commit
7b93d78a04
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
if (d->mux_cnt >= MAX_MUX) {
|
||||
goto unavailable;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -2496,7 +2496,9 @@ if test "$whpx" != "no" ; then
|
|||
#include <WinHvEmulation.h>
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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': {
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue