Revision 2ed51f5b target-i386/op_helper.c
b/target-i386/op_helper.c | ||
---|---|---|
595 | 595 |
return 0xffff; |
596 | 596 |
} |
597 | 597 |
|
598 |
static int exeption_has_error_code(int intno) |
|
599 |
{ |
|
600 |
switch(intno) { |
|
601 |
case 8: |
|
602 |
case 10: |
|
603 |
case 11: |
|
604 |
case 12: |
|
605 |
case 13: |
|
606 |
case 14: |
|
607 |
case 17: |
|
608 |
return 1; |
|
609 |
} |
|
610 |
return 0; |
|
611 |
} |
|
612 |
|
|
598 | 613 |
#ifdef TARGET_X86_64 |
599 | 614 |
#define SET_ESP(val, sp_mask)\ |
600 | 615 |
do {\ |
... | ... | |
650 | 665 |
uint32_t old_eip, sp_mask; |
651 | 666 |
|
652 | 667 |
has_error_code = 0; |
653 |
if (!is_int && !is_hw) { |
|
654 |
switch(intno) { |
|
655 |
case 8: |
|
656 |
case 10: |
|
657 |
case 11: |
|
658 |
case 12: |
|
659 |
case 13: |
|
660 |
case 14: |
|
661 |
case 17: |
|
662 |
has_error_code = 1; |
|
663 |
break; |
|
664 |
} |
|
665 |
} |
|
668 |
if (!is_int && !is_hw) |
|
669 |
has_error_code = exeption_has_error_code(intno); |
|
666 | 670 |
if (is_int) |
667 | 671 |
old_eip = next_eip; |
668 | 672 |
else |
... | ... | |
886 | 890 |
target_ulong old_eip, esp, offset; |
887 | 891 |
|
888 | 892 |
has_error_code = 0; |
889 |
if (!is_int && !is_hw) { |
|
890 |
switch(intno) { |
|
891 |
case 8: |
|
892 |
case 10: |
|
893 |
case 11: |
|
894 |
case 12: |
|
895 |
case 13: |
|
896 |
case 14: |
|
897 |
case 17: |
|
898 |
has_error_code = 1; |
|
899 |
break; |
|
900 |
} |
|
901 |
} |
|
893 |
if (!is_int && !is_hw) |
|
894 |
has_error_code = exeption_has_error_code(intno); |
|
902 | 895 |
if (is_int) |
903 | 896 |
old_eip = next_eip; |
904 | 897 |
else |
... | ... | |
1198 | 1191 |
EIP = next_eip; |
1199 | 1192 |
} |
1200 | 1193 |
|
1194 |
static void handle_even_inj(int intno, int is_int, int error_code, |
|
1195 |
int is_hw, int rm) |
|
1196 |
{ |
|
1197 |
uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); |
|
1198 |
if (!(event_inj & SVM_EVTINJ_VALID)) { |
|
1199 |
int type; |
|
1200 |
if (is_int) |
|
1201 |
type = SVM_EVTINJ_TYPE_SOFT; |
|
1202 |
else |
|
1203 |
type = SVM_EVTINJ_TYPE_EXEPT; |
|
1204 |
event_inj = intno | type | SVM_EVTINJ_VALID; |
|
1205 |
if (!rm && exeption_has_error_code(intno)) { |
|
1206 |
event_inj |= SVM_EVTINJ_VALID_ERR; |
|
1207 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err), error_code); |
|
1208 |
} |
|
1209 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj); |
|
1210 |
} |
|
1211 |
} |
|
1212 |
|
|
1201 | 1213 |
/* |
1202 | 1214 |
* Begin execution of an interruption. is_int is TRUE if coming from |
1203 | 1215 |
* the int instruction. next_eip is the EIP value AFTER the interrupt |
... | ... | |
1238 | 1250 |
} |
1239 | 1251 |
} |
1240 | 1252 |
if (env->cr[0] & CR0_PE_MASK) { |
1253 |
if (env->hflags & HF_SVMI_MASK) |
|
1254 |
handle_even_inj(intno, is_int, error_code, is_hw, 0); |
|
1241 | 1255 |
#ifdef TARGET_X86_64 |
1242 | 1256 |
if (env->hflags & HF_LMA_MASK) { |
1243 | 1257 |
do_interrupt64(intno, is_int, error_code, next_eip, is_hw); |
... | ... | |
1247 | 1261 |
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); |
1248 | 1262 |
} |
1249 | 1263 |
} else { |
1264 |
if (env->hflags & HF_SVMI_MASK) |
|
1265 |
handle_even_inj(intno, is_int, error_code, is_hw, 1); |
|
1250 | 1266 |
do_interrupt_real(intno, is_int, error_code, next_eip); |
1251 | 1267 |
} |
1268 |
|
|
1269 |
if (env->hflags & HF_SVMI_MASK) { |
|
1270 |
uint32_t event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); |
|
1271 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID); |
|
1272 |
} |
|
1252 | 1273 |
} |
1253 | 1274 |
|
1254 | 1275 |
/* This should come from sysemu.h - if we could include it here... */ |
... | ... | |
4994 | 5015 |
uint8_t vector = event_inj & SVM_EVTINJ_VEC_MASK; |
4995 | 5016 |
uint16_t valid_err = event_inj & SVM_EVTINJ_VALID_ERR; |
4996 | 5017 |
uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err)); |
4997 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID); |
|
4998 | 5018 |
|
4999 | 5019 |
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err); |
5000 | 5020 |
/* FIXME: need to implement valid_err */ |
... | ... | |
5332 | 5352 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); |
5333 | 5353 |
stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1); |
5334 | 5354 |
|
5355 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info), |
|
5356 |
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj))); |
|
5357 |
stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info_err), |
|
5358 |
ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err))); |
|
5359 |
|
|
5335 | 5360 |
env->hflags2 &= ~HF2_GIF_MASK; |
5336 | 5361 |
/* FIXME: Resets the current ASID register to zero (host ASID). */ |
5337 | 5362 |
|
Also available in: Unified diff