aboutsummaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/cpu.h3
-rw-r--r--target-i386/helper.c20
2 files changed, 20 insertions, 3 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 910a4b48ce..2114cba920 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -340,6 +340,9 @@
#define EXCP11_ALGN 17
#define EXCP12_MCHK 18
+#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
+ for syscall instruction */
+
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 0a75e8c335..841824fc9a 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -971,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;
@@ -1024,6 +1032,7 @@ void helper_syscall(int next_eip_addend)
env->eip = (uint32_t)env->star;
}
}
+#endif
void helper_sysret(int dflag)
{
@@ -1143,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