From: Gleb Natapov <gleb@redhat.com>
To: qemu-devel@nongnu.org
Cc: agraf@suse.de
Subject: [Qemu-devel] [PATCH][SVM] put valid data into exit_int_info if needed
Date: Mon, 20 Apr 2009 16:34:39 +0300 [thread overview]
Message-ID: <20090420133439.GY10126@redhat.com> (raw)
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>
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index be09263..091c724 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -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). */
--
Gleb.
next reply other threads:[~2009-04-20 13:34 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-20 13:34 Gleb Natapov [this message]
2009-04-22 20:22 ` [Qemu-devel] [PATCH][SVM] put valid data into exit_int_info if needed Anthony Liguori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090420133439.GY10126@redhat.com \
--to=gleb@redhat.com \
--cc=agraf@suse.de \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.