aboutsummaryrefslogtreecommitdiff
path: root/target-i386/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/helper.c')
-rw-r--r--target-i386/helper.c57
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;