9927b8256a09f7a61eeadd0f750628ffc0cc9bb4
[qemu] / linux-user / main.c
1 /*
2  *  emu main
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
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.
10  *
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.
15  *
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.
19  */
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <unistd.h>
25
26 #include "gemu.h"
27
28 #include "cpu-i386.h"
29
30 #define DEBUG_LOGFILE "/tmp/gemu.log"
31
32 FILE *logfile = NULL;
33 int loglevel;
34
35 unsigned long x86_stack_size;
36 unsigned long stktop;
37
38 void gemu_log(const char *fmt, ...)
39 {
40     va_list ap;
41
42     va_start(ap, fmt);
43     vfprintf(stderr, fmt, ap);
44     va_end(ap);
45 }
46
47 /***********************************************************/
48 /* CPUX86 core interface */
49
50 void cpu_x86_outb(int addr, int val)
51 {
52     fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
53 }
54
55 void cpu_x86_outw(int addr, int val)
56 {
57     fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
58 }
59
60 void cpu_x86_outl(int addr, int val)
61 {
62     fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
63 }
64
65 int cpu_x86_inb(int addr)
66 {
67     fprintf(stderr, "inb: port=0x%04x\n", addr);
68     return 0;
69 }
70
71 int cpu_x86_inw(int addr)
72 {
73     fprintf(stderr, "inw: port=0x%04x\n", addr);
74     return 0;
75 }
76
77 int cpu_x86_inl(int addr)
78 {
79     fprintf(stderr, "inl: port=0x%04x\n", addr);
80     return 0;
81 }
82
83
84 /* XXX: currently we use LDT entries */
85 #define __USER_CS       (0x23|4)
86 #define __USER_DS       (0x2B|4)
87
88 void usage(void)
89 {
90     printf("gemu version" GEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
91            "usage: gemu [-d] program [arguments...]\n"
92            "Linux x86 emulator\n"
93            );
94     exit(1);
95 }
96
97 int main(int argc, char **argv)
98 {
99     const char *filename;
100     struct target_pt_regs regs1, *regs = &regs1;
101     struct image_info info1, *info = &info1;
102     CPUX86State *env;
103     int optind;
104
105     if (argc <= 1)
106         usage();
107     loglevel = 0;
108     optind = 1;
109     if (argv[optind] && !strcmp(argv[optind], "-d")) {
110         loglevel = 1;
111         optind++;
112     }
113     filename = argv[optind];
114
115     /* init debug */
116     if (loglevel) {
117         logfile = fopen(DEBUG_LOGFILE, "w");
118         if (!logfile) {
119             perror(DEBUG_LOGFILE);
120             exit(1);
121         }
122         setvbuf(logfile, NULL, _IOLBF, 0);
123     }
124
125     /* Zero out regs */
126     memset(regs, 0, sizeof(struct target_pt_regs));
127
128     /* Zero out image_info */
129     memset(info, 0, sizeof(struct image_info));
130
131     if(elf_exec(filename, argv+optind, environ, regs, info) != 0) {
132         printf("Error loading %s\n", filename);
133         exit(1);
134     }
135     
136     if (loglevel) {
137         fprintf(logfile, "start_brk   0x%08lx\n" , info->start_brk);
138         fprintf(logfile, "end_code    0x%08lx\n" , info->end_code);
139         fprintf(logfile, "start_code  0x%08lx\n" , info->start_code);
140         fprintf(logfile, "end_data    0x%08lx\n" , info->end_data);
141         fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
142         fprintf(logfile, "brk         0x%08lx\n" , info->brk);
143         fprintf(logfile, "esp         0x%08lx\n" , regs->esp);
144         fprintf(logfile, "eip         0x%08lx\n" , regs->eip);
145     }
146
147     target_set_brk((char *)info->brk);
148     syscall_init();
149
150     env = cpu_x86_init();
151
152     env->regs[R_EAX] = regs->eax;
153     env->regs[R_EBX] = regs->ebx;
154     env->regs[R_ECX] = regs->ecx;
155     env->regs[R_EDX] = regs->edx;
156     env->regs[R_ESI] = regs->esi;
157     env->regs[R_EDI] = regs->edi;
158     env->regs[R_EBP] = regs->ebp;
159     env->regs[R_ESP] = regs->esp;
160     env->segs[R_CS] = __USER_CS;
161     env->segs[R_DS] = __USER_DS;
162     env->segs[R_ES] = __USER_DS;
163     env->segs[R_SS] = __USER_DS;
164     env->segs[R_FS] = __USER_DS;
165     env->segs[R_GS] = __USER_DS;
166     env->pc = regs->eip;
167
168 #if 0
169     LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
170     LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
171     LDT[__USER_CS >> 3].lpSelBase = NULL;
172
173     LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
174     LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
175     LDT[__USER_DS >> 3].lpSelBase = NULL;
176 #endif
177
178     for(;;) {
179         int err;
180         uint8_t *pc;
181         
182         err = cpu_x86_exec(env);
183         switch(err) {
184         case EXCP0D_GPF:
185             pc = (uint8_t *)env->pc;
186             if (pc[0] == 0xcd && pc[1] == 0x80) {
187                 /* syscall */
188                 env->pc += 2;
189                 env->regs[R_EAX] = do_syscall(env->regs[R_EAX], 
190                                               env->regs[R_EBX],
191                                               env->regs[R_ECX],
192                                               env->regs[R_EDX],
193                                               env->regs[R_ESI],
194                                               env->regs[R_EDI],
195                                               env->regs[R_EBP]);
196             } else {
197                 goto trap_error;
198             }
199             break;
200         default:
201         trap_error:
202             fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n", 
203                     (long)env->pc, err);
204             abort();
205         }
206     }
207     return 0;
208 }