Statistics
| Branch: | Revision:

root / darwin-user / main.c @ 1e2bed4f

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