* [PATCH 0/4] Extensible VCPU state IOCTL
@ 2009-10-13 16:06 Jan Kiszka
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
` (5 more replies)
0 siblings, 6 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:06 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
As you may have noticed, we are constantly adding IOCTLs as yet another
state field has to be exchanged between kernel and user space. I was
about to add one for the missing hidden NMI states (pending and masked),
but Avi suggested to take this chance, inventing a more easily
extensible interface.
And here comes my suggestion for VCPU states. Please see patch 2 for
details on this approach, patch 4 demonstrates how extensions may look
like in the future.
I will follow up with a patch against qemu upstream to convert
kvm_arch_get/put_registers to the new interface, ie. query/set all
substates via one IOCTL when available. I did not convert qemu-kvm, only
added support for the NMI substate, as the corresponding code will
likely by modified to use the upstream implementation anyway.
Comments welcome, also suggestion for further substates to be added in
this round.
Jan
Find this series also at git://git.kiszka.org/linux-kvm.git queues/vcpu-state
Jan Kiszka (4):
KVM: Reorder IOCTLs in main kvm.h
KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
KVM: x86: Add support for KVM_GET/SET_VCPU_STATE
KVM: x86: Add VCPU substate for NMI states
arch/ia64/kvm/kvm-ia64.c | 12 ++
arch/powerpc/kvm/powerpc.c | 12 ++
arch/s390/kvm/kvm-s390.c | 12 ++
arch/x86/include/asm/kvm.h | 15 ++-
arch/x86/include/asm/kvm_host.h | 2 +
arch/x86/kvm/svm.c | 22 +++
arch/x86/kvm/vmx.c | 30 ++++
arch/x86/kvm/x86.c | 243 ++++++++++++++++++++---------
include/linux/kvm.h | 246 +++++++++++++++++--------------
include/linux/kvm_host.h | 5 +
virt/kvm/kvm_main.c | 318 +++++++++++++++++++++++++++-----------
11 files changed, 637 insertions(+), 280 deletions(-)
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 3/4] KVM: x86: Add support for KVM_GET/SET_VCPU_STATE
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
` (2 preceding siblings ...)
2009-10-13 16:06 ` [PATCH 1/4] KVM: Reorder IOCTLs in main kvm.h Jan Kiszka
@ 2009-10-13 16:06 ` Jan Kiszka
2009-10-13 16:18 ` [RFC][PATCH] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
2009-10-14 8:52 ` [PATCH] qemu-kvm: x86: Add support for NMI states Jan Kiszka
5 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:06 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
Add support for getting/setting MSRs, CPUID tree, and the LACPIC via the
new VCPU state interface. Also in this case we convert the existing
IOCTLs to use the new infrastructure internally.
The MSR interface has to be extended to pass back the number of
processed MSRs via the header structure instead of the return code as
the latter is not available with the new IOCTL. The semantic of the
original KVM_GET/SET_MSRS is not affected by this change.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
arch/x86/include/asm/kvm.h | 8 +-
arch/x86/kvm/x86.c | 209 ++++++++++++++++++++++++++++----------------
2 files changed, 138 insertions(+), 79 deletions(-)
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index f02e87a..1b184c3 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -150,7 +150,7 @@ struct kvm_msr_entry {
/* for KVM_GET_MSRS and KVM_SET_MSRS */
struct kvm_msrs {
__u32 nmsrs; /* number of msrs in entries */
- __u32 pad;
+ __u32 nprocessed; /* return value: successfully processed entries */
struct kvm_msr_entry entries[0];
};
@@ -251,4 +251,10 @@ struct kvm_reinject_control {
__u8 pit_reinject;
__u8 reserved[31];
};
+
+/* for KVM_GET/SET_VCPU_STATE */
+#define KVM_X86_VCPU_MSRS 1000
+#define KVM_X86_VCPU_CPUID 1001
+#define KVM_X86_VCPU_LAPIC 1002
+
#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 839b1c5..733e2d3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1179,11 +1179,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
int (*do_msr)(struct kvm_vcpu *vcpu,
unsigned index, u64 *data),
- int writeback)
+ int writeback, int write_nprocessed)
{
struct kvm_msrs msrs;
struct kvm_msr_entry *entries;
- int r, n;
+ int r;
unsigned size;
r = -EFAULT;
@@ -1204,15 +1204,22 @@ static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
if (copy_from_user(entries, user_msrs->entries, size))
goto out_free;
- r = n = __msr_io(vcpu, &msrs, entries, do_msr);
+ r = __msr_io(vcpu, &msrs, entries, do_msr);
if (r < 0)
goto out_free;
+ msrs.nprocessed = r;
+
r = -EFAULT;
+ if (write_nprocessed &&
+ copy_to_user(&user_msrs->nprocessed, &msrs.nprocessed,
+ sizeof(msrs.nprocessed)))
+ goto out_free;
+
if (writeback && copy_to_user(user_msrs->entries, entries, size))
goto out_free;
- r = n;
+ r = msrs.nprocessed;
out_free:
vfree(entries);
@@ -1785,55 +1792,36 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
+ struct kvm_vcpu_substate substate;
int r;
- struct kvm_lapic_state *lapic = NULL;
switch (ioctl) {
- case KVM_GET_LAPIC: {
- lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
-
- r = -ENOMEM;
- if (!lapic)
- goto out;
- r = kvm_vcpu_ioctl_get_lapic(vcpu, lapic);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(argp, lapic, sizeof(struct kvm_lapic_state)))
- goto out;
- r = 0;
+ case KVM_GET_LAPIC:
+ substate.type = KVM_X86_VCPU_LAPIC;
+ substate.offset = 0;
+ r = kvm_arch_vcpu_get_substate(vcpu, argp, &substate);
break;
- }
- case KVM_SET_LAPIC: {
- lapic = kmalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
- r = -ENOMEM;
- if (!lapic)
- goto out;
- r = -EFAULT;
- if (copy_from_user(lapic, argp, sizeof(struct kvm_lapic_state)))
- goto out;
- r = kvm_vcpu_ioctl_set_lapic(vcpu, lapic);
- if (r)
- goto out;
- r = 0;
+ case KVM_SET_LAPIC:
+ substate.type = KVM_X86_VCPU_LAPIC;
+ substate.offset = 0;
+ r = kvm_arch_vcpu_set_substate(vcpu, argp, &substate);
break;
- }
case KVM_INTERRUPT: {
struct kvm_interrupt irq;
r = -EFAULT;
if (copy_from_user(&irq, argp, sizeof irq))
- goto out;
+ break;
r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
if (r)
- goto out;
+ break;
r = 0;
break;
}
case KVM_NMI: {
r = kvm_vcpu_ioctl_nmi(vcpu);
if (r)
- goto out;
+ break;
r = 0;
break;
}
@@ -1843,60 +1831,40 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EFAULT;
if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
+ break;
r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
if (r)
- goto out;
+ break;
break;
}
- case KVM_SET_CPUID2: {
- struct kvm_cpuid2 __user *cpuid_arg = argp;
- struct kvm_cpuid2 cpuid;
-
- r = -EFAULT;
- if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
- r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
- cpuid_arg->entries);
- if (r)
- goto out;
+ case KVM_GET_CPUID2:
+ substate.type = KVM_X86_VCPU_CPUID;
+ substate.offset = 0;
+ r = kvm_arch_vcpu_get_substate(vcpu, argp, &substate);
break;
- }
- case KVM_GET_CPUID2: {
- struct kvm_cpuid2 __user *cpuid_arg = argp;
- struct kvm_cpuid2 cpuid;
-
- r = -EFAULT;
- if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
- r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid,
- cpuid_arg->entries);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(cpuid_arg, &cpuid, sizeof cpuid))
- goto out;
- r = 0;
+ case KVM_SET_CPUID2:
+ substate.type = KVM_X86_VCPU_CPUID;
+ substate.offset = 0;
+ r = kvm_arch_vcpu_set_substate(vcpu, argp, &substate);
break;
- }
case KVM_GET_MSRS:
- r = msr_io(vcpu, argp, kvm_get_msr, 1);
+ r = msr_io(vcpu, argp, kvm_get_msr, 1, 0);
break;
case KVM_SET_MSRS:
- r = msr_io(vcpu, argp, do_set_msr, 0);
+ r = msr_io(vcpu, argp, do_set_msr, 0, 0);
break;
case KVM_TPR_ACCESS_REPORTING: {
struct kvm_tpr_access_ctl tac;
r = -EFAULT;
if (copy_from_user(&tac, argp, sizeof tac))
- goto out;
+ break;
r = vcpu_ioctl_tpr_access_reporting(vcpu, &tac);
if (r)
- goto out;
+ break;
r = -EFAULT;
if (copy_to_user(argp, &tac, sizeof tac))
- goto out;
+ break;
r = 0;
break;
};
@@ -1905,10 +1873,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EINVAL;
if (!irqchip_in_kernel(vcpu->kvm))
- goto out;
+ break;
r = -EFAULT;
if (copy_from_user(&va, argp, sizeof va))
- goto out;
+ break;
r = 0;
kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
break;
@@ -1918,7 +1886,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EFAULT;
if (copy_from_user(&mcg_cap, argp, sizeof mcg_cap))
- goto out;
+ break;
r = kvm_vcpu_ioctl_x86_setup_mce(vcpu, mcg_cap);
break;
}
@@ -1927,15 +1895,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EFAULT;
if (copy_from_user(&mce, argp, sizeof mce))
- goto out;
+ break;
r = kvm_vcpu_ioctl_x86_set_mce(vcpu, &mce);
break;
}
default:
r = -EINVAL;
}
-out:
- kfree(lapic);
return r;
}
@@ -4665,13 +4631,100 @@ EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
struct kvm_vcpu_substate *substate)
{
- return -EINVAL;
+ void __user *argp = (void __user *)arg_base + substate->offset;
+ int r;
+
+ switch (substate->type) {
+ case KVM_X86_VCPU_MSRS:
+ r = msr_io(vcpu, argp, kvm_get_msr, 1, 1);
+ break;
+ case KVM_X86_VCPU_CPUID: {
+ struct kvm_cpuid2 __user *cpuid_arg = argp;
+ struct kvm_cpuid2 cpuid;
+
+ r = -EFAULT;
+ if (copy_from_user(&cpuid, cpuid_arg,
+ sizeof(struct kvm_cpuid2)))
+ break;
+ r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid,
+ cpuid_arg->entries);
+ if (r)
+ break;
+ r = -EFAULT;
+ if (copy_to_user(cpuid_arg, &cpuid, sizeof(struct kvm_cpuid2)))
+ break;
+ r = 0;
+ break;
+ }
+ case KVM_X86_VCPU_LAPIC: {
+ struct kvm_lapic_state *lapic;
+
+ lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
+ r = -ENOMEM;
+ if (!lapic)
+ break;
+ r = kvm_vcpu_ioctl_get_lapic(vcpu, lapic);
+ if (r)
+ goto out_free_lapic;
+ r = -EFAULT;
+ if (copy_to_user(argp, lapic, sizeof(struct kvm_lapic_state)))
+ goto out_free_lapic;
+ r = 0;
+out_free_lapic:
+ kfree(lapic);
+ break;
+ }
+ default:
+ r = -EINVAL;
+ }
+ return r;
}
int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
struct kvm_vcpu_substate *substate)
{
- return -EINVAL;
+ void __user *argp = (void __user *)arg_base + substate->offset;
+ int r;
+
+ switch (substate->type) {
+ case KVM_X86_VCPU_MSRS:
+ r = msr_io(vcpu, argp, do_set_msr, 0, 1);
+ break;
+ case KVM_X86_VCPU_CPUID: {
+ struct kvm_cpuid2 __user *cpuid_arg = argp;
+ struct kvm_cpuid2 cpuid;
+
+ r = -EFAULT;
+ if (copy_from_user(&cpuid, cpuid_arg,
+ sizeof(struct kvm_cpuid2)))
+ break;
+ r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
+ cpuid_arg->entries);
+ break;
+ }
+ case KVM_X86_VCPU_LAPIC: {
+ struct kvm_lapic_state *lapic;
+
+ lapic = kmalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
+ r = -ENOMEM;
+ if (!lapic)
+ break;
+ r = -EFAULT;
+ if (copy_from_user(lapic, argp,
+ sizeof(struct kvm_lapic_state)))
+ goto out_free_lapic;
+ r = kvm_vcpu_ioctl_set_lapic(vcpu, lapic);
+ if (r)
+ goto out_free_lapic;
+ r = 0;
+out_free_lapic:
+ kfree(lapic);
+ break;
+ }
+ default:
+ r = -EINVAL;
+ }
+ return r;
}
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
@ 2009-10-13 16:06 ` Jan Kiszka
2009-10-15 8:09 ` Avi Kivity
2009-10-13 16:06 ` [PATCH 1/4] KVM: Reorder IOCTLs in main kvm.h Jan Kiszka
` (3 subsequent siblings)
5 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:06 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
This plugs an NMI-related hole in the VCPU synchronization between
kernel and user space. So far, neither pending NMIs nor the inhibit NMI
mask was properly read/set which was able to cause problems on
vmsave/restore, live migration and system reset. Fix it by making use
of the new VCPU substate interface.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
arch/x86/include/asm/kvm.h | 7 +++++++
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/svm.c | 22 ++++++++++++++++++++++
arch/x86/kvm/vmx.c | 30 ++++++++++++++++++++++++++++++
arch/x86/kvm/x86.c | 26 ++++++++++++++++++++++++++
5 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index 1b184c3..fd5713a 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -256,5 +256,12 @@ struct kvm_reinject_control {
#define KVM_X86_VCPU_MSRS 1000
#define KVM_X86_VCPU_CPUID 1001
#define KVM_X86_VCPU_LAPIC 1002
+#define KVM_X86_VCPU_NMI 1003
+
+struct kvm_nmi_state {
+ __u8 pending;
+ __u8 masked;
+ __u8 pad1[2];
+};
#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 179a919..d22a0cd 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -513,6 +513,8 @@ struct kvm_x86_ops {
unsigned char *hypercall_addr);
void (*set_irq)(struct kvm_vcpu *vcpu);
void (*set_nmi)(struct kvm_vcpu *vcpu);
+ int (*get_nmi_mask)(struct kvm_vcpu *vcpu);
+ void (*set_nmi_mask)(struct kvm_vcpu *vcpu, int masked);
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 279a2ae..67ff5f1 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2456,6 +2456,26 @@ static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
!(svm->vcpu.arch.hflags & HF_NMI_MASK);
}
+static int svm_get_nmi_mask(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ return !!(svm->vcpu.arch.hflags & HF_NMI_MASK);
+}
+
+static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, int masked)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ if (masked) {
+ svm->vcpu.arch.hflags |= HF_NMI_MASK;
+ svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+ } else {
+ svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
+ svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+ }
+}
+
static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -2897,6 +2917,8 @@ static struct kvm_x86_ops svm_x86_ops = {
.queue_exception = svm_queue_exception,
.interrupt_allowed = svm_interrupt_allowed,
.nmi_allowed = svm_nmi_allowed,
+ .get_nmi_mask = svm_get_nmi_mask,
+ .set_nmi_mask = svm_set_nmi_mask,
.enable_nmi_window = enable_nmi_window,
.enable_irq_window = enable_irq_window,
.update_cr8_intercept = update_cr8_intercept,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 70020e5..5dd766b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2619,6 +2619,34 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
GUEST_INTR_STATE_NMI));
}
+static int vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
+{
+ if (!cpu_has_virtual_nmis())
+ return to_vmx(vcpu)->soft_vnmi_blocked;
+ else
+ return !!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ GUEST_INTR_STATE_NMI);
+}
+
+static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, int masked)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!cpu_has_virtual_nmis()) {
+ if (vmx->soft_vnmi_blocked != masked) {
+ vmx->soft_vnmi_blocked = masked;
+ vmx->vnmi_blocked_time = 0;
+ }
+ } else {
+ if (masked)
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ else
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ }
+}
+
static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
{
return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
@@ -3957,6 +3985,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.queue_exception = vmx_queue_exception,
.interrupt_allowed = vmx_interrupt_allowed,
.nmi_allowed = vmx_nmi_allowed,
+ .get_nmi_mask = vmx_get_nmi_mask,
+ .set_nmi_mask = vmx_set_nmi_mask,
.enable_nmi_window = enable_nmi_window,
.enable_irq_window = enable_irq_window,
.update_cr8_intercept = update_cr8_intercept,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 733e2d3..a06fd4d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4674,6 +4674,19 @@ out_free_lapic:
kfree(lapic);
break;
}
+ case KVM_X86_VCPU_NMI: {
+ struct kvm_nmi_state nmi;
+
+ vcpu_load(vcpu);
+ nmi.pending = vcpu->arch.nmi_pending;
+ nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu);
+ vcpu_put(vcpu);
+ r = -EFAULT;
+ if (copy_to_user(argp, &nmi, sizeof(struct kvm_nmi_state)))
+ break;
+ r = 0;
+ break;
+ }
default:
r = -EINVAL;
}
@@ -4721,6 +4734,19 @@ out_free_lapic:
kfree(lapic);
break;
}
+ case KVM_X86_VCPU_NMI: {
+ struct kvm_nmi_state nmi;
+
+ r = -EFAULT;
+ if (copy_from_user(&nmi, argp, sizeof(struct kvm_nmi_state)))
+ break;
+ vcpu_load(vcpu);
+ vcpu->arch.nmi_pending = nmi.pending;
+ kvm_x86_ops->set_nmi_mask(vcpu, nmi.masked);
+ vcpu_put(vcpu);
+ r = 0;
+ break;
+ }
default:
r = -EINVAL;
}
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
@ 2009-10-13 16:06 ` Jan Kiszka
2009-10-15 8:00 ` Avi Kivity
` (2 more replies)
2009-10-13 16:06 ` [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states Jan Kiszka
` (4 subsequent siblings)
5 siblings, 3 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:06 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
More precisely, the IOCTL is able to process a list of substates to be
read or written. This list is easily extensible without breaking the
existing ABI, thus we will no longer have to add new IOCTLs when we
discover a missing VCPU state field or want to support new hardware
features.
This patch establishes the generic infrastructure for KVM_GET/
SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
FPU, and MP. To avoid code duplication, the entry point for the
corresponding original IOCTLs are converted to make use of the new
infrastructure internally, too.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
arch/ia64/kvm/kvm-ia64.c | 12 ++
arch/powerpc/kvm/powerpc.c | 12 ++
arch/s390/kvm/kvm-s390.c | 12 ++
arch/x86/kvm/x86.c | 12 ++
include/linux/kvm.h | 24 +++
include/linux/kvm_host.h | 5 +
virt/kvm/kvm_main.c | 318 +++++++++++++++++++++++++++++++-------------
7 files changed, 303 insertions(+), 92 deletions(-)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 5fdeec5..c3450a6 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1991,3 +1991,15 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
vcpu_put(vcpu);
return r;
}
+
+int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 5902bbc..3336ad5 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -436,3 +436,15 @@ int kvm_arch_init(void *opaque)
void kvm_arch_exit(void)
{
}
+
+int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 5445058..978ed6c 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -450,6 +450,18 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
return -EINVAL; /* not implemented yet */
}
+int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
static void __vcpu_run(struct kvm_vcpu *vcpu)
{
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 11a6f2f..839b1c5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4662,6 +4662,18 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
+int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ return -EINVAL;
+}
+
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
if (vcpu->arch.time_page) {
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 7d8c382..da81b89 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -393,6 +393,26 @@ struct kvm_ioeventfd {
__u8 pad[36];
};
+/* for KVM_GET_VCPU_STATE and KVM_SET_VCPU_STATE */
+#define KVM_VCPU_REGS 0
+#define KVM_VCPU_SREGS 1
+#define KVM_VCPU_FPU 2
+#define KVM_VCPU_MP 3
+
+struct kvm_vcpu_substate {
+ __u32 type;
+ __u32 pad;
+ __s64 offset;
+};
+
+#define KVM_MAX_VCPU_SUBSTATES 64
+
+struct kvm_vcpu_state {
+ __u32 nsubstates; /* number of elements in substates */
+ __u32 nprocessed; /* return value: successfully processed substates */
+ struct kvm_vcpu_substate substates[0];
+};
+
#define KVMIO 0xAE
/*
@@ -480,6 +500,7 @@ struct kvm_ioeventfd {
#endif
#define KVM_CAP_IOEVENTFD 36
#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
+#define KVM_CAP_VCPU_STATE 38
#ifdef KVM_CAP_IRQ_ROUTING
@@ -642,6 +663,9 @@ struct kvm_irqfd {
/* IA64 stack access */
#define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *)
#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *)
+/* Available with KVM_CAP_VCPU_STATE */
+#define KVM_GET_VCPU_STATE _IOR(KVMIO, 0x9f, struct kvm_vcpu_state)
+#define KVM_SET_VCPU_STATE _IOW(KVMIO, 0xa0, struct kvm_vcpu_state)
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b985a29..169e234 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -331,6 +331,11 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
struct kvm_guest_debug *dbg);
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
+int kvm_arch_vcpu_get_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate);
+int kvm_arch_vcpu_set_substate(struct kvm_vcpu *vcpu, uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate);
+
int kvm_arch_init(void *opaque);
void kvm_arch_exit(void);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c0a929f..2e8152e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1231,124 +1231,224 @@ static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
return 0;
}
-static long kvm_vcpu_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+static int kvm_vcpu_get_substate(struct kvm_vcpu *vcpu,
+ uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
{
- struct kvm_vcpu *vcpu = filp->private_data;
- void __user *argp = (void __user *)arg;
+ void __user *argp = (void __user *)arg_base + substate->offset;
int r;
- struct kvm_fpu *fpu = NULL;
- struct kvm_sregs *kvm_sregs = NULL;
- if (vcpu->kvm->mm != current->mm)
- return -EIO;
- switch (ioctl) {
- case KVM_RUN:
- r = -EINVAL;
- if (arg)
- goto out;
- r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);
- break;
- case KVM_GET_REGS: {
+ switch (substate->type) {
+ case KVM_VCPU_REGS: {
struct kvm_regs *kvm_regs;
- r = -ENOMEM;
kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
+ r = -ENOMEM;
if (!kvm_regs)
- goto out;
+ break;
r = kvm_arch_vcpu_ioctl_get_regs(vcpu, kvm_regs);
if (r)
- goto out_free1;
+ goto out_free_regs;
r = -EFAULT;
if (copy_to_user(argp, kvm_regs, sizeof(struct kvm_regs)))
- goto out_free1;
+ goto out_free_regs;
r = 0;
-out_free1:
+out_free_regs:
kfree(kvm_regs);
break;
}
- case KVM_SET_REGS: {
- struct kvm_regs *kvm_regs;
+ case KVM_VCPU_SREGS: {
+ struct kvm_sregs *kvm_sregs;
+ kvm_sregs = kzalloc(sizeof(struct kvm_sregs), GFP_KERNEL);
r = -ENOMEM;
- kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
- if (!kvm_regs)
- goto out;
- r = -EFAULT;
- if (copy_from_user(kvm_regs, argp, sizeof(struct kvm_regs)))
- goto out_free2;
- r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
+ if (!kvm_sregs)
+ break;
+ r = kvm_arch_vcpu_ioctl_get_sregs(vcpu, kvm_sregs);
if (r)
- goto out_free2;
+ goto out_free_sregs;
+ r = -EFAULT;
+ if (copy_to_user(argp, kvm_sregs, sizeof(struct kvm_sregs)))
+ goto out_free_sregs;
r = 0;
-out_free2:
- kfree(kvm_regs);
+out_free_sregs:
+ kfree(kvm_sregs);
break;
}
- case KVM_GET_SREGS: {
- kvm_sregs = kzalloc(sizeof(struct kvm_sregs), GFP_KERNEL);
+ case KVM_VCPU_FPU: {
+ struct kvm_fpu *kvm_fpu;
+
+ kvm_fpu = kzalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
r = -ENOMEM;
- if (!kvm_sregs)
- goto out;
- r = kvm_arch_vcpu_ioctl_get_sregs(vcpu, kvm_sregs);
+ if (!kvm_fpu)
+ break;
+ r = kvm_arch_vcpu_ioctl_get_fpu(vcpu, kvm_fpu);
if (r)
- goto out;
+ break;
r = -EFAULT;
- if (copy_to_user(argp, kvm_sregs, sizeof(struct kvm_sregs)))
- goto out;
+ if (copy_to_user(argp, kvm_fpu, sizeof(struct kvm_fpu)))
+ goto out_free_fpu;
+ r = 0;
+out_free_fpu:
+ kfree(kvm_fpu);
+ break;
+ }
+ case KVM_VCPU_MP: {
+ struct kvm_mp_state mp_state;
+
+ r = kvm_arch_vcpu_ioctl_get_mpstate(vcpu, &mp_state);
+ if (r)
+ break;
+ r = -EFAULT;
+ if (copy_to_user(argp, &mp_state, sizeof(struct kvm_mp_state)))
+ break;
+ r = 0;
+ break;
+ }
+ default:
+ r = kvm_arch_vcpu_get_substate(vcpu, arg_base, substate);
+ }
+ return r;
+}
+
+static int kvm_vcpu_set_substate(struct kvm_vcpu *vcpu,
+ uint8_t __user *arg_base,
+ struct kvm_vcpu_substate *substate)
+{
+ void __user *argp = (void __user *)arg_base + substate->offset;
+ int r;
+
+ switch (substate->type) {
+ case KVM_VCPU_REGS: {
+ struct kvm_regs *kvm_regs;
+
+ kvm_regs = kzalloc(sizeof(struct kvm_regs), GFP_KERNEL);
+ r = -ENOMEM;
+ if (!kvm_regs)
+ break;
+ r = -EFAULT;
+ if (copy_from_user(kvm_regs, argp, sizeof(struct kvm_regs)))
+ goto out_free_regs;
+ r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
+ if (r)
+ goto out_free_regs;
r = 0;
+out_free_regs:
+ kfree(kvm_regs);
break;
}
- case KVM_SET_SREGS: {
+ case KVM_VCPU_SREGS: {
+ struct kvm_sregs *kvm_sregs;
+
kvm_sregs = kmalloc(sizeof(struct kvm_sregs), GFP_KERNEL);
r = -ENOMEM;
if (!kvm_sregs)
- goto out;
+ break;
r = -EFAULT;
if (copy_from_user(kvm_sregs, argp, sizeof(struct kvm_sregs)))
- goto out;
+ goto out_free_sregs;
r = kvm_arch_vcpu_ioctl_set_sregs(vcpu, kvm_sregs);
if (r)
- goto out;
+ goto out_free_sregs;
r = 0;
+out_free_sregs:
+ kfree(kvm_sregs);
break;
}
- case KVM_GET_MP_STATE: {
- struct kvm_mp_state mp_state;
+ case KVM_VCPU_FPU: {
+ struct kvm_fpu *kvm_fpu;
- r = kvm_arch_vcpu_ioctl_get_mpstate(vcpu, &mp_state);
- if (r)
- goto out;
+ kvm_fpu = kmalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
+ r = -ENOMEM;
+ if (!kvm_fpu)
+ break;
r = -EFAULT;
- if (copy_to_user(argp, &mp_state, sizeof mp_state))
- goto out;
+ if (copy_from_user(kvm_fpu, argp, sizeof(struct kvm_fpu)))
+ goto out_free_fpu;
+ r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, kvm_fpu);
+ if (r)
+ goto out_free_fpu;
r = 0;
+out_free_fpu:
+ kfree(kvm_fpu);
break;
}
- case KVM_SET_MP_STATE: {
+ case KVM_VCPU_MP: {
struct kvm_mp_state mp_state;
r = -EFAULT;
- if (copy_from_user(&mp_state, argp, sizeof mp_state))
- goto out;
+ if (copy_from_user(&mp_state, argp,
+ sizeof(struct kvm_mp_state)))
+ break;
r = kvm_arch_vcpu_ioctl_set_mpstate(vcpu, &mp_state);
- if (r)
- goto out;
- r = 0;
break;
}
+ default:
+ r = kvm_arch_vcpu_set_substate(vcpu, arg_base, substate);
+ }
+ return r;
+}
+
+
+static long kvm_vcpu_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ struct kvm_vcpu *vcpu = filp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct kvm_vcpu_substate substate;
+ int r;
+
+ if (vcpu->kvm->mm != current->mm)
+ return -EIO;
+ switch (ioctl) {
+ case KVM_RUN:
+ r = -EINVAL;
+ if (arg)
+ break;
+ r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);
+ break;
+ case KVM_GET_REGS:
+ substate.type = KVM_VCPU_REGS;
+ substate.offset = 0;
+ r = kvm_vcpu_get_substate(vcpu, argp, &substate);
+ break;
+ case KVM_SET_REGS:
+ substate.type = KVM_VCPU_REGS;
+ substate.offset = 0;
+ r = kvm_vcpu_set_substate(vcpu, argp, &substate);
+ break;
+ case KVM_GET_SREGS:
+ substate.type = KVM_VCPU_SREGS;
+ substate.offset = 0;
+ r = kvm_vcpu_get_substate(vcpu, argp, &substate);
+ break;
+ case KVM_SET_SREGS:
+ substate.type = KVM_VCPU_SREGS;
+ substate.offset = 0;
+ r = kvm_vcpu_set_substate(vcpu, argp, &substate);
+ break;
+ case KVM_GET_MP_STATE:
+ substate.type = KVM_VCPU_MP;
+ substate.offset = 0;
+ r = kvm_vcpu_get_substate(vcpu, argp, &substate);
+ break;
+ case KVM_SET_MP_STATE:
+ substate.type = KVM_VCPU_MP;
+ substate.offset = 0;
+ r = kvm_vcpu_set_substate(vcpu, argp, &substate);
+ break;
case KVM_TRANSLATE: {
struct kvm_translation tr;
r = -EFAULT;
if (copy_from_user(&tr, argp, sizeof tr))
- goto out;
+ break;
r = kvm_arch_vcpu_ioctl_translate(vcpu, &tr);
if (r)
- goto out;
+ break;
r = -EFAULT;
if (copy_to_user(argp, &tr, sizeof tr))
- goto out;
+ break;
r = 0;
break;
}
@@ -1357,10 +1457,10 @@ out_free2:
r = -EFAULT;
if (copy_from_user(&dbg, argp, sizeof dbg))
- goto out;
+ break;
r = kvm_arch_vcpu_ioctl_set_guest_debug(vcpu, &dbg);
if (r)
- goto out;
+ break;
r = 0;
break;
}
@@ -1374,53 +1474,86 @@ out_free2:
r = -EFAULT;
if (copy_from_user(&kvm_sigmask, argp,
sizeof kvm_sigmask))
- goto out;
+ break;
r = -EINVAL;
if (kvm_sigmask.len != sizeof sigset)
- goto out;
+ break;
r = -EFAULT;
if (copy_from_user(&sigset, sigmask_arg->sigset,
sizeof sigset))
- goto out;
+ break;
p = &sigset;
}
r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
break;
}
- case KVM_GET_FPU: {
- fpu = kzalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
- r = -ENOMEM;
- if (!fpu)
- goto out;
- r = kvm_arch_vcpu_ioctl_get_fpu(vcpu, fpu);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(argp, fpu, sizeof(struct kvm_fpu)))
- goto out;
- r = 0;
+ case KVM_GET_FPU:
+ substate.type = KVM_VCPU_FPU;
+ substate.offset = 0;
+ r = kvm_vcpu_get_substate(vcpu, argp, &substate);
break;
- }
- case KVM_SET_FPU: {
- fpu = kmalloc(sizeof(struct kvm_fpu), GFP_KERNEL);
- r = -ENOMEM;
- if (!fpu)
- goto out;
+ case KVM_SET_FPU:
+ substate.type = KVM_VCPU_FPU;
+ substate.offset = 0;
+ r = kvm_vcpu_set_substate(vcpu, argp, &substate);
+ break;
+ case KVM_GET_VCPU_STATE:
+ case KVM_SET_VCPU_STATE: {
+ struct kvm_vcpu_state __user *user_head = argp;
+ struct kvm_vcpu_substate *substates = NULL;
+ uint8_t __user *arg_base = argp;
+ struct kvm_vcpu_state head;
+ size_t size;
+ int i;
+
r = -EFAULT;
- if (copy_from_user(fpu, argp, sizeof(struct kvm_fpu)))
- goto out;
- r = kvm_arch_vcpu_ioctl_set_fpu(vcpu, fpu);
- if (r)
- goto out;
+ if (copy_from_user(&head, user_head,
+ sizeof(struct kvm_vcpu_state)))
+ break;
+
+ head.nprocessed = 0;
+
+ size = head.nsubstates * sizeof(struct kvm_vcpu_substate);
+ if (head.nsubstates <= 1) {
+ substates = &substate;
+ } else {
+ r = -E2BIG;
+ if (head.nsubstates > KVM_MAX_VCPU_SUBSTATES)
+ goto vcpu_state_out;
+
+ substates = kmalloc(size, GFP_KERNEL);
+ r = -ENOMEM;
+ if (!substates)
+ goto vcpu_state_out;
+ }
+
+ r = -EFAULT;
+ if (copy_from_user(substates, user_head->substates, size))
+ goto vcpu_state_out;
+
+ for (i = 0; i < head.nsubstates; i++) {
+ if (ioctl == KVM_GET_VCPU_STATE)
+ r = kvm_vcpu_get_substate(vcpu, arg_base,
+ &substates[i]);
+ else
+ r = kvm_vcpu_set_substate(vcpu, arg_base,
+ &substates[i]);
+ if (r < 0)
+ goto vcpu_state_out;
+ head.nprocessed++;
+ }
r = 0;
+vcpu_state_out:
+ if (copy_to_user(&user_head->nprocessed, &head.nprocessed,
+ sizeof(head.nprocessed)))
+ r = -EFAULT;
+ if (head.nsubstates > 1)
+ kfree(substates);
break;
}
default:
r = kvm_arch_vcpu_ioctl(filp, ioctl, arg);
}
-out:
- kfree(fpu);
- kfree(kvm_sregs);
return r;
}
@@ -1586,6 +1719,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
case KVM_CAP_USER_MEMORY:
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
+ case KVM_CAP_VCPU_STATE:
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
case KVM_CAP_SET_BOOT_CPU_ID:
#endif
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 1/4] KVM: Reorder IOCTLs in main kvm.h
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
2009-10-13 16:06 ` [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states Jan Kiszka
@ 2009-10-13 16:06 ` Jan Kiszka
2009-10-13 16:06 ` [PATCH 3/4] KVM: x86: Add support for KVM_GET/SET_VCPU_STATE Jan Kiszka
` (2 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:06 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
Obviously, people tend to extend this header at the bottom - more or
less blindly. Ensure that deprecated stuff gets its own corner again by
moving things to the top. Also add some comments and reindent IOCTLs to
make them more readable and reduce the risk of number collisions.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
include/linux/kvm.h | 228 ++++++++++++++++++++++++++-------------------------
1 files changed, 114 insertions(+), 114 deletions(-)
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index f8f8900..7d8c382 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -14,12 +14,76 @@
#define KVM_API_VERSION 12
-/* for KVM_TRACE_ENABLE, deprecated */
+/* *** Deprecated interfaces *** */
+
+#define KVM_TRC_SHIFT 16
+
+#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
+#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1))
+
+#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
+#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
+#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
+
+#define KVM_TRC_HEAD_SIZE 12
+#define KVM_TRC_CYCLE_SIZE 8
+#define KVM_TRC_EXTRA_MAX 7
+
+#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
+#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
+#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
+#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
+#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
+#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
+#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
+#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
+#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
+#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
+#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
+#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
+#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
+#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
+#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
+#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
+#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
+#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
+#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
+#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15)
+#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16)
+#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17)
+#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
+#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
+
struct kvm_user_trace_setup {
- __u32 buf_size; /* sub_buffer size of each per-cpu */
- __u32 buf_nr; /* the number of sub_buffers of each per-cpu */
+ __u32 buf_size;
+ __u32 buf_nr;
};
+#define __KVM_DEPRECATED_MAIN_W_0x06 \
+ _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
+#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07)
+#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08)
+
+#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq)
+
+struct kvm_breakpoint {
+ __u32 enabled;
+ __u32 padding;
+ __u64 address;
+};
+
+struct kvm_debug_guest {
+ __u32 enabled;
+ __u32 pad;
+ struct kvm_breakpoint breakpoints[4];
+ __u32 singlestep;
+};
+
+#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
+
+/* *** End of deprecated interfaces *** */
+
+
/* for KVM_CREATE_MEMORY_REGION */
struct kvm_memory_region {
__u32 slot;
@@ -329,24 +393,6 @@ struct kvm_ioeventfd {
__u8 pad[36];
};
-#define KVM_TRC_SHIFT 16
-/*
- * kvm trace categories
- */
-#define KVM_TRC_ENTRYEXIT (1 << KVM_TRC_SHIFT)
-#define KVM_TRC_HANDLER (1 << (KVM_TRC_SHIFT + 1)) /* only 12 bits */
-
-/*
- * kvm trace action
- */
-#define KVM_TRC_VMENTRY (KVM_TRC_ENTRYEXIT + 0x01)
-#define KVM_TRC_VMEXIT (KVM_TRC_ENTRYEXIT + 0x02)
-#define KVM_TRC_PAGE_FAULT (KVM_TRC_HANDLER + 0x01)
-
-#define KVM_TRC_HEAD_SIZE 12
-#define KVM_TRC_CYCLE_SIZE 8
-#define KVM_TRC_EXTRA_MAX 7
-
#define KVMIO 0xAE
/*
@@ -367,12 +413,10 @@ struct kvm_ioeventfd {
*/
#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
-/*
- * ioctls for kvm trace
- */
-#define KVM_TRACE_ENABLE _IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
-#define KVM_TRACE_PAUSE _IO(KVMIO, 0x07)
-#define KVM_TRACE_DISABLE _IO(KVMIO, 0x08)
+#define KVM_TRACE_ENABLE __KVM_DEPRECATED_MAIN_W_0x06
+#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
+#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
+
/*
* Extension capability list.
*/
@@ -500,52 +544,54 @@ struct kvm_irqfd {
/*
* ioctls for VM fds
*/
-#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
+#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region)
/*
* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
* a vcpu fd.
*/
-#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
-#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
-#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
-#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
-#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
-#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\
+#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
+#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
+#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
+#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
+#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
+#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
struct kvm_userspace_memory_region)
-#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
-#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
+#define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47)
+#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, __u64)
/* Device model IOC */
-#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
-#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
-#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
-#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
-#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
-#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
-#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
-#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level)
+#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
+#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
+#define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip)
+#define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip)
+#define KVM_CREATE_PIT _IO(KVMIO, 0x64)
+#define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state)
+#define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state)
+#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level)
#define KVM_REGISTER_COALESCED_MMIO \
_IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone)
#define KVM_UNREGISTER_COALESCED_MMIO \
_IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone)
-#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
- struct kvm_assigned_pci_dev)
-#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
+#define KVM_ASSIGN_PCI_DEVICE _IOR(KVMIO, 0x69, \
+ struct kvm_assigned_pci_dev)
+#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing)
/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
-#define KVM_ASSIGN_IRQ _IOR(KVMIO, 0x70, \
- struct kvm_assigned_irq)
-#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
-#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
-#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
- struct kvm_assigned_pci_dev)
-#define KVM_ASSIGN_SET_MSIX_NR \
- _IOW(KVMIO, 0x73, struct kvm_assigned_msix_nr)
-#define KVM_ASSIGN_SET_MSIX_ENTRY \
- _IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)
-#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
-#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
-#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
-#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
-#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+#define KVM_ASSIGN_IRQ __KVM_DEPRECATED_VM_R_0x70
+#define KVM_ASSIGN_DEV_IRQ _IOW(KVMIO, 0x70, struct kvm_assigned_irq)
+#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71)
+#define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \
+ struct kvm_assigned_pci_dev)
+#define KVM_ASSIGN_SET_MSIX_NR _IOW(KVMIO, 0x73, \
+ struct kvm_assigned_msix_nr)
+#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO, 0x74, \
+ struct kvm_assigned_msix_entry)
+#define KVM_DEASSIGN_DEV_IRQ _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
+#define KVM_IRQFD _IOW(KVMIO, 0x76, struct kvm_irqfd)
+#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config)
+#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78)
+#define KVM_IOEVENTFD _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+/* Available with KVM_CAP_PIT_STATE2 */
+#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
+#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
/*
* ioctls for vcpu fds
@@ -558,7 +604,7 @@ struct kvm_irqfd {
#define KVM_TRANSLATE _IOWR(KVMIO, 0x85, struct kvm_translation)
#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt)
/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */
-#define KVM_DEBUG_GUEST __KVM_DEPRECATED_DEBUG_GUEST
+#define KVM_DEBUG_GUEST __KVM_DEPRECATED_VCPU_W_0x87
#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)
#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
@@ -570,7 +616,7 @@ struct kvm_irqfd {
#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
#define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
/* Available with KVM_CAP_VAPIC */
-#define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
+#define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
/* Available with KVM_CAP_VAPIC */
#define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr)
/* valid for virtual machine (for floating interrupt)_and_ vcpu */
@@ -582,67 +628,21 @@ struct kvm_irqfd {
/* initial ipl psw for s390 */
#define KVM_S390_SET_INITIAL_PSW _IOW(KVMIO, 0x96, struct kvm_s390_psw)
/* initial reset for s390 */
-#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
+#define KVM_S390_INITIAL_RESET _IO(KVMIO, 0x97)
#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state)
#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state)
/* Available with KVM_CAP_NMI */
-#define KVM_NMI _IO(KVMIO, 0x9a)
+#define KVM_NMI _IO(KVMIO, 0x9a)
/* Available with KVM_CAP_SET_GUEST_DEBUG */
#define KVM_SET_GUEST_DEBUG _IOW(KVMIO, 0x9b, struct kvm_guest_debug)
/* MCE for x86 */
#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, __u64)
#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, __u64)
#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce)
-
-/*
- * Deprecated interfaces
- */
-struct kvm_breakpoint {
- __u32 enabled;
- __u32 padding;
- __u64 address;
-};
-
-struct kvm_debug_guest {
- __u32 enabled;
- __u32 pad;
- struct kvm_breakpoint breakpoints[4];
- __u32 singlestep;
-};
-
-#define __KVM_DEPRECATED_DEBUG_GUEST _IOW(KVMIO, 0x87, struct kvm_debug_guest)
-
+/* IA64 stack access */
#define KVM_IA64_VCPU_GET_STACK _IOR(KVMIO, 0x9a, void *)
#define KVM_IA64_VCPU_SET_STACK _IOW(KVMIO, 0x9b, void *)
-#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2)
-#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2)
-
-#define KVM_TRC_INJ_VIRQ (KVM_TRC_HANDLER + 0x02)
-#define KVM_TRC_REDELIVER_EVT (KVM_TRC_HANDLER + 0x03)
-#define KVM_TRC_PEND_INTR (KVM_TRC_HANDLER + 0x04)
-#define KVM_TRC_IO_READ (KVM_TRC_HANDLER + 0x05)
-#define KVM_TRC_IO_WRITE (KVM_TRC_HANDLER + 0x06)
-#define KVM_TRC_CR_READ (KVM_TRC_HANDLER + 0x07)
-#define KVM_TRC_CR_WRITE (KVM_TRC_HANDLER + 0x08)
-#define KVM_TRC_DR_READ (KVM_TRC_HANDLER + 0x09)
-#define KVM_TRC_DR_WRITE (KVM_TRC_HANDLER + 0x0A)
-#define KVM_TRC_MSR_READ (KVM_TRC_HANDLER + 0x0B)
-#define KVM_TRC_MSR_WRITE (KVM_TRC_HANDLER + 0x0C)
-#define KVM_TRC_CPUID (KVM_TRC_HANDLER + 0x0D)
-#define KVM_TRC_INTR (KVM_TRC_HANDLER + 0x0E)
-#define KVM_TRC_NMI (KVM_TRC_HANDLER + 0x0F)
-#define KVM_TRC_VMMCALL (KVM_TRC_HANDLER + 0x10)
-#define KVM_TRC_HLT (KVM_TRC_HANDLER + 0x11)
-#define KVM_TRC_CLTS (KVM_TRC_HANDLER + 0x12)
-#define KVM_TRC_LMSW (KVM_TRC_HANDLER + 0x13)
-#define KVM_TRC_APIC_ACCESS (KVM_TRC_HANDLER + 0x14)
-#define KVM_TRC_TDP_FAULT (KVM_TRC_HANDLER + 0x15)
-#define KVM_TRC_GTLB_WRITE (KVM_TRC_HANDLER + 0x16)
-#define KVM_TRC_STLB_WRITE (KVM_TRC_HANDLER + 0x17)
-#define KVM_TRC_STLB_INVAL (KVM_TRC_HANDLER + 0x18)
-#define KVM_TRC_PPC_INSTR (KVM_TRC_HANDLER + 0x19)
-
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
struct kvm_assigned_pci_dev {
@@ -696,4 +696,4 @@ struct kvm_assigned_msix_entry {
__u16 padding[3];
};
-#endif
+#endif /* __LINUX_KVM_H */
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [RFC][PATCH] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
` (3 preceding siblings ...)
2009-10-13 16:06 ` [PATCH 3/4] KVM: x86: Add support for KVM_GET/SET_VCPU_STATE Jan Kiszka
@ 2009-10-13 16:18 ` Jan Kiszka
2009-10-14 8:52 ` [PATCH] qemu-kvm: x86: Add support for NMI states Jan Kiszka
5 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-13 16:18 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm
This is a demonstration patch for the new KVM IOCTLs proposed in [1]. It
converts upstream kvm to use this in favor of the individual IOCTLs to
get/set VCPU registers and related states. It works, fixes the missing
NMI state handling but, of course, only makes sense if the interface is
accepted by kvm.
[1] http://thread.gmane.org/gmane.comp.emulators.kvm.devel/41550
---
kvm-all.c | 2
kvm.h | 2
target-i386/cpu.h | 1
target-i386/kvm.c | 507 +++++++++++++++++++++++++++----------------------
target-i386/machine.c | 1
target-ppc/kvm.c | 4
6 files changed, 294 insertions(+), 223 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 48ae26c..31bc2f8 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -150,6 +150,7 @@ static void kvm_reset_vcpu(void *opaque)
{
CPUState *env = opaque;
+ kvm_arch_reset_vcpu(env);
if (kvm_arch_put_registers(env)) {
fprintf(stderr, "Fatal: kvm vcpu reset failed\n");
abort();
@@ -201,6 +202,7 @@ int kvm_init_vcpu(CPUState *env)
ret = kvm_arch_init_vcpu(env);
if (ret == 0) {
qemu_register_reset(kvm_reset_vcpu, env);
+ kvm_arch_reset_vcpu(env);
ret = kvm_arch_put_registers(env);
}
err:
diff --git a/kvm.h b/kvm.h
index e7d5beb..6a82f6a 100644
--- a/kvm.h
+++ b/kvm.h
@@ -93,6 +93,8 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
int kvm_arch_init_vcpu(CPUState *env);
+void kvm_arch_reset_vcpu(CPUState *env);
+
struct kvm_guest_debug;
struct kvm_debug_exit_arch;
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5929d28..37823fe 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -693,6 +693,7 @@ typedef struct CPUX86State {
/* For KVM */
uint64_t interrupt_bitmap[256 / 64];
uint32_t mp_state;
+ uint32_t nmi_pending;
/* in order to simplify APIC support, we leave this pointer to the
user */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index aa90eff..05ff97a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -221,6 +221,11 @@ int kvm_arch_init_vcpu(CPUState *env)
return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
}
+void kvm_arch_reset_vcpu(CPUState *env)
+{
+ env->nmi_pending = 0;
+}
+
static int kvm_has_msr_star(CPUState *env)
{
static int has_msr_star;
@@ -346,113 +351,93 @@ static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
*qemu_reg = *kvm_reg;
}
-static int kvm_getput_regs(CPUState *env, int set)
+static void kvm_getput_regs(CPUState *env, struct kvm_regs *regs, int set)
{
- struct kvm_regs regs;
- int ret = 0;
-
- if (!set) {
- ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
- if (ret < 0)
- return ret;
- }
-
- kvm_getput_reg(®s.rax, &env->regs[R_EAX], set);
- kvm_getput_reg(®s.rbx, &env->regs[R_EBX], set);
- kvm_getput_reg(®s.rcx, &env->regs[R_ECX], set);
- kvm_getput_reg(®s.rdx, &env->regs[R_EDX], set);
- kvm_getput_reg(®s.rsi, &env->regs[R_ESI], set);
- kvm_getput_reg(®s.rdi, &env->regs[R_EDI], set);
- kvm_getput_reg(®s.rsp, &env->regs[R_ESP], set);
- kvm_getput_reg(®s.rbp, &env->regs[R_EBP], set);
+ kvm_getput_reg(®s->rax, &env->regs[R_EAX], set);
+ kvm_getput_reg(®s->rbx, &env->regs[R_EBX], set);
+ kvm_getput_reg(®s->rcx, &env->regs[R_ECX], set);
+ kvm_getput_reg(®s->rdx, &env->regs[R_EDX], set);
+ kvm_getput_reg(®s->rsi, &env->regs[R_ESI], set);
+ kvm_getput_reg(®s->rdi, &env->regs[R_EDI], set);
+ kvm_getput_reg(®s->rsp, &env->regs[R_ESP], set);
+ kvm_getput_reg(®s->rbp, &env->regs[R_EBP], set);
#ifdef TARGET_X86_64
- kvm_getput_reg(®s.r8, &env->regs[8], set);
- kvm_getput_reg(®s.r9, &env->regs[9], set);
- kvm_getput_reg(®s.r10, &env->regs[10], set);
- kvm_getput_reg(®s.r11, &env->regs[11], set);
- kvm_getput_reg(®s.r12, &env->regs[12], set);
- kvm_getput_reg(®s.r13, &env->regs[13], set);
- kvm_getput_reg(®s.r14, &env->regs[14], set);
- kvm_getput_reg(®s.r15, &env->regs[15], set);
+ kvm_getput_reg(®s->r8, &env->regs[8], set);
+ kvm_getput_reg(®s->r9, &env->regs[9], set);
+ kvm_getput_reg(®s->r10, &env->regs[10], set);
+ kvm_getput_reg(®s->r11, &env->regs[11], set);
+ kvm_getput_reg(®s->r12, &env->regs[12], set);
+ kvm_getput_reg(®s->r13, &env->regs[13], set);
+ kvm_getput_reg(®s->r14, &env->regs[14], set);
+ kvm_getput_reg(®s->r15, &env->regs[15], set);
#endif
- kvm_getput_reg(®s.rflags, &env->eflags, set);
- kvm_getput_reg(®s.rip, &env->eip, set);
-
- if (set)
- ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
-
- return ret;
+ kvm_getput_reg(®s->rflags, &env->eflags, set);
+ kvm_getput_reg(®s->rip, &env->eip, set);
}
-static int kvm_put_fpu(CPUState *env)
+static void kvm_put_fpu(CPUState *env, struct kvm_fpu *fpu)
{
- struct kvm_fpu fpu;
int i;
- memset(&fpu, 0, sizeof fpu);
- fpu.fsw = env->fpus & ~(7 << 11);
- fpu.fsw |= (env->fpstt & 7) << 11;
- fpu.fcw = env->fpuc;
- for (i = 0; i < 8; ++i)
- fpu.ftwx |= (!env->fptags[i]) << i;
- memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
- memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
- fpu.mxcsr = env->mxcsr;
-
- return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu);
+ memset(fpu, 0, sizeof(*fpu));
+ fpu->fsw = env->fpus & ~(7 << 11);
+ fpu->fsw |= (env->fpstt & 7) << 11;
+ fpu->fcw = env->fpuc;
+ for (i = 0; i < 8; ++i) {
+ fpu->ftwx |= (!env->fptags[i]) << i;
+ }
+ memcpy(fpu->fpr, env->fpregs, sizeof env->fpregs);
+ memcpy(fpu->xmm, env->xmm_regs, sizeof env->xmm_regs);
+ fpu->mxcsr = env->mxcsr;
}
-static int kvm_put_sregs(CPUState *env)
+static void kvm_put_sregs(CPUState *env, struct kvm_sregs *sregs)
{
- struct kvm_sregs sregs;
-
- memcpy(sregs.interrupt_bitmap,
+ memcpy(sregs->interrupt_bitmap,
env->interrupt_bitmap,
- sizeof(sregs.interrupt_bitmap));
+ sizeof(sregs->interrupt_bitmap));
if ((env->eflags & VM_MASK)) {
- set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
- set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
- set_v8086_seg(&sregs.es, &env->segs[R_ES]);
- set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
- set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
- set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
+ set_v8086_seg(&sregs->cs, &env->segs[R_CS]);
+ set_v8086_seg(&sregs->ds, &env->segs[R_DS]);
+ set_v8086_seg(&sregs->es, &env->segs[R_ES]);
+ set_v8086_seg(&sregs->fs, &env->segs[R_FS]);
+ set_v8086_seg(&sregs->gs, &env->segs[R_GS]);
+ set_v8086_seg(&sregs->ss, &env->segs[R_SS]);
} else {
- set_seg(&sregs.cs, &env->segs[R_CS]);
- set_seg(&sregs.ds, &env->segs[R_DS]);
- set_seg(&sregs.es, &env->segs[R_ES]);
- set_seg(&sregs.fs, &env->segs[R_FS]);
- set_seg(&sregs.gs, &env->segs[R_GS]);
- set_seg(&sregs.ss, &env->segs[R_SS]);
-
- if (env->cr[0] & CR0_PE_MASK) {
- /* force ss cpl to cs cpl */
- sregs.ss.selector = (sregs.ss.selector & ~3) |
- (sregs.cs.selector & 3);
- sregs.ss.dpl = sregs.ss.selector & 3;
- }
+ set_seg(&sregs->cs, &env->segs[R_CS]);
+ set_seg(&sregs->ds, &env->segs[R_DS]);
+ set_seg(&sregs->es, &env->segs[R_ES]);
+ set_seg(&sregs->fs, &env->segs[R_FS]);
+ set_seg(&sregs->gs, &env->segs[R_GS]);
+ set_seg(&sregs->ss, &env->segs[R_SS]);
+
+ if (env->cr[0] & CR0_PE_MASK) {
+ /* force ss cpl to cs cpl */
+ sregs->ss.selector = (sregs->ss.selector & ~3) |
+ (sregs->cs.selector & 3);
+ sregs->ss.dpl = sregs->ss.selector & 3;
+ }
}
- set_seg(&sregs.tr, &env->tr);
- set_seg(&sregs.ldt, &env->ldt);
+ set_seg(&sregs->tr, &env->tr);
+ set_seg(&sregs->ldt, &env->ldt);
- sregs.idt.limit = env->idt.limit;
- sregs.idt.base = env->idt.base;
- sregs.gdt.limit = env->gdt.limit;
- sregs.gdt.base = env->gdt.base;
+ sregs->idt.limit = env->idt.limit;
+ sregs->idt.base = env->idt.base;
+ sregs->gdt.limit = env->gdt.limit;
+ sregs->gdt.base = env->gdt.base;
- sregs.cr0 = env->cr[0];
- sregs.cr2 = env->cr[2];
- sregs.cr3 = env->cr[3];
- sregs.cr4 = env->cr[4];
+ sregs->cr0 = env->cr[0];
+ sregs->cr2 = env->cr[2];
+ sregs->cr3 = env->cr[3];
+ sregs->cr4 = env->cr[4];
- sregs.cr8 = cpu_get_apic_tpr(env);
- sregs.apic_base = cpu_get_apic_base(env);
+ sregs->cr8 = cpu_get_apic_tpr(env);
+ sregs->apic_base = cpu_get_apic_base(env);
- sregs.efer = env->efer;
-
- return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ sregs->efer = env->efer;
}
static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
@@ -462,93 +447,75 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
entry->data = value;
}
-static int kvm_put_msrs(CPUState *env)
+static void kvm_put_msrs(CPUState *env, struct kvm_msrs *msrs)
{
- struct {
- struct kvm_msrs info;
- struct kvm_msr_entry entries[100];
- } msr_data;
- struct kvm_msr_entry *msrs = msr_data.entries;
+ struct kvm_msr_entry *msr = msrs->entries;
int n = 0;
- 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);
- kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
- if (kvm_has_msr_star(env))
- kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
- kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
+ kvm_msr_entry_set(&msr[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
+ kvm_msr_entry_set(&msr[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
+ kvm_msr_entry_set(&msr[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
+ if (kvm_has_msr_star(env)) {
+ kvm_msr_entry_set(&msr[n++], MSR_STAR, env->star);
+ }
+ kvm_msr_entry_set(&msr[n++], MSR_IA32_TSC, env->tsc);
#ifdef TARGET_X86_64
/* FIXME if lm capable */
- kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
- kvm_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase);
- kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
- kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
+ kvm_msr_entry_set(&msr[n++], MSR_CSTAR, env->cstar);
+ kvm_msr_entry_set(&msr[n++], MSR_KERNELGSBASE, env->kernelgsbase);
+ kvm_msr_entry_set(&msr[n++], MSR_FMASK, env->fmask);
+ kvm_msr_entry_set(&msr[n++], MSR_LSTAR, env->lstar);
#endif
- msr_data.info.nmsrs = n;
-
- return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
+ msrs->nmsrs = n;
}
-
-static int kvm_get_fpu(CPUState *env)
+static void kvm_get_fpu(CPUState *env, struct kvm_fpu *fpu)
{
- struct kvm_fpu fpu;
- int i, ret;
-
- ret = kvm_vcpu_ioctl(env, KVM_GET_FPU, &fpu);
- if (ret < 0)
- return ret;
-
- env->fpstt = (fpu.fsw >> 11) & 7;
- env->fpus = fpu.fsw;
- env->fpuc = fpu.fcw;
- for (i = 0; i < 8; ++i)
- env->fptags[i] = !((fpu.ftwx >> i) & 1);
- memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
- memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
- env->mxcsr = fpu.mxcsr;
+ int i;
- return 0;
+ env->fpstt = (fpu->fsw >> 11) & 7;
+ env->fpus = fpu->fsw;
+ env->fpuc = fpu->fcw;
+ for (i = 0; i < 8; ++i) {
+ env->fptags[i] = !((fpu->ftwx >> i) & 1);
+ }
+ memcpy(env->fpregs, fpu->fpr, sizeof env->fpregs);
+ memcpy(env->xmm_regs, fpu->xmm, sizeof env->xmm_regs);
+ env->mxcsr = fpu->mxcsr;
}
-static int kvm_get_sregs(CPUState *env)
+static void kvm_get_sregs(CPUState *env, struct kvm_sregs *sregs)
{
- struct kvm_sregs sregs;
uint32_t hflags;
- int ret;
-
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret < 0)
- return ret;
memcpy(env->interrupt_bitmap,
- sregs.interrupt_bitmap,
- sizeof(sregs.interrupt_bitmap));
+ sregs->interrupt_bitmap,
+ sizeof(sregs->interrupt_bitmap));
- get_seg(&env->segs[R_CS], &sregs.cs);
- get_seg(&env->segs[R_DS], &sregs.ds);
- get_seg(&env->segs[R_ES], &sregs.es);
- get_seg(&env->segs[R_FS], &sregs.fs);
- get_seg(&env->segs[R_GS], &sregs.gs);
- get_seg(&env->segs[R_SS], &sregs.ss);
+ get_seg(&env->segs[R_CS], &sregs->cs);
+ get_seg(&env->segs[R_DS], &sregs->ds);
+ get_seg(&env->segs[R_ES], &sregs->es);
+ get_seg(&env->segs[R_FS], &sregs->fs);
+ get_seg(&env->segs[R_GS], &sregs->gs);
+ get_seg(&env->segs[R_SS], &sregs->ss);
- get_seg(&env->tr, &sregs.tr);
- get_seg(&env->ldt, &sregs.ldt);
+ get_seg(&env->tr, &sregs->tr);
+ get_seg(&env->ldt, &sregs->ldt);
- env->idt.limit = sregs.idt.limit;
- env->idt.base = sregs.idt.base;
- env->gdt.limit = sregs.gdt.limit;
- env->gdt.base = sregs.gdt.base;
+ env->idt.limit = sregs->idt.limit;
+ env->idt.base = sregs->idt.base;
+ env->gdt.limit = sregs->gdt.limit;
+ env->gdt.base = sregs->gdt.base;
- env->cr[0] = sregs.cr0;
- env->cr[2] = sregs.cr2;
- env->cr[3] = sregs.cr3;
- env->cr[4] = sregs.cr4;
+ env->cr[0] = sregs->cr0;
+ env->cr[2] = sregs->cr2;
+ env->cr[3] = sregs->cr3;
+ env->cr[4] = sregs->cr4;
- cpu_set_apic_base(env, sregs.apic_base);
+ cpu_set_apic_base(env, sregs->apic_base);
- env->efer = sregs.efer;
+ env->efer = sregs->efer;
//cpu_set_apic_tpr(env, sregs.cr8);
#define HFLAG_COPY_MASK ~( \
@@ -557,8 +524,6 @@ static int kvm_get_sregs(CPUState *env)
HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
-
-
hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
@@ -590,125 +555,221 @@ static int kvm_get_sregs(CPUState *env)
}
}
env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
-
- return 0;
}
-static int kvm_get_msrs(CPUState *env)
+static void kvm_prepare_get_msrs(CPUState *env, struct kvm_msrs *msrs)
{
- struct {
- struct kvm_msrs info;
- struct kvm_msr_entry entries[100];
- } msr_data;
- struct kvm_msr_entry *msrs = msr_data.entries;
- int ret, i, n;
+ struct kvm_msr_entry *msr = msrs->entries;
+ int n;
n = 0;
- msrs[n++].index = MSR_IA32_SYSENTER_CS;
- msrs[n++].index = MSR_IA32_SYSENTER_ESP;
- msrs[n++].index = MSR_IA32_SYSENTER_EIP;
- if (kvm_has_msr_star(env))
- msrs[n++].index = MSR_STAR;
- msrs[n++].index = MSR_IA32_TSC;
+ msr[n++].index = MSR_IA32_SYSENTER_CS;
+ msr[n++].index = MSR_IA32_SYSENTER_ESP;
+ msr[n++].index = MSR_IA32_SYSENTER_EIP;
+ if (kvm_has_msr_star(env)) {
+ msr[n++].index = MSR_STAR;
+ }
+ msr[n++].index = MSR_IA32_TSC;
#ifdef TARGET_X86_64
/* FIXME lm_capable_kernel */
- msrs[n++].index = MSR_CSTAR;
- msrs[n++].index = MSR_KERNELGSBASE;
- msrs[n++].index = MSR_FMASK;
- msrs[n++].index = MSR_LSTAR;
+ msr[n++].index = MSR_CSTAR;
+ msr[n++].index = MSR_KERNELGSBASE;
+ msr[n++].index = MSR_FMASK;
+ msr[n++].index = MSR_LSTAR;
#endif
- msr_data.info.nmsrs = n;
- ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
- if (ret < 0)
- return ret;
+ msrs->nmsrs = n;
+}
- for (i = 0; i < ret; i++) {
- switch (msrs[i].index) {
+static void kvm_get_msrs(CPUState *env, struct kvm_msrs *msrs)
+{
+ struct kvm_msr_entry *msr = msrs->entries;
+ int i;
+
+ for (i = 0; i < msrs->nmsrs; i++) {
+ switch (msr[i].index) {
case MSR_IA32_SYSENTER_CS:
- env->sysenter_cs = msrs[i].data;
+ env->sysenter_cs = msr[i].data;
break;
case MSR_IA32_SYSENTER_ESP:
- env->sysenter_esp = msrs[i].data;
+ env->sysenter_esp = msr[i].data;
break;
case MSR_IA32_SYSENTER_EIP:
- env->sysenter_eip = msrs[i].data;
+ env->sysenter_eip = msr[i].data;
break;
case MSR_STAR:
- env->star = msrs[i].data;
+ env->star = msr[i].data;
break;
#ifdef TARGET_X86_64
case MSR_CSTAR:
- env->cstar = msrs[i].data;
+ env->cstar = msr[i].data;
break;
case MSR_KERNELGSBASE:
- env->kernelgsbase = msrs[i].data;
+ env->kernelgsbase = msr[i].data;
break;
case MSR_FMASK:
- env->fmask = msrs[i].data;
+ env->fmask = msr[i].data;
break;
case MSR_LSTAR:
- env->lstar = msrs[i].data;
+ env->lstar = msr[i].data;
break;
#endif
case MSR_IA32_TSC:
- env->tsc = msrs[i].data;
+ env->tsc = msr[i].data;
break;
}
}
+}
- return 0;
+#ifdef KVM_CAP_VCPU_STATE
+static void kvm_put_nmi(CPUState *env, struct kvm_nmi_state *nmi_state)
+{
+ nmi_state->pending = env->nmi_pending;
+ nmi_state->masked = !!(env->hflags2 & HF2_NMI_MASK);
}
+static void kvm_get_nmi(CPUState *env, struct kvm_nmi_state *nmi_state)
+{
+ env->nmi_pending = nmi_state->pending;
+ if (nmi_state->masked) {
+ env->hflags2 |= HF2_NMI_MASK;
+ } else {
+ env->hflags2 &= ~HF2_NMI_MASK;
+ }
+}
+#endif
+
int kvm_arch_put_registers(CPUState *env)
{
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ struct kvm_fpu fpu;
+ struct {
+ struct kvm_msrs info;
+ struct kvm_msr_entry entries[100];
+ } msrs;
int ret;
+#ifdef KVM_CAP_VCPU_STATE
+ struct kvm_mp_state mp_state;
+ struct kvm_nmi_state nmi;
+ struct {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[6];
+ } request;
+#endif
- ret = kvm_getput_regs(env, 1);
- if (ret < 0)
- return ret;
-
- ret = kvm_put_fpu(env);
- if (ret < 0)
- return ret;
-
- ret = kvm_put_sregs(env);
- if (ret < 0)
- return ret;
-
- ret = kvm_put_msrs(env);
- if (ret < 0)
- return ret;
-
- ret = kvm_put_mp_state(env);
+ kvm_getput_regs(env, ®s, 1);
+ kvm_put_fpu(env, &fpu);
+ kvm_put_sregs(env, &sregs);
+ kvm_put_msrs(env, &msrs.info);
+#ifdef KVM_CAP_VCPU_STATE
+ mp_state.mp_state = env->mp_state;
+ kvm_put_nmi(env, &nmi);
+
+ request.header.nsubstates = 6;
+ request.header.substates[0].type = KVM_VCPU_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+ request.header.substates[5].type = KVM_X86_VCPU_NMI;
+ request.header.substates[5].offset = (size_t)&nmi - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_VCPU_STATE, &request);
if (ret < 0)
- return ret;
+#endif
+ {
+ ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msrs);
+ if (ret < 0)
+ return ret;
+ ret = kvm_put_mp_state(env);
+ if (ret < 0)
+ return ret;
+ }
return 0;
}
int kvm_arch_get_registers(CPUState *env)
{
- int ret;
-
- ret = kvm_getput_regs(env, 0);
- if (ret < 0)
- return ret;
-
- ret = kvm_get_fpu(env);
- if (ret < 0)
- return ret;
-
- ret = kvm_get_sregs(env);
- if (ret < 0)
- return ret;
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ struct kvm_fpu fpu;
+ struct {
+ struct kvm_msrs info;
+ struct kvm_msr_entry entries[100];
+ } msrs;
+ int ret = -1;
+#ifdef KVM_CAP_VCPU_STATE
+ struct kvm_mp_state mp_state;
+ struct kvm_nmi_state nmi;
+ struct {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[6];
+ } request;
+#endif
- ret = kvm_get_msrs(env);
- if (ret < 0)
- return ret;
+ kvm_prepare_get_msrs(env, &msrs.info);
+
+#ifdef KVM_CAP_VCPU_STATE
+ request.header.nsubstates = 6;
+ request.header.substates[0].type = KVM_VCPU_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+ request.header.substates[5].type = KVM_X86_VCPU_NMI;
+ request.header.substates[5].offset = (size_t)&nmi - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_STATE, &request);
+
+ if (ret == 0) {
+ msrs.info.nmsrs = msrs.info.nprocessed;
+ env->mp_state = mp_state.mp_state;
+ kvm_get_nmi(env, &nmi);
+ } else
+#endif
+ {
+ ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_GET_FPU, &fpu);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
+ if (ret < 0)
+ return ret;
+ ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msrs);
+ if (ret < 0)
+ return ret;
+ msrs.info.nmsrs = ret;
+ ret = kvm_get_mp_state(env);
+ if (ret < 0)
+ return ret;
+ }
- ret = kvm_get_mp_state(env);
- if (ret < 0)
- return ret;
+ kvm_getput_regs(env, ®s, 0);
+ kvm_get_fpu(env, &fpu);
+ kvm_get_sregs(env, &sregs);
+ kvm_get_msrs(env, &msrs.info);
return 0;
}
diff --git a/target-i386/machine.c b/target-i386/machine.c
index b13eff4..12d5009 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -468,6 +468,7 @@ const VMStateDescription vmstate_cpu = {
VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9),
VMSTATE_UINT32_V(mp_state, CPUState, 9),
VMSTATE_UINT64_V(tsc, CPUState, 9),
+ VMSTATE_UINT32_V(nmi_pending, CPUState, 11),
/* MCE */
VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
VMSTATE_UINT64_V(mcg_status, CPUState, 10),
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index b53d6e9..4e1c65f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -53,6 +53,10 @@ int kvm_arch_init_vcpu(CPUState *cenv)
return ret;
}
+void kvm_arch_reset_vcpu(CPUState *env)
+{
+}
+
int kvm_arch_put_registers(CPUState *env)
{
struct kvm_regs regs;
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH] qemu-kvm: x86: Add support for NMI states
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
` (4 preceding siblings ...)
2009-10-13 16:18 ` [RFC][PATCH] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
@ 2009-10-14 8:52 ` Jan Kiszka
5 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-14 8:52 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: kvm
This adds the required bit to retrieve and set the so far hidden NMI
pending and NMI masked states of the KVM kernel side. It also extends
CPU VMState for proper saving/restoring. We can now savely reset a VM
while NMIs are on the fly, and we can live migrate etc. too.
Fortunately, the probability that this deficit bit normal VMs in
practice was very low.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
qemu-kvm-x86.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
target-i386/cpu.h | 1 +
target-i386/machine.c | 1 +
3 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index acb1b91..86fd341 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -901,6 +901,53 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
| (rhs->avl * DESC_AVL_MASK);
}
+static void kvm_get_nmi_state(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_STATE
+ kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx;
+ struct {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[1];
+ } request;
+ struct kvm_nmi_state nmi_state;
+ int r;
+
+ request.header.nsubstates = 1;
+ request.header.substates[0].type = KVM_X86_VCPU_NMI;
+ request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request;
+ r = ioctl(vcpu->fd, KVM_GET_VCPU_STATE, &request);
+ if (r == 0) {
+ env->nmi_pending = nmi_state.pending;
+ if (nmi_state.masked) {
+ env->hflags2 |= HF2_NMI_MASK;
+ } else {
+ env->hflags2 &= ~HF2_NMI_MASK;
+ }
+ }
+#endif
+ env->nmi_pending = 0;
+ env->hflags2 &= ~HF2_NMI_MASK;
+}
+
+static void kvm_set_nmi_state(CPUState *env)
+{
+#ifdef KVM_CAP_VCPU_STATE
+ kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx;
+ struct {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[1];
+ } request;
+ struct kvm_nmi_state nmi_state;
+
+ request.header.nsubstates = 1;
+ request.header.substates[0].type = KVM_X86_VCPU_NMI;
+ request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request;
+ nmi_state.pending = env->nmi_pending;
+ nmi_state.masked = !!(env->hflags2 & HF2_NMI_MASK);
+ ioctl(vcpu->fd, KVM_SET_VCPU_STATE, &request);
+#endif
+}
+
void kvm_arch_load_regs(CPUState *env)
{
struct kvm_regs regs;
@@ -1010,6 +1057,8 @@ void kvm_arch_load_regs(CPUState *env)
rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n);
if (rc == -1)
perror("kvm_set_msrs FAILED");
+
+ kvm_set_nmi_state(env);
}
void kvm_load_tsc(CPUState *env)
@@ -1195,6 +1244,8 @@ void kvm_arch_save_regs(CPUState *env)
return;
}
}
+
+ kvm_get_nmi_state(env);
}
static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function,
@@ -1438,6 +1489,7 @@ void kvm_arch_push_nmi(void *opaque)
void kvm_arch_cpu_reset(CPUState *env)
{
+ env->nmi_pending = 0;
kvm_arch_load_regs(env);
if (!cpu_is_bsp(env)) {
if (kvm_irqchip_in_kernel(kvm_context)) {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 278d3e3..620822a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -709,6 +709,7 @@ typedef struct CPUX86State {
/* For KVM */
uint64_t interrupt_bitmap[256 / 64];
uint32_t mp_state;
+ uint32_t nmi_pending;
/* in order to simplify APIC support, we leave this pointer to the
user */
diff --git a/target-i386/machine.c b/target-i386/machine.c
index e640dad..5c290f3 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -469,6 +469,7 @@ const VMStateDescription vmstate_cpu = {
VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9),
VMSTATE_UINT32_V(mp_state, CPUState, 9),
VMSTATE_UINT64_V(tsc, CPUState, 9),
+ VMSTATE_UINT32_V(nmi_pending, CPUState, 11),
/* MCE */
VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
VMSTATE_UINT64_V(mcg_status, CPUState, 10),
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
@ 2009-10-15 8:00 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 8:07 ` Avi Kivity
2009-10-15 8:11 ` Avi Kivity
2 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 8:00 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm
On 10/14/2009 01:06 AM, Jan Kiszka wrote:
> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
> More precisely, the IOCTL is able to process a list of substates to be
> read or written. This list is easily extensible without breaking the
> existing ABI, thus we will no longer have to add new IOCTLs when we
> discover a missing VCPU state field or want to support new hardware
> features.
>
> This patch establishes the generic infrastructure for KVM_GET/
> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
> FPU, and MP. To avoid code duplication, the entry point for the
> corresponding original IOCTLs are converted to make use of the new
> infrastructure internally, too.
>
>
>
> +/* for KVM_GET_VCPU_STATE and KVM_SET_VCPU_STATE */
> +#define KVM_VCPU_REGS 0
> +#define KVM_VCPU_SREGS 1
> +#define KVM_VCPU_FPU 2
> +#define KVM_VCPU_MP 3
>
KVM_VCPU_STATE_*, to avoid collisions.
Better to split sse from fpu since we already know it is about to be
replaced.
> +
> +struct kvm_vcpu_substate {
> + __u32 type;
> + __u32 pad;
> + __s64 offset;
> +};
> +
> +#define KVM_MAX_VCPU_SUBSTATES 64
> +
> +struct kvm_vcpu_state {
> + __u32 nsubstates; /* number of elements in substates */
> + __u32 nprocessed; /* return value: successfully processed substates */
> + struct kvm_vcpu_substate substates[0];
> +};
> +
>
Wouldn't having an ordinary struct with lots of reserved space be
simpler? If we add a bitmask, we can even selectively get/set the
fields we want (important if new state extends old state: avx vs sse).
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
2009-10-15 8:00 ` Avi Kivity
@ 2009-10-15 8:07 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 8:11 ` Avi Kivity
2 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 8:07 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm
On 10/14/2009 01:06 AM, Jan Kiszka wrote:
> @@ -1586,6 +1719,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
> case KVM_CAP_USER_MEMORY:
> case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
> case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
> + case KVM_CAP_VCPU_STATE:
> #ifdef CONFIG_KVM_APIC_ARCHITECTURE
> case KVM_CAP_SET_BOOT_CPU_ID:
> #endif
>
This should be done only for the archs that implement the ioctl.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-13 16:06 ` [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states Jan Kiszka
@ 2009-10-15 8:09 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
0 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 8:09 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm
On 10/14/2009 01:06 AM, Jan Kiszka wrote:
> This plugs an NMI-related hole in the VCPU synchronization between
> kernel and user space. So far, neither pending NMIs nor the inhibit NMI
> mask was properly read/set which was able to cause problems on
> vmsave/restore, live migration and system reset. Fix it by making use
> of the new VCPU substate interface.
>
>
> +struct kvm_nmi_state {
> + __u8 pending;
> + __u8 masked;
> + __u8 pad1[2];
> +};
>
Best to be conservative and use 64-bit alignment. Who knows what we
might put after this someday.
> @@ -513,6 +513,8 @@ struct kvm_x86_ops {
> unsigned char *hypercall_addr);
> void (*set_irq)(struct kvm_vcpu *vcpu);
> void (*set_nmi)(struct kvm_vcpu *vcpu);
> + int (*get_nmi_mask)(struct kvm_vcpu *vcpu);
> + void (*set_nmi_mask)(struct kvm_vcpu *vcpu, int masked);
>
Prefer bool for booleans, please.
Needs a KVM_CAP as well.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
2009-10-15 8:00 ` Avi Kivity
2009-10-15 8:07 ` Avi Kivity
@ 2009-10-15 8:11 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
` (2 more replies)
2 siblings, 3 replies; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 8:11 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm, Glauber Costa
On 10/14/2009 01:06 AM, Jan Kiszka wrote:
> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
> More precisely, the IOCTL is able to process a list of substates to be
> read or written. This list is easily extensible without breaking the
> existing ABI, thus we will no longer have to add new IOCTLs when we
> discover a missing VCPU state field or want to support new hardware
> features.
>
> This patch establishes the generic infrastructure for KVM_GET/
> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
> FPU, and MP. To avoid code duplication, the entry point for the
> corresponding original IOCTLs are converted to make use of the new
> infrastructure internally, too.
>
>
One last thing - Documentation/kvm/api.txt needs updating. Glauber,
this holds for your patches as well.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 8:00 ` Avi Kivity
@ 2009-10-15 9:22 ` Jan Kiszka
2009-10-15 9:33 ` Avi Kivity
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 9:22 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
>> More precisely, the IOCTL is able to process a list of substates to be
>> read or written. This list is easily extensible without breaking the
>> existing ABI, thus we will no longer have to add new IOCTLs when we
>> discover a missing VCPU state field or want to support new hardware
>> features.
>>
>> This patch establishes the generic infrastructure for KVM_GET/
>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
>> FPU, and MP. To avoid code duplication, the entry point for the
>> corresponding original IOCTLs are converted to make use of the new
>> infrastructure internally, too.
>>
>>
>>
>> +/* for KVM_GET_VCPU_STATE and KVM_SET_VCPU_STATE */
>> +#define KVM_VCPU_REGS 0
>> +#define KVM_VCPU_SREGS 1
>> +#define KVM_VCPU_FPU 2
>> +#define KVM_VCPU_MP 3
>>
>
> KVM_VCPU_STATE_*, to avoid collisions.
OK.
>
> Better to split sse from fpu since we already know it is about to be
> replaced.
The idea is to reuse the existing state structures, including struct
kvm_fpu. This allows to provide the avoid substates for all archs and
simplifies the migration (see my qemu conversion patch). I think, once
we need support for new/wider registers in x86, we can introduce new
KVM_X86_VCPU_STATE_FPU_WHATEVER substates that are able to replace the
old one.
>
>> +
>> +struct kvm_vcpu_substate {
>> + __u32 type;
>> + __u32 pad;
>> + __s64 offset;
>> +};
>> +
>> +#define KVM_MAX_VCPU_SUBSTATES 64
>> +
>> +struct kvm_vcpu_state {
>> + __u32 nsubstates; /* number of elements in substates */
>> + __u32 nprocessed; /* return value: successfully processed substates */
>> + struct kvm_vcpu_substate substates[0];
>> +};
>> +
>>
>
> Wouldn't having an ordinary struct with lots of reserved space be
> simpler? If we add a bitmask, we can even selectively get/set the
> fields we want (important if new state extends old state: avx vs sse).
Simpler - hmm, maybe. But also less flexible. This would establish a
static order inside this constantly growing mega struct. And a user only
interested in something small at its end would still have to allocate
memory for the whole thing (maybe megabytes in the future, who knows?).
And this mega struct will always carry all the legacy substates, even if
they aren't used anymore in practice.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 8:07 ` Avi Kivity
@ 2009-10-15 9:22 ` Jan Kiszka
0 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 9:22 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> @@ -1586,6 +1719,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg)
>> case KVM_CAP_USER_MEMORY:
>> case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
>> case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
>> + case KVM_CAP_VCPU_STATE:
>> #ifdef CONFIG_KVM_APIC_ARCHITECTURE
>> case KVM_CAP_SET_BOOT_CPU_ID:
>> #endif
>>
>
> This should be done only for the archs that implement the ioctl.
All archs already implement the core substates.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-15 8:09 ` Avi Kivity
@ 2009-10-15 9:22 ` Jan Kiszka
2009-10-15 9:29 ` Avi Kivity
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 9:22 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> This plugs an NMI-related hole in the VCPU synchronization between
>> kernel and user space. So far, neither pending NMIs nor the inhibit NMI
>> mask was properly read/set which was able to cause problems on
>> vmsave/restore, live migration and system reset. Fix it by making use
>> of the new VCPU substate interface.
>>
>>
>> +struct kvm_nmi_state {
>> + __u8 pending;
>> + __u8 masked;
>> + __u8 pad1[2];
>> +};
>>
>
> Best to be conservative and use 64-bit alignment. Who knows what we
> might put after this someday.
OK.
>> @@ -513,6 +513,8 @@ struct kvm_x86_ops {
>> unsigned char *hypercall_addr);
>> void (*set_irq)(struct kvm_vcpu *vcpu);
>> void (*set_nmi)(struct kvm_vcpu *vcpu);
>> + int (*get_nmi_mask)(struct kvm_vcpu *vcpu);
>> + void (*set_nmi_mask)(struct kvm_vcpu *vcpu, int masked);
>>
>
> Prefer bool for booleans, please.
OK.
>
> Needs a KVM_CAP as well.
KVM_CAP_VCPU_STATE will imply KVM_CAP_NMI_STATE, so I skipped the latter
(user space code would use the former anyway to avoid yet another #ifdef
layer).
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 8:11 ` Avi Kivity
@ 2009-10-15 9:22 ` Jan Kiszka
2009-10-15 14:54 ` Glauber Costa
2009-10-15 15:57 ` Glauber Costa
2 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 9:22 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org, Glauber Costa
Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
>> More precisely, the IOCTL is able to process a list of substates to be
>> read or written. This list is easily extensible without breaking the
>> existing ABI, thus we will no longer have to add new IOCTLs when we
>> discover a missing VCPU state field or want to support new hardware
>> features.
>>
>> This patch establishes the generic infrastructure for KVM_GET/
>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
>> FPU, and MP. To avoid code duplication, the entry point for the
>> corresponding original IOCTLs are converted to make use of the new
>> infrastructure internally, too.
>>
>>
>
> One last thing - Documentation/kvm/api.txt needs updating. Glauber,
> this holds for your patches as well.
OK, will be done once the interface settled.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-15 9:22 ` Jan Kiszka
@ 2009-10-15 9:29 ` Avi Kivity
2009-10-15 11:27 ` Jan Kiszka
0 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 9:29 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
On 10/15/2009 06:22 PM, Jan Kiszka wrote:
>> Needs a KVM_CAP as well.
>>
> KVM_CAP_VCPU_STATE will imply KVM_CAP_NMI_STATE, so I skipped the latter
> (user space code would use the former anyway to avoid yet another #ifdef
> layer).
>
OK. New bits will need the KVM_CAP, though.
Perhaps it makes sense to query about individual states, including
existing ones? That will allow us to deprecate and then phase out
broken states. It's probably not worth it.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 9:22 ` Jan Kiszka
@ 2009-10-15 9:33 ` Avi Kivity
0 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2009-10-15 9:33 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
On 10/15/2009 06:22 PM, Jan Kiszka wrote:
>> Better to split sse from fpu since we already know it is about to be
>> replaced.
>>
> The idea is to reuse the existing state structures, including struct
> kvm_fpu. This allows to provide the avoid substates for all archs and
> simplifies the migration (see my qemu conversion patch). I think, once
> we need support for new/wider registers in x86, we can introduce new
> KVM_X86_VCPU_STATE_FPU_WHATEVER substates that are able to replace the
> old one.
>
Makes sense, especially if we keep the list instead of the structure.
>>> +
>>> +struct kvm_vcpu_substate {
>>> + __u32 type;
>>> + __u32 pad;
>>> + __s64 offset;
>>> +};
>>> +
>>> +#define KVM_MAX_VCPU_SUBSTATES 64
>>> +
>>> +struct kvm_vcpu_state {
>>> + __u32 nsubstates; /* number of elements in substates */
>>> + __u32 nprocessed; /* return value: successfully processed substates */
>>> + struct kvm_vcpu_substate substates[0];
>>> +};
>>> +
>>>
>>>
>> Wouldn't having an ordinary struct with lots of reserved space be
>> simpler? If we add a bitmask, we can even selectively get/set the
>> fields we want (important if new state extends old state: avx vs sse).
>>
> Simpler - hmm, maybe. But also less flexible. This would establish a
> static order inside this constantly growing mega struct. And a user only
> interested in something small at its end would still have to allocate
> memory for the whole thing (maybe megabytes in the future, who knows?).
> And this mega struct will always carry all the legacy substates, even if
> they aren't used anymore in practice.
>
I hope cpu state doesn't grow into megabytes, or we'll have problems
live migrating them. But I see your point. The initial split assumed
userspace would be interested in optimizing access (we used to have many
more exits, and really old versions relied on qemu for emulation), that
turned out not to be the case, but it's better to keep this capability
for other possible userspaces. So let's go ahead with the list.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-15 9:29 ` Avi Kivity
@ 2009-10-15 11:27 ` Jan Kiszka
2009-10-25 13:11 ` Avi Kivity
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 11:27 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
Avi Kivity wrote:
> On 10/15/2009 06:22 PM, Jan Kiszka wrote:
>>> Needs a KVM_CAP as well.
>>>
>> KVM_CAP_VCPU_STATE will imply KVM_CAP_NMI_STATE, so I skipped the latter
>> (user space code would use the former anyway to avoid yet another #ifdef
>> layer).
>>
>
> OK. New bits will need the KVM_CAP, though.
For sure.
>
> Perhaps it makes sense to query about individual states, including
> existing ones? That will allow us to deprecate and then phase out
> broken states. It's probably not worth it.
You may do this already with the given design: Set up a VCPU, then issue
KVM_GET_VCPU_STATE on the substate in question. You will either get an
error code or 0 if the substate is supported. At least no additional
kernel code required.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 8:11 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
@ 2009-10-15 14:54 ` Glauber Costa
2009-10-15 15:57 ` Glauber Costa
2 siblings, 0 replies; 24+ messages in thread
From: Glauber Costa @ 2009-10-15 14:54 UTC (permalink / raw)
To: Avi Kivity; +Cc: Jan Kiszka, Marcelo Tosatti, kvm
On Thu, Oct 15, 2009 at 05:11:27PM +0900, Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
>> More precisely, the IOCTL is able to process a list of substates to be
>> read or written. This list is easily extensible without breaking the
>> existing ABI, thus we will no longer have to add new IOCTLs when we
>> discover a missing VCPU state field or want to support new hardware
>> features.
>>
>> This patch establishes the generic infrastructure for KVM_GET/
>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
>> FPU, and MP. To avoid code duplication, the entry point for the
>> corresponding original IOCTLs are converted to make use of the new
>> infrastructure internally, too.
>>
>>
>
> One last thing - Documentation/kvm/api.txt needs updating. Glauber,
> this holds for your patches as well.
Marcelo asked me to send the userspace part together. I will udate the
doc when I do it.
thanks for the reminder.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 8:11 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 14:54 ` Glauber Costa
@ 2009-10-15 15:57 ` Glauber Costa
2009-10-15 16:06 ` Jan Kiszka
2 siblings, 1 reply; 24+ messages in thread
From: Glauber Costa @ 2009-10-15 15:57 UTC (permalink / raw)
To: Avi Kivity; +Cc: Jan Kiszka, Marcelo Tosatti, kvm
On Thu, Oct 15, 2009 at 05:11:27PM +0900, Avi Kivity wrote:
> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
>> More precisely, the IOCTL is able to process a list of substates to be
>> read or written. This list is easily extensible without breaking the
>> existing ABI, thus we will no longer have to add new IOCTLs when we
>> discover a missing VCPU state field or want to support new hardware
>> features.
>>
>> This patch establishes the generic infrastructure for KVM_GET/
>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
>> FPU, and MP. To avoid code duplication, the entry point for the
>> corresponding original IOCTLs are converted to make use of the new
>> infrastructure internally, too.
>>
>>
>
> One last thing - Documentation/kvm/api.txt needs updating. Glauber,
> this holds for your patches as well.
Now looking at it... you do realize that that file is terribly outdated, right?
>
> --
> I have a truly marvellous patch that fixes the bug which this
> signature is too narrow to contain.
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 15:57 ` Glauber Costa
@ 2009-10-15 16:06 ` Jan Kiszka
2009-10-15 16:23 ` Glauber Costa
0 siblings, 1 reply; 24+ messages in thread
From: Jan Kiszka @ 2009-10-15 16:06 UTC (permalink / raw)
To: Glauber Costa; +Cc: Avi Kivity, Marcelo Tosatti, kvm@vger.kernel.org
Glauber Costa wrote:
> On Thu, Oct 15, 2009 at 05:11:27PM +0900, Avi Kivity wrote:
>> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
>>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
>>> More precisely, the IOCTL is able to process a list of substates to be
>>> read or written. This list is easily extensible without breaking the
>>> existing ABI, thus we will no longer have to add new IOCTLs when we
>>> discover a missing VCPU state field or want to support new hardware
>>> features.
>>>
>>> This patch establishes the generic infrastructure for KVM_GET/
>>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
>>> FPU, and MP. To avoid code duplication, the entry point for the
>>> corresponding original IOCTLs are converted to make use of the new
>>> infrastructure internally, too.
>>>
>>>
>> One last thing - Documentation/kvm/api.txt needs updating. Glauber,
>> this holds for your patches as well.
> Now looking at it... you do realize that that file is terribly outdated, right?
At least it's terribly incomplete. I just decided to add my stuff at the
bottom and wait for a bored soul to refactor, fix, extend, whatever this
thing. :)
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL
2009-10-15 16:06 ` Jan Kiszka
@ 2009-10-15 16:23 ` Glauber Costa
0 siblings, 0 replies; 24+ messages in thread
From: Glauber Costa @ 2009-10-15 16:23 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Avi Kivity, Marcelo Tosatti, kvm@vger.kernel.org
On Thu, Oct 15, 2009 at 06:06:04PM +0200, Jan Kiszka wrote:
> Glauber Costa wrote:
> > On Thu, Oct 15, 2009 at 05:11:27PM +0900, Avi Kivity wrote:
> >> On 10/14/2009 01:06 AM, Jan Kiszka wrote:
> >>> Add a new IOCTL pair to retrieve or set the VCPU state in one chunk.
> >>> More precisely, the IOCTL is able to process a list of substates to be
> >>> read or written. This list is easily extensible without breaking the
> >>> existing ABI, thus we will no longer have to add new IOCTLs when we
> >>> discover a missing VCPU state field or want to support new hardware
> >>> features.
> >>>
> >>> This patch establishes the generic infrastructure for KVM_GET/
> >>> SET_VCPU_STATE and adds support for the generic substates REGS, SREGS,
> >>> FPU, and MP. To avoid code duplication, the entry point for the
> >>> corresponding original IOCTLs are converted to make use of the new
> >>> infrastructure internally, too.
> >>>
> >>>
> >> One last thing - Documentation/kvm/api.txt needs updating. Glauber,
> >> this holds for your patches as well.
> > Now looking at it... you do realize that that file is terribly outdated, right?
>
> At least it's terribly incomplete. I just decided to add my stuff at the
> bottom and wait for a bored soul to refactor, fix, extend, whatever this
> thing. :)
We'll probably clash, then =p.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-15 11:27 ` Jan Kiszka
@ 2009-10-25 13:11 ` Avi Kivity
2009-10-26 7:40 ` Jan Kiszka
0 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2009-10-25 13:11 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
On 10/15/2009 01:27 PM, Jan Kiszka wrote:
>
>> Perhaps it makes sense to query about individual states, including
>> existing ones? That will allow us to deprecate and then phase out
>> broken states. It's probably not worth it.
>>
> You may do this already with the given design: Set up a VCPU, then issue
> KVM_GET_VCPU_STATE on the substate in question. You will either get an
> error code or 0 if the substate is supported. At least no additional
> kernel code required.
>
No, if some code requires a feature, we don't want to set up a guest and
a vcpu and issue dummy commands in order to find out if we can actually
run that code.
Feature discovery needs to be a 'system ioctl' in the words of
Documentation/kvm/api.txt.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states
2009-10-25 13:11 ` Avi Kivity
@ 2009-10-26 7:40 ` Jan Kiszka
0 siblings, 0 replies; 24+ messages in thread
From: Jan Kiszka @ 2009-10-26 7:40 UTC (permalink / raw)
To: Avi Kivity; +Cc: Marcelo Tosatti, kvm@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 891 bytes --]
Avi Kivity wrote:
> On 10/15/2009 01:27 PM, Jan Kiszka wrote:
>>> Perhaps it makes sense to query about individual states, including
>>> existing ones? That will allow us to deprecate and then phase out
>>> broken states. It's probably not worth it.
>>>
>> You may do this already with the given design: Set up a VCPU, then issue
>> KVM_GET_VCPU_STATE on the substate in question. You will either get an
>> error code or 0 if the substate is supported. At least no additional
>> kernel code required.
>>
>
> No, if some code requires a feature, we don't want to set up a guest and
> a vcpu and issue dummy commands in order to find out if we can actually
> run that code.
>
> Feature discovery needs to be a 'system ioctl' in the words of
> Documentation/kvm/api.txt.
>
OK, added some system IOCTL 'KVM_GET_VCPU_STATE_LIST' to my to-do list.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2009-10-26 7:40 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-13 16:06 [PATCH 0/4] Extensible VCPU state IOCTL Jan Kiszka
2009-10-13 16:06 ` [PATCH 2/4] KVM: Add unified KVM_GET/SET_VCPU_STATE IOCTL Jan Kiszka
2009-10-15 8:00 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 9:33 ` Avi Kivity
2009-10-15 8:07 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 8:11 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 14:54 ` Glauber Costa
2009-10-15 15:57 ` Glauber Costa
2009-10-15 16:06 ` Jan Kiszka
2009-10-15 16:23 ` Glauber Costa
2009-10-13 16:06 ` [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states Jan Kiszka
2009-10-15 8:09 ` Avi Kivity
2009-10-15 9:22 ` Jan Kiszka
2009-10-15 9:29 ` Avi Kivity
2009-10-15 11:27 ` Jan Kiszka
2009-10-25 13:11 ` Avi Kivity
2009-10-26 7:40 ` Jan Kiszka
2009-10-13 16:06 ` [PATCH 1/4] KVM: Reorder IOCTLs in main kvm.h Jan Kiszka
2009-10-13 16:06 ` [PATCH 3/4] KVM: x86: Add support for KVM_GET/SET_VCPU_STATE Jan Kiszka
2009-10-13 16:18 ` [RFC][PATCH] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
2009-10-14 8:52 ` [PATCH] qemu-kvm: x86: Add support for NMI states Jan Kiszka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).