diff options
author | Peng Hao <peng.hao2@zte.com.cn> | 2017-07-14 23:47:36 +0800 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-08-01 17:27:33 +0200 |
commit | 4fadfa00301695a4985e2a229cab857b2ce5c775 (patch) | |
tree | 40da96ebfb9c07cb51bd5d62c4a5aaae892e108e /target | |
parent | eb22aeca65f3769af33ba559757b42f24f743c18 (diff) |
target-i386: kvm_get/put_vcpu_events don't handle sipi_vector
qemu call kvm_get_vcpu_events, and kernel return sipi_vector always
0, never valid when reporting to user space. But when qemu calls
kvm_put_vcpu_events will make sipi_vector in kernel be 0. This will
accidently modify sipi_vector when sipi_vector in kernel is not 0.
Signed-off-by: Peng Hao <peng.hao2@zte.com.cn>
Reviewed-by: Liu Yi <liu.yi24@zte.com.cn>
Message-Id: <1500047256-8911-1-git-send-email-peng.hao2@zte.com.cn>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/kvm.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/target/i386/kvm.c b/target/i386/kvm.c index a6613e19f2..6db7783edc 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -2444,8 +2444,10 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) } if (level >= KVM_PUT_RESET_STATE) { - events.flags |= - KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR; + events.flags |= KVM_VCPUEVENT_VALID_NMI_PENDING; + if (env->mp_state == KVM_MP_STATE_SIPI_RECEIVED) { + events.flags |= KVM_VCPUEVENT_VALID_SIPI_VECTOR; + } } return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events); @@ -2633,6 +2635,10 @@ int kvm_arch_put_registers(CPUState *cpu, int level) if (ret < 0) { return ret; } + ret = kvm_put_vcpu_events(x86_cpu, level); + if (ret < 0) { + return ret; + } if (level >= KVM_PUT_RESET_STATE) { ret = kvm_put_mp_state(x86_cpu); if (ret < 0) { @@ -2644,11 +2650,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) if (ret < 0) { return ret; } - - ret = kvm_put_vcpu_events(x86_cpu, level); - if (ret < 0) { - return ret; - } ret = kvm_put_debugregs(x86_cpu); if (ret < 0) { return ret; @@ -2668,35 +2669,39 @@ int kvm_arch_get_registers(CPUState *cs) assert(cpu_is_stopped(cs) || qemu_cpu_is_self(cs)); - ret = kvm_getput_regs(cpu, 0); + ret = kvm_get_vcpu_events(cpu); if (ret < 0) { goto out; } - ret = kvm_get_xsave(cpu); + /* + * KVM_GET_MPSTATE can modify CS and RIP, call it before + * KVM_GET_REGS and KVM_GET_SREGS. + */ + ret = kvm_get_mp_state(cpu); if (ret < 0) { goto out; } - ret = kvm_get_xcrs(cpu); + ret = kvm_getput_regs(cpu, 0); if (ret < 0) { goto out; } - ret = kvm_get_sregs(cpu); + ret = kvm_get_xsave(cpu); if (ret < 0) { goto out; } - ret = kvm_get_msrs(cpu); + ret = kvm_get_xcrs(cpu); if (ret < 0) { goto out; } - ret = kvm_get_mp_state(cpu); + ret = kvm_get_sregs(cpu); if (ret < 0) { goto out; } - ret = kvm_get_apic(cpu); + ret = kvm_get_msrs(cpu); if (ret < 0) { goto out; } - ret = kvm_get_vcpu_events(cpu); + ret = kvm_get_apic(cpu); if (ret < 0) { goto out; } |