]>
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.
26 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
27 #include <sys/personality.h>
34 #define DEBUG_LOGFILE "/tmp/qemu.log"
38 const char *interp_prefix
= CONFIG_QEMU_PREFIX
"/qemu-i386";
41 /* Force usage of an ELF interpreter even if it is an ELF shared
43 const char interp
[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
46 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
47 we allocate a bigger stack. Need a better solution, for example
48 by remapping the process stack directly at the right place */
49 unsigned long x86_stack_size
= 512 * 1024;
51 void gemu_log(const char *fmt
, ...)
56 vfprintf(stderr
, fmt
, ap
);
60 /***********************************************************/
61 /* CPUX86 core interface */
63 void cpu_x86_outb(int addr
, int val
)
65 fprintf(stderr
, "outb: port=0x%04x, data=%02x\n", addr
, val
);
68 void cpu_x86_outw(int addr
, int val
)
70 fprintf(stderr
, "outw: port=0x%04x, data=%04x\n", addr
, val
);
73 void cpu_x86_outl(int addr
, int val
)
75 fprintf(stderr
, "outl: port=0x%04x, data=%08x\n", addr
, val
);
78 int cpu_x86_inb(int addr
)
80 fprintf(stderr
, "inb: port=0x%04x\n", addr
);
84 int cpu_x86_inw(int addr
)
86 fprintf(stderr
, "inw: port=0x%04x\n", addr
);
90 int cpu_x86_inl(int addr
)
92 fprintf(stderr
, "inl: port=0x%04x\n", addr
);
96 void write_dt(void *ptr
, unsigned long addr
, unsigned long limit
,
99 unsigned int e1
, e2
, limit_in_pages
;
101 if (limit
> 0xffff) {
105 e1
= (addr
<< 16) | (limit
& 0xffff);
106 e2
= ((addr
>> 16) & 0xff) | (addr
& 0xff000000) | (limit
& 0x000f0000);
107 e2
|= limit_in_pages
<< 23; /* byte granularity */
108 e2
|= seg32_bit
<< 22; /* 32 bit segment */
109 stl((uint8_t *)ptr
, e1
);
110 stl((uint8_t *)ptr
+ 4, e2
);
113 uint64_t gdt_table
[6];
117 static inline int is_revectored(int nr
, struct target_revectored_struct
*bitmap
)
119 return (tswap32(bitmap
->__map
[nr
>> 5]) >> (nr
& 0x1f)) & 1;
122 static inline uint8_t *seg_to_linear(unsigned int seg
, unsigned int reg
)
124 return (uint8_t *)((seg
<< 4) + (reg
& 0xffff));
127 static inline void pushw(CPUX86State
*env
, int val
)
129 env
->regs
[R_ESP
] = (env
->regs
[R_ESP
] & ~0xffff) |
130 ((env
->regs
[R_ESP
] - 2) & 0xffff);
131 *(uint16_t *)seg_to_linear(env
->segs
[R_SS
], env
->regs
[R_ESP
]) = val
;
134 static inline unsigned int get_vflags(CPUX86State
*env
)
137 eflags
= env
->eflags
& ~(VM_MASK
| RF_MASK
| IF_MASK
);
138 if (eflags
& VIF_MASK
)
143 void save_v86_state(CPUX86State
*env
)
145 TaskState
*ts
= env
->opaque
;
147 printf("save_v86_state\n");
150 /* put the VM86 registers in the userspace register structure */
151 ts
->target_v86
->regs
.eax
= tswap32(env
->regs
[R_EAX
]);
152 ts
->target_v86
->regs
.ebx
= tswap32(env
->regs
[R_EBX
]);
153 ts
->target_v86
->regs
.ecx
= tswap32(env
->regs
[R_ECX
]);
154 ts
->target_v86
->regs
.edx
= tswap32(env
->regs
[R_EDX
]);
155 ts
->target_v86
->regs
.esi
= tswap32(env
->regs
[R_ESI
]);
156 ts
->target_v86
->regs
.edi
= tswap32(env
->regs
[R_EDI
]);
157 ts
->target_v86
->regs
.ebp
= tswap32(env
->regs
[R_EBP
]);
158 ts
->target_v86
->regs
.esp
= tswap32(env
->regs
[R_ESP
]);
159 ts
->target_v86
->regs
.eip
= tswap32(env
->eip
);
160 ts
->target_v86
->regs
.cs
= tswap16(env
->segs
[R_CS
]);
161 ts
->target_v86
->regs
.ss
= tswap16(env
->segs
[R_SS
]);
162 ts
->target_v86
->regs
.ds
= tswap16(env
->segs
[R_DS
]);
163 ts
->target_v86
->regs
.es
= tswap16(env
->segs
[R_ES
]);
164 ts
->target_v86
->regs
.fs
= tswap16(env
->segs
[R_FS
]);
165 ts
->target_v86
->regs
.gs
= tswap16(env
->segs
[R_GS
]);
166 ts
->target_v86
->regs
.eflags
= tswap32(env
->eflags
);
168 /* restore 32 bit registers */
169 env
->regs
[R_EAX
] = ts
->vm86_saved_regs
.eax
;
170 env
->regs
[R_EBX
] = ts
->vm86_saved_regs
.ebx
;
171 env
->regs
[R_ECX
] = ts
->vm86_saved_regs
.ecx
;
172 env
->regs
[R_EDX
] = ts
->vm86_saved_regs
.edx
;
173 env
->regs
[R_ESI
] = ts
->vm86_saved_regs
.esi
;
174 env
->regs
[R_EDI
] = ts
->vm86_saved_regs
.edi
;
175 env
->regs
[R_EBP
] = ts
->vm86_saved_regs
.ebp
;
176 env
->regs
[R_ESP
] = ts
->vm86_saved_regs
.esp
;
177 env
->eflags
= ts
->vm86_saved_regs
.eflags
;
178 env
->eip
= ts
->vm86_saved_regs
.eip
;
180 cpu_x86_load_seg(env
, R_CS
, ts
->vm86_saved_regs
.cs
);
181 cpu_x86_load_seg(env
, R_SS
, ts
->vm86_saved_regs
.ss
);
182 cpu_x86_load_seg(env
, R_DS
, ts
->vm86_saved_regs
.ds
);
183 cpu_x86_load_seg(env
, R_ES
, ts
->vm86_saved_regs
.es
);
184 cpu_x86_load_seg(env
, R_FS
, ts
->vm86_saved_regs
.fs
);
185 cpu_x86_load_seg(env
, R_GS
, ts
->vm86_saved_regs
.gs
);
188 /* return from vm86 mode to 32 bit. The vm86() syscall will return
190 static inline void return_to_32bit(CPUX86State
*env
, int retval
)
193 printf("return_to_32bit: ret=0x%x\n", retval
);
196 env
->regs
[R_EAX
] = retval
;
199 /* handle VM86 interrupt (NOTE: the CPU core currently does not
200 support TSS interrupt revectoring, so this code is always executed) */
201 static void do_int(CPUX86State
*env
, int intno
)
203 TaskState
*ts
= env
->opaque
;
204 uint32_t *int_ptr
, segoffs
;
206 if (env
->segs
[R_CS
] == TARGET_BIOSSEG
)
207 goto cannot_handle
; /* XXX: I am not sure this is really useful */
208 if (is_revectored(intno
, &ts
->target_v86
->int_revectored
))
210 if (intno
== 0x21 && is_revectored((env
->regs
[R_EAX
] >> 8) & 0xff,
211 &ts
->target_v86
->int21_revectored
))
213 int_ptr
= (uint32_t *)(intno
<< 2);
214 segoffs
= tswap32(*int_ptr
);
215 if ((segoffs
>> 16) == TARGET_BIOSSEG
)
218 printf("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n",
219 intno
, segoffs
>> 16, segoffs
& 0xffff);
222 pushw(env
, get_vflags(env
));
223 pushw(env
, env
->segs
[R_CS
]);
224 pushw(env
, env
->eip
);
225 /* goto interrupt handler */
226 env
->eip
= segoffs
& 0xffff;
227 cpu_x86_load_seg(env
, R_CS
, segoffs
>> 16);
228 env
->eflags
&= ~(VIF_MASK
| TF_MASK
);
232 printf("VM86: return to 32 bits int 0x%x\n", intno
);
234 return_to_32bit(env
, TARGET_VM86_INTx
| (intno
<< 8));
237 void cpu_loop(struct CPUX86State
*env
)
241 target_siginfo_t info
;
244 trapnr
= cpu_x86_exec(env
);
245 pc
= env
->seg_cache
[R_CS
].base
+ env
->eip
;
248 if (env
->eflags
& VM_MASK
) {
250 printf("VM86 exception %04x:%08x %02x %02x\n",
251 env
->segs
[R_CS
], env
->eip
, pc
[0], pc
[1]);
262 case 0x9d: /* popf */
263 case 0xcf: /* iret */
265 return_to_32bit(env
, TARGET_VM86_STI
);
272 case 0x9d: /* popf */
273 case 0xcf: /* iret */
275 return_to_32bit(env
, TARGET_VM86_STI
);
279 /* real VM86 GPF exception */
280 return_to_32bit(env
, TARGET_VM86_UNKNOWN
);
284 if (pc
[0] == 0xcd && pc
[1] == 0x80) {
287 env
->regs
[R_EAX
] = do_syscall(env
,
296 /* XXX: more precise info */
297 info
.si_signo
= SIGSEGV
;
300 info
._sifields
._sigfault
._addr
= 0;
301 queue_signal(info
.si_signo
, &info
);
306 if (env
->eflags
& VM_MASK
) {
309 /* division by zero */
310 info
.si_signo
= SIGFPE
;
312 info
.si_code
= TARGET_FPE_INTDIV
;
313 info
._sifields
._sigfault
._addr
= env
->eip
;
314 queue_signal(info
.si_signo
, &info
);
319 if (env
->eflags
& VM_MASK
) {
322 info
.si_signo
= SIGSEGV
;
325 info
._sifields
._sigfault
._addr
= 0;
326 queue_signal(info
.si_signo
, &info
);
330 info
.si_signo
= SIGILL
;
332 info
.si_code
= TARGET_ILL_ILLOPN
;
333 info
._sifields
._sigfault
._addr
= env
->eip
;
334 queue_signal(info
.si_signo
, &info
);
337 /* just indicate that signals should be handled asap */
340 fprintf(stderr
, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
344 process_pending_signals(env
);
350 printf("qemu version " QEMU_VERSION
", Copyright (c) 2003 Fabrice Bellard\n"
351 "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
352 "Linux x86 emulator\n"
354 "-h print this help\n"
355 "-d activate log (logfile=%s)\n"
356 "-L path set the x86 elf interpreter prefix (default=%s)\n"
357 "-s size set the x86 stack size in bytes (default=%ld)\n",
364 /* XXX: currently only used for async signals (see signal.c) */
365 CPUX86State
*global_env
;
366 /* used to free thread contexts */
367 TaskState
*first_task_state
;
369 int main(int argc
, char **argv
)
371 const char *filename
;
372 struct target_pt_regs regs1
, *regs
= ®s1
;
373 struct image_info info1
, *info
= &info1
;
374 TaskState ts1
, *ts
= &ts1
;
382 /* Set personality to X86_LINUX. May fail on unpatched kernels:
383 if so, they need to have munged paths themselves (eg. chroot,
384 hacked ld.so, whatever). */
385 if (personality(0x11) >= 0)
398 if (!strcmp(r
, "-")) {
400 } else if (!strcmp(r
, "d")) {
402 } else if (!strcmp(r
, "s")) {
404 x86_stack_size
= strtol(r
, (char **)&r
, 0);
405 if (x86_stack_size
<= 0)
408 x86_stack_size
*= 1024 * 1024;
409 else if (*r
== 'k' || *r
== 'K')
410 x86_stack_size
*= 1024;
411 } else if (!strcmp(r
, "L")) {
412 interp_prefix
= argv
[optind
++];
419 filename
= argv
[optind
];
423 logfile
= fopen(DEBUG_LOGFILE
, "w");
425 perror(DEBUG_LOGFILE
);
428 setvbuf(logfile
, NULL
, _IOLBF
, 0);
432 memset(regs
, 0, sizeof(struct target_pt_regs
));
434 /* Zero out image_info */
435 memset(info
, 0, sizeof(struct image_info
));
437 if(elf_exec(interp_prefix
, filename
, argv
+optind
, environ
, regs
, info
) != 0) {
438 printf("Error loading %s\n", filename
);
443 fprintf(logfile
, "start_brk 0x%08lx\n" , info
->start_brk
);
444 fprintf(logfile
, "end_code 0x%08lx\n" , info
->end_code
);
445 fprintf(logfile
, "start_code 0x%08lx\n" , info
->start_code
);
446 fprintf(logfile
, "end_data 0x%08lx\n" , info
->end_data
);
447 fprintf(logfile
, "start_stack 0x%08lx\n" , info
->start_stack
);
448 fprintf(logfile
, "brk 0x%08lx\n" , info
->brk
);
449 fprintf(logfile
, "esp 0x%08lx\n" , regs
->esp
);
450 fprintf(logfile
, "eip 0x%08lx\n" , regs
->eip
);
453 target_set_brk((char *)info
->brk
);
457 env
= cpu_x86_init();
460 /* build Task State */
461 memset(ts
, 0, sizeof(TaskState
));
465 /* linux register setup */
466 env
->regs
[R_EAX
] = regs
->eax
;
467 env
->regs
[R_EBX
] = regs
->ebx
;
468 env
->regs
[R_ECX
] = regs
->ecx
;
469 env
->regs
[R_EDX
] = regs
->edx
;
470 env
->regs
[R_ESI
] = regs
->esi
;
471 env
->regs
[R_EDI
] = regs
->edi
;
472 env
->regs
[R_EBP
] = regs
->ebp
;
473 env
->regs
[R_ESP
] = regs
->esp
;
474 env
->eip
= regs
->eip
;
476 /* linux segment setup */
477 env
->gdt
.base
= (void *)gdt_table
;
478 env
->gdt
.limit
= sizeof(gdt_table
) - 1;
479 write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xffffffff, 1);
480 write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xffffffff, 1);
481 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
482 cpu_x86_load_seg(env
, R_DS
, __USER_DS
);
483 cpu_x86_load_seg(env
, R_ES
, __USER_DS
);
484 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
485 cpu_x86_load_seg(env
, R_FS
, __USER_DS
);
486 cpu_x86_load_seg(env
, R_GS
, __USER_DS
);