Statistics
| Branch: | Revision:

root / bsd-user / main.c @ ab1cbe1c

History | View | Annotate | Download (34.7 kB)

1 84778508 blueswir1
/*
2 84778508 blueswir1
 *  qemu user main
3 84778508 blueswir1
 *
4 84778508 blueswir1
 *  Copyright (c) 2003-2008 Fabrice Bellard
5 84778508 blueswir1
 *
6 84778508 blueswir1
 *  This program is free software; you can redistribute it and/or modify
7 84778508 blueswir1
 *  it under the terms of the GNU General Public License as published by
8 84778508 blueswir1
 *  the Free Software Foundation; either version 2 of the License, or
9 84778508 blueswir1
 *  (at your option) any later version.
10 84778508 blueswir1
 *
11 84778508 blueswir1
 *  This program is distributed in the hope that it will be useful,
12 84778508 blueswir1
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 84778508 blueswir1
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 84778508 blueswir1
 *  GNU General Public License for more details.
15 84778508 blueswir1
 *
16 84778508 blueswir1
 *  You should have received a copy of the GNU General Public License
17 8167ee88 Blue Swirl
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18 84778508 blueswir1
 */
19 84778508 blueswir1
#include <stdlib.h>
20 84778508 blueswir1
#include <stdio.h>
21 84778508 blueswir1
#include <stdarg.h>
22 84778508 blueswir1
#include <string.h>
23 84778508 blueswir1
#include <errno.h>
24 84778508 blueswir1
#include <unistd.h>
25 84778508 blueswir1
#include <machine/trap.h>
26 31fc12df blueswir1
#include <sys/types.h>
27 31fc12df blueswir1
#include <sys/mman.h>
28 84778508 blueswir1
29 84778508 blueswir1
#include "qemu.h"
30 84778508 blueswir1
#include "qemu-common.h"
31 84778508 blueswir1
/* For tb_lock */
32 84778508 blueswir1
#include "exec-all.h"
33 9002ec79 Richard Henderson
#include "tcg.h"
34 2ae144c9 Blue Swirl
#include "qemu-timer.h"
35 fc0d96b4 Blue Swirl
#include "envlist.h"
36 fc0d96b4 Blue Swirl
37 84778508 blueswir1
#define DEBUG_LOGFILE "/tmp/qemu.log"
38 84778508 blueswir1
39 1b530a6d aurel32
int singlestep;
40 2fa5d9ba Blue Swirl
#if defined(CONFIG_USE_GUEST_BASE)
41 2fa5d9ba Blue Swirl
unsigned long mmap_min_addr;
42 2fa5d9ba Blue Swirl
unsigned long guest_base;
43 2fa5d9ba Blue Swirl
int have_guest_base;
44 2fa5d9ba Blue Swirl
#endif
45 1b530a6d aurel32
46 7ee2822c Paolo Bonzini
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
47 84778508 blueswir1
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
48 84778508 blueswir1
extern char **environ;
49 78cfb07f Juergen Lock
enum BSDType bsd_type;
50 84778508 blueswir1
51 84778508 blueswir1
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
52 84778508 blueswir1
   we allocate a bigger stack. Need a better solution, for example
53 84778508 blueswir1
   by remapping the process stack directly at the right place */
54 84778508 blueswir1
unsigned long x86_stack_size = 512 * 1024;
55 84778508 blueswir1
56 84778508 blueswir1
void gemu_log(const char *fmt, ...)
57 84778508 blueswir1
{
58 84778508 blueswir1
    va_list ap;
59 84778508 blueswir1
60 84778508 blueswir1
    va_start(ap, fmt);
61 84778508 blueswir1
    vfprintf(stderr, fmt, ap);
62 84778508 blueswir1
    va_end(ap);
63 84778508 blueswir1
}
64 9399f095 blueswir1
65 31fc12df blueswir1
#if defined(TARGET_I386)
66 31fc12df blueswir1
int cpu_get_pic_interrupt(CPUState *env)
67 31fc12df blueswir1
{
68 31fc12df blueswir1
    return -1;
69 31fc12df blueswir1
}
70 31fc12df blueswir1
#endif
71 31fc12df blueswir1
72 9399f095 blueswir1
/* These are no-ops because we are not threadsafe.  */
73 9399f095 blueswir1
static inline void cpu_exec_start(CPUState *env)
74 9399f095 blueswir1
{
75 9399f095 blueswir1
}
76 9399f095 blueswir1
77 9399f095 blueswir1
static inline void cpu_exec_end(CPUState *env)
78 9399f095 blueswir1
{
79 9399f095 blueswir1
}
80 9399f095 blueswir1
81 9399f095 blueswir1
static inline void start_exclusive(void)
82 9399f095 blueswir1
{
83 9399f095 blueswir1
}
84 9399f095 blueswir1
85 9399f095 blueswir1
static inline void end_exclusive(void)
86 9399f095 blueswir1
{
87 9399f095 blueswir1
}
88 9399f095 blueswir1
89 9399f095 blueswir1
void fork_start(void)
90 9399f095 blueswir1
{
91 9399f095 blueswir1
}
92 9399f095 blueswir1
93 9399f095 blueswir1
void fork_end(int child)
94 9399f095 blueswir1
{
95 9399f095 blueswir1
    if (child) {
96 9399f095 blueswir1
        gdbserver_fork(thread_env);
97 9399f095 blueswir1
    }
98 9399f095 blueswir1
}
99 9399f095 blueswir1
100 9399f095 blueswir1
void cpu_list_lock(void)
101 9399f095 blueswir1
{
102 9399f095 blueswir1
}
103 9399f095 blueswir1
104 9399f095 blueswir1
void cpu_list_unlock(void)
105 9399f095 blueswir1
{
106 9399f095 blueswir1
}
107 9399f095 blueswir1
108 31fc12df blueswir1
#ifdef TARGET_I386
109 31fc12df blueswir1
/***********************************************************/
110 31fc12df blueswir1
/* CPUX86 core interface */
111 31fc12df blueswir1
112 31fc12df blueswir1
void cpu_smm_update(CPUState *env)
113 31fc12df blueswir1
{
114 31fc12df blueswir1
}
115 31fc12df blueswir1
116 31fc12df blueswir1
uint64_t cpu_get_tsc(CPUX86State *env)
117 31fc12df blueswir1
{
118 31fc12df blueswir1
    return cpu_get_real_ticks();
119 31fc12df blueswir1
}
120 31fc12df blueswir1
121 31fc12df blueswir1
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
122 31fc12df blueswir1
                     int flags)
123 31fc12df blueswir1
{
124 31fc12df blueswir1
    unsigned int e1, e2;
125 31fc12df blueswir1
    uint32_t *p;
126 31fc12df blueswir1
    e1 = (addr << 16) | (limit & 0xffff);
127 31fc12df blueswir1
    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
128 31fc12df blueswir1
    e2 |= flags;
129 31fc12df blueswir1
    p = ptr;
130 31fc12df blueswir1
    p[0] = tswap32(e1);
131 31fc12df blueswir1
    p[1] = tswap32(e2);
132 31fc12df blueswir1
}
133 31fc12df blueswir1
134 31fc12df blueswir1
static uint64_t *idt_table;
135 31fc12df blueswir1
#ifdef TARGET_X86_64
136 31fc12df blueswir1
static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
137 31fc12df blueswir1
                       uint64_t addr, unsigned int sel)
138 31fc12df blueswir1
{
139 31fc12df blueswir1
    uint32_t *p, e1, e2;
140 31fc12df blueswir1
    e1 = (addr & 0xffff) | (sel << 16);
141 31fc12df blueswir1
    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
142 31fc12df blueswir1
    p = ptr;
143 31fc12df blueswir1
    p[0] = tswap32(e1);
144 31fc12df blueswir1
    p[1] = tswap32(e2);
145 31fc12df blueswir1
    p[2] = tswap32(addr >> 32);
146 31fc12df blueswir1
    p[3] = 0;
147 31fc12df blueswir1
}
148 31fc12df blueswir1
/* only dpl matters as we do only user space emulation */
149 31fc12df blueswir1
static void set_idt(int n, unsigned int dpl)
150 31fc12df blueswir1
{
151 31fc12df blueswir1
    set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
152 31fc12df blueswir1
}
153 31fc12df blueswir1
#else
154 31fc12df blueswir1
static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
155 31fc12df blueswir1
                     uint32_t addr, unsigned int sel)
156 31fc12df blueswir1
{
157 31fc12df blueswir1
    uint32_t *p, e1, e2;
158 31fc12df blueswir1
    e1 = (addr & 0xffff) | (sel << 16);
159 31fc12df blueswir1
    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
160 31fc12df blueswir1
    p = ptr;
161 31fc12df blueswir1
    p[0] = tswap32(e1);
162 31fc12df blueswir1
    p[1] = tswap32(e2);
163 31fc12df blueswir1
}
164 31fc12df blueswir1
165 31fc12df blueswir1
/* only dpl matters as we do only user space emulation */
166 31fc12df blueswir1
static void set_idt(int n, unsigned int dpl)
167 31fc12df blueswir1
{
168 31fc12df blueswir1
    set_gate(idt_table + n, 0, dpl, 0, 0);
169 31fc12df blueswir1
}
170 31fc12df blueswir1
#endif
171 31fc12df blueswir1
172 78cfb07f Juergen Lock
void cpu_loop(CPUX86State *env)
173 31fc12df blueswir1
{
174 31fc12df blueswir1
    int trapnr;
175 31fc12df blueswir1
    abi_ulong pc;
176 31fc12df blueswir1
    //target_siginfo_t info;
177 31fc12df blueswir1
178 31fc12df blueswir1
    for(;;) {
179 31fc12df blueswir1
        trapnr = cpu_x86_exec(env);
180 31fc12df blueswir1
        switch(trapnr) {
181 31fc12df blueswir1
        case 0x80:
182 31fc12df blueswir1
            /* syscall from int $0x80 */
183 78cfb07f Juergen Lock
            if (bsd_type == target_freebsd) {
184 78cfb07f Juergen Lock
                abi_ulong params = (abi_ulong) env->regs[R_ESP] +
185 78cfb07f Juergen Lock
                    sizeof(int32_t);
186 78cfb07f Juergen Lock
                int32_t syscall_nr = env->regs[R_EAX];
187 78cfb07f Juergen Lock
                int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
188 78cfb07f Juergen Lock
189 78cfb07f Juergen Lock
                if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
190 78cfb07f Juergen Lock
                    get_user_s32(syscall_nr, params);
191 78cfb07f Juergen Lock
                    params += sizeof(int32_t);
192 78cfb07f Juergen Lock
                } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
193 78cfb07f Juergen Lock
                    get_user_s32(syscall_nr, params);
194 78cfb07f Juergen Lock
                    params += sizeof(int64_t);
195 78cfb07f Juergen Lock
                }
196 78cfb07f Juergen Lock
                get_user_s32(arg1, params);
197 78cfb07f Juergen Lock
                params += sizeof(int32_t);
198 78cfb07f Juergen Lock
                get_user_s32(arg2, params);
199 78cfb07f Juergen Lock
                params += sizeof(int32_t);
200 78cfb07f Juergen Lock
                get_user_s32(arg3, params);
201 78cfb07f Juergen Lock
                params += sizeof(int32_t);
202 78cfb07f Juergen Lock
                get_user_s32(arg4, params);
203 78cfb07f Juergen Lock
                params += sizeof(int32_t);
204 78cfb07f Juergen Lock
                get_user_s32(arg5, params);
205 78cfb07f Juergen Lock
                params += sizeof(int32_t);
206 78cfb07f Juergen Lock
                get_user_s32(arg6, params);
207 78cfb07f Juergen Lock
                params += sizeof(int32_t);
208 78cfb07f Juergen Lock
                get_user_s32(arg7, params);
209 78cfb07f Juergen Lock
                params += sizeof(int32_t);
210 78cfb07f Juergen Lock
                get_user_s32(arg8, params);
211 78cfb07f Juergen Lock
                env->regs[R_EAX] = do_freebsd_syscall(env,
212 78cfb07f Juergen Lock
                                                      syscall_nr,
213 78cfb07f Juergen Lock
                                                      arg1,
214 78cfb07f Juergen Lock
                                                      arg2,
215 78cfb07f Juergen Lock
                                                      arg3,
216 78cfb07f Juergen Lock
                                                      arg4,
217 78cfb07f Juergen Lock
                                                      arg5,
218 78cfb07f Juergen Lock
                                                      arg6,
219 78cfb07f Juergen Lock
                                                      arg7,
220 78cfb07f Juergen Lock
                                                      arg8);
221 78cfb07f Juergen Lock
            } else { //if (bsd_type == target_openbsd)
222 78cfb07f Juergen Lock
                env->regs[R_EAX] = do_openbsd_syscall(env,
223 78cfb07f Juergen Lock
                                                      env->regs[R_EAX],
224 78cfb07f Juergen Lock
                                                      env->regs[R_EBX],
225 78cfb07f Juergen Lock
                                                      env->regs[R_ECX],
226 78cfb07f Juergen Lock
                                                      env->regs[R_EDX],
227 78cfb07f Juergen Lock
                                                      env->regs[R_ESI],
228 78cfb07f Juergen Lock
                                                      env->regs[R_EDI],
229 78cfb07f Juergen Lock
                                                      env->regs[R_EBP]);
230 78cfb07f Juergen Lock
            }
231 78cfb07f Juergen Lock
            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
232 78cfb07f Juergen Lock
                env->regs[R_EAX] = -env->regs[R_EAX];
233 78cfb07f Juergen Lock
                env->eflags |= CC_C;
234 78cfb07f Juergen Lock
            } else {
235 78cfb07f Juergen Lock
                env->eflags &= ~CC_C;
236 78cfb07f Juergen Lock
            }
237 31fc12df blueswir1
            break;
238 31fc12df blueswir1
#ifndef TARGET_ABI32
239 31fc12df blueswir1
        case EXCP_SYSCALL:
240 78cfb07f Juergen Lock
            /* syscall from syscall intruction */
241 78cfb07f Juergen Lock
            if (bsd_type == target_freebsd)
242 78cfb07f Juergen Lock
                env->regs[R_EAX] = do_freebsd_syscall(env,
243 78cfb07f Juergen Lock
                                                      env->regs[R_EAX],
244 78cfb07f Juergen Lock
                                                      env->regs[R_EDI],
245 78cfb07f Juergen Lock
                                                      env->regs[R_ESI],
246 78cfb07f Juergen Lock
                                                      env->regs[R_EDX],
247 78cfb07f Juergen Lock
                                                      env->regs[R_ECX],
248 78cfb07f Juergen Lock
                                                      env->regs[8],
249 78cfb07f Juergen Lock
                                                      env->regs[9], 0, 0);
250 78cfb07f Juergen Lock
            else { //if (bsd_type == target_openbsd)
251 78cfb07f Juergen Lock
                env->regs[R_EAX] = do_openbsd_syscall(env,
252 78cfb07f Juergen Lock
                                                      env->regs[R_EAX],
253 78cfb07f Juergen Lock
                                                      env->regs[R_EDI],
254 78cfb07f Juergen Lock
                                                      env->regs[R_ESI],
255 78cfb07f Juergen Lock
                                                      env->regs[R_EDX],
256 78cfb07f Juergen Lock
                                                      env->regs[10],
257 78cfb07f Juergen Lock
                                                      env->regs[8],
258 78cfb07f Juergen Lock
                                                      env->regs[9]);
259 78cfb07f Juergen Lock
            }
260 31fc12df blueswir1
            env->eip = env->exception_next_eip;
261 78cfb07f Juergen Lock
            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
262 78cfb07f Juergen Lock
                env->regs[R_EAX] = -env->regs[R_EAX];
263 78cfb07f Juergen Lock
                env->eflags |= CC_C;
264 78cfb07f Juergen Lock
            } else {
265 78cfb07f Juergen Lock
                env->eflags &= ~CC_C;
266 78cfb07f Juergen Lock
            }
267 31fc12df blueswir1
            break;
268 31fc12df blueswir1
#endif
269 31fc12df blueswir1
#if 0
270 31fc12df blueswir1
        case EXCP0B_NOSEG:
271 31fc12df blueswir1
        case EXCP0C_STACK:
272 31fc12df blueswir1
            info.si_signo = SIGBUS;
273 31fc12df blueswir1
            info.si_errno = 0;
274 31fc12df blueswir1
            info.si_code = TARGET_SI_KERNEL;
275 31fc12df blueswir1
            info._sifields._sigfault._addr = 0;
276 31fc12df blueswir1
            queue_signal(env, info.si_signo, &info);
277 31fc12df blueswir1
            break;
278 31fc12df blueswir1
        case EXCP0D_GPF:
279 31fc12df blueswir1
            /* XXX: potential problem if ABI32 */
280 31fc12df blueswir1
#ifndef TARGET_X86_64
281 31fc12df blueswir1
            if (env->eflags & VM_MASK) {
282 31fc12df blueswir1
                handle_vm86_fault(env);
283 31fc12df blueswir1
            } else
284 31fc12df blueswir1
#endif
285 31fc12df blueswir1
            {
286 31fc12df blueswir1
                info.si_signo = SIGSEGV;
287 31fc12df blueswir1
                info.si_errno = 0;
288 31fc12df blueswir1
                info.si_code = TARGET_SI_KERNEL;
289 31fc12df blueswir1
                info._sifields._sigfault._addr = 0;
290 31fc12df blueswir1
                queue_signal(env, info.si_signo, &info);
291 31fc12df blueswir1
            }
292 31fc12df blueswir1
            break;
293 31fc12df blueswir1
        case EXCP0E_PAGE:
294 31fc12df blueswir1
            info.si_signo = SIGSEGV;
295 31fc12df blueswir1
            info.si_errno = 0;
296 31fc12df blueswir1
            if (!(env->error_code & 1))
297 31fc12df blueswir1
                info.si_code = TARGET_SEGV_MAPERR;
298 31fc12df blueswir1
            else
299 31fc12df blueswir1
                info.si_code = TARGET_SEGV_ACCERR;
300 31fc12df blueswir1
            info._sifields._sigfault._addr = env->cr[2];
301 31fc12df blueswir1
            queue_signal(env, info.si_signo, &info);
302 31fc12df blueswir1
            break;
303 31fc12df blueswir1
        case EXCP00_DIVZ:
304 31fc12df blueswir1
#ifndef TARGET_X86_64
305 31fc12df blueswir1
            if (env->eflags & VM_MASK) {
306 31fc12df blueswir1
                handle_vm86_trap(env, trapnr);
307 31fc12df blueswir1
            } else
308 31fc12df blueswir1
#endif
309 31fc12df blueswir1
            {
310 31fc12df blueswir1
                /* division by zero */
311 31fc12df blueswir1
                info.si_signo = SIGFPE;
312 31fc12df blueswir1
                info.si_errno = 0;
313 31fc12df blueswir1
                info.si_code = TARGET_FPE_INTDIV;
314 31fc12df blueswir1
                info._sifields._sigfault._addr = env->eip;
315 31fc12df blueswir1
                queue_signal(env, info.si_signo, &info);
316 31fc12df blueswir1
            }
317 31fc12df blueswir1
            break;
318 31fc12df blueswir1
        case EXCP01_DB:
319 31fc12df blueswir1
        case EXCP03_INT3:
320 31fc12df blueswir1
#ifndef TARGET_X86_64
321 31fc12df blueswir1
            if (env->eflags & VM_MASK) {
322 31fc12df blueswir1
                handle_vm86_trap(env, trapnr);
323 31fc12df blueswir1
            } else
324 31fc12df blueswir1
#endif
325 31fc12df blueswir1
            {
326 31fc12df blueswir1
                info.si_signo = SIGTRAP;
327 31fc12df blueswir1
                info.si_errno = 0;
328 31fc12df blueswir1
                if (trapnr == EXCP01_DB) {
329 31fc12df blueswir1
                    info.si_code = TARGET_TRAP_BRKPT;
330 31fc12df blueswir1
                    info._sifields._sigfault._addr = env->eip;
331 31fc12df blueswir1
                } else {
332 31fc12df blueswir1
                    info.si_code = TARGET_SI_KERNEL;
333 31fc12df blueswir1
                    info._sifields._sigfault._addr = 0;
334 31fc12df blueswir1
                }
335 31fc12df blueswir1
                queue_signal(env, info.si_signo, &info);
336 31fc12df blueswir1
            }
337 31fc12df blueswir1
            break;
338 31fc12df blueswir1
        case EXCP04_INTO:
339 31fc12df blueswir1
        case EXCP05_BOUND:
340 31fc12df blueswir1
#ifndef TARGET_X86_64
341 31fc12df blueswir1
            if (env->eflags & VM_MASK) {
342 31fc12df blueswir1
                handle_vm86_trap(env, trapnr);
343 31fc12df blueswir1
            } else
344 31fc12df blueswir1
#endif
345 31fc12df blueswir1
            {
346 31fc12df blueswir1
                info.si_signo = SIGSEGV;
347 31fc12df blueswir1
                info.si_errno = 0;
348 31fc12df blueswir1
                info.si_code = TARGET_SI_KERNEL;
349 31fc12df blueswir1
                info._sifields._sigfault._addr = 0;
350 31fc12df blueswir1
                queue_signal(env, info.si_signo, &info);
351 31fc12df blueswir1
            }
352 31fc12df blueswir1
            break;
353 31fc12df blueswir1
        case EXCP06_ILLOP:
354 31fc12df blueswir1
            info.si_signo = SIGILL;
355 31fc12df blueswir1
            info.si_errno = 0;
356 31fc12df blueswir1
            info.si_code = TARGET_ILL_ILLOPN;
357 31fc12df blueswir1
            info._sifields._sigfault._addr = env->eip;
358 31fc12df blueswir1
            queue_signal(env, info.si_signo, &info);
359 31fc12df blueswir1
            break;
360 31fc12df blueswir1
#endif
361 31fc12df blueswir1
        case EXCP_INTERRUPT:
362 31fc12df blueswir1
            /* just indicate that signals should be handled asap */
363 31fc12df blueswir1
            break;
364 31fc12df blueswir1
#if 0
365 31fc12df blueswir1
        case EXCP_DEBUG:
366 31fc12df blueswir1
            {
367 31fc12df blueswir1
                int sig;
368 31fc12df blueswir1

369 31fc12df blueswir1
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
370 31fc12df blueswir1
                if (sig)
371 31fc12df blueswir1
                  {
372 31fc12df blueswir1
                    info.si_signo = sig;
373 31fc12df blueswir1
                    info.si_errno = 0;
374 31fc12df blueswir1
                    info.si_code = TARGET_TRAP_BRKPT;
375 31fc12df blueswir1
                    queue_signal(env, info.si_signo, &info);
376 31fc12df blueswir1
                  }
377 31fc12df blueswir1
            }
378 31fc12df blueswir1
            break;
379 31fc12df blueswir1
#endif
380 31fc12df blueswir1
        default:
381 31fc12df blueswir1
            pc = env->segs[R_CS].base + env->eip;
382 31fc12df blueswir1
            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
383 31fc12df blueswir1
                    (long)pc, trapnr);
384 31fc12df blueswir1
            abort();
385 31fc12df blueswir1
        }
386 31fc12df blueswir1
        process_pending_signals(env);
387 31fc12df blueswir1
    }
388 31fc12df blueswir1
}
389 31fc12df blueswir1
#endif
390 31fc12df blueswir1
391 84778508 blueswir1
#ifdef TARGET_SPARC
392 84778508 blueswir1
#define SPARC64_STACK_BIAS 2047
393 84778508 blueswir1
394 84778508 blueswir1
//#define DEBUG_WIN
395 84778508 blueswir1
/* WARNING: dealing with register windows _is_ complicated. More info
396 84778508 blueswir1
   can be found at http://www.sics.se/~psm/sparcstack.html */
397 84778508 blueswir1
static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
398 84778508 blueswir1
{
399 84778508 blueswir1
    index = (index + cwp * 16) % (16 * env->nwindows);
400 84778508 blueswir1
    /* wrap handling : if cwp is on the last window, then we use the
401 84778508 blueswir1
       registers 'after' the end */
402 84778508 blueswir1
    if (index < 8 && env->cwp == env->nwindows - 1)
403 84778508 blueswir1
        index += 16 * env->nwindows;
404 84778508 blueswir1
    return index;
405 84778508 blueswir1
}
406 84778508 blueswir1
407 84778508 blueswir1
/* save the register window 'cwp1' */
408 84778508 blueswir1
static inline void save_window_offset(CPUSPARCState *env, int cwp1)
409 84778508 blueswir1
{
410 84778508 blueswir1
    unsigned int i;
411 84778508 blueswir1
    abi_ulong sp_ptr;
412 84778508 blueswir1
413 84778508 blueswir1
    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
414 84778508 blueswir1
#ifdef TARGET_SPARC64
415 84778508 blueswir1
    if (sp_ptr & 3)
416 84778508 blueswir1
        sp_ptr += SPARC64_STACK_BIAS;
417 84778508 blueswir1
#endif
418 84778508 blueswir1
#if defined(DEBUG_WIN)
419 84778508 blueswir1
    printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
420 84778508 blueswir1
           sp_ptr, cwp1);
421 84778508 blueswir1
#endif
422 84778508 blueswir1
    for(i = 0; i < 16; i++) {
423 84778508 blueswir1
        /* FIXME - what to do if put_user() fails? */
424 84778508 blueswir1
        put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
425 84778508 blueswir1
        sp_ptr += sizeof(abi_ulong);
426 84778508 blueswir1
    }
427 84778508 blueswir1
}
428 84778508 blueswir1
429 84778508 blueswir1
static void save_window(CPUSPARCState *env)
430 84778508 blueswir1
{
431 84778508 blueswir1
#ifndef TARGET_SPARC64
432 84778508 blueswir1
    unsigned int new_wim;
433 84778508 blueswir1
    new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
434 84778508 blueswir1
        ((1LL << env->nwindows) - 1);
435 84778508 blueswir1
    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
436 84778508 blueswir1
    env->wim = new_wim;
437 84778508 blueswir1
#else
438 84778508 blueswir1
    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
439 84778508 blueswir1
    env->cansave++;
440 84778508 blueswir1
    env->canrestore--;
441 84778508 blueswir1
#endif
442 84778508 blueswir1
}
443 84778508 blueswir1
444 84778508 blueswir1
static void restore_window(CPUSPARCState *env)
445 84778508 blueswir1
{
446 84778508 blueswir1
#ifndef TARGET_SPARC64
447 84778508 blueswir1
    unsigned int new_wim;
448 84778508 blueswir1
#endif
449 84778508 blueswir1
    unsigned int i, cwp1;
450 84778508 blueswir1
    abi_ulong sp_ptr;
451 84778508 blueswir1
452 84778508 blueswir1
#ifndef TARGET_SPARC64
453 84778508 blueswir1
    new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
454 84778508 blueswir1
        ((1LL << env->nwindows) - 1);
455 84778508 blueswir1
#endif
456 84778508 blueswir1
457 84778508 blueswir1
    /* restore the invalid window */
458 84778508 blueswir1
    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
459 84778508 blueswir1
    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
460 84778508 blueswir1
#ifdef TARGET_SPARC64
461 84778508 blueswir1
    if (sp_ptr & 3)
462 84778508 blueswir1
        sp_ptr += SPARC64_STACK_BIAS;
463 84778508 blueswir1
#endif
464 84778508 blueswir1
#if defined(DEBUG_WIN)
465 84778508 blueswir1
    printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
466 84778508 blueswir1
           sp_ptr, cwp1);
467 84778508 blueswir1
#endif
468 84778508 blueswir1
    for(i = 0; i < 16; i++) {
469 84778508 blueswir1
        /* FIXME - what to do if get_user() fails? */
470 84778508 blueswir1
        get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
471 84778508 blueswir1
        sp_ptr += sizeof(abi_ulong);
472 84778508 blueswir1
    }
473 84778508 blueswir1
#ifdef TARGET_SPARC64
474 84778508 blueswir1
    env->canrestore++;
475 84778508 blueswir1
    if (env->cleanwin < env->nwindows - 1)
476 84778508 blueswir1
        env->cleanwin++;
477 84778508 blueswir1
    env->cansave--;
478 84778508 blueswir1
#else
479 84778508 blueswir1
    env->wim = new_wim;
480 84778508 blueswir1
#endif
481 84778508 blueswir1
}
482 84778508 blueswir1
483 84778508 blueswir1
static void flush_windows(CPUSPARCState *env)
484 84778508 blueswir1
{
485 84778508 blueswir1
    int offset, cwp1;
486 84778508 blueswir1
487 84778508 blueswir1
    offset = 1;
488 84778508 blueswir1
    for(;;) {
489 84778508 blueswir1
        /* if restore would invoke restore_window(), then we can stop */
490 84778508 blueswir1
        cwp1 = cpu_cwp_inc(env, env->cwp + offset);
491 84778508 blueswir1
#ifndef TARGET_SPARC64
492 84778508 blueswir1
        if (env->wim & (1 << cwp1))
493 84778508 blueswir1
            break;
494 84778508 blueswir1
#else
495 84778508 blueswir1
        if (env->canrestore == 0)
496 84778508 blueswir1
            break;
497 84778508 blueswir1
        env->cansave++;
498 84778508 blueswir1
        env->canrestore--;
499 84778508 blueswir1
#endif
500 84778508 blueswir1
        save_window_offset(env, cwp1);
501 84778508 blueswir1
        offset++;
502 84778508 blueswir1
    }
503 84778508 blueswir1
    cwp1 = cpu_cwp_inc(env, env->cwp + 1);
504 84778508 blueswir1
#ifndef TARGET_SPARC64
505 84778508 blueswir1
    /* set wim so that restore will reload the registers */
506 84778508 blueswir1
    env->wim = 1 << cwp1;
507 84778508 blueswir1
#endif
508 84778508 blueswir1
#if defined(DEBUG_WIN)
509 84778508 blueswir1
    printf("flush_windows: nb=%d\n", offset - 1);
510 84778508 blueswir1
#endif
511 84778508 blueswir1
}
512 84778508 blueswir1
513 78cfb07f Juergen Lock
void cpu_loop(CPUSPARCState *env)
514 84778508 blueswir1
{
515 84778508 blueswir1
    int trapnr, ret, syscall_nr;
516 84778508 blueswir1
    //target_siginfo_t info;
517 84778508 blueswir1
518 84778508 blueswir1
    while (1) {
519 84778508 blueswir1
        trapnr = cpu_sparc_exec (env);
520 84778508 blueswir1
521 84778508 blueswir1
        switch (trapnr) {
522 77b9435f blueswir1
#ifndef TARGET_SPARC64
523 77b9435f blueswir1
        case 0x80:
524 77b9435f blueswir1
#else
525 78cfb07f Juergen Lock
        /* FreeBSD uses 0x141 for syscalls too */
526 78cfb07f Juergen Lock
        case 0x141:
527 78cfb07f Juergen Lock
            if (bsd_type != target_freebsd)
528 78cfb07f Juergen Lock
                goto badtrap;
529 84778508 blueswir1
        case 0x100:
530 77b9435f blueswir1
#endif
531 84778508 blueswir1
            syscall_nr = env->gregs[1];
532 84778508 blueswir1
            if (bsd_type == target_freebsd)
533 84778508 blueswir1
                ret = do_freebsd_syscall(env, syscall_nr,
534 84778508 blueswir1
                                         env->regwptr[0], env->regwptr[1],
535 84778508 blueswir1
                                         env->regwptr[2], env->regwptr[3],
536 78cfb07f Juergen Lock
                                         env->regwptr[4], env->regwptr[5], 0, 0);
537 84778508 blueswir1
            else if (bsd_type == target_netbsd)
538 84778508 blueswir1
                ret = do_netbsd_syscall(env, syscall_nr,
539 84778508 blueswir1
                                        env->regwptr[0], env->regwptr[1],
540 84778508 blueswir1
                                        env->regwptr[2], env->regwptr[3],
541 84778508 blueswir1
                                        env->regwptr[4], env->regwptr[5]);
542 cdba95bd blueswir1
            else { //if (bsd_type == target_openbsd)
543 cdba95bd blueswir1
#if defined(TARGET_SPARC64)
544 cdba95bd blueswir1
                syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
545 cdba95bd blueswir1
                                TARGET_OPENBSD_SYSCALL_G2RFLAG);
546 cdba95bd blueswir1
#endif
547 84778508 blueswir1
                ret = do_openbsd_syscall(env, syscall_nr,
548 84778508 blueswir1
                                         env->regwptr[0], env->regwptr[1],
549 84778508 blueswir1
                                         env->regwptr[2], env->regwptr[3],
550 84778508 blueswir1
                                         env->regwptr[4], env->regwptr[5]);
551 cdba95bd blueswir1
            }
552 84778508 blueswir1
            if ((unsigned int)ret >= (unsigned int)(-515)) {
553 78cfb07f Juergen Lock
                ret = -ret;
554 84778508 blueswir1
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
555 84778508 blueswir1
                env->xcc |= PSR_CARRY;
556 84778508 blueswir1
#else
557 84778508 blueswir1
                env->psr |= PSR_CARRY;
558 84778508 blueswir1
#endif
559 84778508 blueswir1
            } else {
560 84778508 blueswir1
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
561 84778508 blueswir1
                env->xcc &= ~PSR_CARRY;
562 84778508 blueswir1
#else
563 84778508 blueswir1
                env->psr &= ~PSR_CARRY;
564 84778508 blueswir1
#endif
565 84778508 blueswir1
            }
566 84778508 blueswir1
            env->regwptr[0] = ret;
567 84778508 blueswir1
            /* next instruction */
568 cdba95bd blueswir1
#if defined(TARGET_SPARC64)
569 cdba95bd blueswir1
            if (bsd_type == target_openbsd &&
570 cdba95bd blueswir1
                env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
571 84778508 blueswir1
                env->pc = env->gregs[2];
572 84778508 blueswir1
                env->npc = env->pc + 4;
573 cdba95bd blueswir1
            } else if (bsd_type == target_openbsd &&
574 cdba95bd blueswir1
                       env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
575 84778508 blueswir1
                env->pc = env->gregs[7];
576 84778508 blueswir1
                env->npc = env->pc + 4;
577 84778508 blueswir1
            } else {
578 84778508 blueswir1
                env->pc = env->npc;
579 84778508 blueswir1
                env->npc = env->npc + 4;
580 84778508 blueswir1
            }
581 84778508 blueswir1
#else
582 84778508 blueswir1
            env->pc = env->npc;
583 84778508 blueswir1
            env->npc = env->npc + 4;
584 84778508 blueswir1
#endif
585 84778508 blueswir1
            break;
586 84778508 blueswir1
        case 0x83: /* flush windows */
587 84778508 blueswir1
#ifdef TARGET_ABI32
588 84778508 blueswir1
        case 0x103:
589 84778508 blueswir1
#endif
590 84778508 blueswir1
            flush_windows(env);
591 84778508 blueswir1
            /* next instruction */
592 84778508 blueswir1
            env->pc = env->npc;
593 84778508 blueswir1
            env->npc = env->npc + 4;
594 84778508 blueswir1
            break;
595 84778508 blueswir1
#ifndef TARGET_SPARC64
596 84778508 blueswir1
        case TT_WIN_OVF: /* window overflow */
597 84778508 blueswir1
            save_window(env);
598 84778508 blueswir1
            break;
599 84778508 blueswir1
        case TT_WIN_UNF: /* window underflow */
600 84778508 blueswir1
            restore_window(env);
601 84778508 blueswir1
            break;
602 84778508 blueswir1
        case TT_TFAULT:
603 84778508 blueswir1
        case TT_DFAULT:
604 84778508 blueswir1
#if 0
605 84778508 blueswir1
            {
606 84778508 blueswir1
                info.si_signo = SIGSEGV;
607 84778508 blueswir1
                info.si_errno = 0;
608 84778508 blueswir1
                /* XXX: check env->error_code */
609 84778508 blueswir1
                info.si_code = TARGET_SEGV_MAPERR;
610 84778508 blueswir1
                info._sifields._sigfault._addr = env->mmuregs[4];
611 84778508 blueswir1
                queue_signal(env, info.si_signo, &info);
612 84778508 blueswir1
            }
613 84778508 blueswir1
#endif
614 84778508 blueswir1
            break;
615 84778508 blueswir1
#else
616 84778508 blueswir1
        case TT_SPILL: /* window overflow */
617 84778508 blueswir1
            save_window(env);
618 84778508 blueswir1
            break;
619 84778508 blueswir1
        case TT_FILL: /* window underflow */
620 84778508 blueswir1
            restore_window(env);
621 84778508 blueswir1
            break;
622 84778508 blueswir1
        case TT_TFAULT:
623 84778508 blueswir1
        case TT_DFAULT:
624 84778508 blueswir1
#if 0
625 84778508 blueswir1
            {
626 84778508 blueswir1
                info.si_signo = SIGSEGV;
627 84778508 blueswir1
                info.si_errno = 0;
628 84778508 blueswir1
                /* XXX: check env->error_code */
629 84778508 blueswir1
                info.si_code = TARGET_SEGV_MAPERR;
630 84778508 blueswir1
                if (trapnr == TT_DFAULT)
631 84778508 blueswir1
                    info._sifields._sigfault._addr = env->dmmuregs[4];
632 84778508 blueswir1
                else
633 84778508 blueswir1
                    info._sifields._sigfault._addr = env->tsptr->tpc;
634 84778508 blueswir1
                //queue_signal(env, info.si_signo, &info);
635 84778508 blueswir1
            }
636 84778508 blueswir1
#endif
637 84778508 blueswir1
            break;
638 84778508 blueswir1
#endif
639 84778508 blueswir1
        case EXCP_INTERRUPT:
640 84778508 blueswir1
            /* just indicate that signals should be handled asap */
641 84778508 blueswir1
            break;
642 84778508 blueswir1
        case EXCP_DEBUG:
643 84778508 blueswir1
            {
644 84778508 blueswir1
                int sig;
645 84778508 blueswir1
646 84778508 blueswir1
                sig = gdb_handlesig (env, TARGET_SIGTRAP);
647 84778508 blueswir1
#if 0
648 84778508 blueswir1
                if (sig)
649 84778508 blueswir1
                  {
650 84778508 blueswir1
                    info.si_signo = sig;
651 84778508 blueswir1
                    info.si_errno = 0;
652 84778508 blueswir1
                    info.si_code = TARGET_TRAP_BRKPT;
653 84778508 blueswir1
                    //queue_signal(env, info.si_signo, &info);
654 84778508 blueswir1
                  }
655 84778508 blueswir1
#endif
656 84778508 blueswir1
            }
657 84778508 blueswir1
            break;
658 84778508 blueswir1
        default:
659 78cfb07f Juergen Lock
#ifdef TARGET_SPARC64
660 78cfb07f Juergen Lock
        badtrap:
661 78cfb07f Juergen Lock
#endif
662 84778508 blueswir1
            printf ("Unhandled trap: 0x%x\n", trapnr);
663 84778508 blueswir1
            cpu_dump_state(env, stderr, fprintf, 0);
664 84778508 blueswir1
            exit (1);
665 84778508 blueswir1
        }
666 84778508 blueswir1
        process_pending_signals (env);
667 84778508 blueswir1
    }
668 84778508 blueswir1
}
669 84778508 blueswir1
670 84778508 blueswir1
#endif
671 84778508 blueswir1
672 84778508 blueswir1
static void usage(void)
673 84778508 blueswir1
{
674 84778508 blueswir1
    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
675 84778508 blueswir1
           "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
676 84778508 blueswir1
           "BSD CPU emulator (compiled for %s emulation)\n"
677 84778508 blueswir1
           "\n"
678 84778508 blueswir1
           "Standard options:\n"
679 84778508 blueswir1
           "-h                print this help\n"
680 84778508 blueswir1
           "-g port           wait gdb connection to port\n"
681 84778508 blueswir1
           "-L path           set the elf interpreter prefix (default=%s)\n"
682 84778508 blueswir1
           "-s size           set the stack size in bytes (default=%ld)\n"
683 84778508 blueswir1
           "-cpu model        select CPU (-cpu ? for list)\n"
684 84778508 blueswir1
           "-drop-ld-preload  drop LD_PRELOAD for target process\n"
685 fc0d96b4 Blue Swirl
           "-E var=value      sets/modifies targets environment variable(s)\n"
686 fc0d96b4 Blue Swirl
           "-U var            unsets targets environment variable(s)\n"
687 2fa5d9ba Blue Swirl
#if defined(CONFIG_USE_GUEST_BASE)
688 2fa5d9ba Blue Swirl
           "-B address        set guest_base address to address\n"
689 2fa5d9ba Blue Swirl
#endif
690 84778508 blueswir1
           "-bsd type         select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
691 84778508 blueswir1
           "\n"
692 84778508 blueswir1
           "Debug options:\n"
693 84778508 blueswir1
           "-d options   activate log (logfile=%s)\n"
694 84778508 blueswir1
           "-p pagesize  set the host page size to 'pagesize'\n"
695 1b530a6d aurel32
           "-singlestep  always run in singlestep mode\n"
696 84778508 blueswir1
           "-strace      log system calls\n"
697 84778508 blueswir1
           "\n"
698 84778508 blueswir1
           "Environment variables:\n"
699 84778508 blueswir1
           "QEMU_STRACE       Print system calls and arguments similar to the\n"
700 84778508 blueswir1
           "                  'strace' program.  Enable by setting to any value.\n"
701 fc0d96b4 Blue Swirl
           "You can use -E and -U options to set/unset environment variables\n"
702 fc0d96b4 Blue Swirl
           "for target process.  It is possible to provide several variables\n"
703 fc0d96b4 Blue Swirl
           "by repeating the option.  For example:\n"
704 fc0d96b4 Blue Swirl
           "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
705 fc0d96b4 Blue Swirl
           "Note that if you provide several changes to single variable\n"
706 fc0d96b4 Blue Swirl
           "last change will stay in effect.\n"
707 84778508 blueswir1
           ,
708 84778508 blueswir1
           TARGET_ARCH,
709 84778508 blueswir1
           interp_prefix,
710 84778508 blueswir1
           x86_stack_size,
711 84778508 blueswir1
           DEBUG_LOGFILE);
712 2d18e637 blueswir1
    exit(1);
713 84778508 blueswir1
}
714 84778508 blueswir1
715 84778508 blueswir1
THREAD CPUState *thread_env;
716 84778508 blueswir1
717 84778508 blueswir1
/* Assumes contents are already zeroed.  */
718 84778508 blueswir1
void init_task_state(TaskState *ts)
719 84778508 blueswir1
{
720 84778508 blueswir1
    int i;
721 84778508 blueswir1
722 84778508 blueswir1
    ts->used = 1;
723 84778508 blueswir1
    ts->first_free = ts->sigqueue_table;
724 84778508 blueswir1
    for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
725 84778508 blueswir1
        ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
726 84778508 blueswir1
    }
727 84778508 blueswir1
    ts->sigqueue_table[i].next = NULL;
728 84778508 blueswir1
}
729 84778508 blueswir1
730 84778508 blueswir1
int main(int argc, char **argv)
731 84778508 blueswir1
{
732 84778508 blueswir1
    const char *filename;
733 84778508 blueswir1
    const char *cpu_model;
734 84778508 blueswir1
    struct target_pt_regs regs1, *regs = &regs1;
735 84778508 blueswir1
    struct image_info info1, *info = &info1;
736 84778508 blueswir1
    TaskState ts1, *ts = &ts1;
737 84778508 blueswir1
    CPUState *env;
738 84778508 blueswir1
    int optind;
739 84778508 blueswir1
    const char *r;
740 84778508 blueswir1
    int gdbstub_port = 0;
741 fc0d96b4 Blue Swirl
    char **target_environ, **wrk;
742 fc0d96b4 Blue Swirl
    envlist_t *envlist = NULL;
743 78cfb07f Juergen Lock
    bsd_type = target_openbsd;
744 84778508 blueswir1
745 84778508 blueswir1
    if (argc <= 1)
746 84778508 blueswir1
        usage();
747 84778508 blueswir1
748 84778508 blueswir1
    /* init debug */
749 84778508 blueswir1
    cpu_set_log_filename(DEBUG_LOGFILE);
750 84778508 blueswir1
751 fc0d96b4 Blue Swirl
    if ((envlist = envlist_create()) == NULL) {
752 fc0d96b4 Blue Swirl
        (void) fprintf(stderr, "Unable to allocate envlist\n");
753 fc0d96b4 Blue Swirl
        exit(1);
754 fc0d96b4 Blue Swirl
    }
755 fc0d96b4 Blue Swirl
756 fc0d96b4 Blue Swirl
    /* add current environment into the list */
757 fc0d96b4 Blue Swirl
    for (wrk = environ; *wrk != NULL; wrk++) {
758 fc0d96b4 Blue Swirl
        (void) envlist_setenv(envlist, *wrk);
759 fc0d96b4 Blue Swirl
    }
760 fc0d96b4 Blue Swirl
761 84778508 blueswir1
    cpu_model = NULL;
762 0c62de2f Juergen Lock
#if defined(cpudef_setup)
763 0c62de2f Juergen Lock
    cpudef_setup(); /* parse cpu definitions in target config file (TBD) */
764 0c62de2f Juergen Lock
#endif
765 0c62de2f Juergen Lock
766 84778508 blueswir1
    optind = 1;
767 84778508 blueswir1
    for(;;) {
768 84778508 blueswir1
        if (optind >= argc)
769 84778508 blueswir1
            break;
770 84778508 blueswir1
        r = argv[optind];
771 84778508 blueswir1
        if (r[0] != '-')
772 84778508 blueswir1
            break;
773 84778508 blueswir1
        optind++;
774 84778508 blueswir1
        r++;
775 84778508 blueswir1
        if (!strcmp(r, "-")) {
776 84778508 blueswir1
            break;
777 84778508 blueswir1
        } else if (!strcmp(r, "d")) {
778 84778508 blueswir1
            int mask;
779 84778508 blueswir1
            const CPULogItem *item;
780 84778508 blueswir1
781 84778508 blueswir1
            if (optind >= argc)
782 84778508 blueswir1
                break;
783 84778508 blueswir1
784 84778508 blueswir1
            r = argv[optind++];
785 84778508 blueswir1
            mask = cpu_str_to_log_mask(r);
786 84778508 blueswir1
            if (!mask) {
787 84778508 blueswir1
                printf("Log items (comma separated):\n");
788 84778508 blueswir1
                for(item = cpu_log_items; item->mask != 0; item++) {
789 84778508 blueswir1
                    printf("%-10s %s\n", item->name, item->help);
790 84778508 blueswir1
                }
791 84778508 blueswir1
                exit(1);
792 84778508 blueswir1
            }
793 84778508 blueswir1
            cpu_set_log(mask);
794 fc0d96b4 Blue Swirl
        } else if (!strcmp(r, "E")) {
795 fc0d96b4 Blue Swirl
            r = argv[optind++];
796 fc0d96b4 Blue Swirl
            if (envlist_setenv(envlist, r) != 0)
797 fc0d96b4 Blue Swirl
                usage();
798 f66724c9 Stefan Weil
        } else if (!strcmp(r, "ignore-environment")) {
799 f66724c9 Stefan Weil
            envlist_free(envlist);
800 f66724c9 Stefan Weil
            if ((envlist = envlist_create()) == NULL) {
801 f66724c9 Stefan Weil
                (void) fprintf(stderr, "Unable to allocate envlist\n");
802 f66724c9 Stefan Weil
                exit(1);
803 f66724c9 Stefan Weil
            }
804 fc0d96b4 Blue Swirl
        } else if (!strcmp(r, "U")) {
805 fc0d96b4 Blue Swirl
            r = argv[optind++];
806 fc0d96b4 Blue Swirl
            if (envlist_unsetenv(envlist, r) != 0)
807 fc0d96b4 Blue Swirl
                usage();
808 84778508 blueswir1
        } else if (!strcmp(r, "s")) {
809 84778508 blueswir1
            r = argv[optind++];
810 84778508 blueswir1
            x86_stack_size = strtol(r, (char **)&r, 0);
811 84778508 blueswir1
            if (x86_stack_size <= 0)
812 84778508 blueswir1
                usage();
813 84778508 blueswir1
            if (*r == 'M')
814 84778508 blueswir1
                x86_stack_size *= 1024 * 1024;
815 84778508 blueswir1
            else if (*r == 'k' || *r == 'K')
816 84778508 blueswir1
                x86_stack_size *= 1024;
817 84778508 blueswir1
        } else if (!strcmp(r, "L")) {
818 84778508 blueswir1
            interp_prefix = argv[optind++];
819 84778508 blueswir1
        } else if (!strcmp(r, "p")) {
820 84778508 blueswir1
            qemu_host_page_size = atoi(argv[optind++]);
821 84778508 blueswir1
            if (qemu_host_page_size == 0 ||
822 84778508 blueswir1
                (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
823 84778508 blueswir1
                fprintf(stderr, "page size must be a power of two\n");
824 84778508 blueswir1
                exit(1);
825 84778508 blueswir1
            }
826 84778508 blueswir1
        } else if (!strcmp(r, "g")) {
827 84778508 blueswir1
            gdbstub_port = atoi(argv[optind++]);
828 84778508 blueswir1
        } else if (!strcmp(r, "r")) {
829 84778508 blueswir1
            qemu_uname_release = argv[optind++];
830 84778508 blueswir1
        } else if (!strcmp(r, "cpu")) {
831 84778508 blueswir1
            cpu_model = argv[optind++];
832 84778508 blueswir1
            if (strcmp(cpu_model, "?") == 0) {
833 84778508 blueswir1
/* XXX: implement xxx_cpu_list for targets that still miss it */
834 84778508 blueswir1
#if defined(cpu_list)
835 84778508 blueswir1
                    cpu_list(stdout, &fprintf);
836 84778508 blueswir1
#endif
837 2d18e637 blueswir1
                exit(1);
838 84778508 blueswir1
            }
839 2fa5d9ba Blue Swirl
#if defined(CONFIG_USE_GUEST_BASE)
840 2fa5d9ba Blue Swirl
        } else if (!strcmp(r, "B")) {
841 2fa5d9ba Blue Swirl
           guest_base = strtol(argv[optind++], NULL, 0);
842 2fa5d9ba Blue Swirl
           have_guest_base = 1;
843 2fa5d9ba Blue Swirl
#endif
844 84778508 blueswir1
        } else if (!strcmp(r, "drop-ld-preload")) {
845 fc0d96b4 Blue Swirl
            (void) envlist_unsetenv(envlist, "LD_PRELOAD");
846 84778508 blueswir1
        } else if (!strcmp(r, "bsd")) {
847 84778508 blueswir1
            if (!strcasecmp(argv[optind], "freebsd")) {
848 84778508 blueswir1
                bsd_type = target_freebsd;
849 84778508 blueswir1
            } else if (!strcasecmp(argv[optind], "netbsd")) {
850 84778508 blueswir1
                bsd_type = target_netbsd;
851 84778508 blueswir1
            } else if (!strcasecmp(argv[optind], "openbsd")) {
852 84778508 blueswir1
                bsd_type = target_openbsd;
853 84778508 blueswir1
            } else {
854 84778508 blueswir1
                usage();
855 84778508 blueswir1
            }
856 84778508 blueswir1
            optind++;
857 1b530a6d aurel32
        } else if (!strcmp(r, "singlestep")) {
858 1b530a6d aurel32
            singlestep = 1;
859 84778508 blueswir1
        } else if (!strcmp(r, "strace")) {
860 84778508 blueswir1
            do_strace = 1;
861 84778508 blueswir1
        } else
862 84778508 blueswir1
        {
863 84778508 blueswir1
            usage();
864 84778508 blueswir1
        }
865 84778508 blueswir1
    }
866 84778508 blueswir1
    if (optind >= argc)
867 84778508 blueswir1
        usage();
868 84778508 blueswir1
    filename = argv[optind];
869 84778508 blueswir1
870 84778508 blueswir1
    /* Zero out regs */
871 84778508 blueswir1
    memset(regs, 0, sizeof(struct target_pt_regs));
872 84778508 blueswir1
873 84778508 blueswir1
    /* Zero out image_info */
874 84778508 blueswir1
    memset(info, 0, sizeof(struct image_info));
875 84778508 blueswir1
876 84778508 blueswir1
    /* Scan interp_prefix dir for replacement files. */
877 84778508 blueswir1
    init_paths(interp_prefix);
878 84778508 blueswir1
879 84778508 blueswir1
    if (cpu_model == NULL) {
880 31fc12df blueswir1
#if defined(TARGET_I386)
881 31fc12df blueswir1
#ifdef TARGET_X86_64
882 31fc12df blueswir1
        cpu_model = "qemu64";
883 31fc12df blueswir1
#else
884 31fc12df blueswir1
        cpu_model = "qemu32";
885 31fc12df blueswir1
#endif
886 31fc12df blueswir1
#elif defined(TARGET_SPARC)
887 84778508 blueswir1
#ifdef TARGET_SPARC64
888 84778508 blueswir1
        cpu_model = "TI UltraSparc II";
889 84778508 blueswir1
#else
890 84778508 blueswir1
        cpu_model = "Fujitsu MB86904";
891 84778508 blueswir1
#endif
892 84778508 blueswir1
#else
893 84778508 blueswir1
        cpu_model = "any";
894 84778508 blueswir1
#endif
895 84778508 blueswir1
    }
896 84778508 blueswir1
    cpu_exec_init_all(0);
897 84778508 blueswir1
    /* NOTE: we need to init the CPU at this stage to get
898 84778508 blueswir1
       qemu_host_page_size */
899 84778508 blueswir1
    env = cpu_init(cpu_model);
900 84778508 blueswir1
    if (!env) {
901 84778508 blueswir1
        fprintf(stderr, "Unable to find CPU definition\n");
902 84778508 blueswir1
        exit(1);
903 84778508 blueswir1
    }
904 b55a37c9 Blue Swirl
#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
905 b55a37c9 Blue Swirl
    cpu_reset(env);
906 b55a37c9 Blue Swirl
#endif
907 84778508 blueswir1
    thread_env = env;
908 84778508 blueswir1
909 84778508 blueswir1
    if (getenv("QEMU_STRACE")) {
910 84778508 blueswir1
        do_strace = 1;
911 84778508 blueswir1
    }
912 84778508 blueswir1
913 fc0d96b4 Blue Swirl
    target_environ = envlist_to_environ(envlist, NULL);
914 fc0d96b4 Blue Swirl
    envlist_free(envlist);
915 fc0d96b4 Blue Swirl
916 2fa5d9ba Blue Swirl
#if defined(CONFIG_USE_GUEST_BASE)
917 2fa5d9ba Blue Swirl
    /*
918 2fa5d9ba Blue Swirl
     * Now that page sizes are configured in cpu_init() we can do
919 2fa5d9ba Blue Swirl
     * proper page alignment for guest_base.
920 2fa5d9ba Blue Swirl
     */
921 2fa5d9ba Blue Swirl
    guest_base = HOST_PAGE_ALIGN(guest_base);
922 2fa5d9ba Blue Swirl
923 2fa5d9ba Blue Swirl
    /*
924 2fa5d9ba Blue Swirl
     * Read in mmap_min_addr kernel parameter.  This value is used
925 2fa5d9ba Blue Swirl
     * When loading the ELF image to determine whether guest_base
926 2fa5d9ba Blue Swirl
     * is needed.
927 2fa5d9ba Blue Swirl
     *
928 2fa5d9ba Blue Swirl
     * When user has explicitly set the quest base, we skip this
929 2fa5d9ba Blue Swirl
     * test.
930 2fa5d9ba Blue Swirl
     */
931 2fa5d9ba Blue Swirl
    if (!have_guest_base) {
932 2fa5d9ba Blue Swirl
        FILE *fp;
933 2fa5d9ba Blue Swirl
934 2fa5d9ba Blue Swirl
        if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
935 2fa5d9ba Blue Swirl
            unsigned long tmp;
936 2fa5d9ba Blue Swirl
            if (fscanf(fp, "%lu", &tmp) == 1) {
937 2fa5d9ba Blue Swirl
                mmap_min_addr = tmp;
938 2fa5d9ba Blue Swirl
                qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
939 2fa5d9ba Blue Swirl
            }
940 2fa5d9ba Blue Swirl
            fclose(fp);
941 2fa5d9ba Blue Swirl
        }
942 2fa5d9ba Blue Swirl
    }
943 2fa5d9ba Blue Swirl
#endif /* CONFIG_USE_GUEST_BASE */
944 84778508 blueswir1
945 84778508 blueswir1
    if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) {
946 84778508 blueswir1
        printf("Error loading %s\n", filename);
947 84778508 blueswir1
        _exit(1);
948 84778508 blueswir1
    }
949 84778508 blueswir1
950 84778508 blueswir1
    for (wrk = target_environ; *wrk; wrk++) {
951 84778508 blueswir1
        free(*wrk);
952 84778508 blueswir1
    }
953 84778508 blueswir1
954 84778508 blueswir1
    free(target_environ);
955 84778508 blueswir1
956 2e77eac6 blueswir1
    if (qemu_log_enabled()) {
957 2fa5d9ba Blue Swirl
#if defined(CONFIG_USE_GUEST_BASE)
958 2fa5d9ba Blue Swirl
        qemu_log("guest_base  0x%lx\n", guest_base);
959 2fa5d9ba Blue Swirl
#endif
960 2e77eac6 blueswir1
        log_page_dump();
961 2e77eac6 blueswir1
962 2e77eac6 blueswir1
        qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
963 2e77eac6 blueswir1
        qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
964 2e77eac6 blueswir1
        qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n",
965 2e77eac6 blueswir1
                 info->start_code);
966 2e77eac6 blueswir1
        qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n",
967 2e77eac6 blueswir1
                 info->start_data);
968 2e77eac6 blueswir1
        qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
969 2e77eac6 blueswir1
        qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n",
970 2e77eac6 blueswir1
                 info->start_stack);
971 2e77eac6 blueswir1
        qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
972 2e77eac6 blueswir1
        qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
973 2e77eac6 blueswir1
    }
974 84778508 blueswir1
975 84778508 blueswir1
    target_set_brk(info->brk);
976 84778508 blueswir1
    syscall_init();
977 84778508 blueswir1
    signal_init();
978 84778508 blueswir1
979 9002ec79 Richard Henderson
#if defined(CONFIG_USE_GUEST_BASE)
980 9002ec79 Richard Henderson
    /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
981 9002ec79 Richard Henderson
       generating the prologue until now so that the prologue can take
982 9002ec79 Richard Henderson
       the real value of GUEST_BASE into account.  */
983 9002ec79 Richard Henderson
    tcg_prologue_init(&tcg_ctx);
984 9002ec79 Richard Henderson
#endif
985 9002ec79 Richard Henderson
986 84778508 blueswir1
    /* build Task State */
987 84778508 blueswir1
    memset(ts, 0, sizeof(TaskState));
988 84778508 blueswir1
    init_task_state(ts);
989 84778508 blueswir1
    ts->info = info;
990 84778508 blueswir1
    env->opaque = ts;
991 84778508 blueswir1
992 31fc12df blueswir1
#if defined(TARGET_I386)
993 31fc12df blueswir1
    cpu_x86_set_cpl(env, 3);
994 31fc12df blueswir1
995 31fc12df blueswir1
    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
996 31fc12df blueswir1
    env->hflags |= HF_PE_MASK;
997 31fc12df blueswir1
    if (env->cpuid_features & CPUID_SSE) {
998 31fc12df blueswir1
        env->cr[4] |= CR4_OSFXSR_MASK;
999 31fc12df blueswir1
        env->hflags |= HF_OSFXSR_MASK;
1000 31fc12df blueswir1
    }
1001 31fc12df blueswir1
#ifndef TARGET_ABI32
1002 31fc12df blueswir1
    /* enable 64 bit mode if possible */
1003 31fc12df blueswir1
    if (!(env->cpuid_ext2_features & CPUID_EXT2_LM)) {
1004 31fc12df blueswir1
        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
1005 31fc12df blueswir1
        exit(1);
1006 31fc12df blueswir1
    }
1007 31fc12df blueswir1
    env->cr[4] |= CR4_PAE_MASK;
1008 31fc12df blueswir1
    env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
1009 31fc12df blueswir1
    env->hflags |= HF_LMA_MASK;
1010 31fc12df blueswir1
#endif
1011 31fc12df blueswir1
1012 31fc12df blueswir1
    /* flags setup : we activate the IRQs by default as in user mode */
1013 31fc12df blueswir1
    env->eflags |= IF_MASK;
1014 31fc12df blueswir1
1015 31fc12df blueswir1
    /* linux register setup */
1016 31fc12df blueswir1
#ifndef TARGET_ABI32
1017 31fc12df blueswir1
    env->regs[R_EAX] = regs->rax;
1018 31fc12df blueswir1
    env->regs[R_EBX] = regs->rbx;
1019 31fc12df blueswir1
    env->regs[R_ECX] = regs->rcx;
1020 31fc12df blueswir1
    env->regs[R_EDX] = regs->rdx;
1021 31fc12df blueswir1
    env->regs[R_ESI] = regs->rsi;
1022 31fc12df blueswir1
    env->regs[R_EDI] = regs->rdi;
1023 31fc12df blueswir1
    env->regs[R_EBP] = regs->rbp;
1024 31fc12df blueswir1
    env->regs[R_ESP] = regs->rsp;
1025 31fc12df blueswir1
    env->eip = regs->rip;
1026 31fc12df blueswir1
#else
1027 31fc12df blueswir1
    env->regs[R_EAX] = regs->eax;
1028 31fc12df blueswir1
    env->regs[R_EBX] = regs->ebx;
1029 31fc12df blueswir1
    env->regs[R_ECX] = regs->ecx;
1030 31fc12df blueswir1
    env->regs[R_EDX] = regs->edx;
1031 31fc12df blueswir1
    env->regs[R_ESI] = regs->esi;
1032 31fc12df blueswir1
    env->regs[R_EDI] = regs->edi;
1033 31fc12df blueswir1
    env->regs[R_EBP] = regs->ebp;
1034 31fc12df blueswir1
    env->regs[R_ESP] = regs->esp;
1035 31fc12df blueswir1
    env->eip = regs->eip;
1036 31fc12df blueswir1
#endif
1037 31fc12df blueswir1
1038 31fc12df blueswir1
    /* linux interrupt setup */
1039 31fc12df blueswir1
#ifndef TARGET_ABI32
1040 31fc12df blueswir1
    env->idt.limit = 511;
1041 31fc12df blueswir1
#else
1042 31fc12df blueswir1
    env->idt.limit = 255;
1043 31fc12df blueswir1
#endif
1044 31fc12df blueswir1
    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
1045 31fc12df blueswir1
                                PROT_READ|PROT_WRITE,
1046 31fc12df blueswir1
                                MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
1047 31fc12df blueswir1
    idt_table = g2h(env->idt.base);
1048 31fc12df blueswir1
    set_idt(0, 0);
1049 31fc12df blueswir1
    set_idt(1, 0);
1050 31fc12df blueswir1
    set_idt(2, 0);
1051 31fc12df blueswir1
    set_idt(3, 3);
1052 31fc12df blueswir1
    set_idt(4, 3);
1053 31fc12df blueswir1
    set_idt(5, 0);
1054 31fc12df blueswir1
    set_idt(6, 0);
1055 31fc12df blueswir1
    set_idt(7, 0);
1056 31fc12df blueswir1
    set_idt(8, 0);
1057 31fc12df blueswir1
    set_idt(9, 0);
1058 31fc12df blueswir1
    set_idt(10, 0);
1059 31fc12df blueswir1
    set_idt(11, 0);
1060 31fc12df blueswir1
    set_idt(12, 0);
1061 31fc12df blueswir1
    set_idt(13, 0);
1062 31fc12df blueswir1
    set_idt(14, 0);
1063 31fc12df blueswir1
    set_idt(15, 0);
1064 31fc12df blueswir1
    set_idt(16, 0);
1065 31fc12df blueswir1
    set_idt(17, 0);
1066 31fc12df blueswir1
    set_idt(18, 0);
1067 31fc12df blueswir1
    set_idt(19, 0);
1068 31fc12df blueswir1
    set_idt(0x80, 3);
1069 31fc12df blueswir1
1070 31fc12df blueswir1
    /* linux segment setup */
1071 31fc12df blueswir1
    {
1072 31fc12df blueswir1
        uint64_t *gdt_table;
1073 31fc12df blueswir1
        env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
1074 31fc12df blueswir1
                                    PROT_READ|PROT_WRITE,
1075 31fc12df blueswir1
                                    MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
1076 31fc12df blueswir1
        env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
1077 31fc12df blueswir1
        gdt_table = g2h(env->gdt.base);
1078 31fc12df blueswir1
#ifdef TARGET_ABI32
1079 31fc12df blueswir1
        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
1080 31fc12df blueswir1
                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1081 31fc12df blueswir1
                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
1082 31fc12df blueswir1
#else
1083 31fc12df blueswir1
        /* 64 bit code segment */
1084 31fc12df blueswir1
        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
1085 31fc12df blueswir1
                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1086 31fc12df blueswir1
                 DESC_L_MASK |
1087 31fc12df blueswir1
                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
1088 31fc12df blueswir1
#endif
1089 31fc12df blueswir1
        write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
1090 31fc12df blueswir1
                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
1091 31fc12df blueswir1
                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
1092 31fc12df blueswir1
    }
1093 31fc12df blueswir1
1094 31fc12df blueswir1
    cpu_x86_load_seg(env, R_CS, __USER_CS);
1095 31fc12df blueswir1
    cpu_x86_load_seg(env, R_SS, __USER_DS);
1096 31fc12df blueswir1
#ifdef TARGET_ABI32
1097 31fc12df blueswir1
    cpu_x86_load_seg(env, R_DS, __USER_DS);
1098 31fc12df blueswir1
    cpu_x86_load_seg(env, R_ES, __USER_DS);
1099 31fc12df blueswir1
    cpu_x86_load_seg(env, R_FS, __USER_DS);
1100 31fc12df blueswir1
    cpu_x86_load_seg(env, R_GS, __USER_DS);
1101 31fc12df blueswir1
    /* This hack makes Wine work... */
1102 31fc12df blueswir1
    env->segs[R_FS].selector = 0;
1103 31fc12df blueswir1
#else
1104 31fc12df blueswir1
    cpu_x86_load_seg(env, R_DS, 0);
1105 31fc12df blueswir1
    cpu_x86_load_seg(env, R_ES, 0);
1106 31fc12df blueswir1
    cpu_x86_load_seg(env, R_FS, 0);
1107 31fc12df blueswir1
    cpu_x86_load_seg(env, R_GS, 0);
1108 31fc12df blueswir1
#endif
1109 31fc12df blueswir1
#elif defined(TARGET_SPARC)
1110 84778508 blueswir1
    {
1111 84778508 blueswir1
        int i;
1112 84778508 blueswir1
        env->pc = regs->pc;
1113 84778508 blueswir1
        env->npc = regs->npc;
1114 84778508 blueswir1
        env->y = regs->y;
1115 84778508 blueswir1
        for(i = 0; i < 8; i++)
1116 84778508 blueswir1
            env->gregs[i] = regs->u_regs[i];
1117 84778508 blueswir1
        for(i = 0; i < 8; i++)
1118 84778508 blueswir1
            env->regwptr[i] = regs->u_regs[i + 8];
1119 84778508 blueswir1
    }
1120 84778508 blueswir1
#else
1121 84778508 blueswir1
#error unsupported target CPU
1122 84778508 blueswir1
#endif
1123 84778508 blueswir1
1124 84778508 blueswir1
    if (gdbstub_port) {
1125 84778508 blueswir1
        gdbserver_start (gdbstub_port);
1126 84778508 blueswir1
        gdb_handlesig(env, 0);
1127 84778508 blueswir1
    }
1128 78cfb07f Juergen Lock
    cpu_loop(env);
1129 84778508 blueswir1
    /* never exits */
1130 84778508 blueswir1
    return 0;
1131 84778508 blueswir1
}