*/
#include "cpu.h"
-#include "exec/ioport.h"
-#include "helper.h"
+#include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
+#include "exec/address-spaces.h"
-#if !defined(CONFIG_USER_ONLY)
-#include "exec/softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
-/* check if Port I/O is allowed in TSS */
-static inline void check_io(CPUX86State *env, int addr, int size)
-{
- int io_offset, val, mask;
-
- /* TSS must be a valid 32 bit one */
- if (!(env->tr.flags & DESC_P_MASK) ||
- ((env->tr.flags >> DESC_TYPE_SHIFT) & 0xf) != 9 ||
- env->tr.limit < 103) {
- goto fail;
- }
- io_offset = cpu_lduw_kernel(env, env->tr.base + 0x66);
- io_offset += (addr >> 3);
- /* Note: the check needs two bytes */
- if ((io_offset + 1) > env->tr.limit) {
- goto fail;
- }
- val = cpu_lduw_kernel(env, env->tr.base + io_offset);
- val >>= (addr & 7);
- mask = (1 << size) - 1;
- /* all bits must be zero to allow the I/O */
- if ((val & mask) != 0) {
- fail:
- raise_exception_err(env, EXCP0D_GPF, 0);
- }
-}
-
-void helper_check_iob(CPUX86State *env, uint32_t t0)
-{
- check_io(env, t0, 1);
-}
-
-void helper_check_iow(CPUX86State *env, uint32_t t0)
-{
- check_io(env, t0, 2);
-}
-
-void helper_check_iol(CPUX86State *env, uint32_t t0)
-{
- check_io(env, t0, 4);
-}
-
-void helper_outb(uint32_t port, uint32_t data)
+void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
{
- cpu_outb(port, data & 0xff);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "outb: port=0x%04x, data=%02x\n", port, data);
+#else
+ address_space_stb(&address_space_io, port, data,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
-target_ulong helper_inb(uint32_t port)
+target_ulong helper_inb(CPUX86State *env, uint32_t port)
{
- return cpu_inb(port);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "inb: port=0x%04x\n", port);
+ return 0;
+#else
+ return address_space_ldub(&address_space_io, port,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
-void helper_outw(uint32_t port, uint32_t data)
+void helper_outw(CPUX86State *env, uint32_t port, uint32_t data)
{
- cpu_outw(port, data & 0xffff);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "outw: port=0x%04x, data=%04x\n", port, data);
+#else
+ address_space_stw(&address_space_io, port, data,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
-target_ulong helper_inw(uint32_t port)
+target_ulong helper_inw(CPUX86State *env, uint32_t port)
{
- return cpu_inw(port);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "inw: port=0x%04x\n", port);
+ return 0;
+#else
+ return address_space_lduw(&address_space_io, port,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
-void helper_outl(uint32_t port, uint32_t data)
+void helper_outl(CPUX86State *env, uint32_t port, uint32_t data)
{
- cpu_outl(port, data);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "outw: port=0x%04x, data=%08x\n", port, data);
+#else
+ address_space_stl(&address_space_io, port, data,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
-target_ulong helper_inl(uint32_t port)
+target_ulong helper_inl(CPUX86State *env, uint32_t port)
{
- return cpu_inl(port);
+#ifdef CONFIG_USER_ONLY
+ fprintf(stderr, "inl: port=0x%04x\n", port);
+ return 0;
+#else
+ return address_space_ldl(&address_space_io, port,
+ cpu_get_mem_attrs(env), NULL);
+#endif
}
void helper_into(CPUX86State *env, int next_eip_addend)
break;
case 8:
if (!(env->hflags2 & HF2_VINTR_MASK)) {
- val = cpu_get_apic_tpr(env->apic_state);
+ val = cpu_get_apic_tpr(x86_env_get_cpu(env)->apic_state);
} else {
val = env->v_tpr;
}
break;
case 8:
if (!(env->hflags2 & HF2_VINTR_MASK)) {
- cpu_set_apic_tpr(env->apic_state, t0);
+ cpu_set_apic_tpr(x86_env_get_cpu(env)->apic_state, t0);
}
env->v_tpr = t0 & 0x0f;
break;
void helper_invlpg(CPUX86State *env, target_ulong addr)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
- tlb_flush_page(env, addr);
+ tlb_flush_page(CPU(cpu), addr);
}
void helper_rdtsc(CPUX86State *env)
uint64_t val;
if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
- raise_exception(env, EXCP0D_GPF);
+ raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
void helper_rdpmc(CPUX86State *env)
{
if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
- raise_exception(env, EXCP0D_GPF);
+ raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
env->sysenter_eip = val;
break;
case MSR_IA32_APICBASE:
- cpu_set_apic_base(env->apic_state, val);
+ cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val);
break;
case MSR_EFER:
{
val = env->sysenter_eip;
break;
case MSR_IA32_APICBASE:
- val = cpu_get_apic_base(env->apic_state);
+ val = cpu_get_apic_base(x86_env_get_cpu(env)->apic_state);
break;
case MSR_EFER:
val = env->efer;
}
#endif
+static void do_pause(X86CPU *cpu)
+{
+ CPUState *cs = CPU(cpu);
+
+ /* Just let another CPU run. */
+ cs->exception_index = EXCP_INTERRUPT;
+ cpu_loop_exit(cs);
+}
+
static void do_hlt(X86CPU *cpu)
{
CPUState *cs = CPU(cpu);
env->hflags &= ~HF_INHIBIT_IRQ_MASK; /* needed if sti is just before */
cs->halted = 1;
- env->exception_index = EXCP_HLT;
- cpu_loop_exit(env);
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
}
void helper_hlt(CPUX86State *env, int next_eip_addend)
void helper_monitor(CPUX86State *env, target_ulong ptr)
{
if ((uint32_t)env->regs[R_ECX] != 0) {
- raise_exception(env, EXCP0D_GPF);
+ raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
/* XXX: store address? */
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
X86CPU *cpu;
if ((uint32_t)env->regs[R_ECX] != 0) {
- raise_exception(env, EXCP0D_GPF);
+ raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
env->eip += next_eip_addend;
cpu = x86_env_get_cpu(env);
cs = CPU(cpu);
/* XXX: not complete but not completely erroneous */
- if (cs->cpu_index != 0 || cs->next_cpu != NULL) {
- /* more than one CPU: do not sleep because another CPU may
- wake this one */
+ if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) {
+ do_pause(cpu);
} else {
do_hlt(cpu);
}
}
+void helper_pause(CPUX86State *env, int next_eip_addend)
+{
+ X86CPU *cpu = x86_env_get_cpu(env);
+
+ cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
+ env->eip += next_eip_addend;
+
+ do_pause(cpu);
+}
+
void helper_debug(CPUX86State *env)
{
- env->exception_index = EXCP_DEBUG;
- cpu_loop_exit(env);
+ CPUState *cs = CPU(x86_env_get_cpu(env));
+
+ cs->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(cs);
}