Merge remote-tracking branch 'qemu-kvm/uq/master' into stable-1.5
* qemu-kvm/uq/master: kvm-stub: fix compilation kvm: shorten the parameter list for get_real_device() kvm: i386: fix LAPIC TSC deadline timer save/restore kvm-all.c: max_cpus should not exceed KVM vcpu limit kvm: Simplify kvm_handle_io kvm: x86: fix setting IA32_FEATURE_CONTROL with nested VMX disabled kvm: add KVM_IRQFD_FLAG_RESAMPLE support kvm: migrate vPMU state target-i386: remove tabs from target-i386/cpu.h Initialize IA32_FEATURE_CONTROL MSR in reset and migration Conflicts: target-i386/cpu.h target-i386/kvm.c aliguori: fixup trivial conflicts due to whitespace and added cpu argument Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
commit
b5d54bd421
@ -568,8 +568,7 @@ static int get_real_device_id(const char *devpath, uint16_t *val)
|
||||
return get_real_id(devpath, "device", val);
|
||||
}
|
||||
|
||||
static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg,
|
||||
uint8_t r_bus, uint8_t r_dev, uint8_t r_func)
|
||||
static int get_real_device(AssignedDevice *pci_dev)
|
||||
{
|
||||
char dir[128], name[128];
|
||||
int fd, r = 0, v;
|
||||
@ -582,7 +581,8 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg,
|
||||
dev->region_number = 0;
|
||||
|
||||
snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%x/",
|
||||
r_seg, r_bus, r_dev, r_func);
|
||||
pci_dev->host.domain, pci_dev->host.bus,
|
||||
pci_dev->host.slot, pci_dev->host.function);
|
||||
|
||||
snprintf(name, sizeof(name), "%sconfig", dir);
|
||||
|
||||
@ -1769,8 +1769,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev)
|
||||
memcpy(dev->emulate_config_write, dev->emulate_config_read,
|
||||
sizeof(dev->emulate_config_read));
|
||||
|
||||
if (get_real_device(dev, dev->host.domain, dev->host.bus,
|
||||
dev->host.slot, dev->host.function)) {
|
||||
if (get_real_device(dev)) {
|
||||
error_report("pci-assign: Error: Couldn't get real device (%s)!",
|
||||
dev->dev.qdev.id);
|
||||
goto out;
|
||||
|
@ -646,7 +646,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
|
||||
vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1;
|
||||
if (vector->virq < 0 ||
|
||||
kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
|
||||
vector->virq) < 0) {
|
||||
NULL, vector->virq) < 0) {
|
||||
if (vector->virq >= 0) {
|
||||
kvm_irqchip_release_virq(kvm_state, vector->virq);
|
||||
vector->virq = -1;
|
||||
@ -814,7 +814,7 @@ retry:
|
||||
vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg);
|
||||
if (vector->virq < 0 ||
|
||||
kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt,
|
||||
vector->virq) < 0) {
|
||||
NULL, vector->virq) < 0) {
|
||||
qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt),
|
||||
vfio_msi_interrupt, NULL, vector);
|
||||
}
|
||||
|
@ -508,7 +508,7 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
|
||||
VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
|
||||
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
|
||||
int ret;
|
||||
ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
|
||||
ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
|
||||
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
|
||||
void kvm_irqchip_release_virq(KVMState *s, int virq);
|
||||
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
EventNotifier *rn, int virq);
|
||||
int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
|
||||
void kvm_pc_gsi_handler(void *opaque, int n, int level);
|
||||
void kvm_pc_setup_irq_routing(bool pci_enabled);
|
||||
|
52
kvm-all.c
52
kvm-all.c
@ -1230,7 +1230,8 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
|
||||
return kvm_update_routing_entry(s, &kroute);
|
||||
}
|
||||
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
|
||||
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq,
|
||||
bool assign)
|
||||
{
|
||||
struct kvm_irqfd irqfd = {
|
||||
.fd = fd,
|
||||
@ -1238,6 +1239,11 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
|
||||
.flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
|
||||
};
|
||||
|
||||
if (rfd != -1) {
|
||||
irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE;
|
||||
irqfd.resamplefd = rfd;
|
||||
}
|
||||
|
||||
if (!kvm_irqfds_enabled()) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
@ -1276,14 +1282,17 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
|
||||
}
|
||||
#endif /* !KVM_CAP_IRQ_ROUTING */
|
||||
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
EventNotifier *rn, int virq)
|
||||
{
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, true);
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n),
|
||||
rn ? event_notifier_get_fd(rn) : -1, virq, true);
|
||||
}
|
||||
|
||||
int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
|
||||
{
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, false);
|
||||
return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq,
|
||||
false);
|
||||
}
|
||||
|
||||
static int kvm_irqchip_create(KVMState *s)
|
||||
@ -1391,6 +1400,13 @@ int kvm_init(void)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (max_cpus > max_vcpus) {
|
||||
ret = -EINVAL;
|
||||
fprintf(stderr, "Number of hotpluggable cpus requested (%d) exceeds max cpus "
|
||||
"supported by KVM (%d)\n", max_cpus, max_vcpus);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0);
|
||||
if (s->vmfd < 0) {
|
||||
#ifdef TARGET_S390X
|
||||
@ -1499,32 +1515,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
|
||||
uint8_t *ptr = data;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (direction == KVM_EXIT_IO_IN) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
stb_p(ptr, cpu_inb(port));
|
||||
break;
|
||||
case 2:
|
||||
stw_p(ptr, cpu_inw(port));
|
||||
break;
|
||||
case 4:
|
||||
stl_p(ptr, cpu_inl(port));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (size) {
|
||||
case 1:
|
||||
cpu_outb(port, ldub_p(ptr));
|
||||
break;
|
||||
case 2:
|
||||
cpu_outw(port, lduw_p(ptr));
|
||||
break;
|
||||
case 4:
|
||||
cpu_outl(port, ldl_p(ptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
address_space_rw(&address_space_io, port, ptr, size,
|
||||
direction == KVM_EXIT_IO_OUT);
|
||||
ptr += size;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,8 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
|
||||
int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
|
||||
EventNotifier *rn, int virq)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@ -37,9 +37,9 @@
|
||||
#define TARGET_HAS_ICE 1
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
#define ELF_MACHINE EM_X86_64
|
||||
#define ELF_MACHINE EM_X86_64
|
||||
#else
|
||||
#define ELF_MACHINE EM_386
|
||||
#define ELF_MACHINE EM_386
|
||||
#endif
|
||||
|
||||
#define CPUArchState struct CPUX86State
|
||||
@ -98,10 +98,10 @@
|
||||
#define DESC_TSS_BUSY_MASK (1 << 9)
|
||||
|
||||
/* eflags masks */
|
||||
#define CC_C 0x0001
|
||||
#define CC_P 0x0004
|
||||
#define CC_A 0x0010
|
||||
#define CC_Z 0x0040
|
||||
#define CC_C 0x0001
|
||||
#define CC_P 0x0004
|
||||
#define CC_A 0x0010
|
||||
#define CC_Z 0x0040
|
||||
#define CC_S 0x0080
|
||||
#define CC_O 0x0800
|
||||
|
||||
@ -109,14 +109,14 @@
|
||||
#define IOPL_SHIFT 12
|
||||
#define VM_SHIFT 17
|
||||
|
||||
#define TF_MASK 0x00000100
|
||||
#define IF_MASK 0x00000200
|
||||
#define DF_MASK 0x00000400
|
||||
#define IOPL_MASK 0x00003000
|
||||
#define NT_MASK 0x00004000
|
||||
#define RF_MASK 0x00010000
|
||||
#define VM_MASK 0x00020000
|
||||
#define AC_MASK 0x00040000
|
||||
#define TF_MASK 0x00000100
|
||||
#define IF_MASK 0x00000200
|
||||
#define DF_MASK 0x00000400
|
||||
#define IOPL_MASK 0x00003000
|
||||
#define NT_MASK 0x00004000
|
||||
#define RF_MASK 0x00010000
|
||||
#define VM_MASK 0x00020000
|
||||
#define AC_MASK 0x00040000
|
||||
#define VIF_MASK 0x00080000
|
||||
#define VIP_MASK 0x00100000
|
||||
#define ID_MASK 0x00200000
|
||||
@ -238,28 +238,28 @@
|
||||
#define DR7_TYPE_IO_RW 0x2
|
||||
#define DR7_TYPE_DATA_RW 0x3
|
||||
|
||||
#define PG_PRESENT_BIT 0
|
||||
#define PG_RW_BIT 1
|
||||
#define PG_USER_BIT 2
|
||||
#define PG_PWT_BIT 3
|
||||
#define PG_PCD_BIT 4
|
||||
#define PG_ACCESSED_BIT 5
|
||||
#define PG_DIRTY_BIT 6
|
||||
#define PG_PSE_BIT 7
|
||||
#define PG_GLOBAL_BIT 8
|
||||
#define PG_NX_BIT 63
|
||||
#define PG_PRESENT_BIT 0
|
||||
#define PG_RW_BIT 1
|
||||
#define PG_USER_BIT 2
|
||||
#define PG_PWT_BIT 3
|
||||
#define PG_PCD_BIT 4
|
||||
#define PG_ACCESSED_BIT 5
|
||||
#define PG_DIRTY_BIT 6
|
||||
#define PG_PSE_BIT 7
|
||||
#define PG_GLOBAL_BIT 8
|
||||
#define PG_NX_BIT 63
|
||||
|
||||
#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
|
||||
#define PG_RW_MASK (1 << PG_RW_BIT)
|
||||
#define PG_USER_MASK (1 << PG_USER_BIT)
|
||||
#define PG_PWT_MASK (1 << PG_PWT_BIT)
|
||||
#define PG_PCD_MASK (1 << PG_PCD_BIT)
|
||||
#define PG_RW_MASK (1 << PG_RW_BIT)
|
||||
#define PG_USER_MASK (1 << PG_USER_BIT)
|
||||
#define PG_PWT_MASK (1 << PG_PWT_BIT)
|
||||
#define PG_PCD_MASK (1 << PG_PCD_BIT)
|
||||
#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
|
||||
#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
|
||||
#define PG_PSE_MASK (1 << PG_PSE_BIT)
|
||||
#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
|
||||
#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
|
||||
#define PG_PSE_MASK (1 << PG_PSE_BIT)
|
||||
#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
|
||||
#define PG_HI_USER_MASK 0x7ff0000000000000LL
|
||||
#define PG_NX_MASK (1LL << PG_NX_BIT)
|
||||
#define PG_NX_MASK (1LL << PG_NX_BIT)
|
||||
|
||||
#define PG_ERROR_W_BIT 1
|
||||
|
||||
@ -269,45 +269,48 @@
|
||||
#define PG_ERROR_RSVD_MASK 0x08
|
||||
#define PG_ERROR_I_D_MASK 0x10
|
||||
|
||||
#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
|
||||
#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
|
||||
#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */
|
||||
#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */
|
||||
|
||||
#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
|
||||
#define MCE_BANKS_DEF 10
|
||||
#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P)
|
||||
#define MCE_BANKS_DEF 10
|
||||
|
||||
#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */
|
||||
#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */
|
||||
#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */
|
||||
#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */
|
||||
#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */
|
||||
#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */
|
||||
|
||||
#define MCI_STATUS_VAL (1ULL<<63) /* valid error */
|
||||
#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */
|
||||
#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */
|
||||
#define MCI_STATUS_EN (1ULL<<60) /* error enabled */
|
||||
#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */
|
||||
#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */
|
||||
#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */
|
||||
#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
|
||||
#define MCI_STATUS_AR (1ULL<<55) /* Action required */
|
||||
#define MCI_STATUS_VAL (1ULL<<63) /* valid error */
|
||||
#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */
|
||||
#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */
|
||||
#define MCI_STATUS_EN (1ULL<<60) /* error enabled */
|
||||
#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */
|
||||
#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */
|
||||
#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */
|
||||
#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */
|
||||
#define MCI_STATUS_AR (1ULL<<55) /* Action required */
|
||||
|
||||
/* MISC register defines */
|
||||
#define MCM_ADDR_SEGOFF 0 /* segment offset */
|
||||
#define MCM_ADDR_LINEAR 1 /* linear address */
|
||||
#define MCM_ADDR_PHYS 2 /* physical address */
|
||||
#define MCM_ADDR_MEM 3 /* memory address */
|
||||
#define MCM_ADDR_GENERIC 7 /* generic */
|
||||
#define MCM_ADDR_SEGOFF 0 /* segment offset */
|
||||
#define MCM_ADDR_LINEAR 1 /* linear address */
|
||||
#define MCM_ADDR_PHYS 2 /* physical address */
|
||||
#define MCM_ADDR_MEM 3 /* memory address */
|
||||
#define MCM_ADDR_GENERIC 7 /* generic */
|
||||
|
||||
#define MSR_IA32_TSC 0x10
|
||||
#define MSR_IA32_APICBASE 0x1b
|
||||
#define MSR_IA32_APICBASE_BSP (1<<8)
|
||||
#define MSR_IA32_APICBASE_ENABLE (1<<11)
|
||||
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
||||
#define MSR_IA32_FEATURE_CONTROL 0x0000003a
|
||||
#define MSR_TSC_ADJUST 0x0000003b
|
||||
#define MSR_IA32_TSCDEADLINE 0x6e0
|
||||
|
||||
#define MSR_MTRRcap 0xfe
|
||||
#define MSR_MTRRcap_VCNT 8
|
||||
#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8)
|
||||
#define MSR_MTRRcap_WC_SUPPORTED (1 << 10)
|
||||
#define MSR_P6_PERFCTR0 0xc1
|
||||
|
||||
#define MSR_MTRRcap 0xfe
|
||||
#define MSR_MTRRcap_VCNT 8
|
||||
#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8)
|
||||
#define MSR_MTRRcap_WC_SUPPORTED (1 << 10)
|
||||
|
||||
#define MSR_IA32_SYSENTER_CS 0x174
|
||||
#define MSR_IA32_SYSENTER_ESP 0x175
|
||||
@ -317,35 +320,45 @@
|
||||
#define MSR_MCG_STATUS 0x17a
|
||||
#define MSR_MCG_CTL 0x17b
|
||||
|
||||
#define MSR_P6_EVNTSEL0 0x186
|
||||
|
||||
#define MSR_IA32_PERF_STATUS 0x198
|
||||
|
||||
#define MSR_IA32_MISC_ENABLE 0x1a0
|
||||
#define MSR_IA32_MISC_ENABLE 0x1a0
|
||||
/* Indicates good rep/movs microcode on some processors: */
|
||||
#define MSR_IA32_MISC_ENABLE_DEFAULT 1
|
||||
|
||||
#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg))
|
||||
#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1)
|
||||
#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg))
|
||||
#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1)
|
||||
|
||||
#define MSR_MTRRfix64K_00000 0x250
|
||||
#define MSR_MTRRfix16K_80000 0x258
|
||||
#define MSR_MTRRfix16K_A0000 0x259
|
||||
#define MSR_MTRRfix4K_C0000 0x268
|
||||
#define MSR_MTRRfix4K_C8000 0x269
|
||||
#define MSR_MTRRfix4K_D0000 0x26a
|
||||
#define MSR_MTRRfix4K_D8000 0x26b
|
||||
#define MSR_MTRRfix4K_E0000 0x26c
|
||||
#define MSR_MTRRfix4K_E8000 0x26d
|
||||
#define MSR_MTRRfix4K_F0000 0x26e
|
||||
#define MSR_MTRRfix4K_F8000 0x26f
|
||||
#define MSR_MTRRfix64K_00000 0x250
|
||||
#define MSR_MTRRfix16K_80000 0x258
|
||||
#define MSR_MTRRfix16K_A0000 0x259
|
||||
#define MSR_MTRRfix4K_C0000 0x268
|
||||
#define MSR_MTRRfix4K_C8000 0x269
|
||||
#define MSR_MTRRfix4K_D0000 0x26a
|
||||
#define MSR_MTRRfix4K_D8000 0x26b
|
||||
#define MSR_MTRRfix4K_E0000 0x26c
|
||||
#define MSR_MTRRfix4K_E8000 0x26d
|
||||
#define MSR_MTRRfix4K_F0000 0x26e
|
||||
#define MSR_MTRRfix4K_F8000 0x26f
|
||||
|
||||
#define MSR_PAT 0x277
|
||||
|
||||
#define MSR_MTRRdefType 0x2ff
|
||||
#define MSR_MTRRdefType 0x2ff
|
||||
|
||||
#define MSR_MC0_CTL 0x400
|
||||
#define MSR_MC0_STATUS 0x401
|
||||
#define MSR_MC0_ADDR 0x402
|
||||
#define MSR_MC0_MISC 0x403
|
||||
#define MSR_CORE_PERF_FIXED_CTR0 0x309
|
||||
#define MSR_CORE_PERF_FIXED_CTR1 0x30a
|
||||
#define MSR_CORE_PERF_FIXED_CTR2 0x30b
|
||||
#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x38d
|
||||
#define MSR_CORE_PERF_GLOBAL_STATUS 0x38e
|
||||
#define MSR_CORE_PERF_GLOBAL_CTRL 0x38f
|
||||
#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x390
|
||||
|
||||
#define MSR_MC0_CTL 0x400
|
||||
#define MSR_MC0_STATUS 0x401
|
||||
#define MSR_MC0_ADDR 0x402
|
||||
#define MSR_MC0_MISC 0x403
|
||||
|
||||
#define MSR_EFER 0xc0000080
|
||||
|
||||
@ -724,6 +737,9 @@ typedef struct {
|
||||
#define CPU_NB_REGS CPU_NB_REGS32
|
||||
#endif
|
||||
|
||||
#define MAX_FIXED_COUNTERS 3
|
||||
#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0)
|
||||
|
||||
#define NB_MMU_MODES 3
|
||||
|
||||
typedef enum TPRAccess {
|
||||
@ -817,6 +833,15 @@ typedef struct CPUX86State {
|
||||
|
||||
uint64_t mcg_status;
|
||||
uint64_t msr_ia32_misc_enable;
|
||||
uint64_t msr_ia32_feature_control;
|
||||
|
||||
uint64_t msr_fixed_ctr_ctrl;
|
||||
uint64_t msr_global_ctrl;
|
||||
uint64_t msr_global_status;
|
||||
uint64_t msr_global_ovf_ctrl;
|
||||
uint64_t msr_fixed_counters[MAX_FIXED_COUNTERS];
|
||||
uint64_t msr_gp_counters[MAX_GP_COUNTERS];
|
||||
uint64_t msr_gp_evtsel[MAX_GP_COUNTERS];
|
||||
|
||||
/* exception/interrupt handling */
|
||||
int error_code;
|
||||
@ -1089,7 +1114,7 @@ static inline CPUX86State *cpu_init(const char *cpu_model)
|
||||
#define cpu_gen_code cpu_x86_gen_code
|
||||
#define cpu_signal_handler cpu_x86_signal_handler
|
||||
#define cpu_list x86_cpu_list
|
||||
#define cpudef_setup x86_cpudef_setup
|
||||
#define cpudef_setup x86_cpudef_setup
|
||||
|
||||
/* MMU modes definitions */
|
||||
#define MMU_MODE0_SUFFIX _kernel
|
||||
|
@ -65,12 +65,16 @@ static bool has_msr_star;
|
||||
static bool has_msr_hsave_pa;
|
||||
static bool has_msr_tsc_adjust;
|
||||
static bool has_msr_tsc_deadline;
|
||||
static bool has_msr_feature_control;
|
||||
static bool has_msr_async_pf_en;
|
||||
static bool has_msr_pv_eoi_en;
|
||||
static bool has_msr_misc_enable;
|
||||
static bool has_msr_kvm_steal_time;
|
||||
static int lm_capable_kernel;
|
||||
|
||||
static bool has_msr_architectural_pmu;
|
||||
static uint32_t num_architectural_pmu_counters;
|
||||
|
||||
bool kvm_allows_irq0_override(void)
|
||||
{
|
||||
return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
|
||||
@ -597,6 +601,25 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (limit >= 0x0a) {
|
||||
uint32_t ver;
|
||||
|
||||
cpu_x86_cpuid(env, 0x0a, 0, &ver, &unused, &unused, &unused);
|
||||
if ((ver & 0xff) > 0) {
|
||||
has_msr_architectural_pmu = true;
|
||||
num_architectural_pmu_counters = (ver & 0xff00) >> 8;
|
||||
|
||||
/* Shouldn't be more than 32, since that's the number of bits
|
||||
* available in EBX to tell us _which_ counters are available.
|
||||
* Play it safe.
|
||||
*/
|
||||
if (num_architectural_pmu_counters > MAX_GP_COUNTERS) {
|
||||
num_architectural_pmu_counters = MAX_GP_COUNTERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
|
||||
|
||||
for (i = 0x80000000; i <= limit; i++) {
|
||||
@ -660,6 +683,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
|
||||
qemu_add_vm_change_state_handler(cpu_update_state, env);
|
||||
|
||||
c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0);
|
||||
if (c) {
|
||||
has_msr_feature_control = !!(c->ecx & CPUID_EXT_VMX) ||
|
||||
!!(c->ecx & CPUID_EXT_SMX);
|
||||
}
|
||||
|
||||
cpuid_data.cpuid.padding = 0;
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
|
||||
if (r) {
|
||||
@ -1060,6 +1089,26 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
|
||||
entry->data = value;
|
||||
}
|
||||
|
||||
static int kvm_put_tscdeadline_msr(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct {
|
||||
struct kvm_msrs info;
|
||||
struct kvm_msr_entry entries[1];
|
||||
} msr_data;
|
||||
struct kvm_msr_entry *msrs = msr_data.entries;
|
||||
|
||||
if (!has_msr_tsc_deadline) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
kvm_msr_entry_set(&msrs[0], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
|
||||
|
||||
msr_data.info.nmsrs = 1;
|
||||
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data);
|
||||
}
|
||||
|
||||
static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
@ -1068,7 +1117,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
struct kvm_msr_entry entries[100];
|
||||
} msr_data;
|
||||
struct kvm_msr_entry *msrs = msr_data.entries;
|
||||
int n = 0;
|
||||
int n = 0, i;
|
||||
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
|
||||
@ -1083,9 +1132,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (has_msr_tsc_adjust) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust);
|
||||
}
|
||||
if (has_msr_tsc_deadline) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline);
|
||||
}
|
||||
if (has_msr_misc_enable) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_MISC_ENABLE,
|
||||
env->msr_ia32_misc_enable);
|
||||
@ -1110,9 +1156,8 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The following paravirtual MSRs have side effects on the guest or are
|
||||
* too heavy for normal writeback. Limit them to reset or full state
|
||||
* updates.
|
||||
* The following MSRs have side effects on the guest or are too heavy
|
||||
* for normal writeback. Limit them to reset or full state updates.
|
||||
*/
|
||||
if (level >= KVM_PUT_RESET_STATE) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
|
||||
@ -1130,6 +1175,33 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME,
|
||||
env->steal_time_msr);
|
||||
}
|
||||
if (has_msr_architectural_pmu) {
|
||||
/* Stop the counter. */
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, 0);
|
||||
|
||||
/* Set the counter values. */
|
||||
for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR0 + i,
|
||||
env->msr_fixed_counters[i]);
|
||||
}
|
||||
for (i = 0; i < num_architectural_pmu_counters; i++) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_P6_PERFCTR0 + i,
|
||||
env->msr_gp_counters[i]);
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_P6_EVNTSEL0 + i,
|
||||
env->msr_gp_evtsel[i]);
|
||||
}
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_STATUS,
|
||||
env->msr_global_status);
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_OVF_CTRL,
|
||||
env->msr_global_ovf_ctrl);
|
||||
|
||||
/* Now start the PMU. */
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL,
|
||||
env->msr_fixed_ctr_ctrl);
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL,
|
||||
env->msr_global_ctrl);
|
||||
}
|
||||
if (hyperv_hypercall_available(cpu)) {
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
|
||||
@ -1137,6 +1209,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (cpu->hyperv_vapic) {
|
||||
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
|
||||
}
|
||||
if (has_msr_feature_control) {
|
||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_FEATURE_CONTROL,
|
||||
env->msr_ia32_feature_control);
|
||||
}
|
||||
}
|
||||
if (env->mcg_cap) {
|
||||
int i;
|
||||
@ -1361,6 +1437,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_misc_enable) {
|
||||
msrs[n++].index = MSR_IA32_MISC_ENABLE;
|
||||
}
|
||||
if (has_msr_feature_control) {
|
||||
msrs[n++].index = MSR_IA32_FEATURE_CONTROL;
|
||||
}
|
||||
|
||||
if (!env->tsc_valid) {
|
||||
msrs[n++].index = MSR_IA32_TSC;
|
||||
@ -1386,6 +1465,19 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_kvm_steal_time) {
|
||||
msrs[n++].index = MSR_KVM_STEAL_TIME;
|
||||
}
|
||||
if (has_msr_architectural_pmu) {
|
||||
msrs[n++].index = MSR_CORE_PERF_FIXED_CTR_CTRL;
|
||||
msrs[n++].index = MSR_CORE_PERF_GLOBAL_CTRL;
|
||||
msrs[n++].index = MSR_CORE_PERF_GLOBAL_STATUS;
|
||||
msrs[n++].index = MSR_CORE_PERF_GLOBAL_OVF_CTRL;
|
||||
for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
|
||||
msrs[n++].index = MSR_CORE_PERF_FIXED_CTR0 + i;
|
||||
}
|
||||
for (i = 0; i < num_architectural_pmu_counters; i++) {
|
||||
msrs[n++].index = MSR_P6_PERFCTR0 + i;
|
||||
msrs[n++].index = MSR_P6_EVNTSEL0 + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (env->mcg_cap) {
|
||||
msrs[n++].index = MSR_MCG_STATUS;
|
||||
@ -1402,7 +1494,8 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
}
|
||||
|
||||
for (i = 0; i < ret; i++) {
|
||||
switch (msrs[i].index) {
|
||||
uint32_t index = msrs[i].index;
|
||||
switch (index) {
|
||||
case MSR_IA32_SYSENTER_CS:
|
||||
env->sysenter_cs = msrs[i].data;
|
||||
break;
|
||||
@ -1459,6 +1552,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case MSR_IA32_MISC_ENABLE:
|
||||
env->msr_ia32_misc_enable = msrs[i].data;
|
||||
break;
|
||||
case MSR_IA32_FEATURE_CONTROL:
|
||||
env->msr_ia32_feature_control = msrs[i].data;
|
||||
break;
|
||||
default:
|
||||
if (msrs[i].index >= MSR_MC0_CTL &&
|
||||
msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) {
|
||||
@ -1474,6 +1570,27 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case MSR_KVM_STEAL_TIME:
|
||||
env->steal_time_msr = msrs[i].data;
|
||||
break;
|
||||
case MSR_CORE_PERF_FIXED_CTR_CTRL:
|
||||
env->msr_fixed_ctr_ctrl = msrs[i].data;
|
||||
break;
|
||||
case MSR_CORE_PERF_GLOBAL_CTRL:
|
||||
env->msr_global_ctrl = msrs[i].data;
|
||||
break;
|
||||
case MSR_CORE_PERF_GLOBAL_STATUS:
|
||||
env->msr_global_status = msrs[i].data;
|
||||
break;
|
||||
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
|
||||
env->msr_global_ovf_ctrl = msrs[i].data;
|
||||
break;
|
||||
case MSR_CORE_PERF_FIXED_CTR0 ... MSR_CORE_PERF_FIXED_CTR0 + MAX_FIXED_COUNTERS - 1:
|
||||
env->msr_fixed_counters[index - MSR_CORE_PERF_FIXED_CTR0] = msrs[i].data;
|
||||
break;
|
||||
case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR0 + MAX_GP_COUNTERS - 1:
|
||||
env->msr_gp_counters[index - MSR_P6_PERFCTR0] = msrs[i].data;
|
||||
break;
|
||||
case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL0 + MAX_GP_COUNTERS - 1:
|
||||
env->msr_gp_evtsel[index - MSR_P6_EVNTSEL0] = msrs[i].data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1724,6 +1841,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = kvm_put_tscdeadline_msr(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = kvm_put_vcpu_events(x86_cpu, level);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -435,6 +435,14 @@ static bool misc_enable_needed(void *opaque)
|
||||
return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT;
|
||||
}
|
||||
|
||||
static bool feature_control_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
return env->msr_ia32_feature_control != 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_msr_ia32_misc_enable = {
|
||||
.name = "cpu/msr_ia32_misc_enable",
|
||||
.version_id = 1,
|
||||
@ -446,6 +454,58 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = {
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_msr_ia32_feature_control = {
|
||||
.name = "cpu/msr_ia32_feature_control",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool pmu_enable_needed(void *opaque)
|
||||
{
|
||||
X86CPU *cpu = opaque;
|
||||
CPUX86State *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
if (env->msr_fixed_ctr_ctrl || env->msr_global_ctrl ||
|
||||
env->msr_global_status || env->msr_global_ovf_ctrl) {
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
|
||||
if (env->msr_fixed_counters[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_GP_COUNTERS; i++) {
|
||||
if (env->msr_gp_counters[i] || env->msr_gp_evtsel[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_msr_architectural_pmu = {
|
||||
.name = "cpu/msr_architectural_pmu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.minimum_version_id_old = 1,
|
||||
.fields = (VMStateField []) {
|
||||
VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_global_ctrl, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_global_status, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_global_ovf_ctrl, X86CPU),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_fixed_counters, X86CPU, MAX_FIXED_COUNTERS),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_gp_counters, X86CPU, MAX_GP_COUNTERS),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_gp_evtsel, X86CPU, MAX_GP_COUNTERS),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
const VMStateDescription vmstate_x86_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 12,
|
||||
@ -571,6 +631,12 @@ const VMStateDescription vmstate_x86_cpu = {
|
||||
}, {
|
||||
.vmsd = &vmstate_msr_ia32_misc_enable,
|
||||
.needed = misc_enable_needed,
|
||||
}, {
|
||||
.vmsd = &vmstate_msr_ia32_feature_control,
|
||||
.needed = feature_control_needed,
|
||||
}, {
|
||||
.vmsd = &vmstate_msr_architectural_pmu,
|
||||
.needed = pmu_enable_needed,
|
||||
} , {
|
||||
/* empty */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user