diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-07 11:11:03 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-07 11:11:03 +0200 |
commit | c859bf47e565062b7801a18966913142cf59eda8 (patch) | |
tree | 45b0d133200af9e62d052d7145a604e7d3d23cc0 /target-i386 | |
parent | Merge commit '40ff6d7e8dceca227e7f8a3e8e0d58b2c66d19b4' into upstream-merge (diff) | |
parent | kvm: x86: Add support for VCPU event states (diff) | |
download | qemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.tar.gz qemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.tar.bz2 qemu-kvm-c859bf47e565062b7801a18966913142cf59eda8.zip |
Merge commit 'a0fb002c6462d21ceb9eac8c5772e469ec189374' into upstream-merge
* commit 'a0fb002c6462d21ceb9eac8c5772e469ec189374':
kvm: x86: Add support for VCPU event states
kvm: x86: Fix merge artifact of f8d926e9 about mp_state
targe-ppc: Sync CPU state for KVM
target-ppc: Get MMU state on register sync
qemu: cleanup unused macros in cirrus
qemu: make cirrus init value pci spec compliant
Conflicts:
kvm-all.c
target-i386/kvm.c
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/cpu.h | 5 | ||||
-rw-r--r-- | target-i386/kvm.c | 81 | ||||
-rw-r--r-- | target-i386/machine.c | 6 |
3 files changed, 92 insertions, 0 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h index a638e702b..31412a803 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -711,6 +711,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 552866563..568e2117b 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -226,6 +226,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) @@ -700,6 +702,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; @@ -724,6 +793,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; } @@ -747,6 +820,14 @@ int kvm_arch_get_registers(CPUState *env) if (ret < 0) return ret; + ret = kvm_get_mp_state(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 9ac477b35..402eddc7e 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -460,6 +460,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), @@ -471,6 +476,7 @@ static const VMStateDescription vmstate_cpu = { VMSTATE_UINT64_V(system_time_msr, CPUState, 12), VMSTATE_UINT64_V(wall_clock_msr, CPUState, 12), VMSTATE_END_OF_LIST() + /* The above list is not sorted /wrt version numbers, watch out! */ } }; |