put valid data into exit_int_info if needed (Gleb Natapov)
If fault happened during event delivery exit_int_info should contain valid info about the event on vm exit. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7230 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
e268ca5232
commit
2ed51f5bfd
@ -595,6 +595,21 @@ static inline unsigned int get_sp_mask(unsigned int e2)
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
static int exeption_has_error_code(int intno)
|
||||
{
|
||||
switch(intno) {
|
||||
case 8:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 17:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
#define SET_ESP(val, sp_mask)\
|
||||
do {\
|
||||
@ -650,19 +665,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
|
||||
uint32_t old_eip, sp_mask;
|
||||
|
||||
has_error_code = 0;
|
||||
if (!is_int && !is_hw) {
|
||||
switch(intno) {
|
||||
case 8:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 17:
|
||||
has_error_code = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_int && !is_hw)
|
||||
has_error_code = exeption_has_error_code(intno);
|
||||
if (is_int)
|
||||
old_eip = next_eip;
|
||||
else
|
||||
@ -886,19 +890,8 @@ static void do_interrupt64(int intno, int is_int, int error_code,
|
||||
target_ulong old_eip, esp, offset;
|
||||
|
||||
has_error_code = 0;
|
||||
if (!is_int && !is_hw) {
|
||||
switch(intno) {
|
||||
case 8:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 17:
|
||||
has_error_code = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_int && !is_hw)
|
||||
has_error_code = exeption_has_error_code(intno);
|
||||
if (is_int)
|
||||
old_eip = next_eip;
|
||||
else
|
||||
@ -1198,6 +1191,25 @@ void do_interrupt_user(int intno, int is_int, int error_code,
|
||||
EIP = next_eip;
|
||||
}
|
||||
|
||||
static void handle_even_inj(int intno, int is_int, int error_code,
|
||||
int is_hw, int rm)
|
||||
{
|
||||
uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
|
||||
if (!(event_inj & SVM_EVTINJ_VALID)) {
|
||||
int type;
|
||||
if (is_int)
|
||||
type = SVM_EVTINJ_TYPE_SOFT;
|
||||
else
|
||||
type = SVM_EVTINJ_TYPE_EXEPT;
|
||||
event_inj = intno | type | SVM_EVTINJ_VALID;
|
||||
if (!rm && exeption_has_error_code(intno)) {
|
||||
event_inj |= SVM_EVTINJ_VALID_ERR;
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code);
|
||||
}
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin execution of an interruption. is_int is TRUE if coming from
|
||||
* the int instruction. next_eip is the EIP value AFTER the interrupt
|
||||
@ -1238,6 +1250,8 @@ void do_interrupt(int intno, int is_int, int error_code,
|
||||
}
|
||||
}
|
||||
if (env->cr[0] & CR0_PE_MASK) {
|
||||
if (env->hflags & HF_SVMI_MASK)
|
||||
handle_even_inj(intno, is_int, error_code, is_hw, 0);
|
||||
#ifdef TARGET_X86_64
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
|
||||
@ -1247,8 +1261,15 @@ void do_interrupt(int intno, int is_int, int error_code,
|
||||
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
|
||||
}
|
||||
} else {
|
||||
if (env->hflags & HF_SVMI_MASK)
|
||||
handle_even_inj(intno, is_int, error_code, is_hw, 1);
|
||||
do_interrupt_real(intno, is_int, error_code, next_eip);
|
||||
}
|
||||
|
||||
if (env->hflags & HF_SVMI_MASK) {
|
||||
uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj));
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
/* This should come from sysemu.h - if we could include it here... */
|
||||
@ -4994,7 +5015,6 @@ void helper_vmrun(int aflag, int next_eip_addend)
|
||||
uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK;
|
||||
uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR;
|
||||
uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
|
||||
|
||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
|
||||
/* FIXME: need to implement valid_err */
|
||||
@ -5332,6 +5352,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
|
||||
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code);
|
||||
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1);
|
||||
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info),
|
||||
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)));
|
||||
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err),
|
||||
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)));
|
||||
|
||||
env->hflags2 &= ~HF2_GIF_MASK;
|
||||
/* FIXME: Resets the current ASID register to zero (host ASID). */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user