mirror of https://gitee.com/openkylin/qemu.git
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>
This commit is contained in:
parent
5a2e3c2e11
commit
a0fb002c64
11
kvm-all.c
11
kvm-all.c
|
@ -61,6 +61,7 @@ struct KVMState
|
|||
int coalesced_mmio;
|
||||
int broken_set_mem_region;
|
||||
int migration_log;
|
||||
int vcpu_events;
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
|
||||
#endif
|
||||
|
@ -479,6 +480,11 @@ int kvm_init(int smp_cpus)
|
|||
}
|
||||
#endif
|
||||
|
||||
s->vcpu_events = 0;
|
||||
#ifdef KVM_CAP_VCPU_EVENTS
|
||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||
#endif
|
||||
|
||||
ret = kvm_arch_init(s, smp_cpus);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
@ -868,6 +874,11 @@ int kvm_has_sync_mmu(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
int kvm_has_vcpu_events(void)
|
||||
{
|
||||
return kvm_state->vcpu_events;
|
||||
}
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size)
|
||||
{
|
||||
if (!kvm_has_sync_mmu()) {
|
||||
|
|
1
kvm.h
1
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_events(void);
|
||||
|
||||
void kvm_setup_guest_memory(void *start, size_t size);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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! */
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue