Statistics
| Branch: | Revision:

root / darwin-user / main.c @ a74cdab4

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