Revision bc8a22cc
b/Changelog | ||
---|---|---|
1 |
version 0.1.4: |
|
2 |
|
|
3 |
- more accurate VM86 emulation (can launch small DOS 16 bit |
|
4 |
executables in wine). |
|
5 |
- fixed push/pop fs/gs |
|
6 |
- added iret instruction. |
|
7 |
|
|
8 |
version 0.1.3: |
|
9 |
|
|
10 |
- S390 support (Ulrich Weigand) |
|
11 |
- glibc 2.3.x compile fix (Ulrich Weigand) |
|
12 |
- socketcall endian fix (Ulrich Weigand) |
|
13 |
- struct sockaddr endian fix (Ulrich Weigand) |
|
14 |
- sendmsg/recvmsg endian fix (Ulrich Weigand) |
|
15 |
- execve endian fix (Ulrich Weigand) |
|
16 |
- fdset endian fix (Ulrich Weigand) |
|
17 |
- partial setsockopt syscall support (Ulrich Weigand) |
|
18 |
- more accurate pushf/popf emulation |
|
19 |
- first partial vm86() syscall support (can be used with runcom example). |
|
20 |
- added bound, cmpxchg8b, cpuid instructions |
|
21 |
- added 16 bit addressing support/override for string operations |
|
22 |
- poll() fix |
|
23 |
|
|
24 |
version 0.1.2: |
|
25 |
|
|
26 |
- compile fixes |
|
27 |
- xlat instruction |
|
28 |
- xchg instruction memory lock |
|
29 |
- added simple vm86 example (not working with QEMU yet). The 54 byte |
|
30 |
DOS executable 'pi_10.com' program was released by Bertram |
|
31 |
Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html). |
|
32 |
|
|
1 | 33 |
version 0.1.1: |
2 | 34 |
|
3 | 35 |
- glibc 2.2 compilation fixes |
4 | 36 |
- added -s and -L options |
5 | 37 |
- binary distribution of x86 glibc and wine |
38 |
- big endian fixes in ELF loader and getdents. |
|
6 | 39 |
|
7 | 40 |
version 0.1: |
8 | 41 |
|
b/TODO | ||
---|---|---|
1 |
- fix thread locks |
|
2 |
- fix thread stack liberation |
|
3 |
- fix x86 stack allocation |
|
1 | 4 |
- optimize translated cache chaining (DLL PLT-like system) |
2 | 5 |
- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit |
3 | 6 |
issues, fix 16 bit uid issues) |
4 | 7 |
- finish signal handing (fp87 state, more siginfo conversions) |
5 | 8 |
- verify thread support (clone() and various locks) |
6 |
- vm86 syscall support |
|
7 | 9 |
- overrides/16bit for string ops |
8 | 10 |
- make it self runnable (use same trick as ld.so : include its own relocator and libc) |
9 |
- improved 16 bit support |
|
10 | 11 |
- fix FPU exceptions (in particular: gen_op_fpush not before mem load) |
b/cpu-i386.h | ||
---|---|---|
68 | 68 |
#define VIP_MASK 0x00100000 |
69 | 69 |
#define ID_MASK 0x00200000 |
70 | 70 |
|
71 |
#define EXCP00_DIVZ 1
|
|
72 |
#define EXCP01_SSTP 2
|
|
73 |
#define EXCP02_NMI 3
|
|
74 |
#define EXCP03_INT3 4
|
|
75 |
#define EXCP04_INTO 5
|
|
76 |
#define EXCP05_BOUND 6
|
|
77 |
#define EXCP06_ILLOP 7
|
|
78 |
#define EXCP07_PREX 8
|
|
79 |
#define EXCP08_DBLE 9
|
|
80 |
#define EXCP09_XERR 10
|
|
81 |
#define EXCP0A_TSS 11
|
|
82 |
#define EXCP0B_NOSEG 12
|
|
83 |
#define EXCP0C_STACK 13
|
|
84 |
#define EXCP0D_GPF 14
|
|
85 |
#define EXCP0E_PAGE 15
|
|
86 |
#define EXCP10_COPR 17
|
|
87 |
#define EXCP11_ALGN 18
|
|
88 |
#define EXCP12_MCHK 19
|
|
71 |
#define EXCP00_DIVZ 0
|
|
72 |
#define EXCP01_SSTP 1
|
|
73 |
#define EXCP02_NMI 2
|
|
74 |
#define EXCP03_INT3 3
|
|
75 |
#define EXCP04_INTO 4
|
|
76 |
#define EXCP05_BOUND 5
|
|
77 |
#define EXCP06_ILLOP 6
|
|
78 |
#define EXCP07_PREX 7
|
|
79 |
#define EXCP08_DBLE 8
|
|
80 |
#define EXCP09_XERR 9
|
|
81 |
#define EXCP0A_TSS 10
|
|
82 |
#define EXCP0B_NOSEG 11
|
|
83 |
#define EXCP0C_STACK 12
|
|
84 |
#define EXCP0D_GPF 13
|
|
85 |
#define EXCP0E_PAGE 14
|
|
86 |
#define EXCP10_COPR 16
|
|
87 |
#define EXCP11_ALGN 17
|
|
88 |
#define EXCP12_MCHK 18
|
|
89 | 89 |
|
90 | 90 |
#define EXCP_INTERRUPT 256 /* async interruption */ |
91 | 91 |
|
b/linux-user/main.c | ||
---|---|---|
106 | 106 |
|
107 | 107 |
//#define DEBUG_VM86 |
108 | 108 |
|
109 |
static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) |
|
110 |
{ |
|
111 |
return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1; |
|
112 |
} |
|
113 |
|
|
114 |
static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) |
|
115 |
{ |
|
116 |
return (uint8_t *)((seg << 4) + (reg & 0xffff)); |
|
117 |
} |
|
118 |
|
|
119 |
static inline void pushw(CPUX86State *env, int val) |
|
120 |
{ |
|
121 |
env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | |
|
122 |
((env->regs[R_ESP] - 2) & 0xffff); |
|
123 |
*(uint16_t *)seg_to_linear(env->segs[R_SS], env->regs[R_ESP]) = val; |
|
124 |
} |
|
125 |
|
|
126 |
static inline unsigned int get_vflags(CPUX86State *env) |
|
127 |
{ |
|
128 |
unsigned int eflags; |
|
129 |
eflags = env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); |
|
130 |
if (eflags & VIF_MASK) |
|
131 |
eflags |= IF_MASK; |
|
132 |
return eflags; |
|
133 |
} |
|
134 |
|
|
135 |
void save_v86_state(CPUX86State *env) |
|
136 |
{ |
|
137 |
TaskState *ts = env->opaque; |
|
138 |
#ifdef DEBUG_VM86 |
|
139 |
printf("save_v86_state\n"); |
|
140 |
#endif |
|
141 |
|
|
142 |
/* put the VM86 registers in the userspace register structure */ |
|
143 |
ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); |
|
144 |
ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); |
|
145 |
ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); |
|
146 |
ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); |
|
147 |
ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); |
|
148 |
ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); |
|
149 |
ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); |
|
150 |
ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); |
|
151 |
ts->target_v86->regs.eip = tswap32(env->eip); |
|
152 |
ts->target_v86->regs.cs = tswap16(env->segs[R_CS]); |
|
153 |
ts->target_v86->regs.ss = tswap16(env->segs[R_SS]); |
|
154 |
ts->target_v86->regs.ds = tswap16(env->segs[R_DS]); |
|
155 |
ts->target_v86->regs.es = tswap16(env->segs[R_ES]); |
|
156 |
ts->target_v86->regs.fs = tswap16(env->segs[R_FS]); |
|
157 |
ts->target_v86->regs.gs = tswap16(env->segs[R_GS]); |
|
158 |
ts->target_v86->regs.eflags = tswap32(env->eflags); |
|
159 |
|
|
160 |
/* restore 32 bit registers */ |
|
161 |
env->regs[R_EAX] = ts->vm86_saved_regs.eax; |
|
162 |
env->regs[R_EBX] = ts->vm86_saved_regs.ebx; |
|
163 |
env->regs[R_ECX] = ts->vm86_saved_regs.ecx; |
|
164 |
env->regs[R_EDX] = ts->vm86_saved_regs.edx; |
|
165 |
env->regs[R_ESI] = ts->vm86_saved_regs.esi; |
|
166 |
env->regs[R_EDI] = ts->vm86_saved_regs.edi; |
|
167 |
env->regs[R_EBP] = ts->vm86_saved_regs.ebp; |
|
168 |
env->regs[R_ESP] = ts->vm86_saved_regs.esp; |
|
169 |
env->eflags = ts->vm86_saved_regs.eflags; |
|
170 |
env->eip = ts->vm86_saved_regs.eip; |
|
171 |
|
|
172 |
cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); |
|
173 |
cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); |
|
174 |
cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); |
|
175 |
cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); |
|
176 |
cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); |
|
177 |
cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); |
|
178 |
} |
|
179 |
|
|
180 |
/* return from vm86 mode to 32 bit. The vm86() syscall will return |
|
181 |
'retval' */ |
|
182 |
static inline void return_to_32bit(CPUX86State *env, int retval) |
|
183 |
{ |
|
184 |
#ifdef DEBUG_VM86 |
|
185 |
printf("return_to_32bit: ret=0x%x\n", retval); |
|
186 |
#endif |
|
187 |
save_v86_state(env); |
|
188 |
env->regs[R_EAX] = retval; |
|
189 |
} |
|
190 |
|
|
191 |
/* handle VM86 interrupt (NOTE: the CPU core currently does not |
|
192 |
support TSS interrupt revectoring, so this code is always executed) */ |
|
193 |
static void do_int(CPUX86State *env, int intno) |
|
194 |
{ |
|
195 |
TaskState *ts = env->opaque; |
|
196 |
uint32_t *int_ptr, segoffs; |
|
197 |
|
|
198 |
if (env->segs[R_CS] == TARGET_BIOSSEG) |
|
199 |
goto cannot_handle; /* XXX: I am not sure this is really useful */ |
|
200 |
if (is_revectored(intno, &ts->target_v86->int_revectored)) |
|
201 |
goto cannot_handle; |
|
202 |
if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, |
|
203 |
&ts->target_v86->int21_revectored)) |
|
204 |
goto cannot_handle; |
|
205 |
int_ptr = (uint32_t *)(intno << 2); |
|
206 |
segoffs = tswap32(*int_ptr); |
|
207 |
if ((segoffs >> 16) == TARGET_BIOSSEG) |
|
208 |
goto cannot_handle; |
|
209 |
#ifdef DEBUG_VM86 |
|
210 |
printf("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", |
|
211 |
intno, segoffs >> 16, segoffs & 0xffff); |
|
212 |
#endif |
|
213 |
/* save old state */ |
|
214 |
pushw(env, get_vflags(env)); |
|
215 |
pushw(env, env->segs[R_CS]); |
|
216 |
pushw(env, env->eip); |
|
217 |
/* goto interrupt handler */ |
|
218 |
env->eip = segoffs & 0xffff; |
|
219 |
cpu_x86_load_seg(env, R_CS, segoffs >> 16); |
|
220 |
env->eflags &= ~(VIF_MASK | TF_MASK); |
|
221 |
return; |
|
222 |
cannot_handle: |
|
223 |
#ifdef DEBUG_VM86 |
|
224 |
printf("VM86: return to 32 bits int 0x%x\n", intno); |
|
225 |
#endif |
|
226 |
return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); |
|
227 |
} |
|
228 |
|
|
109 | 229 |
void cpu_loop(struct CPUX86State *env) |
110 | 230 |
{ |
111 |
int err;
|
|
231 |
int trapnr;
|
|
112 | 232 |
uint8_t *pc; |
113 | 233 |
target_siginfo_t info; |
114 | 234 |
|
115 | 235 |
for(;;) { |
116 |
err = cpu_x86_exec(env);
|
|
236 |
trapnr = cpu_x86_exec(env);
|
|
117 | 237 |
pc = env->seg_cache[R_CS].base + env->eip; |
118 |
switch(err) {
|
|
238 |
switch(trapnr) {
|
|
119 | 239 |
case EXCP0D_GPF: |
120 | 240 |
if (env->eflags & VM_MASK) { |
121 |
TaskState *ts; |
|
122 |
int ret; |
|
123 | 241 |
#ifdef DEBUG_VM86 |
124 |
printf("VM86 exception %04x:%08x %02x\n", |
|
125 |
env->segs[R_CS], env->eip, pc[0]); |
|
242 |
printf("VM86 exception %04x:%08x %02x %02x\n",
|
|
243 |
env->segs[R_CS], env->eip, pc[0], pc[1]);
|
|
126 | 244 |
#endif |
127 | 245 |
/* VM86 mode */ |
128 |
ts = env->opaque; |
|
129 |
|
|
130 |
/* XXX: add all cases */ |
|
131 | 246 |
switch(pc[0]) { |
132 | 247 |
case 0xcd: /* int */ |
133 | 248 |
env->eip += 2; |
134 |
ret = TARGET_VM86_INTx | (pc[1] << 8); |
|
249 |
do_int(env, pc[1]); |
|
250 |
break; |
|
251 |
case 0x66: |
|
252 |
switch(pc[1]) { |
|
253 |
case 0xfb: /* sti */ |
|
254 |
case 0x9d: /* popf */ |
|
255 |
case 0xcf: /* iret */ |
|
256 |
env->eip += 2; |
|
257 |
return_to_32bit(env, TARGET_VM86_STI); |
|
258 |
break; |
|
259 |
default: |
|
260 |
goto vm86_gpf; |
|
261 |
} |
|
262 |
break; |
|
263 |
case 0xfb: /* sti */ |
|
264 |
case 0x9d: /* popf */ |
|
265 |
case 0xcf: /* iret */ |
|
266 |
env->eip++; |
|
267 |
return_to_32bit(env, TARGET_VM86_STI); |
|
135 | 268 |
break; |
136 | 269 |
default: |
270 |
vm86_gpf: |
|
137 | 271 |
/* real VM86 GPF exception */ |
138 |
ret = TARGET_VM86_UNKNOWN;
|
|
272 |
return_to_32bit(env, TARGET_VM86_UNKNOWN);
|
|
139 | 273 |
break; |
140 | 274 |
} |
141 |
#ifdef DEBUG_VM86 |
|
142 |
printf("ret=0x%x\n", ret); |
|
143 |
#endif |
|
144 |
/* put the VM86 registers in the userspace register structure */ |
|
145 |
ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); |
|
146 |
ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); |
|
147 |
ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); |
|
148 |
ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); |
|
149 |
ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); |
|
150 |
ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); |
|
151 |
ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); |
|
152 |
ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); |
|
153 |
ts->target_v86->regs.eip = tswap32(env->eip); |
|
154 |
ts->target_v86->regs.cs = tswap16(env->segs[R_CS]); |
|
155 |
ts->target_v86->regs.ss = tswap16(env->segs[R_SS]); |
|
156 |
ts->target_v86->regs.ds = tswap16(env->segs[R_DS]); |
|
157 |
ts->target_v86->regs.es = tswap16(env->segs[R_ES]); |
|
158 |
ts->target_v86->regs.fs = tswap16(env->segs[R_FS]); |
|
159 |
ts->target_v86->regs.gs = tswap16(env->segs[R_GS]); |
|
160 |
|
|
161 |
/* restore 32 bit registers */ |
|
162 |
env->regs[R_EBX] = ts->vm86_saved_regs.ebx; |
|
163 |
env->regs[R_ECX] = ts->vm86_saved_regs.ecx; |
|
164 |
env->regs[R_EDX] = ts->vm86_saved_regs.edx; |
|
165 |
env->regs[R_ESI] = ts->vm86_saved_regs.esi; |
|
166 |
env->regs[R_EDI] = ts->vm86_saved_regs.edi; |
|
167 |
env->regs[R_EBP] = ts->vm86_saved_regs.ebp; |
|
168 |
env->regs[R_ESP] = ts->vm86_saved_regs.esp; |
|
169 |
env->eflags = ts->vm86_saved_regs.eflags; |
|
170 |
env->eip = ts->vm86_saved_regs.eip; |
|
171 |
|
|
172 |
cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); |
|
173 |
cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); |
|
174 |
cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); |
|
175 |
cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); |
|
176 |
cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); |
|
177 |
cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); |
|
178 |
|
|
179 |
env->regs[R_EAX] = ret; |
|
180 | 275 |
} else { |
181 | 276 |
if (pc[0] == 0xcd && pc[1] == 0x80) { |
182 | 277 |
/* syscall */ |
... | ... | |
200 | 295 |
} |
201 | 296 |
break; |
202 | 297 |
case EXCP00_DIVZ: |
203 |
/* division by zero */ |
|
204 |
info.si_signo = SIGFPE; |
|
205 |
info.si_errno = 0; |
|
206 |
info.si_code = TARGET_FPE_INTDIV; |
|
207 |
info._sifields._sigfault._addr = env->eip; |
|
208 |
queue_signal(info.si_signo, &info); |
|
298 |
if (env->eflags & VM_MASK) { |
|
299 |
do_int(env, trapnr); |
|
300 |
} else { |
|
301 |
/* division by zero */ |
|
302 |
info.si_signo = SIGFPE; |
|
303 |
info.si_errno = 0; |
|
304 |
info.si_code = TARGET_FPE_INTDIV; |
|
305 |
info._sifields._sigfault._addr = env->eip; |
|
306 |
queue_signal(info.si_signo, &info); |
|
307 |
} |
|
209 | 308 |
break; |
210 | 309 |
case EXCP04_INTO: |
211 | 310 |
case EXCP05_BOUND: |
212 |
info.si_signo = SIGSEGV; |
|
213 |
info.si_errno = 0; |
|
214 |
info.si_code = 0; |
|
215 |
info._sifields._sigfault._addr = 0; |
|
216 |
queue_signal(info.si_signo, &info); |
|
311 |
if (env->eflags & VM_MASK) { |
|
312 |
do_int(env, trapnr); |
|
313 |
} else { |
|
314 |
info.si_signo = SIGSEGV; |
|
315 |
info.si_errno = 0; |
|
316 |
info.si_code = 0; |
|
317 |
info._sifields._sigfault._addr = 0; |
|
318 |
queue_signal(info.si_signo, &info); |
|
319 |
} |
|
217 | 320 |
break; |
218 | 321 |
case EXCP06_ILLOP: |
219 | 322 |
info.si_signo = SIGILL; |
... | ... | |
226 | 329 |
/* just indicate that signals should be handled asap */ |
227 | 330 |
break; |
228 | 331 |
default: |
229 |
fprintf(stderr, "0x%08lx: Unknown exception CPU %d, aborting\n",
|
|
230 |
(long)pc, err);
|
|
332 |
fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
|
|
333 |
(long)pc, trapnr);
|
|
231 | 334 |
abort(); |
232 | 335 |
} |
233 | 336 |
process_pending_signals(env); |
b/linux-user/qemu.h | ||
---|---|---|
74 | 74 |
void process_pending_signals(void *cpu_env); |
75 | 75 |
void signal_init(void); |
76 | 76 |
int queue_signal(int sig, target_siginfo_t *info); |
77 |
void save_v86_state(CPUX86State *env); |
|
77 | 78 |
|
78 | 79 |
#endif |
b/linux-user/signal.c | ||
---|---|---|
198 | 198 |
{ |
199 | 199 |
int host_sig; |
200 | 200 |
host_sig = target_to_host_signal(sig); |
201 |
fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n",
|
|
201 |
fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
|
|
202 | 202 |
sig, strsignal(host_sig)); |
203 | 203 |
#if 1 |
204 | 204 |
_exit(-host_sig); |
... | ... | |
223 | 223 |
target_ulong handler; |
224 | 224 |
|
225 | 225 |
#if defined(DEBUG_SIGNAL) |
226 |
fprintf(stderr, "queue_sigal: sig=%d\n", |
|
226 |
fprintf(stderr, "queue_signal: sig=%d\n",
|
|
227 | 227 |
sig); |
228 | 228 |
#endif |
229 | 229 |
k = &sigact_table[sig - 1]; |
... | ... | |
317 | 317 |
if (sig < 1 || sig > TARGET_NSIG) |
318 | 318 |
return; |
319 | 319 |
#if defined(DEBUG_SIGNAL) |
320 |
fprintf(stderr, "gemu: got signal %d\n", sig);
|
|
320 |
fprintf(stderr, "qemu: got signal %d\n", sig);
|
|
321 | 321 |
dump_regs(puc); |
322 | 322 |
#endif |
323 | 323 |
host_to_target_siginfo_noswap(&tinfo, info); |
... | ... | |
538 | 538 |
/* non-iBCS2 extensions.. */ |
539 | 539 |
err |= __put_user(mask, &sc->oldmask); |
540 | 540 |
err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2); |
541 |
|
|
542 | 541 |
return err; |
543 | 542 |
} |
544 | 543 |
|
... | ... | |
859 | 858 |
|
860 | 859 |
handle_signal: |
861 | 860 |
#ifdef DEBUG_SIGNAL |
862 |
fprintf(stderr, "gemu: process signal %d\n", sig);
|
|
861 |
fprintf(stderr, "qemu: process signal %d\n", sig);
|
|
863 | 862 |
#endif |
864 | 863 |
/* dequeue signal */ |
865 | 864 |
q = k->first; |
... | ... | |
893 | 892 |
end of the signal execution (see do_sigreturn) */ |
894 | 893 |
host_to_target_sigset(&target_old_set, &old_set); |
895 | 894 |
|
895 |
/* if the CPU is in VM86 mode, we restore the 32 bit values */ |
|
896 |
#ifdef TARGET_I386 |
|
897 |
{ |
|
898 |
CPUX86State *env = cpu_env; |
|
899 |
if (env->eflags & VM_MASK) |
|
900 |
save_v86_state(env); |
|
901 |
} |
|
902 |
#endif |
|
896 | 903 |
/* prepare the stack frame of the virtual CPU */ |
897 | 904 |
if (k->sa.sa_flags & TARGET_SA_SIGINFO) |
898 | 905 |
setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env); |
b/syscall-i386.h | ||
---|---|---|
755 | 755 |
unsigned int flags; |
756 | 756 |
}; |
757 | 757 |
|
758 |
|
|
759 |
/* vm86 defines */ |
|
760 |
|
|
761 |
#define TARGET_BIOSSEG 0x0f000 |
|
762 |
|
|
758 | 763 |
#define TARGET_VM86_SIGNAL 0 /* return due to signal */ |
759 | 764 |
#define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ |
760 | 765 |
#define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ |
Also available in: Unified diff