Statistics
| Branch: | Revision:

root / darwin-user / main.c @ 239fbd86

History | View | Annotate | Download (29.7 kB)

1 831b7825 ths
/*
2 831b7825 ths
 *  qemu user main
3 831b7825 ths
 *
4 831b7825 ths
 *  Copyright (c) 2003 Fabrice Bellard
5 831b7825 ths
 *  Copyright (c) 2006 Pierre d'Herbemont
6 831b7825 ths
 *
7 831b7825 ths
 *  This program is free software; you can redistribute it and/or modify
8 831b7825 ths
 *  it under the terms of the GNU General Public License as published by
9 831b7825 ths
 *  the Free Software Foundation; either version 2 of the License, or
10 831b7825 ths
 *  (at your option) any later version.
11 831b7825 ths
 *
12 831b7825 ths
 *  This program is distributed in the hope that it will be useful,
13 831b7825 ths
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 831b7825 ths
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 831b7825 ths
 *  GNU General Public License for more details.
16 831b7825 ths
 *
17 831b7825 ths
 *  You should have received a copy of the GNU General Public License
18 831b7825 ths
 *  along with this program; if not, write to the Free Software
19 831b7825 ths
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 831b7825 ths
 */
21 831b7825 ths
#include <stdlib.h>
22 831b7825 ths
#include <stdio.h>
23 831b7825 ths
#include <stdarg.h>
24 831b7825 ths
#include <string.h>
25 831b7825 ths
#include <errno.h>
26 831b7825 ths
#include <unistd.h>
27 831b7825 ths
28 831b7825 ths
#include <sys/syscall.h>
29 831b7825 ths
#include <sys/mman.h>
30 831b7825 ths
31 831b7825 ths
#include "qemu.h"
32 831b7825 ths
33 831b7825 ths
#define DEBUG_LOGFILE "/tmp/qemu.log"
34 831b7825 ths
35 831b7825 ths
#ifdef __APPLE__
36 831b7825 ths
#include <crt_externs.h>
37 831b7825 ths
# define environ  (*_NSGetEnviron())
38 831b7825 ths
#endif
39 831b7825 ths
40 831b7825 ths
#include <mach/mach_init.h>
41 831b7825 ths
#include <mach/vm_map.h>
42 831b7825 ths
43 831b7825 ths
const char *interp_prefix = "";
44 831b7825 ths
45 831b7825 ths
asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
46 831b7825 ths
47 831b7825 ths
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
48 831b7825 ths
   we allocate a bigger stack. Need a better solution, for example
49 831b7825 ths
   by remapping the process stack directly at the right place */
50 831b7825 ths
unsigned long stack_size = 512 * 1024;
51 831b7825 ths
52 831b7825 ths
void qerror(const char *fmt, ...)
53 831b7825 ths
{
54 831b7825 ths
    va_list ap;
55 831b7825 ths
56 831b7825 ths
    va_start(ap, fmt);
57 831b7825 ths
    vfprintf(stderr, fmt, ap);
58 831b7825 ths
    va_end(ap);
59 831b7825 ths
    fprintf(stderr, "\n");
60 831b7825 ths
    exit(1);
61 831b7825 ths
}
62 831b7825 ths
63 831b7825 ths
void gemu_log(const char *fmt, ...)
64 831b7825 ths
{
65 831b7825 ths
    va_list ap;
66 831b7825 ths
67 831b7825 ths
    va_start(ap, fmt);
68 831b7825 ths
    vfprintf(stderr, fmt, ap);
69 831b7825 ths
    va_end(ap);
70 831b7825 ths
}
71 831b7825 ths
72 831b7825 ths
void cpu_outb(CPUState *env, int addr, int val)
73 831b7825 ths
{
74 831b7825 ths
    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
75 831b7825 ths
}
76 831b7825 ths
77 831b7825 ths
void cpu_outw(CPUState *env, int addr, int val)
78 831b7825 ths
{
79 831b7825 ths
    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
80 831b7825 ths
}
81 831b7825 ths
82 831b7825 ths
void cpu_outl(CPUState *env, int addr, int val)
83 831b7825 ths
{
84 831b7825 ths
    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
85 831b7825 ths
}
86 831b7825 ths
87 831b7825 ths
int cpu_inb(CPUState *env, int addr)
88 831b7825 ths
{
89 831b7825 ths
    fprintf(stderr, "inb: port=0x%04x\n", addr);
90 831b7825 ths
    return 0;
91 831b7825 ths
}
92 831b7825 ths
93 831b7825 ths
int cpu_inw(CPUState *env, int addr)
94 831b7825 ths
{
95 831b7825 ths
    fprintf(stderr, "inw: port=0x%04x\n", addr);
96 831b7825 ths
    return 0;
97 831b7825 ths
}
98 831b7825 ths
99 831b7825 ths
int cpu_inl(CPUState *env, int addr)
100 831b7825 ths
{
101 831b7825 ths
    fprintf(stderr, "inl: port=0x%04x\n", addr);
102 831b7825 ths
    return 0;
103 831b7825 ths
}
104 831b7825 ths
105 831b7825 ths
int cpu_get_pic_interrupt(CPUState *env)
106 831b7825 ths
{
107 831b7825 ths
    return -1;
108 831b7825 ths
}
109 831b7825 ths
#ifdef TARGET_PPC
110 831b7825 ths
111 831b7825 ths
static inline uint64_t cpu_ppc_get_tb (CPUState *env)
112 831b7825 ths
{
113 831b7825 ths
    /* TO FIX */
114 831b7825 ths
    return 0;
115 831b7825 ths
}
116 831b7825 ths
117 831b7825 ths
uint32_t cpu_ppc_load_tbl (CPUState *env)
118 831b7825 ths
{
119 831b7825 ths
    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
120 831b7825 ths
}
121 831b7825 ths
122 831b7825 ths
uint32_t cpu_ppc_load_tbu (CPUState *env)
123 831b7825 ths
{
124 831b7825 ths
    return cpu_ppc_get_tb(env) >> 32;
125 831b7825 ths
}
126 831b7825 ths
127 831b7825 ths
static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
128 831b7825 ths
{
129 831b7825 ths
    /* TO FIX */
130 831b7825 ths
}
131 831b7825 ths
132 831b7825 ths
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
133 831b7825 ths
{
134 831b7825 ths
    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
135 831b7825 ths
}
136 831b7825 ths
137 831b7825 ths
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
138 831b7825 ths
{
139 831b7825 ths
    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
140 831b7825 ths
}
141 831b7825 ths
142 831b7825 ths
uint32_t cpu_ppc_load_decr (CPUState *env)
143 831b7825 ths
{
144 831b7825 ths
    /* TO FIX */
145 831b7825 ths
    return -1;
146 831b7825 ths
}
147 831b7825 ths
148 831b7825 ths
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
149 831b7825 ths
{
150 831b7825 ths
    /* TO FIX */
151 831b7825 ths
}
152 831b7825 ths
153 c0009975 ths
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
154 c0009975 ths
{
155 c0009975 ths
    cpu_ppc_store_tbu( env, value );
156 c0009975 ths
}
157 c0009975 ths
158 c0009975 ths
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
159 c0009975 ths
{
160 c0009975 ths
    cpu_ppc_load_tbu(env);
161 c0009975 ths
}
162 c0009975 ths
163 c0009975 ths
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
164 c0009975 ths
{
165 c0009975 ths
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
166 c0009975 ths
}
167 c0009975 ths
168 831b7825 ths
void cpu_loop(CPUPPCState *env)
169 831b7825 ths
{
170 831b7825 ths
    int trapnr;
171 831b7825 ths
    uint32_t ret;
172 831b7825 ths
    target_siginfo_t info;
173 831b7825 ths
174 831b7825 ths
    for(;;) {
175 831b7825 ths
        trapnr = cpu_ppc_exec(env);
176 831b7825 ths
        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
177 831b7825 ths
            trapnr != EXCP_TRACE) {
178 831b7825 ths
            if (loglevel > 0) {
179 831b7825 ths
                cpu_dump_state(env, logfile, fprintf, 0);
180 831b7825 ths
            }
181 831b7825 ths
        }
182 831b7825 ths
        switch(trapnr) {
183 831b7825 ths
        case EXCP_NONE:
184 831b7825 ths
            break;
185 831b7825 ths
        case EXCP_SYSCALL_USER:
186 831b7825 ths
            /* system call */
187 831b7825 ths
            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
188 831b7825 ths
                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
189 831b7825 ths
                                      env->gpr[5], env->gpr[6], env->gpr[7],
190 831b7825 ths
                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
191 831b7825 ths
            else if(((int)env->gpr[0])<0)
192 831b7825 ths
                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
193 831b7825 ths
                                      env->gpr[5], env->gpr[6], env->gpr[7],
194 831b7825 ths
                                      env->gpr[8], env->gpr[9], env->gpr[10]);
195 831b7825 ths
            else
196 831b7825 ths
                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
197 831b7825 ths
                                        env->gpr[5], env->gpr[6], env->gpr[7],
198 831b7825 ths
                                        env->gpr[8], env->gpr[9], env->gpr[10]);
199 831b7825 ths
200 831b7825 ths
            /* Unix syscall error signaling */
201 831b7825 ths
            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
202 831b7825 ths
            {
203 831b7825 ths
                if( (int)ret < 0 )
204 831b7825 ths
                    env->nip += 0;
205 831b7825 ths
                else
206 831b7825 ths
                    env->nip += 4;
207 831b7825 ths
            }
208 831b7825 ths
209 831b7825 ths
            /* Return value */
210 831b7825 ths
            env->gpr[3] = ret;
211 831b7825 ths
            break;
212 831b7825 ths
        case EXCP_RESET:
213 831b7825 ths
            /* Should not happen ! */
214 831b7825 ths
            fprintf(stderr, "RESET asked... Stop emulation\n");
215 831b7825 ths
            if (loglevel)
216 831b7825 ths
                fprintf(logfile, "RESET asked... Stop emulation\n");
217 831b7825 ths
                abort();
218 831b7825 ths
        case EXCP_MACHINE_CHECK:
219 831b7825 ths
            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
220 831b7825 ths
            if (loglevel)
221 831b7825 ths
                fprintf(logfile, "RESET asked... Stop emulation\n");
222 831b7825 ths
                info.si_signo = SIGBUS;
223 831b7825 ths
            info.si_errno = 0;
224 831b7825 ths
            info.si_code = BUS_OBJERR;
225 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
226 831b7825 ths
            queue_signal(info.si_signo, &info);
227 831b7825 ths
        case EXCP_DSI:
228 831b7825 ths
#ifndef DAR
229 831b7825 ths
/* To deal with multiple qemu header version as host for the darwin-user code */
230 831b7825 ths
# define DAR SPR_DAR
231 831b7825 ths
#endif
232 831b7825 ths
            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
233 831b7825 ths
            if (loglevel) {
234 831b7825 ths
                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
235 831b7825 ths
                        env->spr[DAR]);
236 831b7825 ths
            }
237 831b7825 ths
            /* Handle this via the gdb */
238 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
239 831b7825 ths
240 831b7825 ths
            info.si_addr = (void*)env->nip;
241 831b7825 ths
            queue_signal(info.si_signo, &info);
242 831b7825 ths
            break;
243 831b7825 ths
        case EXCP_ISI:
244 831b7825 ths
            fprintf(stderr, "Invalid instruction fetch\n");
245 831b7825 ths
            if (loglevel)
246 831b7825 ths
                fprintf(logfile, "Invalid instruction fetch\n");
247 831b7825 ths
            /* Handle this via the gdb */
248 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
249 831b7825 ths
250 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
251 831b7825 ths
            queue_signal(info.si_signo, &info);
252 831b7825 ths
            break;
253 831b7825 ths
        case EXCP_EXTERNAL:
254 831b7825 ths
            /* Should not happen ! */
255 831b7825 ths
            fprintf(stderr, "External interruption... Stop emulation\n");
256 831b7825 ths
            if (loglevel)
257 831b7825 ths
                fprintf(logfile, "External interruption... Stop emulation\n");
258 831b7825 ths
                abort();
259 831b7825 ths
        case EXCP_ALIGN:
260 831b7825 ths
            fprintf(stderr, "Invalid unaligned memory access\n");
261 831b7825 ths
            if (loglevel)
262 831b7825 ths
                fprintf(logfile, "Invalid unaligned memory access\n");
263 831b7825 ths
                info.si_signo = SIGBUS;
264 831b7825 ths
            info.si_errno = 0;
265 831b7825 ths
            info.si_code = BUS_ADRALN;
266 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
267 831b7825 ths
            queue_signal(info.si_signo, &info);
268 831b7825 ths
            break;
269 831b7825 ths
        case EXCP_PROGRAM:
270 831b7825 ths
            switch (env->error_code & ~0xF) {
271 831b7825 ths
                case EXCP_FP:
272 831b7825 ths
                    fprintf(stderr, "Program exception\n");
273 831b7825 ths
                    if (loglevel)
274 831b7825 ths
                        fprintf(logfile, "Program exception\n");
275 831b7825 ths
                        /* Set FX */
276 831b7825 ths
                        env->fpscr[7] |= 0x8;
277 831b7825 ths
                    /* Finally, update FEX */
278 831b7825 ths
                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
279 831b7825 ths
                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
280 831b7825 ths
                        env->fpscr[7] |= 0x4;
281 831b7825 ths
                        info.si_signo = SIGFPE;
282 831b7825 ths
                    info.si_errno = 0;
283 831b7825 ths
                    switch (env->error_code & 0xF) {
284 831b7825 ths
                        case EXCP_FP_OX:
285 831b7825 ths
                            info.si_code = FPE_FLTOVF;
286 831b7825 ths
                            break;
287 831b7825 ths
                        case EXCP_FP_UX:
288 831b7825 ths
                            info.si_code = FPE_FLTUND;
289 831b7825 ths
                            break;
290 831b7825 ths
                        case EXCP_FP_ZX:
291 831b7825 ths
                        case EXCP_FP_VXZDZ:
292 831b7825 ths
                            info.si_code = FPE_FLTDIV;
293 831b7825 ths
                            break;
294 831b7825 ths
                        case EXCP_FP_XX:
295 831b7825 ths
                            info.si_code = FPE_FLTRES;
296 831b7825 ths
                            break;
297 831b7825 ths
                        case EXCP_FP_VXSOFT:
298 831b7825 ths
                            info.si_code = FPE_FLTINV;
299 831b7825 ths
                            break;
300 831b7825 ths
                        case EXCP_FP_VXNAN:
301 831b7825 ths
                        case EXCP_FP_VXISI:
302 831b7825 ths
                        case EXCP_FP_VXIDI:
303 831b7825 ths
                        case EXCP_FP_VXIMZ:
304 831b7825 ths
                        case EXCP_FP_VXVC:
305 831b7825 ths
                        case EXCP_FP_VXSQRT:
306 831b7825 ths
                        case EXCP_FP_VXCVI:
307 831b7825 ths
                            info.si_code = FPE_FLTSUB;
308 831b7825 ths
                            break;
309 831b7825 ths
                        default:
310 831b7825 ths
                            fprintf(stderr, "Unknown floating point exception "
311 831b7825 ths
                                    "(%02x)\n", env->error_code);
312 831b7825 ths
                            if (loglevel) {
313 831b7825 ths
                                fprintf(logfile, "Unknown floating point exception "
314 831b7825 ths
                                        "(%02x)\n", env->error_code & 0xF);
315 831b7825 ths
                            }
316 831b7825 ths
                    }
317 831b7825 ths
                        break;
318 831b7825 ths
                case EXCP_INVAL:
319 831b7825 ths
                    fprintf(stderr, "Invalid instruction\n");
320 831b7825 ths
                    if (loglevel)
321 831b7825 ths
                        fprintf(logfile, "Invalid instruction\n");
322 831b7825 ths
                        info.si_signo = SIGILL;
323 831b7825 ths
                    info.si_errno = 0;
324 831b7825 ths
                    switch (env->error_code & 0xF) {
325 831b7825 ths
                        case EXCP_INVAL_INVAL:
326 831b7825 ths
                            info.si_code = ILL_ILLOPC;
327 831b7825 ths
                            break;
328 831b7825 ths
                        case EXCP_INVAL_LSWX:
329 831b7825 ths
                            info.si_code = ILL_ILLOPN;
330 831b7825 ths
                            break;
331 831b7825 ths
                        case EXCP_INVAL_SPR:
332 831b7825 ths
                            info.si_code = ILL_PRVREG;
333 831b7825 ths
                            break;
334 831b7825 ths
                        case EXCP_INVAL_FP:
335 831b7825 ths
                            info.si_code = ILL_COPROC;
336 831b7825 ths
                            break;
337 831b7825 ths
                        default:
338 831b7825 ths
                            fprintf(stderr, "Unknown invalid operation (%02x)\n",
339 831b7825 ths
                                    env->error_code & 0xF);
340 831b7825 ths
                            if (loglevel) {
341 831b7825 ths
                                fprintf(logfile, "Unknown invalid operation (%02x)\n",
342 831b7825 ths
                                        env->error_code & 0xF);
343 831b7825 ths
                            }
344 831b7825 ths
                                info.si_code = ILL_ILLADR;
345 831b7825 ths
                            break;
346 831b7825 ths
                    }
347 831b7825 ths
                        /* Handle this via the gdb */
348 831b7825 ths
                        gdb_handlesig (env, SIGSEGV);
349 831b7825 ths
                    break;
350 831b7825 ths
                case EXCP_PRIV:
351 831b7825 ths
                    fprintf(stderr, "Privilege violation\n");
352 831b7825 ths
                    if (loglevel)
353 831b7825 ths
                        fprintf(logfile, "Privilege violation\n");
354 831b7825 ths
                        info.si_signo = SIGILL;
355 831b7825 ths
                    info.si_errno = 0;
356 831b7825 ths
                    switch (env->error_code & 0xF) {
357 831b7825 ths
                        case EXCP_PRIV_OPC:
358 831b7825 ths
                            info.si_code = ILL_PRVOPC;
359 831b7825 ths
                            break;
360 831b7825 ths
                        case EXCP_PRIV_REG:
361 831b7825 ths
                            info.si_code = ILL_PRVREG;
362 831b7825 ths
                            break;
363 831b7825 ths
                        default:
364 831b7825 ths
                            fprintf(stderr, "Unknown privilege violation (%02x)\n",
365 831b7825 ths
                                    env->error_code & 0xF);
366 831b7825 ths
                            info.si_code = ILL_PRVOPC;
367 831b7825 ths
                            break;
368 831b7825 ths
                    }
369 831b7825 ths
                        break;
370 831b7825 ths
                case EXCP_TRAP:
371 831b7825 ths
                    fprintf(stderr, "Tried to call a TRAP\n");
372 831b7825 ths
                    if (loglevel)
373 831b7825 ths
                        fprintf(logfile, "Tried to call a TRAP\n");
374 831b7825 ths
                        abort();
375 831b7825 ths
                default:
376 831b7825 ths
                    /* Should not happen ! */
377 831b7825 ths
                    fprintf(stderr, "Unknown program exception (%02x)\n",
378 831b7825 ths
                            env->error_code);
379 831b7825 ths
                    if (loglevel) {
380 831b7825 ths
                        fprintf(logfile, "Unknwon program exception (%02x)\n",
381 831b7825 ths
                                env->error_code);
382 831b7825 ths
                    }
383 831b7825 ths
                        abort();
384 831b7825 ths
            }
385 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
386 831b7825 ths
            queue_signal(info.si_signo, &info);
387 831b7825 ths
            break;
388 831b7825 ths
        case EXCP_NO_FP:
389 831b7825 ths
            fprintf(stderr, "No floating point allowed\n");
390 831b7825 ths
            if (loglevel)
391 831b7825 ths
                fprintf(logfile, "No floating point allowed\n");
392 831b7825 ths
                info.si_signo = SIGILL;
393 831b7825 ths
            info.si_errno = 0;
394 831b7825 ths
            info.si_code = ILL_COPROC;
395 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
396 831b7825 ths
            queue_signal(info.si_signo, &info);
397 831b7825 ths
            break;
398 831b7825 ths
        case EXCP_DECR:
399 831b7825 ths
            /* Should not happen ! */
400 831b7825 ths
            fprintf(stderr, "Decrementer exception\n");
401 831b7825 ths
            if (loglevel)
402 831b7825 ths
                fprintf(logfile, "Decrementer exception\n");
403 831b7825 ths
            abort();
404 831b7825 ths
        case EXCP_TRACE:
405 831b7825 ths
            /* Pass to gdb: we use this to trace execution */
406 831b7825 ths
            gdb_handlesig (env, SIGTRAP);
407 831b7825 ths
            break;
408 831b7825 ths
        case EXCP_FP_ASSIST:
409 831b7825 ths
            /* Should not happen ! */
410 831b7825 ths
            fprintf(stderr, "Floating point assist exception\n");
411 831b7825 ths
            if (loglevel)
412 831b7825 ths
                fprintf(logfile, "Floating point assist exception\n");
413 831b7825 ths
            abort();
414 831b7825 ths
        case EXCP_MTMSR:
415 831b7825 ths
            /* We reloaded the msr, just go on */
416 831b7825 ths
            if (msr_pr == 0) {
417 831b7825 ths
                fprintf(stderr, "Tried to go into supervisor mode !\n");
418 831b7825 ths
                if (loglevel)
419 831b7825 ths
                    fprintf(logfile, "Tried to go into supervisor mode !\n");
420 831b7825 ths
                abort();
421 831b7825 ths
            }
422 831b7825 ths
            break;
423 831b7825 ths
        case EXCP_BRANCH:
424 831b7825 ths
            /* We stopped because of a jump... */
425 831b7825 ths
            break;
426 831b7825 ths
        case EXCP_INTERRUPT:
427 831b7825 ths
            /* Don't know why this should ever happen... */
428 831b7825 ths
            fprintf(stderr, "EXCP_INTERRUPT\n");
429 831b7825 ths
            break;
430 831b7825 ths
        case EXCP_DEBUG:
431 831b7825 ths
            gdb_handlesig (env, SIGTRAP);
432 831b7825 ths
            break;
433 831b7825 ths
        default:
434 831b7825 ths
            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
435 831b7825 ths
                    trapnr);
436 831b7825 ths
            if (loglevel) {
437 831b7825 ths
                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
438 831b7825 ths
                        "0x%02x - aborting\n", trapnr, env->error_code);
439 831b7825 ths
            }
440 831b7825 ths
                abort();
441 831b7825 ths
        }
442 831b7825 ths
        process_pending_signals(env);
443 831b7825 ths
    }
444 831b7825 ths
}
445 831b7825 ths
#endif
446 831b7825 ths
447 831b7825 ths
448 831b7825 ths
#ifdef TARGET_I386
449 831b7825 ths
450 831b7825 ths
/***********************************************************/
451 831b7825 ths
/* CPUX86 core interface */
452 831b7825 ths
453 831b7825 ths
uint64_t cpu_get_tsc(CPUX86State *env)
454 831b7825 ths
{
455 831b7825 ths
    return cpu_get_real_ticks();
456 831b7825 ths
}
457 831b7825 ths
458 831b7825 ths
void
459 831b7825 ths
write_dt(void *ptr, unsigned long addr, unsigned long limit,
460 831b7825 ths
                     int flags)
461 831b7825 ths
{
462 831b7825 ths
    unsigned int e1, e2;
463 831b7825 ths
    e1 = (addr << 16) | (limit & 0xffff);
464 831b7825 ths
    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
465 831b7825 ths
    e2 |= flags;
466 831b7825 ths
    stl((uint8_t *)ptr, e1);
467 831b7825 ths
    stl((uint8_t *)ptr + 4, e2);
468 831b7825 ths
}
469 831b7825 ths
470 831b7825 ths
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
471 831b7825 ths
                     unsigned long addr, unsigned int sel)
472 831b7825 ths
{
473 831b7825 ths
    unsigned int e1, e2;
474 831b7825 ths
    e1 = (addr & 0xffff) | (sel << 16);
475 831b7825 ths
    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
476 831b7825 ths
    stl((uint8_t *)ptr, e1);
477 831b7825 ths
    stl((uint8_t *)ptr + 4, e2);
478 831b7825 ths
}
479 831b7825 ths
480 831b7825 ths
#define GDT_TABLE_SIZE 14
481 831b7825 ths
#define LDT_TABLE_SIZE 15
482 831b7825 ths
#define IDT_TABLE_SIZE 256
483 831b7825 ths
#define TSS_SIZE 104
484 831b7825 ths
uint64_t gdt_table[GDT_TABLE_SIZE];
485 831b7825 ths
uint64_t ldt_table[LDT_TABLE_SIZE];
486 831b7825 ths
uint64_t idt_table[IDT_TABLE_SIZE];
487 831b7825 ths
uint32_t tss[TSS_SIZE];
488 831b7825 ths
489 831b7825 ths
/* only dpl matters as we do only user space emulation */
490 831b7825 ths
static void set_idt(int n, unsigned int dpl)
491 831b7825 ths
{
492 831b7825 ths
    set_gate(idt_table + n, 0, dpl, 0, 0);
493 831b7825 ths
}
494 831b7825 ths
495 831b7825 ths
/* ABI convention: after a syscall if there was an error the CF flag is set */
496 46ea3397 ths
static inline void set_error(CPUX86State *env, int ret)
497 831b7825 ths
{
498 831b7825 ths
    if(ret<0)
499 831b7825 ths
        env->eflags = env->eflags | 0x1;
500 831b7825 ths
    else
501 831b7825 ths
        env->eflags &= ~0x1;
502 831b7825 ths
    env->regs[R_EAX] = ret;
503 831b7825 ths
}
504 831b7825 ths
505 831b7825 ths
void cpu_loop(CPUX86State *env)
506 831b7825 ths
{
507 831b7825 ths
    int trapnr;
508 831b7825 ths
    int ret;
509 831b7825 ths
    uint8_t *pc;
510 831b7825 ths
    target_siginfo_t info;
511 831b7825 ths
512 831b7825 ths
    for(;;) {
513 831b7825 ths
        trapnr = cpu_x86_exec(env);
514 831b7825 ths
        uint32_t *params = (uint32_t *)env->regs[R_ESP];
515 831b7825 ths
        switch(trapnr) {
516 831b7825 ths
        case 0x79: /* Our commpage hack back door exit is here */
517 831b7825 ths
            do_commpage(env,  env->eip,   *(params + 1), *(params + 2),
518 831b7825 ths
                                          *(params + 3), *(params + 4),
519 831b7825 ths
                                          *(params + 5), *(params + 6),
520 831b7825 ths
                                          *(params + 7), *(params + 8));
521 831b7825 ths
            break;
522 831b7825 ths
        case 0x81: /* mach syscall */
523 831b7825 ths
        {
524 831b7825 ths
            ret = do_mach_syscall(env,  env->regs[R_EAX],
525 831b7825 ths
                                          *(params + 1), *(params + 2),
526 831b7825 ths
                                          *(params + 3), *(params + 4),
527 831b7825 ths
                                          *(params + 5), *(params + 6),
528 831b7825 ths
                                          *(params + 7), *(params + 8));
529 831b7825 ths
            set_error(env, ret);
530 831b7825 ths
            break;
531 831b7825 ths
        }
532 831b7825 ths
        case 0x90: /* unix backdoor */
533 831b7825 ths
        {
534 831b7825 ths
            /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
535 831b7825 ths
            int saved_stack = env->regs[R_ESP];
536 831b7825 ths
            env->regs[R_ESP] = env->regs[R_ECX];
537 831b7825 ths
538 831b7825 ths
            ret = do_unix_syscall(env, env->regs[R_EAX]);
539 831b7825 ths
540 831b7825 ths
            env->regs[R_ECX] = env->regs[R_ESP];
541 831b7825 ths
            env->regs[R_ESP] = saved_stack;
542 831b7825 ths
543 831b7825 ths
            set_error(env, ret);
544 831b7825 ths
            break;
545 831b7825 ths
        }
546 831b7825 ths
        case 0x80: /* unix syscall */
547 831b7825 ths
        {
548 831b7825 ths
            ret = do_unix_syscall(env, env->regs[R_EAX]/*,
549 831b7825 ths
                                          *(params + 1), *(params + 2),
550 831b7825 ths
                                          *(params + 3), *(params + 4),
551 831b7825 ths
                                          *(params + 5), *(params + 6),
552 831b7825 ths
                                          *(params + 7), *(params + 8)*/);
553 831b7825 ths
            set_error(env, ret);
554 831b7825 ths
            break;
555 831b7825 ths
        }
556 831b7825 ths
        case 0x82: /* thread syscall */
557 831b7825 ths
        {
558 831b7825 ths
            ret = do_thread_syscall(env,  env->regs[R_EAX],
559 831b7825 ths
                                          *(params + 1), *(params + 2),
560 831b7825 ths
                                          *(params + 3), *(params + 4),
561 831b7825 ths
                                          *(params + 5), *(params + 6),
562 831b7825 ths
                                          *(params + 7), *(params + 8));
563 831b7825 ths
            set_error(env, ret);
564 831b7825 ths
            break;
565 831b7825 ths
        }
566 831b7825 ths
        case EXCP0B_NOSEG:
567 831b7825 ths
        case EXCP0C_STACK:
568 831b7825 ths
            info.si_signo = SIGBUS;
569 831b7825 ths
            info.si_errno = 0;
570 831b7825 ths
            info.si_code = BUS_NOOP;
571 831b7825 ths
            info.si_addr = 0;
572 831b7825 ths
            gdb_handlesig (env, SIGBUS);
573 831b7825 ths
            queue_signal(info.si_signo, &info);
574 831b7825 ths
            break;
575 831b7825 ths
        case EXCP0D_GPF:
576 831b7825 ths
            info.si_signo = SIGSEGV;
577 831b7825 ths
            info.si_errno = 0;
578 831b7825 ths
            info.si_code = SEGV_NOOP;
579 831b7825 ths
            info.si_addr = 0;
580 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
581 831b7825 ths
            queue_signal(info.si_signo, &info);
582 831b7825 ths
            break;
583 831b7825 ths
        case EXCP0E_PAGE:
584 831b7825 ths
            info.si_signo = SIGSEGV;
585 831b7825 ths
            info.si_errno = 0;
586 831b7825 ths
            if (!(env->error_code & 1))
587 831b7825 ths
                info.si_code = SEGV_MAPERR;
588 831b7825 ths
            else
589 831b7825 ths
                info.si_code = SEGV_ACCERR;
590 831b7825 ths
            info.si_addr = (void*)env->cr[2];
591 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
592 831b7825 ths
            queue_signal(info.si_signo, &info);
593 831b7825 ths
            break;
594 831b7825 ths
        case EXCP00_DIVZ:
595 831b7825 ths
            /* division by zero */
596 831b7825 ths
            info.si_signo = SIGFPE;
597 831b7825 ths
            info.si_errno = 0;
598 831b7825 ths
            info.si_code = FPE_INTDIV;
599 831b7825 ths
            info.si_addr = (void*)env->eip;
600 831b7825 ths
            gdb_handlesig (env, SIGFPE);
601 831b7825 ths
            queue_signal(info.si_signo, &info);
602 831b7825 ths
            break;
603 831b7825 ths
        case EXCP01_SSTP:
604 831b7825 ths
        case EXCP03_INT3:
605 831b7825 ths
            info.si_signo = SIGTRAP;
606 831b7825 ths
            info.si_errno = 0;
607 831b7825 ths
            info.si_code = TRAP_BRKPT;
608 831b7825 ths
            info.si_addr = (void*)env->eip;
609 831b7825 ths
            gdb_handlesig (env, SIGTRAP);
610 831b7825 ths
            queue_signal(info.si_signo, &info);
611 831b7825 ths
            break;
612 831b7825 ths
        case EXCP04_INTO:
613 831b7825 ths
        case EXCP05_BOUND:
614 831b7825 ths
            info.si_signo = SIGSEGV;
615 831b7825 ths
            info.si_errno = 0;
616 831b7825 ths
            info.si_code = SEGV_NOOP;
617 831b7825 ths
            info.si_addr = 0;
618 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
619 831b7825 ths
            queue_signal(info.si_signo, &info);
620 831b7825 ths
            break;
621 831b7825 ths
        case EXCP06_ILLOP:
622 831b7825 ths
            info.si_signo = SIGILL;
623 831b7825 ths
            info.si_errno = 0;
624 831b7825 ths
            info.si_code = ILL_ILLOPN;
625 831b7825 ths
            info.si_addr = (void*)env->eip;
626 831b7825 ths
            gdb_handlesig (env, SIGILL);
627 831b7825 ths
            queue_signal(info.si_signo, &info);
628 831b7825 ths
            break;
629 831b7825 ths
        case EXCP_INTERRUPT:
630 831b7825 ths
            /* just indicate that signals should be handled asap */
631 831b7825 ths
            break;
632 831b7825 ths
        case EXCP_DEBUG:
633 831b7825 ths
            {
634 831b7825 ths
                int sig;
635 831b7825 ths
636 831b7825 ths
                sig = gdb_handlesig (env, SIGTRAP);
637 831b7825 ths
                if (sig)
638 831b7825 ths
                  {
639 831b7825 ths
                    info.si_signo = sig;
640 831b7825 ths
                    info.si_errno = 0;
641 831b7825 ths
                    info.si_code = TRAP_BRKPT;
642 831b7825 ths
                    queue_signal(info.si_signo, &info);
643 831b7825 ths
                  }
644 831b7825 ths
            }
645 831b7825 ths
            break;
646 831b7825 ths
        default:
647 831b7825 ths
            pc = (void*)(env->segs[R_CS].base + env->eip);
648 831b7825 ths
            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
649 831b7825 ths
                    (long)pc, trapnr);
650 831b7825 ths
            abort();
651 831b7825 ths
        }
652 831b7825 ths
        process_pending_signals(env);
653 831b7825 ths
    }
654 831b7825 ths
}
655 831b7825 ths
#endif
656 831b7825 ths
657 831b7825 ths
void usage(void)
658 831b7825 ths
{
659 831b7825 ths
    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
660 831b7825 ths
           "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
661 831b7825 ths
           "Darwin CPU emulator (compiled for %s emulation)\n"
662 831b7825 ths
           "\n"
663 831b7825 ths
           "-h           print this help\n"
664 1e2bed4f bellard
           "-L path      set the %s library path (default='%s')\n"
665 831b7825 ths
           "-s size      set the stack size in bytes (default=%ld)\n"
666 831b7825 ths
           "\n"
667 831b7825 ths
           "debug options:\n"
668 831b7825 ths
#ifdef USE_CODE_COPY
669 831b7825 ths
           "-no-code-copy   disable code copy acceleration\n"
670 831b7825 ths
#endif
671 1e2bed4f bellard
           "-d options   activate log (logfile='%s')\n"
672 831b7825 ths
           "-g wait for gdb on port 1234\n"
673 831b7825 ths
           "-p pagesize  set the host page size to 'pagesize'\n",
674 831b7825 ths
           TARGET_ARCH,
675 1e2bed4f bellard
           TARGET_ARCH,
676 831b7825 ths
           interp_prefix,
677 831b7825 ths
           stack_size,
678 831b7825 ths
           DEBUG_LOGFILE);
679 831b7825 ths
    _exit(1);
680 831b7825 ths
}
681 831b7825 ths
682 831b7825 ths
/* XXX: currently only used for async signals (see signal.c) */
683 831b7825 ths
CPUState *global_env;
684 831b7825 ths
/* used only if single thread */
685 831b7825 ths
CPUState *cpu_single_env = NULL;
686 831b7825 ths
687 831b7825 ths
/* used to free thread contexts */
688 831b7825 ths
TaskState *first_task_state;
689 831b7825 ths
690 831b7825 ths
int main(int argc, char **argv)
691 831b7825 ths
{
692 831b7825 ths
    const char *filename;
693 831b7825 ths
    struct target_pt_regs regs1, *regs = &regs1;
694 831b7825 ths
    TaskState ts1, *ts = &ts1;
695 831b7825 ths
    CPUState *env;
696 831b7825 ths
    int optind;
697 831b7825 ths
    short use_gdbstub = 0;
698 831b7825 ths
    const char *r;
699 831b7825 ths
700 831b7825 ths
    if (argc <= 1)
701 831b7825 ths
        usage();
702 831b7825 ths
703 831b7825 ths
    /* init debug */
704 831b7825 ths
    cpu_set_log_filename(DEBUG_LOGFILE);
705 831b7825 ths
706 831b7825 ths
    optind = 1;
707 831b7825 ths
    for(;;) {
708 831b7825 ths
        if (optind >= argc)
709 831b7825 ths
            break;
710 831b7825 ths
        r = argv[optind];
711 831b7825 ths
        if (r[0] != '-')
712 831b7825 ths
            break;
713 831b7825 ths
        optind++;
714 831b7825 ths
        r++;
715 831b7825 ths
        if (!strcmp(r, "-")) {
716 831b7825 ths
            break;
717 831b7825 ths
        } else if (!strcmp(r, "d")) {
718 831b7825 ths
            int mask;
719 831b7825 ths
            CPULogItem *item;
720 831b7825 ths
721 831b7825 ths
        if (optind >= argc)
722 831b7825 ths
        break;
723 831b7825 ths
724 831b7825 ths
        r = argv[optind++];
725 831b7825 ths
            mask = cpu_str_to_log_mask(r);
726 831b7825 ths
            if (!mask) {
727 831b7825 ths
                printf("Log items (comma separated):\n");
728 831b7825 ths
                for(item = cpu_log_items; item->mask != 0; item++) {
729 831b7825 ths
                    printf("%-10s %s\n", item->name, item->help);
730 831b7825 ths
                }
731 831b7825 ths
                exit(1);
732 831b7825 ths
            }
733 831b7825 ths
            cpu_set_log(mask);
734 831b7825 ths
        } else if (!strcmp(r, "s")) {
735 831b7825 ths
            r = argv[optind++];
736 831b7825 ths
            stack_size = strtol(r, (char **)&r, 0);
737 831b7825 ths
            if (stack_size <= 0)
738 831b7825 ths
                usage();
739 831b7825 ths
            if (*r == 'M')
740 831b7825 ths
                stack_size *= 1024 * 1024;
741 831b7825 ths
            else if (*r == 'k' || *r == 'K')
742 831b7825 ths
                stack_size *= 1024;
743 831b7825 ths
        } else if (!strcmp(r, "L")) {
744 831b7825 ths
            interp_prefix = argv[optind++];
745 831b7825 ths
        } else if (!strcmp(r, "p")) {
746 831b7825 ths
            qemu_host_page_size = atoi(argv[optind++]);
747 831b7825 ths
            if (qemu_host_page_size == 0 ||
748 831b7825 ths
                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
749 831b7825 ths
                fprintf(stderr, "page size must be a power of two\n");
750 831b7825 ths
                exit(1);
751 831b7825 ths
            }
752 831b7825 ths
        } else
753 831b7825 ths
        if (!strcmp(r, "g")) {
754 831b7825 ths
            use_gdbstub = 1;
755 831b7825 ths
        } else
756 831b7825 ths
#ifdef USE_CODE_COPY
757 831b7825 ths
        if (!strcmp(r, "no-code-copy")) {
758 831b7825 ths
            code_copy_enabled = 0;
759 831b7825 ths
        } else
760 831b7825 ths
#endif
761 831b7825 ths
        {
762 831b7825 ths
            usage();
763 831b7825 ths
        }
764 831b7825 ths
    }
765 831b7825 ths
    if (optind >= argc)
766 831b7825 ths
        usage();
767 831b7825 ths
    filename = argv[optind];
768 831b7825 ths
769 831b7825 ths
    /* Zero out regs */
770 831b7825 ths
    memset(regs, 0, sizeof(struct target_pt_regs));
771 831b7825 ths
772 831b7825 ths
    /* NOTE: we need to init the CPU at this stage to get
773 831b7825 ths
       qemu_host_page_size */
774 831b7825 ths
    env = cpu_init();
775 831b7825 ths
776 831b7825 ths
    printf("Starting %s with qemu\n----------------\n", filename);
777 831b7825 ths
778 831b7825 ths
    commpage_init();
779 831b7825 ths
780 831b7825 ths
    if (mach_exec(filename, argv+optind, environ, regs) != 0) {
781 831b7825 ths
    printf("Error loading %s\n", filename);
782 831b7825 ths
    _exit(1);
783 831b7825 ths
    }
784 831b7825 ths
785 831b7825 ths
    syscall_init();
786 831b7825 ths
    signal_init();
787 831b7825 ths
    global_env = env;
788 831b7825 ths
789 831b7825 ths
    /* build Task State */
790 831b7825 ths
    memset(ts, 0, sizeof(TaskState));
791 831b7825 ths
    env->opaque = ts;
792 831b7825 ths
    ts->used = 1;
793 831b7825 ths
    env->user_mode_only = 1;
794 831b7825 ths
795 831b7825 ths
#if defined(TARGET_I386)
796 831b7825 ths
    cpu_x86_set_cpl(env, 3);
797 831b7825 ths
798 831b7825 ths
    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
799 831b7825 ths
    env->hflags |= HF_PE_MASK;
800 831b7825 ths
801 831b7825 ths
    if (env->cpuid_features & CPUID_SSE) {
802 831b7825 ths
        env->cr[4] |= CR4_OSFXSR_MASK;
803 831b7825 ths
        env->hflags |= HF_OSFXSR_MASK;
804 831b7825 ths
    }
805 831b7825 ths
806 831b7825 ths
    /* flags setup : we activate the IRQs by default as in user mode */
807 831b7825 ths
    env->eflags |= IF_MASK;
808 831b7825 ths
809 831b7825 ths
    /* darwin register setup */
810 831b7825 ths
    env->regs[R_EAX] = regs->eax;
811 831b7825 ths
    env->regs[R_EBX] = regs->ebx;
812 831b7825 ths
    env->regs[R_ECX] = regs->ecx;
813 831b7825 ths
    env->regs[R_EDX] = regs->edx;
814 831b7825 ths
    env->regs[R_ESI] = regs->esi;
815 831b7825 ths
    env->regs[R_EDI] = regs->edi;
816 831b7825 ths
    env->regs[R_EBP] = regs->ebp;
817 831b7825 ths
    env->regs[R_ESP] = regs->esp;
818 831b7825 ths
    env->eip = regs->eip;
819 831b7825 ths
820 831b7825 ths
    /* Darwin LDT setup */
821 831b7825 ths
    /* 2 - User code segment
822 831b7825 ths
       3 - User data segment
823 831b7825 ths
       4 - User cthread */
824 831b7825 ths
    bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
825 831b7825 ths
    env->ldt.base = (uint32_t) ldt_table;
826 831b7825 ths
    env->ldt.limit = sizeof(ldt_table) - 1;
827 831b7825 ths
828 831b7825 ths
    write_dt(ldt_table + 2, 0, 0xfffff,
829 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
830 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
831 831b7825 ths
    write_dt(ldt_table + 3, 0, 0xfffff,
832 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
833 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
834 831b7825 ths
    write_dt(ldt_table + 4, 0, 0xfffff,
835 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
836 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
837 831b7825 ths
838 831b7825 ths
    /* Darwin GDT setup.
839 831b7825 ths
     * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
840 831b7825 ths
       now everything is done via  int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
841 831b7825 ths
    bzero(gdt_table, sizeof(gdt_table));
842 831b7825 ths
    env->gdt.base = (uint32_t)gdt_table;
843 831b7825 ths
    env->gdt.limit = sizeof(gdt_table) - 1;
844 831b7825 ths
845 831b7825 ths
    /* Set up a back door to handle sysenter syscalls (unix) */
846 831b7825 ths
    char * syscallbackdoor = malloc(64);
847 831b7825 ths
    page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
848 831b7825 ths
849 831b7825 ths
    int i = 0;
850 831b7825 ths
    syscallbackdoor[i++] = 0xcd;
851 831b7825 ths
    syscallbackdoor[i++] = 0x90; /* int 0x90 */
852 831b7825 ths
    syscallbackdoor[i++] = 0x0F;
853 831b7825 ths
    syscallbackdoor[i++] = 0x35; /* sysexit */
854 831b7825 ths
855 831b7825 ths
    /* Darwin sysenter/sysexit setup */
856 831b7825 ths
    env->sysenter_cs = 0x1; //XXX
857 831b7825 ths
    env->sysenter_eip = (int)syscallbackdoor;
858 831b7825 ths
    env->sysenter_esp = (int)malloc(64);
859 831b7825 ths
860 831b7825 ths
    /* Darwin TSS setup
861 831b7825 ths
       This must match up with GDT[4] */
862 831b7825 ths
    env->tr.base = (uint32_t) tss;
863 831b7825 ths
    env->tr.limit = sizeof(tss) - 1;
864 831b7825 ths
    env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
865 831b7825 ths
    stw(tss + 2, 0x10);  // ss0 = 0x10 = GDT[2] = Kernel Data Segment
866 831b7825 ths
867 831b7825 ths
    /* Darwin interrupt setup */
868 831b7825 ths
    bzero(idt_table, sizeof(idt_table));
869 831b7825 ths
    env->idt.base = (uint32_t) idt_table;
870 831b7825 ths
    env->idt.limit = sizeof(idt_table) - 1;
871 831b7825 ths
    set_idt(0, 0);
872 831b7825 ths
    set_idt(1, 0);
873 831b7825 ths
    set_idt(2, 0);
874 831b7825 ths
    set_idt(3, 3);
875 831b7825 ths
    set_idt(4, 3);
876 831b7825 ths
    set_idt(5, 3);
877 831b7825 ths
    set_idt(6, 0);
878 831b7825 ths
    set_idt(7, 0);
879 831b7825 ths
    set_idt(8, 0);
880 831b7825 ths
    set_idt(9, 0);
881 831b7825 ths
    set_idt(10, 0);
882 831b7825 ths
    set_idt(11, 0);
883 831b7825 ths
    set_idt(12, 0);
884 831b7825 ths
    set_idt(13, 0);
885 831b7825 ths
    set_idt(14, 0);
886 831b7825 ths
    set_idt(15, 0);
887 831b7825 ths
    set_idt(16, 0);
888 831b7825 ths
    set_idt(17, 0);
889 831b7825 ths
    set_idt(18, 0);
890 831b7825 ths
    set_idt(19, 0);
891 831b7825 ths
    /* Syscalls are done via
892 831b7825 ths
        int 0x80 (unix) (rarely used)
893 831b7825 ths
        int 0x81 (mach)
894 831b7825 ths
        int 0x82 (thread)
895 831b7825 ths
        int 0x83 (diag) (not handled here)
896 831b7825 ths
        sysenter/sysexit (unix) -> we redirect that to int 0x90 */
897 831b7825 ths
    set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
898 831b7825 ths
    set_idt(0x80, 3); /* Unix Syscall */
899 831b7825 ths
    set_idt(0x81, 3); /* Mach Syscalls */
900 831b7825 ths
    set_idt(0x82, 3); /* thread Syscalls */
901 831b7825 ths
902 1e2bed4f bellard
    set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
903 831b7825 ths
904 831b7825 ths
905 831b7825 ths
    cpu_x86_load_seg(env, R_CS, __USER_CS);
906 831b7825 ths
    cpu_x86_load_seg(env, R_DS, __USER_DS);
907 831b7825 ths
    cpu_x86_load_seg(env, R_ES, __USER_DS);
908 831b7825 ths
    cpu_x86_load_seg(env, R_SS, __USER_DS);
909 831b7825 ths
    cpu_x86_load_seg(env, R_FS, __USER_DS);
910 831b7825 ths
    cpu_x86_load_seg(env, R_GS, __USER_DS);
911 831b7825 ths
912 831b7825 ths
#elif defined(TARGET_PPC)
913 831b7825 ths
    {
914 831b7825 ths
        int i;
915 831b7825 ths
        env->nip = regs->nip;
916 831b7825 ths
        for(i = 0; i < 32; i++) {
917 831b7825 ths
            env->gpr[i] = regs->gpr[i];
918 831b7825 ths
        }
919 831b7825 ths
    }
920 831b7825 ths
#else
921 831b7825 ths
#error unsupported target CPU
922 831b7825 ths
#endif
923 831b7825 ths
924 831b7825 ths
    if (use_gdbstub) {
925 831b7825 ths
        printf("Waiting for gdb Connection on port 1234...\n");
926 831b7825 ths
        gdbserver_start (1234);
927 831b7825 ths
        gdb_handlesig(env, 0);
928 831b7825 ths
    }
929 831b7825 ths
930 831b7825 ths
    cpu_loop(env);
931 831b7825 ths
    /* never exits */
932 831b7825 ths
    return 0;
933 831b7825 ths
}