]>
git.proxmox.com Git - mirror_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/gemu.log"
36 unsigned long x86_stack_size
;
39 void gemu_log(const char *fmt
, ...)
44 vfprintf(stderr
, fmt
, ap
);
48 /***********************************************************/
49 /* CPUX86 core interface */
51 void cpu_x86_outb(int addr
, int val
)
53 fprintf(stderr
, "outb: port=0x%04x, data=%02x\n", addr
, val
);
56 void cpu_x86_outw(int addr
, int val
)
58 fprintf(stderr
, "outw: port=0x%04x, data=%04x\n", addr
, val
);
61 void cpu_x86_outl(int addr
, int val
)
63 fprintf(stderr
, "outl: port=0x%04x, data=%08x\n", addr
, val
);
66 int cpu_x86_inb(int addr
)
68 fprintf(stderr
, "inb: port=0x%04x\n", addr
);
72 int cpu_x86_inw(int addr
)
74 fprintf(stderr
, "inw: port=0x%04x\n", addr
);
78 int cpu_x86_inl(int addr
)
80 fprintf(stderr
, "inl: port=0x%04x\n", addr
);
84 /* default linux values for the selectors */
85 #define __USER_CS (0x23)
86 #define __USER_DS (0x2B)
88 void write_dt(void *ptr
, unsigned long addr
, unsigned long limit
,
91 unsigned int e1
, e2
, limit_in_pages
;
97 e1
= (addr
<< 16) | (limit
& 0xffff);
98 e2
= ((addr
>> 16) & 0xff) | (addr
& 0xff000000) | (limit
& 0x000f0000);
99 e2
|= limit_in_pages
<< 23; /* byte granularity */
100 e2
|= seg32_bit
<< 22; /* 32 bit segment */
101 stl((uint8_t *)ptr
, e1
);
102 stl((uint8_t *)ptr
+ 4, e2
);
105 uint64_t gdt_table
[6];
107 void cpu_loop(struct CPUX86State
*env
)
113 err
= cpu_x86_exec(env
);
114 pc
= env
->seg_cache
[R_CS
].base
+ env
->eip
;
117 if (pc
[0] == 0xcd && pc
[1] == 0x80) {
120 env
->regs
[R_EAX
] = do_syscall(env
,
134 fprintf(stderr
, "0x%08lx: Unknown exception %d, aborting\n",
143 printf("gemu version " GEMU_VERSION
", Copyright (c) 2003 Fabrice Bellard\n"
144 "usage: gemu [-d] program [arguments...]\n"
145 "Linux x86 emulator\n"
150 int main(int argc
, char **argv
)
152 const char *filename
;
153 struct target_pt_regs regs1
, *regs
= ®s1
;
154 struct image_info info1
, *info
= &info1
;
162 if (argv
[optind
] && !strcmp(argv
[optind
], "-d")) {
166 filename
= argv
[optind
];
170 logfile
= fopen(DEBUG_LOGFILE
, "w");
172 perror(DEBUG_LOGFILE
);
175 setvbuf(logfile
, NULL
, _IOLBF
, 0);
179 memset(regs
, 0, sizeof(struct target_pt_regs
));
181 /* Zero out image_info */
182 memset(info
, 0, sizeof(struct image_info
));
184 if(elf_exec(filename
, argv
+optind
, environ
, regs
, info
) != 0) {
185 printf("Error loading %s\n", filename
);
190 fprintf(logfile
, "start_brk 0x%08lx\n" , info
->start_brk
);
191 fprintf(logfile
, "end_code 0x%08lx\n" , info
->end_code
);
192 fprintf(logfile
, "start_code 0x%08lx\n" , info
->start_code
);
193 fprintf(logfile
, "end_data 0x%08lx\n" , info
->end_data
);
194 fprintf(logfile
, "start_stack 0x%08lx\n" , info
->start_stack
);
195 fprintf(logfile
, "brk 0x%08lx\n" , info
->brk
);
196 fprintf(logfile
, "esp 0x%08lx\n" , regs
->esp
);
197 fprintf(logfile
, "eip 0x%08lx\n" , regs
->eip
);
200 target_set_brk((char *)info
->brk
);
203 env
= cpu_x86_init();
205 /* linux register setup */
206 env
->regs
[R_EAX
] = regs
->eax
;
207 env
->regs
[R_EBX
] = regs
->ebx
;
208 env
->regs
[R_ECX
] = regs
->ecx
;
209 env
->regs
[R_EDX
] = regs
->edx
;
210 env
->regs
[R_ESI
] = regs
->esi
;
211 env
->regs
[R_EDI
] = regs
->edi
;
212 env
->regs
[R_EBP
] = regs
->ebp
;
213 env
->regs
[R_ESP
] = regs
->esp
;
214 env
->eip
= regs
->eip
;
216 /* linux segment setup */
217 env
->gdt
.base
= (void *)gdt_table
;
218 env
->gdt
.limit
= sizeof(gdt_table
) - 1;
219 write_dt(&gdt_table
[__USER_CS
>> 3], 0, 0xffffffff, 1);
220 write_dt(&gdt_table
[__USER_DS
>> 3], 0, 0xffffffff, 1);
221 cpu_x86_load_seg(env
, R_CS
, __USER_CS
);
222 cpu_x86_load_seg(env
, R_DS
, __USER_DS
);
223 cpu_x86_load_seg(env
, R_ES
, __USER_DS
);
224 cpu_x86_load_seg(env
, R_SS
, __USER_DS
);
225 cpu_x86_load_seg(env
, R_FS
, __USER_DS
);
226 cpu_x86_load_seg(env
, R_GS
, __USER_DS
);