* [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL
@ 2009-11-06 18:39 Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 1/5] kvm: x86: Fix merge artifact of f8d926e9 about mp_state Jan Kiszka
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
This series adds support for the upcoming new KVM IOCTL to get/set VPCU
states as a set up substates. See [1] for more details on this KVM
extension.
While I did not fully convert the corresponding qemu-kvm part (it is
expected to morph into upstream soon), QEMU should receive a complete
conversion. So this series first fixes, cleans up, and refactors some
KVM code, and then adds KVM_GET/SET_VCPU_STATE as an alternative to the
classic multi-IOCTL state getting and setting. I did this full
conversion with all its #ifdefs in order to be able to drop legacy
support at some (still distant) point in the future.
Along with the conversion a few fragile migration, save/restore and
reset cases are fixed. We now have access to all missing exception,
interrupt, and NMI states KVM kept private so far. See [2] for details.
Find this series also at git://git.kiszka.org/qemu.git queues/kvm
Jan Kiszka (5):
kvm: x86: Fix merge artifact of f8d926e9 about mp_state
kvm: Add arch reset handler
kvm: x86: Refactor use of interrupt_bitmap
kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE
kvm: x86: Add support for event states
kvm-all.c | 13 ++
kvm.h | 3 +
target-i386/cpu.h | 8 +-
target-i386/kvm.c | 514 ++++++++++++++++++++++++++++++-------------------
target-i386/machine.c | 29 +--
target-ppc/kvm.c | 4 +
6 files changed, 346 insertions(+), 225 deletions(-)
[1] http://thread.gmane.org/gmane.comp.emulators.kvm.devel/42699
[2] http://thread.gmane.org/gmane.comp.emulators.kvm.devel/42699/focus=42926
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 1/5] kvm: x86: Fix merge artifact of f8d926e9 about mp_state
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
@ 2009-11-06 18:39 ` Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 5/5] kvm: x86: Add support for event states Jan Kiszka
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
target-i386/kvm.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 7010999..aa90eff 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -683,10 +683,6 @@ int kvm_arch_put_registers(CPUState *env)
if (ret < 0)
return ret;
- ret = kvm_get_mp_state(env);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -710,6 +706,10 @@ int kvm_arch_get_registers(CPUState *env)
if (ret < 0)
return ret;
+ ret = kvm_get_mp_state(env);
+ if (ret < 0)
+ return ret;
+
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/5] kvm: Add arch reset handler
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
` (2 preceding siblings ...)
2009-11-06 18:39 ` [Qemu-devel] [PATCH 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
@ 2009-11-06 18:39 ` Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 3/5] kvm: x86: Refactor use of interrupt_bitmap Jan Kiszka
4 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
Will be required by succeeding changes.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 2 ++
kvm.h | 2 ++
target-i386/kvm.c | 4 ++++
target-ppc/kvm.c | 4 ++++
4 files changed, 12 insertions(+), 0 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/kvm.c b/target-i386/kvm.c
index aa90eff..ca99cc7 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -221,6 +221,10 @@ int kvm_arch_init_vcpu(CPUState *env)
return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
}
+void kvm_arch_reset_vcpu(CPUState *env)
+{
+}
+
static int kvm_has_msr_star(CPUState *env)
{
static int has_msr_star;
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] 7+ messages in thread
* [Qemu-devel] [PATCH 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 1/5] kvm: x86: Fix merge artifact of f8d926e9 about mp_state Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 5/5] kvm: x86: Add support for event states Jan Kiszka
@ 2009-11-06 18:39 ` Jan Kiszka
2009-11-09 19:02 ` [Qemu-devel] [PATCH v2 " Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 2/5] kvm: Add arch reset handler Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 3/5] kvm: x86: Refactor use of interrupt_bitmap Jan Kiszka
4 siblings, 1 reply; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
This patch adds support for the new KVM IOCTLs KVM_GET/SET_VCPU_STATE.
They are supposed to be introduced with 2.6.33 or 34 and allow to extend
the VCPU state exchange between kernel and user space without adding new
IOCTLs and to acquire/set a complete state via a single systemcall.
In order to remain backward-compatible to existing kernels, the old
state synchronization interface is of course kept as a fall-back.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 11 +
kvm.h | 1
target-i386/kvm.c | 451 +++++++++++++++++++++++++++++------------------------
3 files changed, 260 insertions(+), 203 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 31bc2f8..0d22e42 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -61,6 +61,7 @@ struct KVMState
int coalesced_mmio;
int broken_set_mem_region;
int migration_log;
+ int vcpu_state;
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
@@ -499,6 +500,11 @@ int kvm_init(int smp_cpus)
}
#endif
+ s->vcpu_state = 0;
+#ifdef KVM_CAP_VCPU_STATE
+ s->vcpu_state = kvm_check_extension(s, KVM_CAP_VCPU_STATE);
+#endif
+
ret = kvm_arch_init(s, smp_cpus);
if (ret < 0)
goto err;
@@ -888,6 +894,11 @@ int kvm_has_sync_mmu(void)
#endif
}
+int kvm_has_vcpu_state(void)
+{
+ return kvm_state->vcpu_state;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index 6a82f6a..9e237d1 100644
--- a/kvm.h
+++ b/kvm.h
@@ -47,6 +47,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
int kvm_set_migration_log(int enable);
int kvm_has_sync_mmu(void);
+int kvm_has_vcpu_state(void);
void kvm_setup_guest_memory(void *start, size_t size);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c769d70..25c6bde 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -352,115 +352,95 @@ 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)
-{
- 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);
+static void kvm_getput_regs(CPUState *env, struct kvm_regs *regs, int 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;
-
- memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
+ memset(sregs->interrupt_bitmap, 0, sizeof(sregs->interrupt_bitmap));
if (env->interrupt_injected >= 0) {
- sregs.interrupt_bitmap[env->interrupt_injected / 64] |=
+ sregs->interrupt_bitmap[env->interrupt_injected / 64] |=
(uint64_t)1 << (env->interrupt_injected % 64);
}
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);
-
- sregs.idt.limit = env->idt.limit;
- sregs.idt.base = env->idt.base;
- sregs.gdt.limit = env->gdt.limit;
- sregs.gdt.base = env->gdt.base;
+ set_seg(&sregs->tr, &env->tr);
+ set_seg(&sregs->ldt, &env->ldt);
- sregs.cr0 = env->cr[0];
- sregs.cr2 = env->cr[2];
- sregs.cr3 = env->cr[3];
- sregs.cr4 = env->cr[4];
+ 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.cr8 = cpu_get_apic_tpr(env);
- sregs.apic_base = cpu_get_apic_base(env);
+ sregs->cr0 = env->cr[0];
+ sregs->cr2 = env->cr[2];
+ sregs->cr3 = env->cr[3];
+ sregs->cr4 = env->cr[4];
- sregs.efer = env->efer;
+ sregs->cr8 = cpu_get_apic_tpr(env);
+ sregs->apic_base = cpu_get_apic_base(env);
- return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ sregs->efer = env->efer;
}
static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
@@ -470,20 +450,17 @@ 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 *msr_list)
{
- 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 *msrs = msr_list->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);
+ 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);
#ifdef TARGET_X86_64
/* FIXME if lm capable */
@@ -492,78 +469,63 @@ static int kvm_put_msrs(CPUState *env)
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
#endif
- msr_data.info.nmsrs = n;
-
- return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
-
+ msr_list->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 bit, i, ret;
-
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret < 0)
- return ret;
+ int bit, i;
/* There can only be one pending IRQ set in the bitmap at a time, so try
to find it and save its number instead (-1 for none). */
env->interrupt_injected = -1;
- for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) {
- if (sregs.interrupt_bitmap[i]) {
- bit = ctz64(sregs.interrupt_bitmap[i]);
+ for (i = 0; i < ARRAY_SIZE(sregs->interrupt_bitmap); i++) {
+ if (sregs->interrupt_bitmap[i]) {
+ bit = ctz64(sregs->interrupt_bitmap[i]);
env->interrupt_injected = i * 64 + bit;
break;
}
}
- 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 ~( \
@@ -572,8 +534,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)) &
@@ -605,25 +565,20 @@ 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 *msr_list)
{
- 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 *msrs = msr_list->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;
+ if (kvm_has_msr_star(env)) {
+ msrs[n++].index = MSR_STAR;
+ }
msrs[n++].index = MSR_IA32_TSC;
#ifdef TARGET_X86_64
/* FIXME lm_capable_kernel */
@@ -632,12 +587,15 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_FMASK;
msrs[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;
+ msr_list->nmsrs = n;
+}
- for (i = 0; i < ret; i++) {
+static void kvm_get_msrs(CPUState *env, struct kvm_msrs *msr_list)
+{
+ struct kvm_msr_entry *msrs = msr_list->entries;
+ int i;
+
+ for (i = 0; i < msr_list->nmsrs; i++) {
switch (msrs[i].index) {
case MSR_IA32_SYSENTER_CS:
env->sysenter_cs = msrs[i].data;
@@ -670,60 +628,147 @@ static int kvm_get_msrs(CPUState *env)
break;
}
}
-
- return 0;
}
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 {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[5];
+ } 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);
- if (ret < 0)
- return ret;
+ 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;
+
+ if (kvm_has_vcpu_state()) {
+ request.header.nsubstates = ARRAY_SIZE(request.header.substates);
+ request.header.substates[0].type = KVM_VCPU_STATE_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_STATE_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_STATE_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_STATE_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_STATE_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_VCPU_STATE, &request);
+ if (ret < 0) {
+ return ret;
+ }
+ } else
+#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;
-
- ret = kvm_get_msrs(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 {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[5];
+ } request;
+#endif
- ret = kvm_get_mp_state(env);
- if (ret < 0)
- return ret;
+ kvm_prepare_get_msrs(env, &msrs.info);
+
+#ifdef KVM_CAP_VCPU_STATE
+ if (kvm_has_vcpu_state()) {
+ request.header.nsubstates = ARRAY_SIZE(request.header.substates);
+ request.header.substates[0].type = KVM_VCPU_STATE_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_STATE_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_STATE_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_STATE_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_STATE_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_STATE, &request);
+ if (ret < 0) {
+ return ret;
+ }
+ msrs.info.nmsrs = msrs.info.nprocessed;
+ env->mp_state = mp_state.mp_state;
+ } 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;
+ }
+ }
+ kvm_getput_regs(env, ®s, 0);
+ kvm_get_fpu(env, &fpu);
+ kvm_get_sregs(env, &sregs);
+ kvm_get_msrs(env, &msrs.info);
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/5] kvm: x86: Refactor use of interrupt_bitmap
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
` (3 preceding siblings ...)
2009-11-06 18:39 ` [Qemu-devel] [PATCH 2/5] kvm: Add arch reset handler Jan Kiszka
@ 2009-11-06 18:39 ` Jan Kiszka
4 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
Drop interrupt_bitmap from the cpustate and solely rely on the integer
interupt_injected. This prepares us for the new injected-interrupt
interface, which will deprecate the bitmap, while preserving
compatibility.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
target-i386/cpu.h | 3 +--
target-i386/kvm.c | 25 ++++++++++++++++++-------
target-i386/machine.c | 24 ++----------------------
3 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5929d28..eb9532a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -691,8 +691,8 @@ typedef struct CPUX86State {
MTRRVar mtrr_var[8];
/* For KVM */
- uint64_t interrupt_bitmap[256 / 64];
uint32_t mp_state;
+ int32_t interrupt_injected;
/* in order to simplify APIC support, we leave this pointer to the
user */
@@ -709,7 +709,6 @@ typedef struct CPUX86State {
uint16_t fpus_vmstate;
uint16_t fptag_vmstate;
uint16_t fpregs_format_vmstate;
- int32_t pending_irq_vmstate;
} CPUX86State;
CPUX86State *cpu_x86_init(const char *cpu_model);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ca99cc7..c769d70 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -23,6 +23,7 @@
#include "kvm.h"
#include "cpu.h"
#include "gdbstub.h"
+#include "host-utils.h"
//#define DEBUG_KVM
@@ -223,6 +224,7 @@ int kvm_arch_init_vcpu(CPUState *env)
void kvm_arch_reset_vcpu(CPUState *env)
{
+ env->interrupt_injected = -1;
}
static int kvm_has_msr_star(CPUState *env)
@@ -411,9 +413,11 @@ static int kvm_put_sregs(CPUState *env)
{
struct kvm_sregs sregs;
- memcpy(sregs.interrupt_bitmap,
- env->interrupt_bitmap,
- sizeof(sregs.interrupt_bitmap));
+ memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
+ if (env->interrupt_injected >= 0) {
+ sregs.interrupt_bitmap[env->interrupt_injected / 64] |=
+ (uint64_t)1 << (env->interrupt_injected % 64);
+ }
if ((env->eflags & VM_MASK)) {
set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
@@ -520,15 +524,22 @@ static int kvm_get_sregs(CPUState *env)
{
struct kvm_sregs sregs;
uint32_t hflags;
- int ret;
+ int bit, i, 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));
+ /* There can only be one pending IRQ set in the bitmap at a time, so try
+ to find it and save its number instead (-1 for none). */
+ env->interrupt_injected = -1;
+ for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) {
+ if (sregs.interrupt_bitmap[i]) {
+ bit = ctz64(sregs.interrupt_bitmap[i]);
+ env->interrupt_injected = i * 64 + bit;
+ break;
+ }
+ }
get_seg(&env->segs[R_CS], &sregs.cs);
get_seg(&env->segs[R_DS], &sregs.ds);
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 869c681..c09b049 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -2,7 +2,6 @@
#include "hw/boards.h"
#include "hw/pc.h"
#include "hw/isa.h"
-#include "host-utils.h"
#include "exec-all.h"
#include "kvm.h"
@@ -320,7 +319,7 @@ static const VMStateInfo vmstate_hack_uint64_as_uint32 = {
static void cpu_pre_save(void *opaque)
{
CPUState *env = opaque;
- int i, bit;
+ int i;
cpu_synchronize_state(env);
@@ -336,17 +335,6 @@ static void cpu_pre_save(void *opaque)
#else
env->fpregs_format_vmstate = 1;
#endif
-
- /* There can only be one pending IRQ set in the bitmap at a time, so try
- to find it and save its number instead (-1 for none). */
- env->pending_irq_vmstate = -1;
- for (i = 0; i < ARRAY_SIZE(env->interrupt_bitmap); i++) {
- if (env->interrupt_bitmap[i]) {
- bit = ctz64(env->interrupt_bitmap[i]);
- env->pending_irq_vmstate = i * 64 + bit;
- break;
- }
- }
}
static int cpu_pre_load(void *opaque)
@@ -375,14 +363,6 @@ static int cpu_post_load(void *opaque, int version_id)
for (i = 0; i < 4; i++)
hw_breakpoint_insert(env, i);
- if (version_id >= 9) {
- memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
- if (env->pending_irq_vmstate >= 0) {
- env->interrupt_bitmap[env->pending_irq_vmstate / 64] |=
- (uint64_t)1 << (env->pending_irq_vmstate % 64);
- }
- }
-
tlb_flush(env, 1);
return 0;
}
@@ -465,7 +445,7 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_UINT64_V(mtrr_deftype, CPUState, 8),
VMSTATE_MTRR_VARS(mtrr_var, CPUState, 8, 8),
/* KVM-related states */
- VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9),
+ VMSTATE_INT32_V(interrupt_injected, CPUState, 9),
VMSTATE_UINT32_V(mp_state, CPUState, 9),
VMSTATE_UINT64_V(tsc, CPUState, 9),
/* MCE */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 5/5] kvm: x86: Add support for event states
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 1/5] kvm: x86: Fix merge artifact of f8d926e9 about mp_state Jan Kiszka
@ 2009-11-06 18:39 ` Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-06 18:39 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
This patch extends the KVM state sync logic with the event substate from
the new VCPU state interface, giving access to yet missing exception,
interrupt and NMI states.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
target-i386/cpu.h | 5 ++++
target-i386/kvm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++--
target-i386/machine.c | 5 ++++
3 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index eb9532a..9c3e905 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -693,6 +693,11 @@ typedef struct CPUX86State {
/* For KVM */
uint32_t mp_state;
int32_t interrupt_injected;
+ uint8_t soft_interrupt;
+ uint8_t nmi_injected;
+ uint8_t nmi_pending;
+ uint8_t has_error_code;
+ uint32_t sipi_vector;
/* 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 25c6bde..a995847 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -225,6 +225,8 @@ int kvm_arch_init_vcpu(CPUState *env)
void kvm_arch_reset_vcpu(CPUState *env)
{
env->interrupt_injected = -1;
+ env->nmi_injected = 0;
+ env->nmi_pending = 0;
}
static int kvm_has_msr_star(CPUState *env)
@@ -630,6 +632,48 @@ static void kvm_get_msrs(CPUState *env, struct kvm_msrs *msr_list)
}
}
+#ifdef KVM_CAP_VCPU_STATE
+static void kvm_put_events(CPUState *env, struct kvm_x86_event_state *events)
+{
+ events->exception.injected = (env->exception_index >= 0);
+ events->exception.nr = env->exception_index;
+ events->exception.has_error_code = env->has_error_code;
+ events->exception.error_code = env->error_code;
+
+ events->interrupt.injected = (env->interrupt_injected >= 0);
+ events->interrupt.nr = env->interrupt_injected;
+ events->interrupt.soft = env->soft_interrupt;
+
+ events->nmi.injected = env->nmi_injected;
+ events->nmi.pending = env->nmi_pending;
+ events->nmi.masked = !!(env->hflags2 & HF2_NMI_MASK);
+
+ events->sipi_vector = env->sipi_vector;
+}
+
+static void kvm_get_events(CPUState *env, struct kvm_x86_event_state *events)
+{
+ env->exception_index =
+ events->exception.injected ? events->exception.nr : -1;
+ env->has_error_code = events->exception.has_error_code;
+ env->error_code = events->exception.error_code;
+
+ env->interrupt_injected =
+ events->interrupt.injected ? events->interrupt.nr : -1;
+ env->soft_interrupt = events->interrupt.soft;
+
+ env->nmi_injected = events->nmi.injected;
+ env->nmi_pending = events->nmi.pending;
+ if (events->nmi.masked) {
+ env->hflags2 |= HF2_NMI_MASK;
+ } else {
+ env->hflags2 &= ~HF2_NMI_MASK;
+ }
+
+ env->sipi_vector = events->sipi_vector;
+}
+#endif
+
int kvm_arch_put_registers(CPUState *env)
{
struct kvm_regs regs;
@@ -642,9 +686,10 @@ int kvm_arch_put_registers(CPUState *env)
int ret;
#ifdef KVM_CAP_VCPU_STATE
struct kvm_mp_state mp_state;
+ struct kvm_x86_event_state events;
struct {
struct kvm_vcpu_state header;
- struct kvm_vcpu_substate substates[5];
+ struct kvm_vcpu_substate substates[6];
} request;
#endif
@@ -654,6 +699,7 @@ int kvm_arch_put_registers(CPUState *env)
kvm_put_msrs(env, &msrs.info);
#ifdef KVM_CAP_VCPU_STATE
mp_state.mp_state = env->mp_state;
+ kvm_put_events(env, &events);
if (kvm_has_vcpu_state()) {
request.header.nsubstates = ARRAY_SIZE(request.header.substates);
@@ -667,6 +713,8 @@ int kvm_arch_put_registers(CPUState *env)
request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
request.header.substates[4].type = KVM_VCPU_STATE_MP;
request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+ request.header.substates[5].type = KVM_X86_VCPU_STATE_EVENTS;
+ request.header.substates[5].offset = (size_t)&events - (size_t)&request;
ret = kvm_vcpu_ioctl(env, KVM_SET_VCPU_STATE, &request);
if (ret < 0) {
@@ -712,9 +760,10 @@ int kvm_arch_get_registers(CPUState *env)
int ret = -1;
#ifdef KVM_CAP_VCPU_STATE
struct kvm_mp_state mp_state;
+ struct kvm_x86_event_state events;
struct {
struct kvm_vcpu_state header;
- struct kvm_vcpu_substate substates[5];
+ struct kvm_vcpu_substate substates[6];
} request;
#endif
@@ -733,6 +782,8 @@ int kvm_arch_get_registers(CPUState *env)
request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
request.header.substates[4].type = KVM_VCPU_STATE_MP;
request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+ request.header.substates[5].type = KVM_X86_VCPU_STATE_EVENTS;
+ request.header.substates[5].offset = (size_t)&events - (size_t)&request;
ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_STATE, &request);
if (ret < 0) {
@@ -740,6 +791,7 @@ int kvm_arch_get_registers(CPUState *env)
}
msrs.info.nmsrs = msrs.info.nprocessed;
env->mp_state = mp_state.mp_state;
+ kvm_get_events(env, &events);
} else
#endif
{
diff --git a/target-i386/machine.c b/target-i386/machine.c
index c09b049..54d324e 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -448,6 +448,11 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_INT32_V(interrupt_injected, CPUState, 9),
VMSTATE_UINT32_V(mp_state, CPUState, 9),
VMSTATE_UINT64_V(tsc, CPUState, 9),
+ VMSTATE_UINT8_V(soft_interrupt, CPUState, 11),
+ VMSTATE_UINT8_V(nmi_injected, CPUState, 11),
+ VMSTATE_UINT8_V(nmi_pending, CPUState, 11),
+ VMSTATE_UINT8_V(has_error_code, CPUState, 11),
+ VMSTATE_UINT32_V(sipi_vector, CPUState, 11),
/* MCE */
VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
VMSTATE_UINT64_V(mcg_status, CPUState, 10),
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH v2 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE
2009-11-06 18:39 ` [Qemu-devel] [PATCH 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
@ 2009-11-09 19:02 ` Jan Kiszka
0 siblings, 0 replies; 7+ messages in thread
From: Jan Kiszka @ 2009-11-09 19:02 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Marcelo Tosatti, qemu-devel, Avi Kivity
This patch adds support for the new KVM IOCTLs KVM_GET/SET_VCPU_STATE.
They are supposed to be introduced with 2.6.33 or 34 and allow to extend
the VCPU state exchange between kernel and user space without adding new
IOCTLs and to acquire/set a complete state via a single systemcall.
In order to remain backward-compatible to existing kernels, the old
state synchronization interface is of course kept as a fall-back.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
Changes in v2:
- A classic: Let's make it cleaner, use ARRAY_SIZE, no need to test.
IOW: fix request.header.nsubstates initialization
(queue on kiszka.org updated)
kvm-all.c | 11 +
kvm.h | 1
target-i386/kvm.c | 451 +++++++++++++++++++++++++++++------------------------
3 files changed, 260 insertions(+), 203 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 31bc2f8..0d22e42 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -61,6 +61,7 @@ struct KVMState
int coalesced_mmio;
int broken_set_mem_region;
int migration_log;
+ int vcpu_state;
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
@@ -499,6 +500,11 @@ int kvm_init(int smp_cpus)
}
#endif
+ s->vcpu_state = 0;
+#ifdef KVM_CAP_VCPU_STATE
+ s->vcpu_state = kvm_check_extension(s, KVM_CAP_VCPU_STATE);
+#endif
+
ret = kvm_arch_init(s, smp_cpus);
if (ret < 0)
goto err;
@@ -888,6 +894,11 @@ int kvm_has_sync_mmu(void)
#endif
}
+int kvm_has_vcpu_state(void)
+{
+ return kvm_state->vcpu_state;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
diff --git a/kvm.h b/kvm.h
index 6a82f6a..9e237d1 100644
--- a/kvm.h
+++ b/kvm.h
@@ -47,6 +47,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
int kvm_set_migration_log(int enable);
int kvm_has_sync_mmu(void);
+int kvm_has_vcpu_state(void);
void kvm_setup_guest_memory(void *start, size_t size);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c769d70..101c313 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -352,115 +352,95 @@ 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)
-{
- 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);
+static void kvm_getput_regs(CPUState *env, struct kvm_regs *regs, int 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;
-
- memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
+ memset(sregs->interrupt_bitmap, 0, sizeof(sregs->interrupt_bitmap));
if (env->interrupt_injected >= 0) {
- sregs.interrupt_bitmap[env->interrupt_injected / 64] |=
+ sregs->interrupt_bitmap[env->interrupt_injected / 64] |=
(uint64_t)1 << (env->interrupt_injected % 64);
}
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);
-
- sregs.idt.limit = env->idt.limit;
- sregs.idt.base = env->idt.base;
- sregs.gdt.limit = env->gdt.limit;
- sregs.gdt.base = env->gdt.base;
+ set_seg(&sregs->tr, &env->tr);
+ set_seg(&sregs->ldt, &env->ldt);
- sregs.cr0 = env->cr[0];
- sregs.cr2 = env->cr[2];
- sregs.cr3 = env->cr[3];
- sregs.cr4 = env->cr[4];
+ 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.cr8 = cpu_get_apic_tpr(env);
- sregs.apic_base = cpu_get_apic_base(env);
+ sregs->cr0 = env->cr[0];
+ sregs->cr2 = env->cr[2];
+ sregs->cr3 = env->cr[3];
+ sregs->cr4 = env->cr[4];
- sregs.efer = env->efer;
+ sregs->cr8 = cpu_get_apic_tpr(env);
+ sregs->apic_base = cpu_get_apic_base(env);
- return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
+ sregs->efer = env->efer;
}
static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
@@ -470,20 +450,17 @@ 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 *msr_list)
{
- 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 *msrs = msr_list->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);
+ 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);
#ifdef TARGET_X86_64
/* FIXME if lm capable */
@@ -492,78 +469,63 @@ static int kvm_put_msrs(CPUState *env)
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
#endif
- msr_data.info.nmsrs = n;
-
- return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
-
+ msr_list->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 bit, i, ret;
-
- ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret < 0)
- return ret;
+ int bit, i;
/* There can only be one pending IRQ set in the bitmap at a time, so try
to find it and save its number instead (-1 for none). */
env->interrupt_injected = -1;
- for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) {
- if (sregs.interrupt_bitmap[i]) {
- bit = ctz64(sregs.interrupt_bitmap[i]);
+ for (i = 0; i < ARRAY_SIZE(sregs->interrupt_bitmap); i++) {
+ if (sregs->interrupt_bitmap[i]) {
+ bit = ctz64(sregs->interrupt_bitmap[i]);
env->interrupt_injected = i * 64 + bit;
break;
}
}
- 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 ~( \
@@ -572,8 +534,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)) &
@@ -605,25 +565,20 @@ 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 *msr_list)
{
- 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 *msrs = msr_list->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;
+ if (kvm_has_msr_star(env)) {
+ msrs[n++].index = MSR_STAR;
+ }
msrs[n++].index = MSR_IA32_TSC;
#ifdef TARGET_X86_64
/* FIXME lm_capable_kernel */
@@ -632,12 +587,15 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_FMASK;
msrs[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;
+ msr_list->nmsrs = n;
+}
- for (i = 0; i < ret; i++) {
+static void kvm_get_msrs(CPUState *env, struct kvm_msrs *msr_list)
+{
+ struct kvm_msr_entry *msrs = msr_list->entries;
+ int i;
+
+ for (i = 0; i < msr_list->nmsrs; i++) {
switch (msrs[i].index) {
case MSR_IA32_SYSENTER_CS:
env->sysenter_cs = msrs[i].data;
@@ -670,60 +628,147 @@ static int kvm_get_msrs(CPUState *env)
break;
}
}
-
- return 0;
}
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 {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[5];
+ } 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);
- if (ret < 0)
- return ret;
+ 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;
+
+ if (kvm_has_vcpu_state()) {
+ request.header.nsubstates = ARRAY_SIZE(request.substates);
+ request.header.substates[0].type = KVM_VCPU_STATE_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_STATE_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_STATE_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_STATE_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_STATE_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_SET_VCPU_STATE, &request);
+ if (ret < 0) {
+ return ret;
+ }
+ } else
+#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;
-
- ret = kvm_get_msrs(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 {
+ struct kvm_vcpu_state header;
+ struct kvm_vcpu_substate substates[5];
+ } request;
+#endif
- ret = kvm_get_mp_state(env);
- if (ret < 0)
- return ret;
+ kvm_prepare_get_msrs(env, &msrs.info);
+
+#ifdef KVM_CAP_VCPU_STATE
+ if (kvm_has_vcpu_state()) {
+ request.header.nsubstates = ARRAY_SIZE(request.substates);
+ request.header.substates[0].type = KVM_VCPU_STATE_REGS;
+ request.header.substates[0].offset = (size_t)®s - (size_t)&request;
+ request.header.substates[1].type = KVM_VCPU_STATE_FPU;
+ request.header.substates[1].offset = (size_t)&fpu - (size_t)&request;
+ request.header.substates[2].type = KVM_VCPU_STATE_SREGS;
+ request.header.substates[2].offset = (size_t)&sregs - (size_t)&request;
+ request.header.substates[3].type = KVM_X86_VCPU_STATE_MSRS;
+ request.header.substates[3].offset = (size_t)&msrs - (size_t)&request;
+ request.header.substates[4].type = KVM_VCPU_STATE_MP;
+ request.header.substates[4].offset = (size_t)&mp_state - (size_t)&request;
+
+ ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_STATE, &request);
+ if (ret < 0) {
+ return ret;
+ }
+ msrs.info.nmsrs = msrs.info.nprocessed;
+ env->mp_state = mp_state.mp_state;
+ } 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;
+ }
+ }
+ kvm_getput_regs(env, ®s, 0);
+ kvm_get_fpu(env, &fpu);
+ kvm_get_sregs(env, &sregs);
+ kvm_get_msrs(env, &msrs.info);
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-11-09 19:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-06 18:39 [Qemu-devel] [PATCH 0/5] Extensible VCPU state IOCTL Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 1/5] kvm: x86: Fix merge artifact of f8d926e9 about mp_state Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 5/5] kvm: x86: Add support for event states Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 4/5] kvm: x86: Add support for KVM_GET/PUT_VCPU_STATE Jan Kiszka
2009-11-09 19:02 ` [Qemu-devel] [PATCH v2 " Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 2/5] kvm: Add arch reset handler Jan Kiszka
2009-11-06 18:39 ` [Qemu-devel] [PATCH 3/5] kvm: x86: Refactor use of interrupt_bitmap 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).