mirror of https://gitee.com/openkylin/qemu.git
Bug fixes.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJbTgXfAAoJEL/70l94x66DTbYH/3NutBAkNZKX7EImj/d0I1O8 nERMVH1R70KBcugdsjhaBfTRoATDXdrBng4MBqloIK9dEMT3g6D4TFZJLU+WAjOc 8sItx0BrUR7Sl8SnAvWNFoqVtvVancFiLnu11DsFGM0l8mJHRlZSkQZ0Fd0FL2W/ OPnW7t6F7B2bc1VlPfSs093FVCoD3S+lJmbj64dwNrn8+fOX918V6gSaYQe92aIY pSbJjkRDx2iULmzMY8QH4OQiHgnd/Pijj+D628DMrUc0iW1Rsw5V2Yq7SMY6zoa8 MoI/YDwX6eRMU2mq74BrKlULZrpmQn+6ZCdZTvXzLwc2zpKD4puO4FuMBOA7yx4= =GcxI -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging Bug fixes. # gpg: Signature made Tue 17 Jul 2018 16:06:07 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: Document command line options with single dash opts: remove redundant check for NULL parameter i386: only parse the initrd_filename once for multiboot modules i386: fix regression parsing multiboot initrd modules virtio-scsi: fix hotplug ->reset() vs event race qdev: add HotplugHandler->post_plug() callback hw/char/serial: retry write if EAGAIN PC Chipset: Improve serial divisor calculation vhost-user-test: added proper TestServer *dest initialization in test_migrate() hyperv: ensure VP index equal to QEMU cpu_index hyperv: rename vcpu_id to vp_index accel: Fix typo and grammar in comment dump: add kernel_gs_base to QEMU CPU state Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
59b5552f02
|
@ -1795,7 +1795,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||
tb->jmp_dest[0] = (uintptr_t)NULL;
|
||||
tb->jmp_dest[1] = (uintptr_t)NULL;
|
||||
|
||||
/* init original jump addresses wich has been set during tcg_gen_code() */
|
||||
/* init original jump addresses which have been set during tcg_gen_code() */
|
||||
if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) {
|
||||
tb_reset_jump(tb, 0);
|
||||
}
|
||||
|
|
|
@ -150,13 +150,10 @@ static void serial_update_irq(SerialState *s)
|
|||
|
||||
static void serial_update_parameters(SerialState *s)
|
||||
{
|
||||
int speed, parity, data_bits, stop_bits, frame_size;
|
||||
float speed;
|
||||
int parity, data_bits, stop_bits, frame_size;
|
||||
QEMUSerialSetParams ssp;
|
||||
|
||||
if (s->divider == 0 || s->divider > s->baudbase) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start bit. */
|
||||
frame_size = 1;
|
||||
if (s->lcr & 0x08) {
|
||||
|
@ -169,14 +166,16 @@ static void serial_update_parameters(SerialState *s)
|
|||
} else {
|
||||
parity = 'N';
|
||||
}
|
||||
if (s->lcr & 0x04)
|
||||
if (s->lcr & 0x04) {
|
||||
stop_bits = 2;
|
||||
else
|
||||
} else {
|
||||
stop_bits = 1;
|
||||
}
|
||||
|
||||
data_bits = (s->lcr & 0x03) + 5;
|
||||
frame_size += data_bits + stop_bits;
|
||||
speed = s->baudbase / s->divider;
|
||||
/* Zero divisor should give about 3500 baud */
|
||||
speed = (s->divider == 0) ? 3500 : (float) s->baudbase / s->divider;
|
||||
ssp.speed = speed;
|
||||
ssp.parity = parity;
|
||||
ssp.data_bits = data_bits;
|
||||
|
@ -184,7 +183,7 @@ static void serial_update_parameters(SerialState *s)
|
|||
s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size;
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
|
||||
|
||||
DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
|
||||
DPRINTF("speed=%.2f parity=%c data=%d stop=%d\n",
|
||||
speed, parity, data_bits, stop_bits);
|
||||
}
|
||||
|
||||
|
@ -261,15 +260,20 @@ static void serial_xmit(SerialState *s)
|
|||
if (s->mcr & UART_MCR_LOOP) {
|
||||
/* in loopback mode, say that we just received a char */
|
||||
serial_receive1(s, &s->tsr, 1);
|
||||
} else if (qemu_chr_fe_write(&s->chr, &s->tsr, 1) == 0 &&
|
||||
s->tsr_retry < MAX_XMIT_RETRY) {
|
||||
assert(s->watch_tag == 0);
|
||||
s->watch_tag =
|
||||
qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
|
||||
serial_watch_cb, s);
|
||||
if (s->watch_tag > 0) {
|
||||
s->tsr_retry++;
|
||||
return;
|
||||
} else {
|
||||
int rc = qemu_chr_fe_write(&s->chr, &s->tsr, 1);
|
||||
|
||||
if ((rc == 0 ||
|
||||
(rc == -1 && errno == EAGAIN)) &&
|
||||
s->tsr_retry < MAX_XMIT_RETRY) {
|
||||
assert(s->watch_tag == 0);
|
||||
s->watch_tag =
|
||||
qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
|
||||
serial_watch_cb, s);
|
||||
if (s->watch_tag > 0) {
|
||||
s->tsr_retry++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
s->tsr_retry = 0;
|
||||
|
@ -341,7 +345,11 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
|
|||
default:
|
||||
case 0:
|
||||
if (s->lcr & UART_LCR_DLAB) {
|
||||
s->divider = (s->divider & 0xff00) | val;
|
||||
if (size == 2) {
|
||||
s->divider = (s->divider & 0xff00) | val;
|
||||
} else if (size == 4) {
|
||||
s->divider = val;
|
||||
}
|
||||
serial_update_parameters(s);
|
||||
} else {
|
||||
s->thr = (uint8_t) val;
|
||||
|
|
|
@ -35,6 +35,16 @@ void hotplug_handler_plug(HotplugHandler *plug_handler,
|
|||
}
|
||||
}
|
||||
|
||||
void hotplug_handler_post_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev)
|
||||
{
|
||||
HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler);
|
||||
|
||||
if (hdc->post_plug) {
|
||||
hdc->post_plug(plug_handler, plugged_dev);
|
||||
}
|
||||
}
|
||||
|
||||
void hotplug_handler_unplug_request(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev,
|
||||
Error **errp)
|
||||
|
|
|
@ -867,6 +867,10 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
|
|||
device_reset(dev);
|
||||
}
|
||||
dev->pending_deleted_event = false;
|
||||
|
||||
if (hotplug_ctrl) {
|
||||
hotplug_handler_post_plug(hotplug_ctrl, dev);
|
||||
}
|
||||
} else if (!value && dev->realized) {
|
||||
Error **local_errp = NULL;
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
|
|
|
@ -161,6 +161,7 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||
uint8_t bootinfo[MBI_SIZE];
|
||||
uint8_t *mb_bootinfo_data;
|
||||
uint32_t cmdline_len;
|
||||
GList *mods = NULL;
|
||||
|
||||
/* Ok, let's see if it is a multiboot image.
|
||||
The header is 12x32bit long, so the latest entry may be 8192 - 48. */
|
||||
|
@ -291,16 +292,16 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||
cmdline_len = strlen(kernel_filename) + 1;
|
||||
cmdline_len += strlen(kernel_cmdline) + 1;
|
||||
if (initrd_filename) {
|
||||
const char *r = get_opt_value(initrd_filename, NULL);
|
||||
cmdline_len += strlen(r) + 1;
|
||||
mbs.mb_mods_avail = 1;
|
||||
while (1) {
|
||||
const char *r = initrd_filename;
|
||||
cmdline_len += strlen(initrd_filename) + 1;
|
||||
while (*r) {
|
||||
char *value;
|
||||
r = get_opt_value(r, &value);
|
||||
mbs.mb_mods_avail++;
|
||||
r = get_opt_value(r, NULL);
|
||||
if (!*r) {
|
||||
break;
|
||||
mods = g_list_append(mods, value);
|
||||
if (*r) {
|
||||
r++;
|
||||
}
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,20 +316,16 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||
mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE;
|
||||
mbs.offset_bootloader = mbs.offset_cmdlines + cmdline_len;
|
||||
|
||||
if (initrd_filename) {
|
||||
const char *next_initrd;
|
||||
char not_last;
|
||||
char *one_file = NULL;
|
||||
|
||||
if (mods) {
|
||||
GList *tmpl = mods;
|
||||
mbs.offset_mods = mbs.mb_buf_size;
|
||||
|
||||
do {
|
||||
while (tmpl) {
|
||||
char *next_space;
|
||||
int mb_mod_length;
|
||||
uint32_t offs = mbs.mb_buf_size;
|
||||
char *one_file = tmpl->data;
|
||||
|
||||
next_initrd = get_opt_value(initrd_filename, &one_file);
|
||||
not_last = *next_initrd;
|
||||
/* if a space comes after the module filename, treat everything
|
||||
after that as parameters */
|
||||
hwaddr c = mb_add_cmdline(&mbs, one_file);
|
||||
|
@ -353,10 +350,10 @@ int load_multiboot(FWCfgState *fw_cfg,
|
|||
mb_debug("mod_start: %p\nmod_end: %p\n cmdline: "TARGET_FMT_plx,
|
||||
(char *)mbs.mb_buf + offs,
|
||||
(char *)mbs.mb_buf + offs + mb_mod_length, c);
|
||||
initrd_filename = next_initrd+1;
|
||||
g_free(one_file);
|
||||
one_file = NULL;
|
||||
} while (not_last);
|
||||
tmpl = tmpl->next;
|
||||
}
|
||||
g_list_free(mods);
|
||||
}
|
||||
|
||||
/* Commandline support */
|
||||
|
|
|
@ -1999,6 +1999,11 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
|||
}
|
||||
cpu->thread_id = topo.smt_id;
|
||||
|
||||
if (cpu->hyperv_vpindex && !kvm_hv_vpindex_settable()) {
|
||||
error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX");
|
||||
return;
|
||||
}
|
||||
|
||||
cs = CPU(cpu);
|
||||
cs->cpu_index = idx;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static void free_sint_route_index(HypervTestDev *dev, int i)
|
|||
dev->sint_route[i] = NULL;
|
||||
}
|
||||
|
||||
static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id,
|
||||
static int find_sint_route_index(HypervTestDev *dev, uint32_t vp_index,
|
||||
uint32_t sint)
|
||||
{
|
||||
HvSintRoute *sint_route;
|
||||
|
@ -65,7 +65,7 @@ static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) {
|
||||
sint_route = dev->sint_route[i];
|
||||
if (sint_route && sint_route->vcpu_id == vcpu_id &&
|
||||
if (sint_route && sint_route->vp_index == vp_index &&
|
||||
sint_route->sint == sint) {
|
||||
return i;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id,
|
|||
}
|
||||
|
||||
static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl,
|
||||
uint32_t vcpu_id, uint32_t sint)
|
||||
uint32_t vp_index, uint32_t sint)
|
||||
{
|
||||
int i;
|
||||
HvSintRoute *sint_route;
|
||||
|
@ -83,19 +83,19 @@ static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl,
|
|||
case HV_TEST_DEV_SINT_ROUTE_CREATE:
|
||||
i = alloc_sint_route_index(dev);
|
||||
assert(i >= 0);
|
||||
sint_route = kvm_hv_sint_route_create(vcpu_id, sint, NULL);
|
||||
sint_route = kvm_hv_sint_route_create(vp_index, sint, NULL);
|
||||
assert(sint_route);
|
||||
dev->sint_route[i] = sint_route;
|
||||
break;
|
||||
case HV_TEST_DEV_SINT_ROUTE_DESTROY:
|
||||
i = find_sint_route_index(dev, vcpu_id, sint);
|
||||
i = find_sint_route_index(dev, vp_index, sint);
|
||||
assert(i >= 0);
|
||||
sint_route = dev->sint_route[i];
|
||||
kvm_hv_sint_route_destroy(sint_route);
|
||||
free_sint_route_index(dev, i);
|
||||
break;
|
||||
case HV_TEST_DEV_SINT_ROUTE_SET_SINT:
|
||||
i = find_sint_route_index(dev, vcpu_id, sint);
|
||||
i = find_sint_route_index(dev, vp_index, sint);
|
||||
assert(i >= 0);
|
||||
sint_route = dev->sint_route[i];
|
||||
kvm_hv_sint_route_set_sint(sint_route);
|
||||
|
@ -117,8 +117,8 @@ static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data,
|
|||
case HV_TEST_DEV_SINT_ROUTE_DESTROY:
|
||||
case HV_TEST_DEV_SINT_ROUTE_SET_SINT: {
|
||||
uint8_t sint = data & 0xFF;
|
||||
uint8_t vcpu_id = (data >> 8ULL) & 0xFF;
|
||||
hv_synic_test_dev_control(dev, ctl, vcpu_id, sint);
|
||||
uint8_t vp_index = (data >> 8ULL) & 0xFF;
|
||||
hv_synic_test_dev_control(dev, ctl, vp_index, sint);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -797,8 +797,16 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
|||
virtio_scsi_acquire(s);
|
||||
blk_set_aio_context(sd->conf.blk, s->ctx);
|
||||
virtio_scsi_release(s);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Announce the new device after it has been plugged */
|
||||
static void virtio_scsi_post_hotplug(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
|
||||
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
|
||||
SCSIDevice *sd = SCSI_DEVICE(dev);
|
||||
|
||||
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
|
||||
virtio_scsi_acquire(s);
|
||||
|
@ -968,6 +976,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
|
|||
vdc->start_ioeventfd = virtio_scsi_dataplane_start;
|
||||
vdc->stop_ioeventfd = virtio_scsi_dataplane_stop;
|
||||
hc->plug = virtio_scsi_hotplug;
|
||||
hc->post_plug = virtio_scsi_post_hotplug;
|
||||
hc->unplug = virtio_scsi_hotunplug;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler,
|
|||
* @parent: Opaque parent interface.
|
||||
* @pre_plug: pre plug callback called at start of device.realize(true)
|
||||
* @plug: plug callback called at end of device.realize(true).
|
||||
* @post_plug: post plug callback called after device.realize(true) and device
|
||||
* reset
|
||||
* @unplug_request: unplug request callback.
|
||||
* Used as a means to initiate device unplug for devices that
|
||||
* require asynchronous unplug handling.
|
||||
|
@ -61,6 +63,7 @@ typedef struct HotplugHandlerClass {
|
|||
/* <public> */
|
||||
hotplug_fn pre_plug;
|
||||
hotplug_fn plug;
|
||||
void (*post_plug)(HotplugHandler *plug_handler, DeviceState *plugged_dev);
|
||||
hotplug_fn unplug_request;
|
||||
hotplug_fn unplug;
|
||||
} HotplugHandlerClass;
|
||||
|
@ -83,6 +86,14 @@ void hotplug_handler_pre_plug(HotplugHandler *plug_handler,
|
|||
DeviceState *plugged_dev,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* hotplug_handler_post_plug:
|
||||
*
|
||||
* Call #HotplugHandlerClass.post_plug callback of @plug_handler.
|
||||
*/
|
||||
void hotplug_handler_post_plug(HotplugHandler *plug_handler,
|
||||
DeviceState *plugged_dev);
|
||||
|
||||
/**
|
||||
* hotplug_handler_unplug_request:
|
||||
*
|
||||
|
|
|
@ -471,7 +471,7 @@ STEXI
|
|||
@item -balloon virtio[,addr=@var{addr}]
|
||||
@findex -balloon
|
||||
Enable virtio balloon device, optionally with PCI address @var{addr}. This
|
||||
option is deprecated, use @option{--device virtio-balloon} instead.
|
||||
option is deprecated, use @option{-device virtio-balloon} instead.
|
||||
ETEXI
|
||||
|
||||
DEF("device", HAS_ARG, QEMU_OPTION_device,
|
||||
|
@ -2005,7 +2005,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
|
|||
"-netdev hubport,id=str,hubid=n[,netdev=nd]\n"
|
||||
" configure a hub port on the hub with ID 'n'\n", QEMU_ARCH_ALL)
|
||||
DEF("nic", HAS_ARG, QEMU_OPTION_nic,
|
||||
"--nic [tap|bridge|"
|
||||
"-nic [tap|bridge|"
|
||||
#ifdef CONFIG_SLIRP
|
||||
"user|"
|
||||
#endif
|
||||
|
@ -2024,7 +2024,7 @@ DEF("nic", HAS_ARG, QEMU_OPTION_nic,
|
|||
"socket][,option][,...][mac=macaddr]\n"
|
||||
" initialize an on-board / default host NIC (using MAC address\n"
|
||||
" macaddr) and connect it to the given host network backend\n"
|
||||
"--nic none use it alone to have zero network devices (the default is to\n"
|
||||
"-nic none use it alone to have zero network devices (the default is to\n"
|
||||
" provided a 'user' network connection)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
DEF("net", HAS_ARG, QEMU_OPTION_net,
|
||||
|
@ -3339,7 +3339,7 @@ mlocking qemu and guest memory can be enabled via @option{mlock=on}
|
|||
ETEXI
|
||||
|
||||
DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit,
|
||||
"--overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
|
||||
"-overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
|
||||
" run qemu with overcommit hints\n"
|
||||
" mem-lock=on|off controls memory lock support (default: off)\n"
|
||||
" cpu-pm=on|off controls cpu power management (default: off)\n",
|
||||
|
|
|
@ -258,6 +258,12 @@ struct QEMUCPUState {
|
|||
QEMUCPUSegment cs, ds, es, fs, gs, ss;
|
||||
QEMUCPUSegment ldt, tr, gdt, idt;
|
||||
uint64_t cr[5];
|
||||
/*
|
||||
* Fields below are optional and are being added at the end without
|
||||
* changing the version. External tools may identify their presence
|
||||
* by checking 'size' field.
|
||||
*/
|
||||
uint64_t kernel_gs_base;
|
||||
};
|
||||
|
||||
typedef struct QEMUCPUState QEMUCPUState;
|
||||
|
@ -315,6 +321,10 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
|
|||
s->cr[2] = env->cr[2];
|
||||
s->cr[3] = env->cr[3];
|
||||
s->cr[4] = env->cr[4];
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
s->kernel_gs_base = env->kernelgsbase;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
|
||||
|
|
|
@ -16,6 +16,16 @@
|
|||
#include "hyperv.h"
|
||||
#include "hyperv-proto.h"
|
||||
|
||||
uint32_t hyperv_vp_index(X86CPU *cpu)
|
||||
{
|
||||
return CPU(cpu)->cpu_index;
|
||||
}
|
||||
|
||||
X86CPU *hyperv_find_vcpu(uint32_t vp_index)
|
||||
{
|
||||
return X86_CPU(qemu_get_cpu(vp_index));
|
||||
}
|
||||
|
||||
int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
@ -72,7 +82,7 @@ static void kvm_hv_sint_ack_handler(EventNotifier *notifier)
|
|||
}
|
||||
}
|
||||
|
||||
HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
||||
HvSintRoute *kvm_hv_sint_route_create(uint32_t vp_index, uint32_t sint,
|
||||
HvSintAckClb sint_ack_clb)
|
||||
{
|
||||
HvSintRoute *sint_route;
|
||||
|
@ -92,7 +102,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
|||
event_notifier_set_handler(&sint_route->sint_ack_notifier,
|
||||
kvm_hv_sint_ack_handler);
|
||||
|
||||
gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
|
||||
gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vp_index, sint);
|
||||
if (gsi < 0) {
|
||||
goto err_gsi;
|
||||
}
|
||||
|
@ -105,7 +115,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
|||
}
|
||||
sint_route->gsi = gsi;
|
||||
sint_route->sint_ack_clb = sint_ack_clb;
|
||||
sint_route->vcpu_id = vcpu_id;
|
||||
sint_route->vp_index = vp_index;
|
||||
sint_route->sint = sint;
|
||||
|
||||
return sint_route;
|
||||
|
|
|
@ -23,7 +23,7 @@ typedef void (*HvSintAckClb)(HvSintRoute *sint_route);
|
|||
|
||||
struct HvSintRoute {
|
||||
uint32_t sint;
|
||||
uint32_t vcpu_id;
|
||||
uint32_t vp_index;
|
||||
int gsi;
|
||||
EventNotifier sint_set_notifier;
|
||||
EventNotifier sint_ack_notifier;
|
||||
|
@ -32,11 +32,14 @@ struct HvSintRoute {
|
|||
|
||||
int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit);
|
||||
|
||||
HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
|
||||
HvSintRoute *kvm_hv_sint_route_create(uint32_t vp_index, uint32_t sint,
|
||||
HvSintAckClb sint_ack_clb);
|
||||
|
||||
void kvm_hv_sint_route_destroy(HvSintRoute *sint_route);
|
||||
|
||||
int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route);
|
||||
|
||||
uint32_t hyperv_vp_index(X86CPU *cpu);
|
||||
X86CPU *hyperv_find_vcpu(uint32_t vp_index);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,3 +40,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
|
|||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool kvm_hv_vpindex_settable(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ static bool has_msr_hv_hypercall;
|
|||
static bool has_msr_hv_crash;
|
||||
static bool has_msr_hv_reset;
|
||||
static bool has_msr_hv_vpindex;
|
||||
static bool hv_vpindex_settable;
|
||||
static bool has_msr_hv_runtime;
|
||||
static bool has_msr_hv_synic;
|
||||
static bool has_msr_hv_stimer;
|
||||
|
@ -162,6 +163,11 @@ bool kvm_enable_x2apic(void)
|
|||
has_x2apic_api);
|
||||
}
|
||||
|
||||
bool kvm_hv_vpindex_settable(void)
|
||||
{
|
||||
return hv_vpindex_settable;
|
||||
}
|
||||
|
||||
static int kvm_get_tsc(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
|
@ -745,6 +751,37 @@ static int hyperv_handle_properties(CPUState *cs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hyperv_init_vcpu(X86CPU *cpu)
|
||||
{
|
||||
if (cpu->hyperv_vpindex && !hv_vpindex_settable) {
|
||||
/*
|
||||
* the kernel doesn't support setting vp_index; assert that its value
|
||||
* is in sync
|
||||
*/
|
||||
int ret;
|
||||
struct {
|
||||
struct kvm_msrs info;
|
||||
struct kvm_msr_entry entries[1];
|
||||
} msr_data = {
|
||||
.info.nmsrs = 1,
|
||||
.entries[0].index = HV_X64_MSR_VP_INDEX,
|
||||
};
|
||||
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
assert(ret == 1);
|
||||
|
||||
if (msr_data.entries[0].data != hyperv_vp_index(cpu)) {
|
||||
error_report("kernel's vp_index != QEMU's vp_index");
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Error *invtsc_mig_blocker;
|
||||
|
||||
#define KVM_MAX_CPUID_ENTRIES 100
|
||||
|
@ -1160,6 +1197,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||
has_msr_tsc_aux = false;
|
||||
}
|
||||
|
||||
r = hyperv_init_vcpu(cpu);
|
||||
if (r) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -1351,6 +1393,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
|||
has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
|
||||
#endif
|
||||
|
||||
hv_vpindex_settable = kvm_check_extension(s, KVM_CAP_HYPERV_VP_INDEX);
|
||||
|
||||
ret = kvm_get_supported_msrs(s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -1900,6 +1944,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
|||
if (has_msr_hv_runtime) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime);
|
||||
}
|
||||
if (cpu->hyperv_vpindex && hv_vpindex_settable) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_VP_INDEX, hyperv_vp_index(cpu));
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
int j;
|
||||
|
||||
|
|
|
@ -63,4 +63,6 @@ void kvm_put_apicbase(X86CPU *cpu, uint64_t value);
|
|||
|
||||
bool kvm_enable_x2apic(void);
|
||||
bool kvm_has_x2apic_api(void);
|
||||
|
||||
bool kvm_hv_vpindex_settable(void);
|
||||
#endif
|
||||
|
|
|
@ -537,6 +537,7 @@ static gboolean _test_server_free(TestServer *server)
|
|||
g_free(server->mig_path);
|
||||
|
||||
g_free(server->chr_name);
|
||||
g_assert(server->bus);
|
||||
qpci_free_pc(server->bus);
|
||||
|
||||
g_free(server);
|
||||
|
@ -684,6 +685,7 @@ static void test_migrate(void)
|
|||
g_free(cmd);
|
||||
|
||||
init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
|
||||
init_virtio_dev(dest, 1u << VIRTIO_NET_F_MAC);
|
||||
wait_for_fds(s);
|
||||
size = get_log_size(s);
|
||||
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
|
||||
|
@ -739,6 +741,7 @@ static void test_migrate(void)
|
|||
read_guest_mem_server(dest);
|
||||
|
||||
uninit_virtio_dev(s);
|
||||
uninit_virtio_dev(dest);
|
||||
|
||||
g_source_destroy(source);
|
||||
g_source_unref(source);
|
||||
|
|
|
@ -82,11 +82,9 @@ const char *get_opt_value(const char *p, char **value)
|
|||
if (*offset != '\0' && *(offset + 1) == ',') {
|
||||
length++;
|
||||
}
|
||||
if (value) {
|
||||
*value = g_renew(char, *value, capacity + length + 1);
|
||||
strncpy(*value + capacity, p, length);
|
||||
(*value)[capacity + length] = '\0';
|
||||
}
|
||||
*value = g_renew(char, *value, capacity + length + 1);
|
||||
strncpy(*value + capacity, p, length);
|
||||
(*value)[capacity + length] = '\0';
|
||||
capacity += length;
|
||||
if (*offset == '\0' ||
|
||||
*(offset + 1) != ',') {
|
||||
|
|
Loading…
Reference in New Issue