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.
8 #include <l4/x86emu/x86emu.h>
14 #include <l4/sys/types.h>
15 #include <l4/sys/ipc.h>
16 #include <l4/sys/kdebug.h>
17 #include <l4/util/rdtsc.h>
20 printk(const char *format,...)
23 va_start(list, format);
24 vprintf(format, list);
30 static unsigned emu_mem;
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);
47 X86API my_inb(X86EMU_pioAddr addr)
50 asm volatile ("inb %w1, %b0" : "=a" (r) : "d" (addr));
55 X86API my_inw(X86EMU_pioAddr addr)
58 asm volatile ("inw %w1, %w0" : "=a" (r) : "d" (addr));
63 X86API my_inl(X86EMU_pioAddr addr)
66 asm volatile ("inl %w1, %0" : "=a" (r) : "d" (addr));
71 X86API my_outb(X86EMU_pioAddr addr, u8 val)
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));
79 X86API my_outw(X86EMU_pioAddr addr, u16 val)
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));
87 X86API my_outl(X86EMU_pioAddr addr, u32 val)
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));
95 X86API my_rdb(u32 addr)
97 return *(u32*)(M.mem_base + addr);
101 X86API my_rdw(u32 addr)
103 return *(u16*)(M.mem_base + addr);
107 X86API my_rdl(u32 addr)
109 return *(u32*)(M.mem_base + addr);
113 X86API my_wrb(u32 addr, u8 val)
115 *(u8*)(M.mem_base + addr) = val;
119 X86API my_wrw(u32 addr, u16 val)
121 *(u16*)(M.mem_base + addr) = val;
125 X86API my_wrl(u32 addr, u32 val)
127 *(u32*)(M.mem_base + addr) = val;
130 X86EMU_pioFuncs my_pioFuncs =
140 X86EMU_memFuncs my_memFuncs =
151 map_emu_page(unsigned get_address, unsigned map_address)
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,
162 L4_IPC_NEVER, &result);
165 printf("Error %02x receiving page at %08x\n", error, get_address);
168 if (!l4_ipc_fpage_received(result))
170 printf("Can't receive page at %08x\n", get_address);
176 main(int argc, char **argv)
178 #define EMU_MEM_SIZE (16*1024)
184 l4_cpu_time_t start, stop;
190 emu_mem = (((l4_umword_t)&_end)+2*L4_PAGESIZE-1) & L4_PAGEMASK;
192 printf("emu_mem = %08x\n", emu_mem);
194 /* build 16-bit address space starting at emu_mem */
196 /* map bios data segment */
197 if ((error = rmgr_get_page0((void*)emu_mem)))
199 printf("Error %02x mapping page 0\n", error & 0xff);
203 /* map VGA bios code segment */
204 for (address=0xC0000; address < 0xD0000; address += L4_PAGESIZE)
205 map_emu_page(address, address);
207 /* map system BIOS code segment */
208 for (address=0xF0000; address < 0x100000; address += L4_PAGESIZE)
209 map_emu_page(address, address);
211 /* map some page for code */
212 map_emu_page(0xfffffffc, L4_PAGESIZE);
215 *((unsigned char*)emu_mem+L4_PAGESIZE ) = 0xcd;
216 *((unsigned char*)emu_mem+L4_PAGESIZE+1) = 0x10;
218 *((unsigned char*)emu_mem+L4_PAGESIZE+2) = 0xf4;
220 M.mem_base = emu_mem;
221 M.mem_size = 1024*1024;
224 X86EMU_setupPioFuncs(&my_pioFuncs);
225 X86EMU_setupMemFuncs(&my_memFuncs);
231 M.x86.R_SP = L4_PAGESIZE;
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;
238 printf("Starting emulator\n");
246 printf("Stopping emulator (time was %d ms)\n",
247 ((unsigned int)l4_tsc_to_ns(stop))/1000000);
252 l4_threadid_t sender;
257 l4_msgdope_t size_dope;
258 l4_msgdope_t send_dope;
263 if (!names_register("X86EMU"))
265 printf("Error registering at names\n");
272 msg.size_dope = L4_IPC_DOPE(12, 0);
273 msg.send_dope = L4_IPC_DOPE(12, 0);
275 error = l4_ipc_wait(&sender,
276 &msg, &msg.dw[0], &msg.dw[1],
277 L4_IPC_NEVER, &result);
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];
291 M.x86.R_CS = msg.dw[9];
292 M.x86.R_DS = msg.dw[10];
293 M.x86.R_ES = msg.dw[11];
295 M.x86.R_ESP = L4_PAGESIZE;
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);
308 enter_kdebug("stop");
317 printf("Stopping emulator (time was %d ms)\n",
318 ((unsigned int)l4_tsc_to_ns(stop))/1000000);
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;
331 msg.dw[9] = M.x86.R_CS;
332 msg.dw[10] = M.x86.R_DS;
333 msg.dw[11] = M.x86.R_ES;
335 error = l4_ipc_reply_and_wait(sender,
336 &msg, msg.dw[0], msg.dw[1],
338 &msg, &msg.dw[0], &msg.dw[1],
339 L4_IPC_SEND_TIMEOUT_0,