summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-user/main.c21
-rw-r--r--linux-user/qemu.h2
-rw-r--r--linux-user/signal.c9
-rw-r--r--linux-user/vm86.c11
-rw-r--r--syscall-i386.h6
5 files changed, 43 insertions, 6 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index c9d0c98604..00dc271778 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -166,7 +166,7 @@ void cpu_loop(CPUX86State *env)
break;
case EXCP00_DIVZ:
if (env->eflags & VM_MASK) {
- do_int(env, trapnr);
+ handle_vm86_trap(env, trapnr);
} else {
/* division by zero */
info.si_signo = SIGFPE;
@@ -176,10 +176,27 @@ void cpu_loop(CPUX86State *env)
queue_signal(info.si_signo, &info);
}
break;
+ case EXCP01_SSTP:
+ case EXCP03_INT3:
+ if (env->eflags & VM_MASK) {
+ handle_vm86_trap(env, trapnr);
+ } else {
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ if (trapnr == EXCP01_SSTP) {
+ info.si_code = TARGET_TRAP_BRKPT;
+ info._sifields._sigfault._addr = env->eip;
+ } else {
+ info.si_code = TARGET_SI_KERNEL;
+ info._sifields._sigfault._addr = 0;
+ }
+ queue_signal(info.si_signo, &info);
+ }
+ break;
case EXCP04_INTO:
case EXCP05_BOUND:
if (env->eflags & VM_MASK) {
- do_int(env, trapnr);
+ handle_vm86_trap(env, trapnr);
} else {
info.si_signo = SIGSEGV;
info.si_errno = 0;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 5613c3ed92..0f004ffa5e 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -83,7 +83,7 @@ extern FILE *logfile;
/* vm86.c */
void save_v86_state(CPUX86State *env);
-void do_int(CPUX86State *env, int intno);
+void handle_vm86_trap(CPUX86State *env, int trapno);
void handle_vm86_fault(CPUX86State *env);
int do_vm86(CPUX86State *env, long subfunction,
struct target_vm86plus_struct * target_v86);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9873071394..145dc29929 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -110,7 +110,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
tinfo->si_signo = sig;
tinfo->si_errno = 0;
tinfo->si_code = 0;
- if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
+ if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
+ sig == SIGBUS || sig == SIGTRAP) {
/* should never come here, but who knows. The information for
the target is irrelevant */
tinfo->_sifields._sigfault._addr = 0;
@@ -131,7 +132,8 @@ static void tswap_siginfo(target_siginfo_t *tinfo,
tinfo->si_signo = tswap32(sig);
tinfo->si_errno = tswap32(info->si_errno);
tinfo->si_code = tswap32(info->si_code);
- if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) {
+ if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV ||
+ sig == SIGBUS || sig == SIGTRAP) {
tinfo->_sifields._sigfault._addr =
tswapl(info->_sifields._sigfault._addr);
} else if (sig >= TARGET_SIGRTMIN) {
@@ -788,6 +790,9 @@ long do_sigreturn(CPUX86State *env)
sigset_t set;
int eax, i;
+#if defined(DEBUG_SIGNAL)
+ fprintf(stderr, "do_sigreturn\n");
+#endif
/* set blocked signals */
target_set.sig[0] = frame->sc.oldmask;
for(i = 1; i < TARGET_NSIG_WORDS; i++)
diff --git a/linux-user/vm86.c b/linux-user/vm86.c
index 8316117e4d..f243af877c 100644
--- a/linux-user/vm86.c
+++ b/linux-user/vm86.c
@@ -178,7 +178,7 @@ static inline unsigned int get_vflags(CPUX86State *env)
/* handle VM86 interrupt (NOTE: the CPU core currently does not
support TSS interrupt revectoring, so this code is always executed) */
-void do_int(CPUX86State *env, int intno)
+static void do_int(CPUX86State *env, int intno)
{
TaskState *ts = env->opaque;
uint32_t *int_ptr, segoffs;
@@ -225,6 +225,15 @@ void do_int(CPUX86State *env, int intno)
return_to_32bit(env, TARGET_VM86_INTx | (intno << 8));
}
+void handle_vm86_trap(CPUX86State *env, int trapno)
+{
+ if (trapno == 1 || trapno == 3) {
+ return_to_32bit(env, TARGET_VM86_TRAP + (trapno << 8));
+ } else {
+ do_int(env, trapno);
+ }
+}
+
#define CHECK_IF_IN_TRAP(disp) \
if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \
(tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \
diff --git a/syscall-i386.h b/syscall-i386.h
index 30e8bc3daa..fbe86109ed 100644
--- a/syscall-i386.h
+++ b/syscall-i386.h
@@ -480,6 +480,12 @@ typedef struct target_siginfo {
#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */
+/*
+ * SIGTRAP si_codes
+ */
+#define TARGET_TRAP_BRKPT (1) /* process breakpoint */
+#define TARGET_TRAP_TRACE (2) /* process trace trap */
+
/* default linux values for the selectors */
#define __USER_CS (0x23)
#define __USER_DS (0x2B)