]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/x86emu/examples/test/emu.c
0c0ec48e77e1b94613d2c1504628b7d918dd7d4f
[l4.git] / l4 / pkg / x86emu / examples / test / emu.c
1 /*
2  * (c) 2008-2009 Technische Universität Dresden
3  * This file is part of TUD:OS and distributed under the terms of the
4  * GNU General Public License 2.
5  * Please see the COPYING-GPL-2 file for details.
6  */
7
8 #include <l4/x86emu/x86emu.h>
9
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <stdlib.h>
13
14 #include <l4/sys/types.h>
15 #include <l4/sys/ipc.h>
16 #include <l4/sys/kdebug.h>
17 #include <l4/util/rdtsc.h>
18
19 void
20 printk(const char *format,...)
21 {
22   va_list list;
23   va_start(list, format);
24   vprintf(format, list);
25   va_end(list);
26 }
27
28 //#define TEST
29
30 static unsigned emu_mem;
31
32 static u8   X86API my_inb(X86EMU_pioAddr addr);
33 static u16  X86API my_inw(X86EMU_pioAddr addr);
34 static u32  X86API my_inl(X86EMU_pioAddr addr);
35 static void X86API my_outb(X86EMU_pioAddr addr, u8 val);
36 static void X86API my_outw(X86EMU_pioAddr addr, u16 val);
37 static void X86API my_outl(X86EMU_pioAddr addr, u32 val);
38 static u8   X86API my_rdb(u32 addr);
39 static u16  X86API my_rdw(u32 addr);
40 static u32  X86API my_rdl(u32 addr);
41 static void X86API my_wrb(u32 addr, u8 val);
42 static void X86API my_wrw(u32 addr, u16 val);
43 static void X86API my_wrl(u32 addr, u32 val);
44
45
46 static u8
47 X86API my_inb(X86EMU_pioAddr addr)
48 {
49   int r;
50   asm volatile ("inb %w1, %b0" : "=a" (r) : "d" (addr));
51   return r;
52 }
53
54 static u16
55 X86API my_inw(X86EMU_pioAddr addr)
56 {
57   u16 r;
58   asm volatile ("inw %w1, %w0" : "=a" (r) : "d" (addr));
59   return r;
60 }
61
62 static u32
63 X86API my_inl(X86EMU_pioAddr addr)
64 {
65   u32 r;
66   asm volatile ("inl %w1, %0" : "=a" (r) : "d" (addr));
67   return r;
68 }
69
70 static void
71 X86API my_outb(X86EMU_pioAddr addr, u8 val)
72 {
73 //  printf("%04x:%04x outb %x -> %x\n", M.x86.R_CS, M.x86.R_IP, val, addr);
74   asm volatile ("outb %b0, %w1" : "=a" (val), "=d" (addr)
75                                 : "a" (val), "d" (addr));
76 }
77
78 static void
79 X86API my_outw(X86EMU_pioAddr addr, u16 val)
80 {
81 //  printf("%04x:%04x outw %x -> %x\n", M.x86.R_CS, M.x86.R_IP, val, addr);
82   asm volatile ("outw %w0, %w1" : "=a" (val), "=d" (addr)
83                                 : "a" (val), "d" (addr));
84 }
85
86 static void
87 X86API my_outl(X86EMU_pioAddr addr, u32 val)
88 {
89 //  printf("%04x:%04x outl %x -> %x\n", M.x86.R_CS, M.x86.R_IP, val, addr);
90   asm volatile ("outl %0, %w1" : "=a"(val), "=d" (addr) 
91                                : "a" (val), "d" (addr));
92 }
93
94 static u8
95 X86API my_rdb(u32 addr)
96 {
97   return *(u32*)(M.mem_base + addr);
98 }
99
100 static u16
101 X86API my_rdw(u32 addr)
102 {
103   return *(u16*)(M.mem_base + addr);
104 }
105
106 static u32
107 X86API my_rdl(u32 addr)
108 {
109   return *(u32*)(M.mem_base + addr);
110 }
111
112 static void 
113 X86API my_wrb(u32 addr, u8 val)
114 {
115   *(u8*)(M.mem_base + addr) = val;
116 }
117
118 static void 
119 X86API my_wrw(u32 addr, u16 val)
120 {
121   *(u16*)(M.mem_base + addr) = val;
122 }
123
124 static void 
125 X86API my_wrl(u32 addr, u32 val)
126 {
127   *(u32*)(M.mem_base + addr) = val;
128 }
129
130 X86EMU_pioFuncs my_pioFuncs =
131 {
132   my_inb,
133   my_inw,
134   my_inl,
135   my_outb,
136   my_outw,
137   my_outl
138 };
139
140 X86EMU_memFuncs my_memFuncs =
141 {
142   my_rdb,
143   my_rdw,
144   my_rdl,
145   my_wrb,
146   my_wrw,
147   my_wrl
148 };
149
150 static void
151 map_emu_page(unsigned get_address, unsigned map_address)
152 {
153   int error;
154   l4_umword_t dummy;
155   l4_msgdope_t result;
156   
157   error = l4_ipc_call(rmgr_pager_id,
158                       L4_IPC_SHORT_MSG, get_address, 0,
159                       L4_IPC_MAPMSG((l4_umword_t)emu_mem+map_address,
160                                     L4_LOG2_PAGESIZE),
161                       &dummy, &dummy,
162                       L4_IPC_NEVER, &result);
163   if (error)
164     {
165       printf("Error %02x receiving page at %08x\n", error, get_address);
166       exit(-1);
167     }
168   if (!l4_ipc_fpage_received(result))
169     {
170       printf("Can't receive page at %08x\n", get_address);
171       exit(-1);
172     }
173 }
174
175 int 
176 main(int argc, char **argv)
177 {
178 #define EMU_MEM_SIZE (16*1024)
179
180   extern void *_end;
181   int error;
182   l4_umword_t address;
183 #ifdef TEST
184   l4_cpu_time_t start, stop;
185 #endif
186
187   rmgr_init();
188   l4_calibrate_tsc();
189
190   emu_mem = (((l4_umword_t)&_end)+2*L4_PAGESIZE-1) & L4_PAGEMASK;
191   
192   printf("emu_mem = %08x\n", emu_mem);
193
194   /* build 16-bit address space starting at emu_mem */
195
196   /* map bios data segment */
197   if ((error = rmgr_get_page0((void*)emu_mem)))
198     {
199       printf("Error %02x mapping page 0\n", error & 0xff);
200       exit(-1);
201     }
202
203   /* map VGA bios code segment */
204   for (address=0xC0000; address < 0xD0000; address += L4_PAGESIZE)
205     map_emu_page(address, address);
206
207   /* map system BIOS code segment */
208   for (address=0xF0000; address < 0x100000; address += L4_PAGESIZE)
209     map_emu_page(address, address);
210
211   /* map some page for code */
212   map_emu_page(0xfffffffc, L4_PAGESIZE);
213
214   /* int 10 */
215   *((unsigned char*)emu_mem+L4_PAGESIZE  ) = 0xcd;
216   *((unsigned char*)emu_mem+L4_PAGESIZE+1) = 0x10;
217   /* hlt */
218   *((unsigned char*)emu_mem+L4_PAGESIZE+2) = 0xf4;
219
220   M.mem_base = emu_mem;
221   M.mem_size = 1024*1024;
222   M.x86.debug = 0;
223   
224   X86EMU_setupPioFuncs(&my_pioFuncs);
225   X86EMU_setupMemFuncs(&my_memFuncs);
226
227 #ifdef TEST
228
229   M.x86.R_AX = 0x4F02;
230   M.x86.R_BX = 0x114;
231   M.x86.R_SP = L4_PAGESIZE;
232   M.x86.R_IP = 0;
233   M.x86.R_CS = L4_PAGESIZE >> 4;
234   M.x86.R_DS = M.x86.R_CS;
235   M.x86.R_ES = M.x86.R_CS;
236   M.x86.R_SS = M.x86.R_CS;
237
238   printf("Starting emulator\n");
239
240   start = l4_rdtsc();
241   X86EMU_exec();
242   stop  = l4_rdtsc();
243
244   stop -= start;
245   
246   printf("Stopping emulator (time was %d ms)\n",
247       ((unsigned int)l4_tsc_to_ns(stop))/1000000);
248
249 #else
250
251     {
252       l4_threadid_t sender;
253       l4_msgdope_t result;
254       struct
255         {
256           l4_fpage_t fp;
257           l4_msgdope_t size_dope;
258           l4_msgdope_t send_dope;
259           l4_umword_t dw[12];
260         } msg;
261
262 #if 0
263       if (!names_register("X86EMU"))
264         {
265           printf("Error registering at names\n");
266           exit(-1);
267         }
268 #endif
269           
270       for (;;)
271         {
272           msg.size_dope = L4_IPC_DOPE(12, 0);
273           msg.send_dope = L4_IPC_DOPE(12, 0);
274   
275           error = l4_ipc_wait(&sender, 
276                               &msg, &msg.dw[0], &msg.dw[1],
277                               L4_IPC_NEVER, &result);
278
279           while (!error)
280             {
281               M.x86.R_EAX = msg.dw[0];
282               M.x86.R_EBX = msg.dw[1];
283               M.x86.R_ECX = msg.dw[2];
284               M.x86.R_EDX = msg.dw[3];
285               M.x86.R_ESI = msg.dw[4];
286               M.x86.R_EDI = msg.dw[5];
287               M.x86.R_EBP = msg.dw[6];
288               M.x86.R_EIP = msg.dw[7];
289               M.x86.R_EFLG = msg.dw[8];
290           
291               M.x86.R_CS = msg.dw[9];
292               M.x86.R_DS = msg.dw[10];
293               M.x86.R_ES = msg.dw[11];
294           
295               M.x86.R_ESP = L4_PAGESIZE;
296               M.x86.R_SS = 0x0100;
297   
298               printf("Starting emulator:\n"
299                      "eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n"
300                      "esi=%08lx edi=%08lx ebp=%08lx esp=%08lx\n"
301                      "eip=%08lx eflags=%08lx\n"
302                      "cs=%04x ds=%04x es=%04x ss=%04x\n",
303                      M.x86.R_EAX, M.x86.R_EBX, M.x86.R_ECX, M.x86.R_EDX,
304                      M.x86.R_ESI, M.x86.R_EDI, M.x86.R_EBP, M.x86.R_ESP,
305                      M.x86.R_EIP, M.x86.R_EFLG,
306                      M.x86.R_CS, M.x86.R_DS, M.x86.R_ES, M.x86.R_SS);
307
308               enter_kdebug("stop");
309
310 #if 0
311               start = l4_rdtsc();
312               X86EMU_exec();
313               stop  = l4_rdtsc();
314
315               stop -= start;
316   
317               printf("Stopping emulator (time was %d ms)\n",
318                   ((unsigned int)l4_tsc_to_ns(stop))/1000000);
319 #endif
320
321               msg.dw[0] = M.x86.R_EAX;
322               msg.dw[1] = M.x86.R_EBX;
323               msg.dw[2] = M.x86.R_ECX;
324               msg.dw[3] = M.x86.R_EDX;
325               msg.dw[4] = M.x86.R_ESI;
326               msg.dw[5] = M.x86.R_EDI;
327               msg.dw[6] = M.x86.R_EBP;
328               msg.dw[7] = M.x86.R_EIP;
329               msg.dw[8] = M.x86.R_EFLG;
330           
331               msg.dw[9] = M.x86.R_CS;
332               msg.dw[10] = M.x86.R_DS;
333               msg.dw[11] = M.x86.R_ES;
334               
335               error = l4_ipc_reply_and_wait(sender, 
336                                             &msg, msg.dw[0], msg.dw[1],
337                                             &sender,
338                                             &msg, &msg.dw[0], &msg.dw[1],
339                                             L4_IPC_SEND_TIMEOUT_0,
340                                             &result);
341             }
342         }
343     }
344   
345 #endif
346   
347   return 0;
348 }
349