diff options
author | Jan Kiszka <jan.kiszka@web.de> | 2009-11-25 00:33:03 +0100 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2009-12-03 15:25:57 -0600 |
commit | a0fb002c6462d21ceb9eac8c5772e469ec189374 (patch) | |
tree | 03746f1dd29d82b6bf599a0afde1645454ed8593 /target-i386 | |
parent | 5a2e3c2e11802215cbb69d6e5ad35b5bdc7d5382 (diff) |
kvm: x86: Add support for VCPU event states
This patch extends the qemu-kvm state sync logic with support for
KVM_GET/SET_VCPU_EVENTS, giving access to yet missing exception,
interrupt and NMI states.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.h | 5 | ||||
-rw-r--r-- | target-i386/kvm.c | 77 | ||||
-rw-r--r-- | target-i386/machine.c | 6 |
3 files changed, 88 insertions, 0 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h index eb9532aef3..9c3e905f6f 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 89fd7a52b5..3b61a7fc5d 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) @@ -694,6 +696,73 @@ static int kvm_get_mp_state(CPUState *env) return 0; } +static int kvm_put_vcpu_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_EVENTS + struct kvm_vcpu_events events; + + if (!kvm_has_vcpu_events()) { + return 0; + } + + 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; + + return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events); +#else + return 0; +#endif +} + +static int kvm_get_vcpu_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_EVENTS + struct kvm_vcpu_events events; + int ret; + + if (!kvm_has_vcpu_events()) { + return 0; + } + + ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_EVENTS, &events); + if (ret < 0) { + return ret; + } + 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 + + return 0; +} + int kvm_arch_put_registers(CPUState *env) { int ret; @@ -718,6 +787,10 @@ int kvm_arch_put_registers(CPUState *env) if (ret < 0) return ret; + ret = kvm_put_vcpu_events(env); + if (ret < 0) + return ret; + return 0; } @@ -745,6 +818,10 @@ int kvm_arch_get_registers(CPUState *env) if (ret < 0) return ret; + ret = kvm_get_vcpu_events(env); + if (ret < 0) + return ret; + return 0; } diff --git a/target-i386/machine.c b/target-i386/machine.c index c09b049d90..cdc8898a6f 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), @@ -456,6 +461,7 @@ static const VMStateDescription vmstate_cpu = { /* rdtscp */ VMSTATE_UINT64_V(tsc_aux, CPUState, 11), VMSTATE_END_OF_LIST() + /* The above list is not sorted /wrt version numbers, watch out! */ } }; |