diff options
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r-- | target-i386/helper.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c index 154708e56..bad3f7c1b 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "exec.h" +#include "host-utils.h" + //#define DEBUG_PCALL #if 0 @@ -969,6 +971,14 @@ static void do_interrupt64(int intno, int is_int, int error_code, } #endif +#if defined(CONFIG_USER_ONLY) +void helper_syscall(int next_eip_addend) +{ + env->exception_index = EXCP_SYSCALL; + env->exception_next_eip = env->eip + next_eip_addend; + cpu_loop_exit(); +} +#else void helper_syscall(int next_eip_addend) { int selector; @@ -1022,6 +1032,7 @@ void helper_syscall(int next_eip_addend) env->eip = (uint32_t)env->star; } } +#endif void helper_sysret(int dflag) { @@ -1141,18 +1152,23 @@ void do_interrupt_user(int intno, int is_int, int error_code, { SegmentCache *dt; target_ulong ptr; - int dpl, cpl; + int dpl, cpl, shift; uint32_t e2; dt = &env->idt; - ptr = dt->base + (intno * 8); + if (env->hflags & HF_LMA_MASK) { + shift = 4; + } else { + shift = 3; + } + ptr = dt->base + (intno << shift); e2 = ldl_kernel(ptr + 4); dpl = (e2 >> DESC_DPL_SHIFT) & 3; cpl = env->hflags & HF_CPL_MASK; /* check privledge if software int */ if (is_int && dpl < cpl) - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); + raise_exception_err(EXCP0D_GPF, (intno << shift) + 2); /* Since we emulate only user space, we cannot do more than exiting the emulation with the suitable exception and error @@ -1219,7 +1235,7 @@ void do_interrupt(int intno, int is_int, int error_code, * needed. It should only be called, if this is not an interrupt. * Returns the new exception number. */ -int check_exception(int intno, int *error_code) +static int check_exception(int intno, int *error_code) { char first_contributory = env->old_exception == 0 || (env->old_exception >= 10 && @@ -2727,6 +2743,18 @@ void helper_rdtsc(void) EDX = (uint32_t)(val >> 32); } +void helper_rdpmc(void) +{ + if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { + raise_exception(EXCP0D_GPF); + } + + if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) { + /* currently unimplemented */ + raise_exception_err(EXCP06_ILLOP, 0); + } +} + #if defined(CONFIG_USER_ONLY) void helper_wrmsr(void) { @@ -3035,7 +3063,7 @@ void helper_fstt_ST0_A0(void) helper_fstt(ST0, A0); } -void fpu_set_exception(int mask) +static void fpu_set_exception(int mask) { env->fpus |= mask; if (env->fpus & (~env->fpuc & FPUC_EM)) @@ -3723,7 +3751,7 @@ void helper_mulq_EAX_T0(void) { uint64_t r0, r1; - mulu64(&r1, &r0, EAX, T0); + mulu64(&r0, &r1, EAX, T0); EAX = r0; EDX = r1; CC_DST = r0; @@ -3734,7 +3762,7 @@ void helper_imulq_EAX_T0(void) { uint64_t r0, r1; - muls64(&r1, &r0, EAX, T0); + muls64(&r0, &r1, EAX, T0); EAX = r0; EDX = r1; CC_DST = r0; @@ -3745,7 +3773,7 @@ void helper_imulq_T0_T1(void) { uint64_t r0, r1; - muls64(&r1, &r0, T0, T1); + muls64(&r0, &r1, T0, T1); T0 = r0; CC_DST = r0; CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); @@ -3864,7 +3892,11 @@ void update_fp_status(void) #if !defined(CONFIG_USER_ONLY) #define MMUSUFFIX _mmu -#define GETPC() (__builtin_return_address(0)) +#ifdef __s390__ +# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) +#else +# define GETPC() (__builtin_return_address(0)) +#endif #define SHIFT 0 #include "softmmu_template.h" @@ -3884,7 +3916,7 @@ void update_fp_status(void) NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ /* XXX: fix it to restore all registers */ -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) +void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) { TranslationBlock *tb; int ret; @@ -3896,7 +3928,7 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) saved_env = env; env = cpu_single_env; - ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1); + ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); if (ret) { if (retaddr) { /* now we have a real cpu fault */ @@ -4230,7 +4262,8 @@ int svm_check_intercept_param(uint32_t type, uint64_t param) uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); uint16_t port = (uint16_t) (param >> 16); - if(ldub_phys(addr + port / 8) & (1 << (port % 8))) + uint16_t mask = (1 << ((param >> 4) & 7)) - 1; + if(lduw_phys(addr + port / 8) & (mask << (port & 7))) vmexit(type, param); } break; |