]>
git.proxmox.com Git - qemu.git/blob - linux-user/main.c
4 * Copyright (c) 2003 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 #define DEBUG_LOGFILE "/tmp/qemu.log"
35 static const char *interp_prefix
= CONFIG_QEMU_PREFIX
;
38 /* Force usage of an ELF interpreter even if it is an ELF shared
40 const char interp
[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
42 /* for recent libc, we add these dummies symbol which are not declared
43 when generating a linked object (bug in ld ?) */
44 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
45 long __init_array_start
[0];
46 long __init_array_end
[0];
47 long __fini_array_start
[0];
48 long __fini_array_end
[0];
53 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
54 we allocate a bigger stack. Need a better solution, for example
55 by remapping the process stack directly at the right place */
56 unsigned long x86_stack_size
= 512 * 1024;
58 void gemu_log(const char *fmt
, ...)
63 vfprintf(stderr
, fmt
, ap
);
67 /***********************************************************/
68 /* CPUX86 core interface */
70 void cpu_x86_outb(CPUX86State
*env
, int addr
, int val
)
72 fprintf(stderr
, "outb: port=0x%04x, data=%02x\n", addr
, val
);
75 void cpu_x86_outw(CPUX86State
*env
, int addr
, int val
)
77 fprintf(stderr
, "outw: port=0x%04x, data=%04x\n", addr
, val
);
80 void cpu_x86_outl(CPUX86State
*env
, int addr
, int val
)
82 fprintf(stderr
, "outl: port=0x%04x, data=%08x\n", addr
, val
);
85 int cpu_x86_inb(CPUX86State
*env
, int addr
)
87 fprintf(stderr
, "inb: port=0x%04x\n", addr
);
91 int cpu_x86_inw(CPUX86State
*env
, int addr
)
93 fprintf(stderr
, "inw: port=0x%04x\n", addr
);
97 int cpu_x86_inl(CPUX86State
*env
, int addr
)
99 fprintf(stderr
, "inl: port=0x%04x\n", addr
);
103 void write_dt(void *ptr
, unsigned long addr
, unsigned long limit
,
106 unsigned int e1
, e2
, limit_in_pages
;
108 if (limit
> 0xffff) {
112 e1
= (addr
<< 16) | (limit
& 0xffff);
113 e2
= ((addr
>> 16) & 0xff) | (addr
& 0xff000000) | (limit
& 0x000f0000);
114 e2
|= limit_in_pages
<< 23; /* byte granularity */
115 e2
|= seg32_bit
<< 22; /* 32 bit segment */
116 stl((uint8_t *)ptr
, e1
);
117 stl((uint8_t *)ptr
+ 4, e2
);
120 uint64_t gdt_table
[6];
122 void cpu_loop(CPUX86State
*env
)
126 target_siginfo_t info
;
129 trapnr
= cpu_x86_exec(env
);
132 if (env
->eflags
& VM_MASK
) {
133 handle_vm86_fault(env
);
135 pc
= env
->seg_cache
[R_CS
].base
+ env
->eip
;
136 if (pc
[0] == 0xcd && pc
[1] == 0x80) {
139 env
->regs
[R_EAX
] = do_syscall(env
,
148 /* XXX: more precise info */
149 info
.si_signo
= SIGSEGV
;
151 info
.si_code
= TARGET_SI_KERNEL
;
152 info
._sifields
._sigfault
._addr
= 0;
153 queue_signal(info
.si_signo
, &info
);
158 info
.si_signo
= SIGSEGV
;
160 if (!(env
->error_code
& 1))
161 info
.si_code
= TARGET_SEGV_MAPERR
;
163 info
.si_code
= TARGET_SEGV_ACCERR
;
164 info
._sifields
._sigfault
._addr
= env
->cr2
;
165 queue_signal(info
.si_signo
, &info
);
168 if (env
->eflags
& VM_MASK
) {
171 /* division by zero */
172 info
.si_signo
= SIGFPE
;
174 info
.si_code
= TARGET_FPE_INTDIV
;
175 info
._sifields
._sigfault
._addr
= env
->eip
;
176 queue_signal(info
.si_signo
, &info
);
181 if (env
->eflags
& VM_MASK
) {
184 info
.si_signo
= SIGSEGV
;
186 info
.si_code
= TARGET_SI_KERNEL
;
187 info
._sifields
._sigfault
._addr
= 0;
188 queue_signal(info
.si_signo
, &info
);
192 info
.si_signo
= SIGILL
;
194 info
.si_code
= TARGET_ILL_ILLOPN
;
195 info
._sifields
._sigfault
._addr
= env
->eip
;
196 queue_signal(info
.si_signo
, &info
);
199 /* just indicate that signals should be handled asap */
202 pc
= env
->seg_cache
[R_CS
].base
+ env
->eip
;
203 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
207 process_pending_signals(env
);
213 printf("qemu version " QEMU_VERSION
", Copyright (c) 2003 Fabrice Bellard\n"
214 "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
215 "Linux x86 emulator\n"
217 "-h print this help\n"
218 "-d activate log (logfile=%s)\n"
219 "-L path set the x86 elf interpreter prefix (default=%s)\n"
220 "-s size set the x86 stack size in bytes (default=%ld)\n",
227 /* XXX: currently only used for async signals (see signal.c) */
228 CPUX86State
*global_env
;
229 /* used to free thread contexts */
230 TaskState
*first_task_state
;
232 int main(int argc
, char **argv
)
234 const char *filename
;
235 struct target_pt_regs regs1
, *regs
= ®s1
;
236 struct image_info info1
, *info
= &info1
;
237 TaskState ts1
, *ts
= &ts1
;
255 if (!strcmp(r
, "-")) {
257 } else if (!strcmp(r
, "d")) {
259 } else if (!strcmp(r
, "s")) {
261 x86_stack_size
= strtol(r
, (char **)&r
, 0);
262 if (x86_stack_size
<= 0)
265 x86_stack_size
*= 1024 * 1024;
266 else if (*r
== 'k' || *r
== 'K')
267 x86_stack_size
*= 1024;
268 } else if (!strcmp(r
, "L")) {
269 interp_prefix
= argv
[optind
++];
276 filename
= argv
[optind
];
280 logfile
= fopen(DEBUG_LOGFILE
, "w");
282 perror(DEBUG_LOGFILE
);
285 setvbuf(logfile
, NULL
, _IOLBF
, 0);
289 memset(regs
, 0, sizeof(struct target_pt_regs
));
291 /* Zero out image_info */
292 memset(info
, 0, sizeof(struct image_info
));
294 /* Scan interp_prefix dir for replacement files. */
295 init_paths(interp_prefix
);
297 if (elf_exec(filename
, argv
+optind
, environ
, regs
, info
) != 0) {
298 printf("Error loading %s\n", filename
);
303 fprintf(logfile
, "start_brk 0x%08lx\n" , info
->start_brk
);
304 fprintf(logfile
, "end_code 0x%08lx\n" , info
->end_code
);
305 fprintf(logfile
, "start_code 0x%08lx\n" , info
->start_code
);
306 fprintf(logfile
, "end_data 0x%08lx\n" , info
->end_data
);
307 fprintf(logfile
, "start_stack 0x%08lx\n" , info
->start_stack
);
308 fprintf(logfile
, "brk 0x%08lx\n" , info
->brk
);
309 fprintf(logfile
, "esp 0x%08lx\n" , regs
->esp
);
310 fprintf(logfile
, "eip 0x%08lx\n" , regs
->eip
);
313 target_set_brk((char *)info
->brk
);
317 env
= cpu_x86_init();
320 /* build Task State */
321 memset(ts
, 0, sizeof(TaskState
));
325 /* linux register setup */
326 env
->regs
[R_EAX
] = regs
->eax
;
327 env
->regs
[R_EBX
] = regs
->ebx
;
328 env
->regs
[R_ECX
] = regs
->ecx
;
329 env
->regs
[R_EDX
] = regs
->edx
;
330 env
->regs
[R_ESI
] = regs
->esi
;
331 env
->regs
[R_EDI
] = regs
->edi
;
332 env
->regs
[R_EBP
] = regs
->ebp
;
333 env
->regs
[R_ESP
] = regs
->esp
;
334 env
->eip
= regs
->eip
;
336 /* linux segment setup */
337 env
->gdt
.base
= (void *)gdt_table
;
338 env
->gdt
.limit
= sizeof(gdt_table
) - 1;
339 write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xffffffff, 1);
340 write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xffffffff, 1);
341 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
342 cpu_x86_load_seg(env
, R_DS
, __USER_DS
);
343 cpu_x86_load_seg(env
, R_ES
, __USER_DS
);
344 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
345 cpu_x86_load_seg(env
, R_FS
, __USER_DS
);
346 cpu_x86_load_seg(env
, R_GS
, __USER_DS
);