aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--block/iscsi.c7
-rw-r--r--hw/acpi_piix4.c5
-rw-r--r--hw/arm_gic.c1
-rw-r--r--hw/esp.c16
-rw-r--r--hw/ivshmem.c15
-rw-r--r--hw/megasas.c9
-rw-r--r--hw/msix.c13
-rw-r--r--hw/scsi-disk.c3
-rw-r--r--hw/scsi-generic.c3
-rw-r--r--hw/virtio-pci.c2
-rw-r--r--linux-headers/asm-s390/kvm.h2
-rw-r--r--linux-headers/asm-s390/kvm_para.h2
-rw-r--r--linux-headers/asm-x86/kvm.h1
-rw-r--r--linux-headers/asm-x86/kvm_para.h7
-rw-r--r--linux-headers/linux/kvm.h3
-rw-r--r--linux-user/main.c11
-rw-r--r--linux-user/syscall.c11
-rw-r--r--linux-user/syscall_defs.h8
-rw-r--r--memory.c2
-rw-r--r--qemu-ga.c4
-rw-r--r--target-i386/cpu.c15
-rw-r--r--target-i386/cpu.h1
-rw-r--r--target-i386/kvm.c13
-rw-r--r--target-i386/machine.c21
25 files changed, 128 insertions, 49 deletions
diff --git a/VERSION b/VERSION
index 069199b82a..99f6a00b10 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.91
+1.1.92
diff --git a/block/iscsi.c b/block/iscsi.c
index 4828b83927..0b96165ec2 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -721,7 +721,12 @@ iscsi_readcapacity10_cb(struct iscsi_context *iscsi, int status,
}
itask->iscsilun->block_size = rc10->block_size;
- itask->iscsilun->num_blocks = rc10->lba + 1;
+ if (rc10->lba == 0) {
+ /* blank disk loaded */
+ itask->iscsilun->num_blocks = 0;
+ } else {
+ itask->iscsilun->num_blocks = rc10->lba + 1;
+ }
itask->bs->total_sectors = itask->iscsilun->num_blocks *
itask->iscsilun->block_size / BDRV_SECTOR_SIZE ;
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 72d6e5c904..c56220b368 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -352,6 +352,9 @@ static void piix4_reset(void *opaque)
pci_conf[0x5a] = 0;
pci_conf[0x5b] = 0;
+ pci_conf[0x40] = 0x01; /* PM io base read only bit */
+ pci_conf[0x80] = 0;
+
if (s->kvm_enabled) {
/* Mark SMM as already inited (until KVM supports SMM). */
pci_conf[0x5B] = 0x02;
@@ -391,8 +394,6 @@ static int piix4_pm_initfn(PCIDevice *dev)
pci_conf[0x09] = 0x00;
pci_conf[0x3d] = 0x01; // interrupt pin 1
- pci_conf[0x40] = 0x01; /* PM io base read only bit */
-
/* APM */
apm_init(&s->apm, apm_ctrl_changed, s);
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 186ac66f00..55871fad19 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -703,6 +703,7 @@ static TypeInfo arm_gic_info = {
.parent = TYPE_ARM_GIC_COMMON,
.instance_size = sizeof(gic_state),
.class_init = arm_gic_class_init,
+ .class_size = sizeof(ARMGICClass),
};
static void arm_gic_register_types(void)
diff --git a/hw/esp.c b/hw/esp.c
index 52c46e615f..84a4e74e25 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -87,7 +87,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
target = s->wregs[ESP_WBUSID] & BUSID_DID;
if (s->dma) {
- dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
+ dmalen = s->rregs[ESP_TCLO];
+ dmalen |= s->rregs[ESP_TCMID] << 8;
+ dmalen |= s->rregs[ESP_TCHI] << 16;
s->dma_memory_read(s->dma_opaque, buf, dmalen);
} else {
dmalen = s->ti_size;
@@ -226,6 +228,7 @@ static void esp_dma_done(ESPState *s)
s->rregs[ESP_RFLAGS] = 0;
s->rregs[ESP_TCLO] = 0;
s->rregs[ESP_TCMID] = 0;
+ s->rregs[ESP_TCHI] = 0;
esp_raise_irq(s);
}
@@ -328,7 +331,9 @@ static void handle_ti(ESPState *s)
return;
}
- dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
+ dmalen = s->rregs[ESP_TCLO];
+ dmalen |= s->rregs[ESP_TCMID] << 8;
+ dmalen |= s->rregs[ESP_TCHI] << 16;
if (dmalen==0) {
dmalen=0x10000;
}
@@ -429,6 +434,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
switch (saddr) {
case ESP_TCLO:
case ESP_TCMID:
+ case ESP_TCHI:
s->rregs[ESP_RSTAT] &= ~STAT_TC;
break;
case ESP_FIFO:
@@ -448,6 +454,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
/* Reload DMA counter. */
s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
+ s->rregs[ESP_TCHI] = s->wregs[ESP_TCHI];
} else {
s->dma = 0;
}
@@ -530,13 +537,12 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
case ESP_WBUSID ... ESP_WSYNO:
break;
case ESP_CFG1:
+ case ESP_CFG2: case ESP_CFG3:
+ case ESP_RES3: case ESP_RES4:
s->rregs[saddr] = val;
break;
case ESP_WCCF ... ESP_WTEST:
break;
- case ESP_CFG2 ... ESP_RES4:
- s->rregs[saddr] = val;
- break;
default:
trace_esp_error_invalid_write(val, saddr);
return;
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 47f2a16833..62fe53ae2b 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -385,17 +385,6 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
s->peers[posn].nb_eventfds = 0;
}
-static void setup_ioeventfds(IVShmemState *s) {
-
- int i, j;
-
- for (i = 0; i <= s->max_peer; i++) {
- for (j = 0; j < s->peers[i].nb_eventfds; j++) {
- ivshmem_add_eventfd(s, i, j);
- }
- }
-}
-
/* this function increase the dynamic storage need to store data about other
* guests */
static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
@@ -696,10 +685,6 @@ static int pci_ivshmem_init(PCIDevice *dev)
memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s,
"ivshmem-mmio", IVSHMEM_REG_BAR_SIZE);
- if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
- setup_ioeventfds(s);
- }
-
/* region for registers*/
pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
&s->ivshmem_mmio);
diff --git a/hw/megasas.c b/hw/megasas.c
index c35a15db4f..c728aea699 100644
--- a/hw/megasas.c
+++ b/hw/megasas.c
@@ -38,6 +38,7 @@
#define MEGASAS_MAX_SECTORS 0xFFFF /* No real limit */
#define MEGASAS_MAX_ARRAYS 128
+#define MEGASAS_HBA_SERIAL "QEMU123456"
#define NAA_LOCALLY_ASSIGNED_ID 0x3ULL
#define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400
@@ -93,6 +94,7 @@ typedef struct MegasasState {
int boot_event;
uint64_t sas_addr;
+ char *hba_serial;
uint64_t reply_queue_pa;
void *reply_queue;
@@ -698,8 +700,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
}
memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
- snprintf(info.serial_number, 32, "QEMU%08lx",
- (unsigned long)s & 0xFFFFFFFF);
+ snprintf(info.serial_number, 32, "%s", s->hba_serial);
snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION);
memcpy(info.image_component[0].name, "APP", 3);
memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9);
@@ -2132,6 +2133,9 @@ static int megasas_scsi_init(PCIDevice *dev)
s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
s->sas_addr |= PCI_FUNC(dev->devfn);
}
+ if (!s->hba_serial) {
+ s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL);
+ }
if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) {
s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE;
} else if (s->fw_sge >= 128 - MFI_PASS_FRAME_SIZE) {
@@ -2166,6 +2170,7 @@ static Property megasas_properties[] = {
MEGASAS_DEFAULT_SGE),
DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
MEGASAS_DEFAULT_FRAMES),
+ DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
DEFINE_PROP_HEX64("sas_address", MegasasState, sas_addr, 0),
#ifdef USE_MSIX
DEFINE_PROP_BIT("use_msix", MegasasState, flags,
diff --git a/hw/msix.c b/hw/msix.c
index aea340b7c7..d812094139 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -336,6 +336,15 @@ static void msix_free_irq_entries(PCIDevice *dev)
}
}
+static void msix_clear_all_vectors(PCIDevice *dev)
+{
+ int vector;
+
+ for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+ msix_clr_pending(dev, vector);
+ }
+}
+
/* Clean up resources for the device. */
void msix_uninit(PCIDevice *dev, MemoryRegion *table_bar, MemoryRegion *pba_bar)
{
@@ -390,7 +399,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
return;
}
- msix_free_irq_entries(dev);
+ msix_clear_all_vectors(dev);
qemu_get_buffer(f, dev->msix_table, n * PCI_MSIX_ENTRY_SIZE);
qemu_get_buffer(f, dev->msix_pba, (n + 7) / 8);
msix_update_function_masked(dev);
@@ -436,7 +445,7 @@ void msix_reset(PCIDevice *dev)
if (!msix_present(dev)) {
return;
}
- msix_free_irq_entries(dev);
+ msix_clear_all_vectors(dev);
dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &=
~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET];
memset(dev->msix_table, 0, dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 409f760ef7..1585683bce 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -1461,7 +1461,7 @@ static void scsi_unmap_complete(void *opaque, int ret)
SCSIDiskReq *r = data->r;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint64_t sector_num;
- uint32 nb_sectors;
+ uint32_t nb_sectors;
r->req.aiocb = NULL;
if (ret < 0) {
@@ -2421,6 +2421,7 @@ static TypeInfo scsi_cd_info = {
#ifdef __linux__
static Property scsi_block_properties[] = {
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
+ DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index 8d5106061e..a5eb663ecf 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -479,7 +479,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
}
static Property scsi_generic_properties[] = {
- DEFINE_BLOCK_PROPERTIES(SCSIDevice, conf),
+ DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
+ DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 2a3d86f176..b3f0710f39 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -131,6 +131,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
if (ret) {
return ret;
}
+ msix_unuse_all_vectors(&proxy->pci_dev);
msix_load(&proxy->pci_dev, f);
if (msix_present(&proxy->pci_dev)) {
qemu_get_be16s(f, &proxy->vdev->config_vector);
@@ -246,6 +247,7 @@ void virtio_pci_reset(DeviceState *d)
VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
virtio_pci_stop_ioeventfd(proxy);
virtio_reset(proxy->vdev);
+ msix_unuse_all_vectors(&proxy->pci_dev);
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index bdcbe0f8dd..d25da598ec 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -1,7 +1,7 @@
#ifndef __LINUX_KVM_S390_H
#define __LINUX_KVM_S390_H
/*
- * asm-s390/kvm.h - KVM s390 specific structures and definitions
+ * KVM s390 specific structures and definitions
*
* Copyright IBM Corp. 2008
*
diff --git a/linux-headers/asm-s390/kvm_para.h b/linux-headers/asm-s390/kvm_para.h
index 8e2dd6706b..870051f645 100644
--- a/linux-headers/asm-s390/kvm_para.h
+++ b/linux-headers/asm-s390/kvm_para.h
@@ -1,5 +1,5 @@
/*
- * asm-s390/kvm_para.h - definition for paravirtual devices on s390
+ * definition for paravirtual devices on s390
*
* Copyright IBM Corp. 2008
*
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
index e7d1c194d2..246617efd6 100644
--- a/linux-headers/asm-x86/kvm.h
+++ b/linux-headers/asm-x86/kvm.h
@@ -12,6 +12,7 @@
/* Select x86 specific features in <linux/kvm.h> */
#define __KVM_HAVE_PIT
#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_DEVICE_ASSIGNMENT
#define __KVM_HAVE_MSI
#define __KVM_HAVE_USER_NMI
diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h
index f2ac46a2a2..a1c3d72acd 100644
--- a/linux-headers/asm-x86/kvm_para.h
+++ b/linux-headers/asm-x86/kvm_para.h
@@ -22,6 +22,7 @@
#define KVM_FEATURE_CLOCKSOURCE2 3
#define KVM_FEATURE_ASYNC_PF 4
#define KVM_FEATURE_STEAL_TIME 5
+#define KVM_FEATURE_PV_EOI 6
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
@@ -37,6 +38,7 @@
#define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
#define MSR_KVM_ASYNC_PF_EN 0x4b564d02
#define MSR_KVM_STEAL_TIME 0x4b564d03
+#define MSR_KVM_PV_EOI_EN 0x4b564d04
struct kvm_steal_time {
__u64 steal;
@@ -89,5 +91,10 @@ struct kvm_vcpu_pv_apf_data {
__u32 enabled;
};
+#define KVM_PV_EOI_BIT 0
+#define KVM_PV_EOI_MASK (0x1 << KVM_PV_EOI_BIT)
+#define KVM_PV_EOI_ENABLED KVM_PV_EOI_MASK
+#define KVM_PV_EOI_DISABLED 0x0
+
#endif /* _ASM_X86_KVM_PARA_H */
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 5a9d4e350d..4b9e575dd0 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -617,6 +617,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_SIGNAL_MSI 77
#define KVM_CAP_PPC_GET_SMMU_INFO 78
#define KVM_CAP_S390_COW 79
+#define KVM_CAP_PPC_ALLOC_HTAB 80
#ifdef KVM_CAP_IRQ_ROUTING
@@ -828,6 +829,8 @@ struct kvm_s390_ucas_mapping {
#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
/* Available with KVM_CAP_PPC_GET_SMMU_INFO */
#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
+/* Available with KVM_CAP_PPC_ALLOC_HTAB */
+#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
/*
* ioctls for vcpu fds
diff --git a/linux-user/main.c b/linux-user/main.c
index 7dea084873..1a1c661ee4 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3222,7 +3222,7 @@ struct qemu_argument {
const char *help;
};
-struct qemu_argument arg_table[] = {
+static const struct qemu_argument arg_table[] = {
{"h", "", false, handle_arg_help,
"", "print this help"},
{"g", "QEMU_GDB", true, handle_arg_gdb,
@@ -3264,7 +3264,7 @@ struct qemu_argument arg_table[] = {
static void usage(void)
{
- struct qemu_argument *arginfo;
+ const struct qemu_argument *arginfo;
int maxarglen;
int maxenvlen;
@@ -3330,7 +3330,7 @@ static int parse_args(int argc, char **argv)
{
const char *r;
int optind;
- struct qemu_argument *arginfo;
+ const struct qemu_argument *arginfo;
for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
if (arginfo->env == NULL) {
@@ -3519,7 +3519,10 @@ int main(int argc, char **argv, char **envp)
guest_base = init_guest_space(guest_base, reserved_va, 0,
have_guest_base);
if (guest_base == (unsigned long)-1) {
- fprintf(stderr, "Unable to reserve guest address space\n");
+ fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
+ "space for use as guest address space (check your virtual "
+ "memory ulimit setting or reserve less using -R option)\n",
+ reserved_va);
exit(1);
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 11743065e9..6257a04d0a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7025,15 +7025,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
tde = target_dirp;
while (len > 0) {
reclen = de->d_reclen;
- treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
+ tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+ assert(tnamelen >= 0);
+ treclen = tnamelen + offsetof(struct target_dirent, d_name);
+ assert(count1 + treclen <= count);
tde->d_reclen = tswap16(treclen);
tde->d_ino = tswapal(de->d_ino);
tde->d_off = tswapal(de->d_off);
- tnamelen = treclen - (2 * sizeof(abi_long) + 2);
- if (tnamelen > 256)
- tnamelen = 256;
- /* XXX: may not be correct */
- pstrcpy(tde->d_name, tnamelen, de->d_name);
+ memcpy(tde->d_name, de->d_name, tnamelen);
de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
tde = (struct target_dirent *)((char *)tde + treclen);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 2cfda5afd5..a98cbf7b80 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -255,10 +255,10 @@ struct kernel_statfs {
};
struct target_dirent {
- abi_long d_ino;
- abi_long d_off;
- unsigned short d_reclen;
- char d_name[256]; /* We must not include limits.h! */
+ abi_long d_ino;
+ abi_long d_off;
+ unsigned short d_reclen;
+ char d_name[];
};
struct target_dirent64 {
diff --git a/memory.c b/memory.c
index 643871bafa..d528d1f7f3 100644
--- a/memory.c
+++ b/memory.c
@@ -426,7 +426,7 @@ static void memory_region_iorange_write(IORange *iorange,
if (mrp) {
mrp->write(mr->opaque, offset, data);
} else if (width == 2) {
- mrp = find_portio(mr, offset - mrio->offset, 1, false);
+ mrp = find_portio(mr, offset - mrio->offset, 1, true);
assert(mrp);
mrp->write(mr->opaque, offset, data & 0xff);
mrp->write(mr->opaque, offset + 1, data >> 8);
diff --git a/qemu-ga.c b/qemu-ga.c
index 26671fee3f..7623079887 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -438,7 +438,9 @@ static void become_daemon(const char *pidfile)
return;
fail:
- unlink(pidfile);
+ if (pidfile) {
+ unlink(pidfile);
+ }
g_critical("failed to daemonize");
exit(EXIT_FAILURE);
#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 120a2e3d3e..423e00905d 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -33,6 +33,9 @@
#include "hyperv.h"
#include "hw/hw.h"
+#if defined(CONFIG_KVM)
+#include <linux/kvm_para.h>
+#endif
/* feature flags taken from "Intel Processor Identification and the CPUID
* Instruction" and AMD's "CPUID Specification". In cases of disagreement
@@ -887,7 +890,17 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
memcpy(x86_cpu_def, def, sizeof(*def));
}
- plus_kvm_features = ~0; /* not supported bits will be filtered out later */
+#if defined(CONFIG_KVM)
+ plus_kvm_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
+ (1 << KVM_FEATURE_NOP_IO_DELAY) |
+ (1 << KVM_FEATURE_MMU_OP) |
+ (1 << KVM_FEATURE_CLOCKSOURCE2) |
+ (1 << KVM_FEATURE_ASYNC_PF) |
+ (1 << KVM_FEATURE_STEAL_TIME) |
+ (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
+#else
+ plus_kvm_features = 0;
+#endif
add_flagname_to_bitmaps("hypervisor", &plus_features,
&plus_ext_features, &plus_ext2_features, &plus_ext3_features,
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 60f9e972bd..0677502dcc 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -699,6 +699,7 @@ typedef struct CPUX86State {
uint64_t system_time_msr;
uint64_t wall_clock_msr;
uint64_t async_pf_en_msr;
+ uint64_t pv_eoi_en_msr;
uint64_t tsc;
uint64_t tsc_deadline;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 696b14a04a..ffc294ec39 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -63,6 +63,7 @@ static bool has_msr_star;
static bool has_msr_hsave_pa;
static bool has_msr_tsc_deadline;
static bool has_msr_async_pf_en;
+static bool has_msr_pv_eoi_en;
static bool has_msr_misc_enable;
static int lm_capable_kernel;
@@ -455,6 +456,8 @@ int kvm_arch_init_vcpu(CPUX86State *env)
has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
+ has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);
+
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
for (i = 0; i <= limit; i++) {
@@ -1017,6 +1020,10 @@ static int kvm_put_msrs(CPUX86State *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
env->async_pf_en_msr);
}
+ if (has_msr_pv_eoi_en) {
+ kvm_msr_entry_set(&msrs[n++], MSR_KVM_PV_EOI_EN,
+ env->pv_eoi_en_msr);
+ }
if (hyperv_hypercall_available()) {
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
@@ -1259,6 +1266,9 @@ static int kvm_get_msrs(CPUX86State *env)
if (has_msr_async_pf_en) {
msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
}
+ if (has_msr_pv_eoi_en) {
+ msrs[n++].index = MSR_KVM_PV_EOI_EN;
+ }
if (env->mcg_cap) {
msrs[n++].index = MSR_MCG_STATUS;
@@ -1338,6 +1348,9 @@ static int kvm_get_msrs(CPUX86State *env)
case MSR_KVM_ASYNC_PF_EN:
env->async_pf_en_msr = msrs[i].data;
break;
+ case MSR_KVM_PV_EOI_EN:
+ env->pv_eoi_en_msr = msrs[i].data;
+ break;
}
}
diff --git a/target-i386/machine.c b/target-i386/machine.c
index a8be058d2d..477150887b 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -279,6 +279,13 @@ static bool async_pf_msr_needed(void *opaque)
return cpu->async_pf_en_msr != 0;
}
+static bool pv_eoi_msr_needed(void *opaque)
+{
+ CPUX86State *cpu = opaque;
+
+ return cpu->pv_eoi_en_msr != 0;
+}
+
static const VMStateDescription vmstate_async_pf_msr = {
.name = "cpu/async_pf_msr",
.version_id = 1,
@@ -290,6 +297,17 @@ static const VMStateDescription vmstate_async_pf_msr = {
}
};
+static const VMStateDescription vmstate_pv_eoi_msr = {
+ .name = "cpu/async_pv_eoi_msr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64(pv_eoi_en_msr, CPUX86State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool fpop_ip_dp_needed(void *opaque)
{
CPUX86State *env = opaque;
@@ -454,6 +472,9 @@ static const VMStateDescription vmstate_cpu = {
.vmsd = &vmstate_async_pf_msr,
.needed = async_pf_msr_needed,
} , {
+ .vmsd = &vmstate_pv_eoi_msr,
+ .needed = pv_eoi_msr_needed,
+ } , {
.vmsd = &vmstate_fpop_ip_dp,
.needed = fpop_ip_dp_needed,
}, {