Statistics
| Branch: | Revision:

root / darwin-user / main.c @ e1833e1f

History | View | Annotate | Download (35.8 kB)

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