* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#define CPU_NO_GLOBAL_REGS
#include "exec.h"
void helper_outb(uint32_t port, uint32_t data)
{
- cpu_outb(env, port, data & 0xff);
+ cpu_outb(port, data & 0xff);
}
target_ulong helper_inb(uint32_t port)
{
- return cpu_inb(env, port);
+ return cpu_inb(port);
}
void helper_outw(uint32_t port, uint32_t data)
{
- cpu_outw(env, port, data & 0xffff);
+ cpu_outw(port, data & 0xffff);
}
target_ulong helper_inw(uint32_t port)
{
- return cpu_inw(env, port);
+ return cpu_inw(port);
}
void helper_outl(uint32_t port, uint32_t data)
{
- cpu_outl(env, port, data);
+ cpu_outl(port, data);
}
target_ulong helper_inl(uint32_t port)
{
- return cpu_inl(env, port);
+ return cpu_inl(port);
}
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 {\
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
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
env->eflags |= IF_MASK;
cpu_x86_set_cpl(env, 3);
}
-#ifdef CONFIG_KQEMU
- if (kqemu_is_ok(env)) {
- if (env->hflags & HF_LMA_MASK)
- CC_OP = CC_OP_EFLAGS;
- env->exception_index = -1;
- cpu_loop_exit();
- }
-#endif
}
#endif
EIP = next_eip;
}
+#if !defined(CONFIG_USER_ONLY)
+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);
+ }
+}
+#endif
+
/*
* Begin execution of an interruption. is_int is TRUE if coming from
* the int instruction. next_eip is the EIP value AFTER the interrupt
}
}
if (env->cr[0] & CR0_PE_MASK) {
+#if !defined(CONFIG_USER_ONLY)
+ if (env->hflags & HF_SVMI_MASK)
+ handle_even_inj(intno, is_int, error_code, is_hw, 0);
+#endif
#ifdef TARGET_X86_64
if (env->hflags & HF_LMA_MASK) {
do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
}
} else {
+#if !defined(CONFIG_USER_ONLY)
+ if (env->hflags & HF_SVMI_MASK)
+ handle_even_inj(intno, is_int, error_code, is_hw, 1);
+#endif
do_interrupt_real(intno, is_int, error_code, next_eip);
}
+
+#if !defined(CONFIG_USER_ONLY)
+ 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);
+ }
+#endif
}
/* This should come from sysemu.h - if we could include it here... */
SET_ESP(sp, sp_mask);
EIP = offset;
}
-#ifdef CONFIG_KQEMU
- if (kqemu_is_ok(env)) {
- env->exception_index = -1;
- cpu_loop_exit();
- }
-#endif
}
/* real and vm86 mode iret */
helper_ret_protected(shift, 1, 0);
}
env->hflags2 &= ~HF2_NMI_MASK;
-#ifdef CONFIG_KQEMU
- if (kqemu_is_ok(env)) {
- CC_OP = CC_OP_EFLAGS;
- env->exception_index = -1;
- cpu_loop_exit();
- }
-#endif
}
void helper_lret_protected(int shift, int addend)
{
helper_ret_protected(shift, 0, addend);
-#ifdef CONFIG_KQEMU
- if (kqemu_is_ok(env)) {
- env->exception_index = -1;
- cpu_loop_exit();
- }
-#endif
}
void helper_sysenter(void)
}
ESP = ECX;
EIP = EDX;
-#ifdef CONFIG_KQEMU
- if (kqemu_is_ok(env)) {
- env->exception_index = -1;
- cpu_loop_exit();
- }
-#endif
}
#if defined(CONFIG_USER_ONLY)
case MSR_MTRRdefType:
env->mtrr_deftype = val;
break;
+ case MSR_MCG_STATUS:
+ env->mcg_status = val;
+ break;
+ case MSR_MCG_CTL:
+ if ((env->mcg_cap & MCG_CTL_P)
+ && (val == 0 || val == ~(uint64_t)0))
+ env->mcg_ctl = val;
+ break;
default:
+ if ((uint32_t)ECX >= MSR_MC0_CTL
+ && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
+ uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
+ if ((offset & 0x3) != 0
+ || (val == 0 || val == ~(uint64_t)0))
+ env->mce_banks[offset] = val;
+ break;
+ }
/* XXX: exception ? */
break;
}
case MSR_KERNELGSBASE:
val = env->kernelgsbase;
break;
-#endif
-#ifdef CONFIG_KQEMU
- case MSR_QPI_COMMBASE:
- if (env->kqemu_enabled) {
- val = kqemu_comm_base;
- } else {
- val = 0;
- }
- break;
#endif
case MSR_MTRRphysBase(0):
case MSR_MTRRphysBase(1):
/* XXX: exception ? */
val = 0;
break;
+ case MSR_MCG_CAP:
+ val = env->mcg_cap;
+ break;
+ case MSR_MCG_CTL:
+ if (env->mcg_cap & MCG_CTL_P)
+ val = env->mcg_ctl;
+ else
+ val = 0;
+ break;
+ case MSR_MCG_STATUS:
+ val = env->mcg_status;
+ break;
default:
+ if ((uint32_t)ECX >= MSR_MC0_CTL
+ && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
+ uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
+ val = env->mce_banks[offset];
+ break;
+ }
/* XXX: exception ? */
val = 0;
break;
cpu_loop_exit();
}
+void helper_reset_rf(void)
+{
+ env->eflags &= ~RF_MASK;
+}
+
void helper_raise_interrupt(int intno, int next_eip_addend)
{
raise_interrupt(intno, 1, 0, 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 */
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). */