Statistics
| Branch: | Revision:

root / darwin-user / main.c @ 4870852c

History | View | Annotate | Download (35.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 530e7615 blueswir1
 *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 530e7615 blueswir1
 *  MA 02110-1301, USA.
21 831b7825 ths
 */
22 831b7825 ths
#include <stdlib.h>
23 831b7825 ths
#include <stdio.h>
24 831b7825 ths
#include <stdarg.h>
25 831b7825 ths
#include <string.h>
26 831b7825 ths
#include <errno.h>
27 831b7825 ths
#include <unistd.h>
28 831b7825 ths
29 831b7825 ths
#include <sys/syscall.h>
30 831b7825 ths
#include <sys/mman.h>
31 831b7825 ths
32 831b7825 ths
#include "qemu.h"
33 831b7825 ths
34 831b7825 ths
#define DEBUG_LOGFILE "/tmp/qemu.log"
35 831b7825 ths
36 831b7825 ths
#ifdef __APPLE__
37 831b7825 ths
#include <crt_externs.h>
38 831b7825 ths
# define environ  (*_NSGetEnviron())
39 831b7825 ths
#endif
40 831b7825 ths
41 831b7825 ths
#include <mach/mach_init.h>
42 831b7825 ths
#include <mach/vm_map.h>
43 831b7825 ths
44 1b530a6d aurel32
int singlestep;
45 1b530a6d aurel32
46 831b7825 ths
const char *interp_prefix = "";
47 831b7825 ths
48 831b7825 ths
asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
49 831b7825 ths
50 831b7825 ths
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
51 831b7825 ths
   we allocate a bigger stack. Need a better solution, for example
52 831b7825 ths
   by remapping the process stack directly at the right place */
53 831b7825 ths
unsigned long stack_size = 512 * 1024;
54 831b7825 ths
55 831b7825 ths
void qerror(const char *fmt, ...)
56 831b7825 ths
{
57 831b7825 ths
    va_list ap;
58 831b7825 ths
59 831b7825 ths
    va_start(ap, fmt);
60 831b7825 ths
    vfprintf(stderr, fmt, ap);
61 831b7825 ths
    va_end(ap);
62 831b7825 ths
    fprintf(stderr, "\n");
63 831b7825 ths
    exit(1);
64 831b7825 ths
}
65 831b7825 ths
66 831b7825 ths
void gemu_log(const char *fmt, ...)
67 831b7825 ths
{
68 831b7825 ths
    va_list ap;
69 831b7825 ths
70 831b7825 ths
    va_start(ap, fmt);
71 831b7825 ths
    vfprintf(stderr, fmt, ap);
72 831b7825 ths
    va_end(ap);
73 831b7825 ths
}
74 831b7825 ths
75 831b7825 ths
void cpu_outb(CPUState *env, int addr, int val)
76 831b7825 ths
{
77 831b7825 ths
    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
78 831b7825 ths
}
79 831b7825 ths
80 831b7825 ths
void cpu_outw(CPUState *env, int addr, int val)
81 831b7825 ths
{
82 831b7825 ths
    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
83 831b7825 ths
}
84 831b7825 ths
85 831b7825 ths
void cpu_outl(CPUState *env, int addr, int val)
86 831b7825 ths
{
87 831b7825 ths
    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
88 831b7825 ths
}
89 831b7825 ths
90 831b7825 ths
int cpu_inb(CPUState *env, int addr)
91 831b7825 ths
{
92 831b7825 ths
    fprintf(stderr, "inb: port=0x%04x\n", addr);
93 831b7825 ths
    return 0;
94 831b7825 ths
}
95 831b7825 ths
96 831b7825 ths
int cpu_inw(CPUState *env, int addr)
97 831b7825 ths
{
98 831b7825 ths
    fprintf(stderr, "inw: port=0x%04x\n", addr);
99 831b7825 ths
    return 0;
100 831b7825 ths
}
101 831b7825 ths
102 831b7825 ths
int cpu_inl(CPUState *env, int addr)
103 831b7825 ths
{
104 831b7825 ths
    fprintf(stderr, "inl: port=0x%04x\n", addr);
105 831b7825 ths
    return 0;
106 831b7825 ths
}
107 831b7825 ths
108 831b7825 ths
int cpu_get_pic_interrupt(CPUState *env)
109 831b7825 ths
{
110 831b7825 ths
    return -1;
111 831b7825 ths
}
112 831b7825 ths
#ifdef TARGET_PPC
113 831b7825 ths
114 831b7825 ths
static inline uint64_t cpu_ppc_get_tb (CPUState *env)
115 831b7825 ths
{
116 831b7825 ths
    /* TO FIX */
117 831b7825 ths
    return 0;
118 831b7825 ths
}
119 831b7825 ths
120 831b7825 ths
uint32_t cpu_ppc_load_tbl (CPUState *env)
121 831b7825 ths
{
122 831b7825 ths
    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
123 831b7825 ths
}
124 831b7825 ths
125 831b7825 ths
uint32_t cpu_ppc_load_tbu (CPUState *env)
126 831b7825 ths
{
127 831b7825 ths
    return cpu_ppc_get_tb(env) >> 32;
128 831b7825 ths
}
129 831b7825 ths
130 a062e36c j_mayer
uint32_t cpu_ppc_load_atbl (CPUState *env)
131 831b7825 ths
{
132 a062e36c j_mayer
    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
133 831b7825 ths
}
134 831b7825 ths
135 a062e36c j_mayer
uint32_t cpu_ppc_load_atbu (CPUState *env)
136 c0009975 ths
{
137 a062e36c j_mayer
    return cpu_ppc_get_tb(env) >> 32;
138 c0009975 ths
}
139 c0009975 ths
140 c0009975 ths
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
141 c0009975 ths
{
142 c0009975 ths
    cpu_ppc_load_tbu(env);
143 c0009975 ths
}
144 c0009975 ths
145 c0009975 ths
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
146 c0009975 ths
{
147 c0009975 ths
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
148 c0009975 ths
}
149 c0009975 ths
150 e1833e1f j_mayer
/* XXX: to be fixed */
151 e1833e1f j_mayer
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
152 e1833e1f j_mayer
{
153 e1833e1f j_mayer
    return -1;
154 e1833e1f j_mayer
}
155 e1833e1f j_mayer
156 e1833e1f j_mayer
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
157 e1833e1f j_mayer
{
158 e1833e1f j_mayer
    return -1;
159 e1833e1f j_mayer
}
160 e1833e1f j_mayer
161 e1833e1f j_mayer
#define EXCP_DUMP(env, fmt, args...)                                         \
162 e1833e1f j_mayer
do {                                                                          \
163 e1833e1f j_mayer
    fprintf(stderr, fmt , ##args);                                            \
164 e1833e1f j_mayer
    cpu_dump_state(env, stderr, fprintf, 0);                                  \
165 93fcfe39 aliguori
    qemu_log(fmt, ##args);                                                   \
166 93fcfe39 aliguori
    log_cpu_state(env, 0);                                                      \
167 e1833e1f j_mayer
} while (0)
168 e1833e1f j_mayer
169 831b7825 ths
void cpu_loop(CPUPPCState *env)
170 831b7825 ths
{
171 831b7825 ths
    int trapnr;
172 831b7825 ths
    uint32_t ret;
173 831b7825 ths
    target_siginfo_t info;
174 831b7825 ths
175 831b7825 ths
    for(;;) {
176 831b7825 ths
        trapnr = cpu_ppc_exec(env);
177 831b7825 ths
        switch(trapnr) {
178 e1833e1f j_mayer
        case POWERPC_EXCP_NONE:
179 e1833e1f j_mayer
            /* Just go on */
180 831b7825 ths
            break;
181 e1833e1f j_mayer
        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
182 e1833e1f j_mayer
            cpu_abort(env, "Critical interrupt while in user mode. "
183 e1833e1f j_mayer
                      "Aborting\n");
184 831b7825 ths
            break;
185 e1833e1f j_mayer
        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
186 e1833e1f j_mayer
            cpu_abort(env, "Machine check exception while in user mode. "
187 e1833e1f j_mayer
                      "Aborting\n");
188 e1833e1f j_mayer
            break;
189 e1833e1f j_mayer
        case POWERPC_EXCP_DSI:      /* Data storage exception                */
190 831b7825 ths
#ifndef DAR
191 831b7825 ths
/* To deal with multiple qemu header version as host for the darwin-user code */
192 831b7825 ths
# define DAR SPR_DAR
193 831b7825 ths
#endif
194 e1833e1f j_mayer
            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
195 e1833e1f j_mayer
                      env->spr[SPR_DAR]);
196 831b7825 ths
            /* Handle this via the gdb */
197 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
198 831b7825 ths
199 831b7825 ths
            info.si_addr = (void*)env->nip;
200 831b7825 ths
            queue_signal(info.si_signo, &info);
201 831b7825 ths
            break;
202 e1833e1f j_mayer
        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
203 e1833e1f j_mayer
            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
204 e1833e1f j_mayer
                      env->spr[SPR_DAR]);
205 831b7825 ths
            /* Handle this via the gdb */
206 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
207 831b7825 ths
208 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
209 831b7825 ths
            queue_signal(info.si_signo, &info);
210 831b7825 ths
            break;
211 e1833e1f j_mayer
        case POWERPC_EXCP_EXTERNAL: /* External input                        */
212 e1833e1f j_mayer
            cpu_abort(env, "External interrupt while in user mode. "
213 e1833e1f j_mayer
                      "Aborting\n");
214 e1833e1f j_mayer
            break;
215 e1833e1f j_mayer
        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
216 e1833e1f j_mayer
            EXCP_DUMP(env, "Unaligned memory access\n");
217 831b7825 ths
            info.si_errno = 0;
218 831b7825 ths
            info.si_code = BUS_ADRALN;
219 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
220 831b7825 ths
            queue_signal(info.si_signo, &info);
221 831b7825 ths
            break;
222 e1833e1f j_mayer
        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
223 e1833e1f j_mayer
            /* XXX: check this */
224 831b7825 ths
            switch (env->error_code & ~0xF) {
225 e1833e1f j_mayer
            case POWERPC_EXCP_FP:
226 e1833e1f j_mayer
                EXCP_DUMP(env, "Floating point program exception\n");
227 e1833e1f j_mayer
                /* Set FX */
228 e1833e1f j_mayer
                info.si_signo = SIGFPE;
229 e1833e1f j_mayer
                info.si_errno = 0;
230 e1833e1f j_mayer
                switch (env->error_code & 0xF) {
231 e1833e1f j_mayer
                case POWERPC_EXCP_FP_OX:
232 e1833e1f j_mayer
                    info.si_code = FPE_FLTOVF;
233 e1833e1f j_mayer
                    break;
234 e1833e1f j_mayer
                case POWERPC_EXCP_FP_UX:
235 e1833e1f j_mayer
                    info.si_code = FPE_FLTUND;
236 e1833e1f j_mayer
                    break;
237 e1833e1f j_mayer
                case POWERPC_EXCP_FP_ZX:
238 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXZDZ:
239 e1833e1f j_mayer
                    info.si_code = FPE_FLTDIV;
240 e1833e1f j_mayer
                    break;
241 e1833e1f j_mayer
                case POWERPC_EXCP_FP_XX:
242 e1833e1f j_mayer
                    info.si_code = FPE_FLTRES;
243 e1833e1f j_mayer
                    break;
244 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXSOFT:
245 e1833e1f j_mayer
                    info.si_code = FPE_FLTINV;
246 e1833e1f j_mayer
                    break;
247 7c58044c j_mayer
                case POWERPC_EXCP_FP_VXSNAN:
248 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXISI:
249 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXIDI:
250 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXIMZ:
251 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXVC:
252 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXSQRT:
253 e1833e1f j_mayer
                case POWERPC_EXCP_FP_VXCVI:
254 e1833e1f j_mayer
                    info.si_code = FPE_FLTSUB;
255 831b7825 ths
                    break;
256 831b7825 ths
                default:
257 e1833e1f j_mayer
                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
258 e1833e1f j_mayer
                              env->error_code);
259 e1833e1f j_mayer
                    break;
260 e1833e1f j_mayer
                }
261 e1833e1f j_mayer
                break;
262 e1833e1f j_mayer
            case POWERPC_EXCP_INVAL:
263 e1833e1f j_mayer
                EXCP_DUMP(env, "Invalid instruction\n");
264 e1833e1f j_mayer
                info.si_signo = SIGILL;
265 e1833e1f j_mayer
                info.si_errno = 0;
266 e1833e1f j_mayer
                switch (env->error_code & 0xF) {
267 e1833e1f j_mayer
                case POWERPC_EXCP_INVAL_INVAL:
268 e1833e1f j_mayer
                    info.si_code = ILL_ILLOPC;
269 e1833e1f j_mayer
                    break;
270 e1833e1f j_mayer
                case POWERPC_EXCP_INVAL_LSWX:
271 e1833e1f j_mayer
                    info.si_code = ILL_ILLOPN;
272 e1833e1f j_mayer
                    break;
273 e1833e1f j_mayer
                case POWERPC_EXCP_INVAL_SPR:
274 e1833e1f j_mayer
                    info.si_code = ILL_PRVREG;
275 e1833e1f j_mayer
                    break;
276 e1833e1f j_mayer
                case POWERPC_EXCP_INVAL_FP:
277 e1833e1f j_mayer
                    info.si_code = ILL_COPROC;
278 e1833e1f j_mayer
                    break;
279 e1833e1f j_mayer
                default:
280 e1833e1f j_mayer
                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
281 e1833e1f j_mayer
                              env->error_code & 0xF);
282 e1833e1f j_mayer
                    info.si_code = ILL_ILLADR;
283 e1833e1f j_mayer
                    break;
284 e1833e1f j_mayer
                }
285 e1833e1f j_mayer
                /* Handle this via the gdb */
286 e1833e1f j_mayer
                gdb_handlesig (env, SIGSEGV);
287 e1833e1f j_mayer
                break;
288 e1833e1f j_mayer
            case POWERPC_EXCP_PRIV:
289 e1833e1f j_mayer
                EXCP_DUMP(env, "Privilege violation\n");
290 e1833e1f j_mayer
                info.si_signo = SIGILL;
291 e1833e1f j_mayer
                info.si_errno = 0;
292 e1833e1f j_mayer
                switch (env->error_code & 0xF) {
293 e1833e1f j_mayer
                case POWERPC_EXCP_PRIV_OPC:
294 e1833e1f j_mayer
                    info.si_code = ILL_PRVOPC;
295 e1833e1f j_mayer
                    break;
296 e1833e1f j_mayer
                case POWERPC_EXCP_PRIV_REG:
297 e1833e1f j_mayer
                    info.si_code = ILL_PRVREG;
298 e1833e1f j_mayer
                    break;
299 e1833e1f j_mayer
                default:
300 e1833e1f j_mayer
                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
301 e1833e1f j_mayer
                              env->error_code & 0xF);
302 e1833e1f j_mayer
                    info.si_code = ILL_PRVOPC;
303 e1833e1f j_mayer
                    break;
304 e1833e1f j_mayer
                }
305 e1833e1f j_mayer
                break;
306 e1833e1f j_mayer
            case POWERPC_EXCP_TRAP:
307 e1833e1f j_mayer
                cpu_abort(env, "Tried to call a TRAP\n");
308 e1833e1f j_mayer
                break;
309 e1833e1f j_mayer
            default:
310 e1833e1f j_mayer
                /* Should not happen ! */
311 e1833e1f j_mayer
                cpu_abort(env, "Unknown program exception (%02x)\n",
312 e1833e1f j_mayer
                          env->error_code);
313 e1833e1f j_mayer
                break;
314 831b7825 ths
            }
315 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
316 831b7825 ths
            queue_signal(info.si_signo, &info);
317 831b7825 ths
            break;
318 e1833e1f j_mayer
        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
319 e1833e1f j_mayer
            EXCP_DUMP(env, "No floating point allowed\n");
320 e1833e1f j_mayer
            info.si_signo = SIGILL;
321 831b7825 ths
            info.si_errno = 0;
322 831b7825 ths
            info.si_code = ILL_COPROC;
323 831b7825 ths
            info.si_addr = (void*)(env->nip - 4);
324 831b7825 ths
            queue_signal(info.si_signo, &info);
325 831b7825 ths
            break;
326 e1833e1f j_mayer
        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
327 e1833e1f j_mayer
            cpu_abort(env, "Syscall exception while in user mode. "
328 e1833e1f j_mayer
                      "Aborting\n");
329 831b7825 ths
            break;
330 e1833e1f j_mayer
        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
331 e1833e1f j_mayer
            EXCP_DUMP(env, "No APU instruction allowed\n");
332 e1833e1f j_mayer
            info.si_signo = SIGILL;
333 e1833e1f j_mayer
            info.si_errno = 0;
334 e1833e1f j_mayer
            info.si_code = ILL_COPROC;
335 e1833e1f j_mayer
            info.si_addr = (void*)(env->nip - 4);
336 e1833e1f j_mayer
            queue_signal(info.si_signo, &info);
337 e1833e1f j_mayer
            break;
338 e1833e1f j_mayer
        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
339 e1833e1f j_mayer
            cpu_abort(env, "Decrementer interrupt while in user mode. "
340 e1833e1f j_mayer
                      "Aborting\n");
341 e1833e1f j_mayer
            break;
342 e1833e1f j_mayer
        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
343 e1833e1f j_mayer
            cpu_abort(env, "Fix interval timer interrupt while in user mode. "
344 e1833e1f j_mayer
                      "Aborting\n");
345 e1833e1f j_mayer
            break;
346 e1833e1f j_mayer
        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
347 e1833e1f j_mayer
            cpu_abort(env, "Watchdog timer interrupt while in user mode. "
348 e1833e1f j_mayer
                      "Aborting\n");
349 831b7825 ths
            break;
350 e1833e1f j_mayer
        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
351 e1833e1f j_mayer
            cpu_abort(env, "Data TLB exception while in user mode. "
352 e1833e1f j_mayer
                      "Aborting\n");
353 831b7825 ths
            break;
354 e1833e1f j_mayer
        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
355 e1833e1f j_mayer
            cpu_abort(env, "Instruction TLB exception while in user mode. "
356 e1833e1f j_mayer
                      "Aborting\n");
357 831b7825 ths
            break;
358 e1833e1f j_mayer
        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */
359 831b7825 ths
            gdb_handlesig (env, SIGTRAP);
360 831b7825 ths
            break;
361 e1833e1f j_mayer
        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
362 e1833e1f j_mayer
            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
363 e1833e1f j_mayer
            info.si_signo = SIGILL;
364 e1833e1f j_mayer
            info.si_errno = 0;
365 e1833e1f j_mayer
            info.si_code = ILL_COPROC;
366 e1833e1f j_mayer
            info.si_addr = (void*)(env->nip - 4);
367 e1833e1f j_mayer
            queue_signal(info.si_signo, &info);
368 e1833e1f j_mayer
            break;
369 e1833e1f j_mayer
        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
370 e1833e1f j_mayer
            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
371 e1833e1f j_mayer
            break;
372 e1833e1f j_mayer
        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
373 e1833e1f j_mayer
            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
374 e1833e1f j_mayer
            break;
375 e1833e1f j_mayer
        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
376 e1833e1f j_mayer
            cpu_abort(env, "Performance monitor exception not handled\n");
377 e1833e1f j_mayer
            break;
378 e1833e1f j_mayer
        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
379 e1833e1f j_mayer
            cpu_abort(env, "Doorbell interrupt while in user mode. "
380 e1833e1f j_mayer
                       "Aborting\n");
381 e1833e1f j_mayer
            break;
382 e1833e1f j_mayer
        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
383 e1833e1f j_mayer
            cpu_abort(env, "Doorbell critical interrupt while in user mode. "
384 e1833e1f j_mayer
                      "Aborting\n");
385 e1833e1f j_mayer
            break;
386 e1833e1f j_mayer
        case POWERPC_EXCP_RESET:    /* System reset exception                */
387 e1833e1f j_mayer
            cpu_abort(env, "Reset interrupt while in user mode. "
388 e1833e1f j_mayer
                      "Aborting\n");
389 e1833e1f j_mayer
            break;
390 e1833e1f j_mayer
        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
391 e1833e1f j_mayer
            cpu_abort(env, "Data segment exception while in user mode. "
392 e1833e1f j_mayer
                      "Aborting\n");
393 e1833e1f j_mayer
            break;
394 e1833e1f j_mayer
        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
395 e1833e1f j_mayer
            cpu_abort(env, "Instruction segment exception "
396 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
397 e1833e1f j_mayer
            break;
398 e1833e1f j_mayer
        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
399 e1833e1f j_mayer
            cpu_abort(env, "Hypervisor decrementer interrupt "
400 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
401 e1833e1f j_mayer
            break;
402 e1833e1f j_mayer
        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
403 e1833e1f j_mayer
            /* Nothing to do:
404 e1833e1f j_mayer
             * we use this exception to emulate step-by-step execution mode.
405 e1833e1f j_mayer
             */
406 e1833e1f j_mayer
            break;
407 e1833e1f j_mayer
        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
408 e1833e1f j_mayer
            cpu_abort(env, "Hypervisor data storage exception "
409 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
410 e1833e1f j_mayer
            break;
411 e1833e1f j_mayer
        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
412 e1833e1f j_mayer
            cpu_abort(env, "Hypervisor instruction storage exception "
413 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
414 e1833e1f j_mayer
            break;
415 e1833e1f j_mayer
        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
416 e1833e1f j_mayer
            cpu_abort(env, "Hypervisor data segment exception "
417 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
418 e1833e1f j_mayer
            break;
419 e1833e1f j_mayer
        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
420 e1833e1f j_mayer
            cpu_abort(env, "Hypervisor instruction segment exception "
421 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
422 e1833e1f j_mayer
            break;
423 e1833e1f j_mayer
        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
424 e1833e1f j_mayer
            EXCP_DUMP(env, "No Altivec instructions allowed\n");
425 e1833e1f j_mayer
            info.si_signo = SIGILL;
426 e1833e1f j_mayer
            info.si_errno = 0;
427 e1833e1f j_mayer
            info.si_code = ILL_COPROC;
428 e1833e1f j_mayer
            info.si_addr = (void*)(env->nip - 4);
429 e1833e1f j_mayer
            queue_signal(info.si_signo, &info);
430 e1833e1f j_mayer
            break;
431 e1833e1f j_mayer
        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
432 e1833e1f j_mayer
            cpu_abort(env, "Programable interval timer interrupt "
433 e1833e1f j_mayer
                      "while in user mode. Aborting\n");
434 e1833e1f j_mayer
            break;
435 e1833e1f j_mayer
        case POWERPC_EXCP_IO:       /* IO error exception                    */
436 e1833e1f j_mayer
            cpu_abort(env, "IO error exception while in user mode. "
437 e1833e1f j_mayer
                      "Aborting\n");
438 e1833e1f j_mayer
            break;
439 e1833e1f j_mayer
        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
440 e1833e1f j_mayer
            cpu_abort(env, "Run mode exception while in user mode. "
441 e1833e1f j_mayer
                      "Aborting\n");
442 e1833e1f j_mayer
            break;
443 e1833e1f j_mayer
        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
444 e1833e1f j_mayer
            cpu_abort(env, "Emulation trap exception not handled\n");
445 e1833e1f j_mayer
            break;
446 e1833e1f j_mayer
        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
447 e1833e1f j_mayer
            cpu_abort(env, "Instruction fetch TLB exception "
448 e1833e1f j_mayer
                      "while in user-mode. Aborting");
449 e1833e1f j_mayer
            break;
450 e1833e1f j_mayer
        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
451 e1833e1f j_mayer
            cpu_abort(env, "Data load TLB exception while in user-mode. "
452 e1833e1f j_mayer
                      "Aborting");
453 e1833e1f j_mayer
            break;
454 e1833e1f j_mayer
        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
455 e1833e1f j_mayer
            cpu_abort(env, "Data store TLB exception while in user-mode. "
456 e1833e1f j_mayer
                      "Aborting");
457 e1833e1f j_mayer
            break;
458 e1833e1f j_mayer
        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
459 e1833e1f j_mayer
            cpu_abort(env, "Floating-point assist exception not handled\n");
460 e1833e1f j_mayer
            break;
461 e1833e1f j_mayer
        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
462 e1833e1f j_mayer
            cpu_abort(env, "Instruction address breakpoint exception "
463 e1833e1f j_mayer
                      "not handled\n");
464 e1833e1f j_mayer
            break;
465 e1833e1f j_mayer
        case POWERPC_EXCP_SMI:      /* System management interrupt           */
466 e1833e1f j_mayer
            cpu_abort(env, "System management interrupt while in user mode. "
467 e1833e1f j_mayer
                      "Aborting\n");
468 e1833e1f j_mayer
            break;
469 e1833e1f j_mayer
        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
470 e1833e1f j_mayer
            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
471 e1833e1f j_mayer
                      "Aborting\n");
472 e1833e1f j_mayer
            break;
473 e1833e1f j_mayer
        case POWERPC_EXCP_PERFM:    /* Embedded performance monitor IRQ      */
474 e1833e1f j_mayer
            cpu_abort(env, "Performance monitor exception not handled\n");
475 e1833e1f j_mayer
            break;
476 e1833e1f j_mayer
        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
477 e1833e1f j_mayer
            cpu_abort(env, "Vector assist exception not handled\n");
478 e1833e1f j_mayer
            break;
479 e1833e1f j_mayer
        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
480 e1833e1f j_mayer
            cpu_abort(env, "Soft patch exception not handled\n");
481 e1833e1f j_mayer
            break;
482 e1833e1f j_mayer
        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
483 e1833e1f j_mayer
            cpu_abort(env, "Maintenance exception while in user mode. "
484 e1833e1f j_mayer
                      "Aborting\n");
485 e1833e1f j_mayer
            break;
486 e1833e1f j_mayer
        case POWERPC_EXCP_STOP:     /* stop translation                      */
487 e1833e1f j_mayer
            /* We did invalidate the instruction cache. Go on */
488 e1833e1f j_mayer
            break;
489 e1833e1f j_mayer
        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
490 e1833e1f j_mayer
            /* We just stopped because of a branch. Go on */
491 e1833e1f j_mayer
            break;
492 e1833e1f j_mayer
        case POWERPC_EXCP_SYSCALL_USER:
493 e1833e1f j_mayer
            /* system call in user-mode emulation */
494 e1833e1f j_mayer
            /* system call */
495 e1833e1f j_mayer
            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
496 e1833e1f j_mayer
                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
497 e1833e1f j_mayer
                                      env->gpr[5], env->gpr[6], env->gpr[7],
498 e1833e1f j_mayer
                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
499 e1833e1f j_mayer
            else if(((int)env->gpr[0])<0)
500 e1833e1f j_mayer
                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
501 e1833e1f j_mayer
                                      env->gpr[5], env->gpr[6], env->gpr[7],
502 e1833e1f j_mayer
                                      env->gpr[8], env->gpr[9], env->gpr[10]);
503 e1833e1f j_mayer
            else
504 e1833e1f j_mayer
                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
505 e1833e1f j_mayer
                                        env->gpr[5], env->gpr[6], env->gpr[7],
506 e1833e1f j_mayer
                                        env->gpr[8], env->gpr[9], env->gpr[10]);
507 e1833e1f j_mayer
508 e1833e1f j_mayer
            /* Unix syscall error signaling */
509 e1833e1f j_mayer
            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
510 e1833e1f j_mayer
            {
511 e1833e1f j_mayer
                if( (int)ret < 0 )
512 e1833e1f j_mayer
                    env->nip += 0;
513 e1833e1f j_mayer
                else
514 e1833e1f j_mayer
                    env->nip += 4;
515 831b7825 ths
            }
516 e1833e1f j_mayer
517 e1833e1f j_mayer
            /* Return value */
518 e1833e1f j_mayer
            env->gpr[3] = ret;
519 e1833e1f j_mayer
            break;
520 56ba31ff j_mayer
        case EXCP_INTERRUPT:
521 56ba31ff j_mayer
            /* just indicate that signals should be handled asap */
522 56ba31ff j_mayer
            break;
523 e1833e1f j_mayer
        default:
524 e1833e1f j_mayer
            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
525 e1833e1f j_mayer
            break;
526 831b7825 ths
        }
527 831b7825 ths
        process_pending_signals(env);
528 831b7825 ths
    }
529 831b7825 ths
}
530 831b7825 ths
#endif
531 831b7825 ths
532 831b7825 ths
533 831b7825 ths
#ifdef TARGET_I386
534 831b7825 ths
535 831b7825 ths
/***********************************************************/
536 831b7825 ths
/* CPUX86 core interface */
537 831b7825 ths
538 831b7825 ths
uint64_t cpu_get_tsc(CPUX86State *env)
539 831b7825 ths
{
540 831b7825 ths
    return cpu_get_real_ticks();
541 831b7825 ths
}
542 831b7825 ths
543 831b7825 ths
void
544 831b7825 ths
write_dt(void *ptr, unsigned long addr, unsigned long limit,
545 831b7825 ths
                     int flags)
546 831b7825 ths
{
547 831b7825 ths
    unsigned int e1, e2;
548 831b7825 ths
    e1 = (addr << 16) | (limit & 0xffff);
549 831b7825 ths
    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
550 831b7825 ths
    e2 |= flags;
551 831b7825 ths
    stl((uint8_t *)ptr, e1);
552 831b7825 ths
    stl((uint8_t *)ptr + 4, e2);
553 831b7825 ths
}
554 831b7825 ths
555 831b7825 ths
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
556 831b7825 ths
                     unsigned long addr, unsigned int sel)
557 831b7825 ths
{
558 831b7825 ths
    unsigned int e1, e2;
559 831b7825 ths
    e1 = (addr & 0xffff) | (sel << 16);
560 831b7825 ths
    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
561 831b7825 ths
    stl((uint8_t *)ptr, e1);
562 831b7825 ths
    stl((uint8_t *)ptr + 4, e2);
563 831b7825 ths
}
564 831b7825 ths
565 831b7825 ths
#define GDT_TABLE_SIZE 14
566 831b7825 ths
#define LDT_TABLE_SIZE 15
567 831b7825 ths
#define IDT_TABLE_SIZE 256
568 831b7825 ths
#define TSS_SIZE 104
569 831b7825 ths
uint64_t gdt_table[GDT_TABLE_SIZE];
570 831b7825 ths
uint64_t ldt_table[LDT_TABLE_SIZE];
571 831b7825 ths
uint64_t idt_table[IDT_TABLE_SIZE];
572 831b7825 ths
uint32_t tss[TSS_SIZE];
573 831b7825 ths
574 831b7825 ths
/* only dpl matters as we do only user space emulation */
575 831b7825 ths
static void set_idt(int n, unsigned int dpl)
576 831b7825 ths
{
577 831b7825 ths
    set_gate(idt_table + n, 0, dpl, 0, 0);
578 831b7825 ths
}
579 831b7825 ths
580 831b7825 ths
/* ABI convention: after a syscall if there was an error the CF flag is set */
581 46ea3397 ths
static inline void set_error(CPUX86State *env, int ret)
582 831b7825 ths
{
583 831b7825 ths
    if(ret<0)
584 831b7825 ths
        env->eflags = env->eflags | 0x1;
585 831b7825 ths
    else
586 831b7825 ths
        env->eflags &= ~0x1;
587 831b7825 ths
    env->regs[R_EAX] = ret;
588 831b7825 ths
}
589 831b7825 ths
590 831b7825 ths
void cpu_loop(CPUX86State *env)
591 831b7825 ths
{
592 831b7825 ths
    int trapnr;
593 831b7825 ths
    int ret;
594 831b7825 ths
    uint8_t *pc;
595 831b7825 ths
    target_siginfo_t info;
596 831b7825 ths
597 831b7825 ths
    for(;;) {
598 831b7825 ths
        trapnr = cpu_x86_exec(env);
599 831b7825 ths
        uint32_t *params = (uint32_t *)env->regs[R_ESP];
600 831b7825 ths
        switch(trapnr) {
601 831b7825 ths
        case 0x79: /* Our commpage hack back door exit is here */
602 831b7825 ths
            do_commpage(env,  env->eip,   *(params + 1), *(params + 2),
603 831b7825 ths
                                          *(params + 3), *(params + 4),
604 831b7825 ths
                                          *(params + 5), *(params + 6),
605 831b7825 ths
                                          *(params + 7), *(params + 8));
606 831b7825 ths
            break;
607 831b7825 ths
        case 0x81: /* mach syscall */
608 831b7825 ths
        {
609 831b7825 ths
            ret = do_mach_syscall(env,  env->regs[R_EAX],
610 831b7825 ths
                                          *(params + 1), *(params + 2),
611 831b7825 ths
                                          *(params + 3), *(params + 4),
612 831b7825 ths
                                          *(params + 5), *(params + 6),
613 831b7825 ths
                                          *(params + 7), *(params + 8));
614 831b7825 ths
            set_error(env, ret);
615 831b7825 ths
            break;
616 831b7825 ths
        }
617 831b7825 ths
        case 0x90: /* unix backdoor */
618 831b7825 ths
        {
619 831b7825 ths
            /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
620 831b7825 ths
            int saved_stack = env->regs[R_ESP];
621 831b7825 ths
            env->regs[R_ESP] = env->regs[R_ECX];
622 831b7825 ths
623 831b7825 ths
            ret = do_unix_syscall(env, env->regs[R_EAX]);
624 831b7825 ths
625 831b7825 ths
            env->regs[R_ECX] = env->regs[R_ESP];
626 831b7825 ths
            env->regs[R_ESP] = saved_stack;
627 831b7825 ths
628 831b7825 ths
            set_error(env, ret);
629 831b7825 ths
            break;
630 831b7825 ths
        }
631 831b7825 ths
        case 0x80: /* unix syscall */
632 831b7825 ths
        {
633 831b7825 ths
            ret = do_unix_syscall(env, env->regs[R_EAX]/*,
634 831b7825 ths
                                          *(params + 1), *(params + 2),
635 831b7825 ths
                                          *(params + 3), *(params + 4),
636 831b7825 ths
                                          *(params + 5), *(params + 6),
637 831b7825 ths
                                          *(params + 7), *(params + 8)*/);
638 831b7825 ths
            set_error(env, ret);
639 831b7825 ths
            break;
640 831b7825 ths
        }
641 831b7825 ths
        case 0x82: /* thread syscall */
642 831b7825 ths
        {
643 831b7825 ths
            ret = do_thread_syscall(env,  env->regs[R_EAX],
644 831b7825 ths
                                          *(params + 1), *(params + 2),
645 831b7825 ths
                                          *(params + 3), *(params + 4),
646 831b7825 ths
                                          *(params + 5), *(params + 6),
647 831b7825 ths
                                          *(params + 7), *(params + 8));
648 831b7825 ths
            set_error(env, ret);
649 831b7825 ths
            break;
650 831b7825 ths
        }
651 831b7825 ths
        case EXCP0B_NOSEG:
652 831b7825 ths
        case EXCP0C_STACK:
653 831b7825 ths
            info.si_signo = SIGBUS;
654 831b7825 ths
            info.si_errno = 0;
655 831b7825 ths
            info.si_code = BUS_NOOP;
656 831b7825 ths
            info.si_addr = 0;
657 831b7825 ths
            gdb_handlesig (env, SIGBUS);
658 831b7825 ths
            queue_signal(info.si_signo, &info);
659 831b7825 ths
            break;
660 831b7825 ths
        case EXCP0D_GPF:
661 831b7825 ths
            info.si_signo = SIGSEGV;
662 831b7825 ths
            info.si_errno = 0;
663 831b7825 ths
            info.si_code = SEGV_NOOP;
664 831b7825 ths
            info.si_addr = 0;
665 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
666 831b7825 ths
            queue_signal(info.si_signo, &info);
667 831b7825 ths
            break;
668 831b7825 ths
        case EXCP0E_PAGE:
669 831b7825 ths
            info.si_signo = SIGSEGV;
670 831b7825 ths
            info.si_errno = 0;
671 831b7825 ths
            if (!(env->error_code & 1))
672 831b7825 ths
                info.si_code = SEGV_MAPERR;
673 831b7825 ths
            else
674 831b7825 ths
                info.si_code = SEGV_ACCERR;
675 831b7825 ths
            info.si_addr = (void*)env->cr[2];
676 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
677 831b7825 ths
            queue_signal(info.si_signo, &info);
678 831b7825 ths
            break;
679 831b7825 ths
        case EXCP00_DIVZ:
680 831b7825 ths
            /* division by zero */
681 831b7825 ths
            info.si_signo = SIGFPE;
682 831b7825 ths
            info.si_errno = 0;
683 831b7825 ths
            info.si_code = FPE_INTDIV;
684 831b7825 ths
            info.si_addr = (void*)env->eip;
685 831b7825 ths
            gdb_handlesig (env, SIGFPE);
686 831b7825 ths
            queue_signal(info.si_signo, &info);
687 831b7825 ths
            break;
688 831b7825 ths
        case EXCP01_SSTP:
689 831b7825 ths
        case EXCP03_INT3:
690 831b7825 ths
            info.si_signo = SIGTRAP;
691 831b7825 ths
            info.si_errno = 0;
692 831b7825 ths
            info.si_code = TRAP_BRKPT;
693 831b7825 ths
            info.si_addr = (void*)env->eip;
694 831b7825 ths
            gdb_handlesig (env, SIGTRAP);
695 831b7825 ths
            queue_signal(info.si_signo, &info);
696 831b7825 ths
            break;
697 831b7825 ths
        case EXCP04_INTO:
698 831b7825 ths
        case EXCP05_BOUND:
699 831b7825 ths
            info.si_signo = SIGSEGV;
700 831b7825 ths
            info.si_errno = 0;
701 831b7825 ths
            info.si_code = SEGV_NOOP;
702 831b7825 ths
            info.si_addr = 0;
703 831b7825 ths
            gdb_handlesig (env, SIGSEGV);
704 831b7825 ths
            queue_signal(info.si_signo, &info);
705 831b7825 ths
            break;
706 831b7825 ths
        case EXCP06_ILLOP:
707 831b7825 ths
            info.si_signo = SIGILL;
708 831b7825 ths
            info.si_errno = 0;
709 831b7825 ths
            info.si_code = ILL_ILLOPN;
710 831b7825 ths
            info.si_addr = (void*)env->eip;
711 831b7825 ths
            gdb_handlesig (env, SIGILL);
712 831b7825 ths
            queue_signal(info.si_signo, &info);
713 831b7825 ths
            break;
714 831b7825 ths
        case EXCP_INTERRUPT:
715 831b7825 ths
            /* just indicate that signals should be handled asap */
716 831b7825 ths
            break;
717 831b7825 ths
        case EXCP_DEBUG:
718 831b7825 ths
            {
719 831b7825 ths
                int sig;
720 831b7825 ths
721 831b7825 ths
                sig = gdb_handlesig (env, SIGTRAP);
722 831b7825 ths
                if (sig)
723 831b7825 ths
                  {
724 831b7825 ths
                    info.si_signo = sig;
725 831b7825 ths
                    info.si_errno = 0;
726 831b7825 ths
                    info.si_code = TRAP_BRKPT;
727 831b7825 ths
                    queue_signal(info.si_signo, &info);
728 831b7825 ths
                  }
729 831b7825 ths
            }
730 831b7825 ths
            break;
731 831b7825 ths
        default:
732 831b7825 ths
            pc = (void*)(env->segs[R_CS].base + env->eip);
733 831b7825 ths
            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
734 831b7825 ths
                    (long)pc, trapnr);
735 831b7825 ths
            abort();
736 831b7825 ths
        }
737 831b7825 ths
        process_pending_signals(env);
738 831b7825 ths
    }
739 831b7825 ths
}
740 831b7825 ths
#endif
741 831b7825 ths
742 831b7825 ths
void usage(void)
743 831b7825 ths
{
744 831b7825 ths
    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
745 831b7825 ths
           "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
746 831b7825 ths
           "Darwin CPU emulator (compiled for %s emulation)\n"
747 831b7825 ths
           "\n"
748 831b7825 ths
           "-h           print this help\n"
749 1e2bed4f bellard
           "-L path      set the %s library path (default='%s')\n"
750 831b7825 ths
           "-s size      set the stack size in bytes (default=%ld)\n"
751 831b7825 ths
           "\n"
752 831b7825 ths
           "debug options:\n"
753 1e2bed4f bellard
           "-d options   activate log (logfile='%s')\n"
754 831b7825 ths
           "-g wait for gdb on port 1234\n"
755 831b7825 ths
           "-p pagesize  set the host page size to 'pagesize'\n",
756 1b530a6d aurel32
           "-singlestep  always run in singlestep mode\n"
757 831b7825 ths
           TARGET_ARCH,
758 1e2bed4f bellard
           TARGET_ARCH,
759 831b7825 ths
           interp_prefix,
760 831b7825 ths
           stack_size,
761 831b7825 ths
           DEBUG_LOGFILE);
762 2d18e637 blueswir1
    exit(1);
763 831b7825 ths
}
764 831b7825 ths
765 831b7825 ths
/* XXX: currently only used for async signals (see signal.c) */
766 831b7825 ths
CPUState *global_env;
767 831b7825 ths
/* used only if single thread */
768 831b7825 ths
CPUState *cpu_single_env = NULL;
769 831b7825 ths
770 831b7825 ths
/* used to free thread contexts */
771 831b7825 ths
TaskState *first_task_state;
772 831b7825 ths
773 831b7825 ths
int main(int argc, char **argv)
774 831b7825 ths
{
775 831b7825 ths
    const char *filename;
776 831b7825 ths
    struct target_pt_regs regs1, *regs = &regs1;
777 831b7825 ths
    TaskState ts1, *ts = &ts1;
778 831b7825 ths
    CPUState *env;
779 831b7825 ths
    int optind;
780 831b7825 ths
    short use_gdbstub = 0;
781 831b7825 ths
    const char *r;
782 aaed909a bellard
    const char *cpu_model;
783 831b7825 ths
784 831b7825 ths
    if (argc <= 1)
785 831b7825 ths
        usage();
786 831b7825 ths
787 831b7825 ths
    /* init debug */
788 831b7825 ths
    cpu_set_log_filename(DEBUG_LOGFILE);
789 831b7825 ths
790 831b7825 ths
    optind = 1;
791 831b7825 ths
    for(;;) {
792 831b7825 ths
        if (optind >= argc)
793 831b7825 ths
            break;
794 831b7825 ths
        r = argv[optind];
795 831b7825 ths
        if (r[0] != '-')
796 831b7825 ths
            break;
797 831b7825 ths
        optind++;
798 831b7825 ths
        r++;
799 831b7825 ths
        if (!strcmp(r, "-")) {
800 831b7825 ths
            break;
801 831b7825 ths
        } else if (!strcmp(r, "d")) {
802 831b7825 ths
            int mask;
803 831b7825 ths
            CPULogItem *item;
804 831b7825 ths
805 831b7825 ths
        if (optind >= argc)
806 831b7825 ths
        break;
807 831b7825 ths
808 831b7825 ths
        r = argv[optind++];
809 831b7825 ths
            mask = cpu_str_to_log_mask(r);
810 831b7825 ths
            if (!mask) {
811 831b7825 ths
                printf("Log items (comma separated):\n");
812 831b7825 ths
                for(item = cpu_log_items; item->mask != 0; item++) {
813 831b7825 ths
                    printf("%-10s %s\n", item->name, item->help);
814 831b7825 ths
                }
815 831b7825 ths
                exit(1);
816 831b7825 ths
            }
817 831b7825 ths
            cpu_set_log(mask);
818 831b7825 ths
        } else if (!strcmp(r, "s")) {
819 831b7825 ths
            r = argv[optind++];
820 831b7825 ths
            stack_size = strtol(r, (char **)&r, 0);
821 831b7825 ths
            if (stack_size <= 0)
822 831b7825 ths
                usage();
823 831b7825 ths
            if (*r == 'M')
824 831b7825 ths
                stack_size *= 1024 * 1024;
825 831b7825 ths
            else if (*r == 'k' || *r == 'K')
826 831b7825 ths
                stack_size *= 1024;
827 831b7825 ths
        } else if (!strcmp(r, "L")) {
828 831b7825 ths
            interp_prefix = argv[optind++];
829 831b7825 ths
        } else if (!strcmp(r, "p")) {
830 831b7825 ths
            qemu_host_page_size = atoi(argv[optind++]);
831 831b7825 ths
            if (qemu_host_page_size == 0 ||
832 831b7825 ths
                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
833 831b7825 ths
                fprintf(stderr, "page size must be a power of two\n");
834 831b7825 ths
                exit(1);
835 831b7825 ths
            }
836 831b7825 ths
        } else
837 831b7825 ths
        if (!strcmp(r, "g")) {
838 831b7825 ths
            use_gdbstub = 1;
839 31fca6ab j_mayer
        } else if (!strcmp(r, "cpu")) {
840 31fca6ab j_mayer
            cpu_model = argv[optind++];
841 31fca6ab j_mayer
            if (strcmp(cpu_model, "?") == 0) {
842 31fca6ab j_mayer
/* XXX: implement xxx_cpu_list for targets that still miss it */
843 31fca6ab j_mayer
#if defined(cpu_list)
844 31fca6ab j_mayer
                    cpu_list(stdout, &fprintf);
845 31fca6ab j_mayer
#endif
846 2d18e637 blueswir1
                exit(1);
847 31fca6ab j_mayer
            }
848 1b530a6d aurel32
        } else if (!strcmp(r, "singlestep")) {
849 1b530a6d aurel32
            singlestep = 1;
850 831b7825 ths
        } else
851 831b7825 ths
        {
852 831b7825 ths
            usage();
853 831b7825 ths
        }
854 831b7825 ths
    }
855 831b7825 ths
    if (optind >= argc)
856 831b7825 ths
        usage();
857 831b7825 ths
    filename = argv[optind];
858 831b7825 ths
859 831b7825 ths
    /* Zero out regs */
860 831b7825 ths
    memset(regs, 0, sizeof(struct target_pt_regs));
861 831b7825 ths
862 31fca6ab j_mayer
    if (cpu_model == NULL) {
863 aaed909a bellard
#if defined(TARGET_I386)
864 31fca6ab j_mayer
#ifdef TARGET_X86_64
865 31fca6ab j_mayer
        cpu_model = "qemu64";
866 31fca6ab j_mayer
#else
867 31fca6ab j_mayer
        cpu_model = "qemu32";
868 31fca6ab j_mayer
#endif
869 aaed909a bellard
#elif defined(TARGET_PPC)
870 31fca6ab j_mayer
#ifdef TARGET_PPC64
871 31fca6ab j_mayer
        cpu_model = "970";
872 31fca6ab j_mayer
#else
873 31fca6ab j_mayer
        cpu_model = "750";
874 31fca6ab j_mayer
#endif
875 aaed909a bellard
#else
876 aaed909a bellard
#error unsupported CPU
877 aaed909a bellard
#endif
878 31fca6ab j_mayer
    }
879 aaed909a bellard
    
880 26a5f13b bellard
    cpu_exec_init_all(0);
881 31fca6ab j_mayer
    /* NOTE: we need to init the CPU at this stage to get
882 31fca6ab j_mayer
       qemu_host_page_size */
883 aaed909a bellard
    env = cpu_init(cpu_model);
884 831b7825 ths
885 831b7825 ths
    printf("Starting %s with qemu\n----------------\n", filename);
886 831b7825 ths
887 831b7825 ths
    commpage_init();
888 831b7825 ths
889 831b7825 ths
    if (mach_exec(filename, argv+optind, environ, regs) != 0) {
890 831b7825 ths
    printf("Error loading %s\n", filename);
891 831b7825 ths
    _exit(1);
892 831b7825 ths
    }
893 831b7825 ths
894 831b7825 ths
    syscall_init();
895 831b7825 ths
    signal_init();
896 831b7825 ths
    global_env = env;
897 831b7825 ths
898 831b7825 ths
    /* build Task State */
899 831b7825 ths
    memset(ts, 0, sizeof(TaskState));
900 831b7825 ths
    env->opaque = ts;
901 831b7825 ths
    ts->used = 1;
902 831b7825 ths
903 831b7825 ths
#if defined(TARGET_I386)
904 831b7825 ths
    cpu_x86_set_cpl(env, 3);
905 831b7825 ths
906 831b7825 ths
    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
907 831b7825 ths
    env->hflags |= HF_PE_MASK;
908 831b7825 ths
909 831b7825 ths
    if (env->cpuid_features & CPUID_SSE) {
910 831b7825 ths
        env->cr[4] |= CR4_OSFXSR_MASK;
911 831b7825 ths
        env->hflags |= HF_OSFXSR_MASK;
912 831b7825 ths
    }
913 831b7825 ths
914 831b7825 ths
    /* flags setup : we activate the IRQs by default as in user mode */
915 831b7825 ths
    env->eflags |= IF_MASK;
916 831b7825 ths
917 831b7825 ths
    /* darwin register setup */
918 831b7825 ths
    env->regs[R_EAX] = regs->eax;
919 831b7825 ths
    env->regs[R_EBX] = regs->ebx;
920 831b7825 ths
    env->regs[R_ECX] = regs->ecx;
921 831b7825 ths
    env->regs[R_EDX] = regs->edx;
922 831b7825 ths
    env->regs[R_ESI] = regs->esi;
923 831b7825 ths
    env->regs[R_EDI] = regs->edi;
924 831b7825 ths
    env->regs[R_EBP] = regs->ebp;
925 831b7825 ths
    env->regs[R_ESP] = regs->esp;
926 831b7825 ths
    env->eip = regs->eip;
927 831b7825 ths
928 831b7825 ths
    /* Darwin LDT setup */
929 831b7825 ths
    /* 2 - User code segment
930 831b7825 ths
       3 - User data segment
931 831b7825 ths
       4 - User cthread */
932 831b7825 ths
    bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
933 831b7825 ths
    env->ldt.base = (uint32_t) ldt_table;
934 831b7825 ths
    env->ldt.limit = sizeof(ldt_table) - 1;
935 831b7825 ths
936 831b7825 ths
    write_dt(ldt_table + 2, 0, 0xfffff,
937 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
938 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
939 831b7825 ths
    write_dt(ldt_table + 3, 0, 0xfffff,
940 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
941 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
942 831b7825 ths
    write_dt(ldt_table + 4, 0, 0xfffff,
943 831b7825 ths
             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
944 831b7825 ths
             (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
945 831b7825 ths
946 831b7825 ths
    /* Darwin GDT setup.
947 831b7825 ths
     * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
948 831b7825 ths
       now everything is done via  int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
949 831b7825 ths
    bzero(gdt_table, sizeof(gdt_table));
950 831b7825 ths
    env->gdt.base = (uint32_t)gdt_table;
951 831b7825 ths
    env->gdt.limit = sizeof(gdt_table) - 1;
952 831b7825 ths
953 831b7825 ths
    /* Set up a back door to handle sysenter syscalls (unix) */
954 831b7825 ths
    char * syscallbackdoor = malloc(64);
955 831b7825 ths
    page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
956 831b7825 ths
957 831b7825 ths
    int i = 0;
958 831b7825 ths
    syscallbackdoor[i++] = 0xcd;
959 831b7825 ths
    syscallbackdoor[i++] = 0x90; /* int 0x90 */
960 831b7825 ths
    syscallbackdoor[i++] = 0x0F;
961 831b7825 ths
    syscallbackdoor[i++] = 0x35; /* sysexit */
962 831b7825 ths
963 831b7825 ths
    /* Darwin sysenter/sysexit setup */
964 831b7825 ths
    env->sysenter_cs = 0x1; //XXX
965 831b7825 ths
    env->sysenter_eip = (int)syscallbackdoor;
966 831b7825 ths
    env->sysenter_esp = (int)malloc(64);
967 831b7825 ths
968 831b7825 ths
    /* Darwin TSS setup
969 831b7825 ths
       This must match up with GDT[4] */
970 831b7825 ths
    env->tr.base = (uint32_t) tss;
971 831b7825 ths
    env->tr.limit = sizeof(tss) - 1;
972 831b7825 ths
    env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
973 831b7825 ths
    stw(tss + 2, 0x10);  // ss0 = 0x10 = GDT[2] = Kernel Data Segment
974 831b7825 ths
975 831b7825 ths
    /* Darwin interrupt setup */
976 831b7825 ths
    bzero(idt_table, sizeof(idt_table));
977 831b7825 ths
    env->idt.base = (uint32_t) idt_table;
978 831b7825 ths
    env->idt.limit = sizeof(idt_table) - 1;
979 831b7825 ths
    set_idt(0, 0);
980 831b7825 ths
    set_idt(1, 0);
981 831b7825 ths
    set_idt(2, 0);
982 831b7825 ths
    set_idt(3, 3);
983 831b7825 ths
    set_idt(4, 3);
984 831b7825 ths
    set_idt(5, 3);
985 831b7825 ths
    set_idt(6, 0);
986 831b7825 ths
    set_idt(7, 0);
987 831b7825 ths
    set_idt(8, 0);
988 831b7825 ths
    set_idt(9, 0);
989 831b7825 ths
    set_idt(10, 0);
990 831b7825 ths
    set_idt(11, 0);
991 831b7825 ths
    set_idt(12, 0);
992 831b7825 ths
    set_idt(13, 0);
993 831b7825 ths
    set_idt(14, 0);
994 831b7825 ths
    set_idt(15, 0);
995 831b7825 ths
    set_idt(16, 0);
996 831b7825 ths
    set_idt(17, 0);
997 831b7825 ths
    set_idt(18, 0);
998 831b7825 ths
    set_idt(19, 0);
999 831b7825 ths
    /* Syscalls are done via
1000 831b7825 ths
        int 0x80 (unix) (rarely used)
1001 831b7825 ths
        int 0x81 (mach)
1002 831b7825 ths
        int 0x82 (thread)
1003 831b7825 ths
        int 0x83 (diag) (not handled here)
1004 831b7825 ths
        sysenter/sysexit (unix) -> we redirect that to int 0x90 */
1005 831b7825 ths
    set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
1006 831b7825 ths
    set_idt(0x80, 3); /* Unix Syscall */
1007 831b7825 ths
    set_idt(0x81, 3); /* Mach Syscalls */
1008 831b7825 ths
    set_idt(0x82, 3); /* thread Syscalls */
1009 831b7825 ths
1010 1e2bed4f bellard
    set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */
1011 831b7825 ths
1012 831b7825 ths
1013 831b7825 ths
    cpu_x86_load_seg(env, R_CS, __USER_CS);
1014 831b7825 ths
    cpu_x86_load_seg(env, R_DS, __USER_DS);
1015 831b7825 ths
    cpu_x86_load_seg(env, R_ES, __USER_DS);
1016 831b7825 ths
    cpu_x86_load_seg(env, R_SS, __USER_DS);
1017 831b7825 ths
    cpu_x86_load_seg(env, R_FS, __USER_DS);
1018 831b7825 ths
    cpu_x86_load_seg(env, R_GS, __USER_DS);
1019 831b7825 ths
1020 831b7825 ths
#elif defined(TARGET_PPC)
1021 831b7825 ths
    {
1022 831b7825 ths
        int i;
1023 31fca6ab j_mayer
1024 31fca6ab j_mayer
#if defined(TARGET_PPC64)
1025 31fca6ab j_mayer
#if defined(TARGET_ABI32)
1026 31fca6ab j_mayer
        env->msr &= ~((target_ulong)1 << MSR_SF);
1027 31fca6ab j_mayer
#else
1028 31fca6ab j_mayer
        env->msr |= (target_ulong)1 << MSR_SF;
1029 31fca6ab j_mayer
#endif
1030 31fca6ab j_mayer
#endif
1031 831b7825 ths
        env->nip = regs->nip;
1032 831b7825 ths
        for(i = 0; i < 32; i++) {
1033 831b7825 ths
            env->gpr[i] = regs->gpr[i];
1034 831b7825 ths
        }
1035 831b7825 ths
    }
1036 831b7825 ths
#else
1037 831b7825 ths
#error unsupported target CPU
1038 831b7825 ths
#endif
1039 831b7825 ths
1040 831b7825 ths
    if (use_gdbstub) {
1041 831b7825 ths
        printf("Waiting for gdb Connection on port 1234...\n");
1042 831b7825 ths
        gdbserver_start (1234);
1043 831b7825 ths
        gdb_handlesig(env, 0);
1044 831b7825 ths
    }
1045 831b7825 ths
1046 831b7825 ths
    cpu_loop(env);
1047 831b7825 ths
    /* never exits */
1048 831b7825 ths
    return 0;
1049 831b7825 ths
}