Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added support for in/out instructions
[palacios.git] / palacios / src / geekos / main.c
1 /*
2  * GeekOS C code entry point
3  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
4  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
5  * Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
6  * $Revision: 1.29 $
7  * 
8  * This is free software.  You are permitted to use,
9  * redistribute, and modify it as specified in the file "COPYING".
10  */
11
12 #include <geekos/bootinfo.h>
13 #include <geekos/string.h>
14 #include <geekos/screen.h>
15 #include <geekos/mem.h>
16 #include <geekos/crc32.h>
17 #include <geekos/tss.h>
18 #include <geekos/int.h>
19 #include <geekos/kthread.h>
20 #include <geekos/trap.h>
21 #include <geekos/timer.h>
22 #include <geekos/keyboard.h>
23 #include <geekos/io.h>
24 #include <geekos/serial.h>
25 #include <geekos/reboot.h>
26 #include <geekos/mem.h>
27 #include <geekos/paging.h>
28 #include <geekos/ide.h>
29 #include <geekos/malloc.h>
30
31 #include <geekos/debug.h>
32 #include <geekos/vmm.h>
33
34
35 #include <geekos/gdt.h>
36
37
38 #include <geekos/vmm_stubs.h>
39
40
41 #define SPEAKER_PORT 0x61
42
43
44 void Buzz(unsigned delay, unsigned num)
45 {
46   volatile int x;
47   int i,j;
48   unsigned char init;
49   
50   init=In_Byte(SPEAKER_PORT);
51
52   for (i=0;i<num;i++) { 
53     Out_Byte(SPEAKER_PORT, init|0x2);
54     for (j=0;j<delay;j++) { 
55       x+=j;
56     }
57     Out_Byte(SPEAKER_PORT, init);
58     for (j=0;j<delay;j++) { 
59       x+=j;
60     }
61   }
62 }
63
64 inline void MyOut_Byte(ushort_t port, uchar_t value)
65 {
66     __asm__ __volatile__ (
67         "outb %b0, %w1"
68         :
69         : "a" (value), "Nd" (port)
70     );
71 }
72
73 /*
74  * Read a byte from an I/O port.
75  */
76 inline uchar_t MyIn_Byte(ushort_t port)
77 {
78     uchar_t value;
79
80     __asm__ __volatile__ (
81         "inb %w1, %b0"
82         : "=a" (value)
83         : "Nd" (port)
84     );
85
86     return value;
87 }
88
89
90
91 int IO_Read(ushort_t port, void * dst, uint_t length, uint_t io_width) {
92   uchar_t * iter = dst;
93   uint_t i;
94
95   for (i = 0; i < length; i++) {
96     *iter = MyIn_Byte(port);    
97     iter++;
98   }
99   
100   return 0;
101 }
102
103
104
105 int IO_Write(ushort_t port, void * src, uint_t length, uint_t io_width) {
106   uchar_t * iter = src;
107   uint_t i;
108
109
110   for (i = 0; i < length; i++) {
111     MyOut_Byte(port, *iter);    
112     iter++;
113   }
114
115   return 0;
116 }
117
118
119
120 int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, uint_t io_width) {
121   SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
122   SerialMemDump(src, length);
123   return length;
124 }
125
126
127 void BuzzVM()
128 {
129   int x;
130   int j;
131   unsigned char init;
132
133 #if 0  
134   __asm__ __volatile__ (
135     "popf"
136     );
137     
138 #endif
139     
140   PrintBoth("Starting To Buzz\n");
141
142   init=MyIn_Byte(SPEAKER_PORT);
143
144   while (1) {
145     MyOut_Byte(SPEAKER_PORT, init|0x2);
146     for (j=0;j<1000000;j++) { 
147       x+=j;
148     }
149     MyOut_Byte(SPEAKER_PORT, init);
150     for (j=0;j<1000000;j++) { 
151       x+=j;
152     }
153   }
154 }
155
156
157
158
159
160
161
162
163 void Buzzer(ulong_t arg) {
164   ulong_t *doIBuzz = (ulong_t*)arg;
165   while (1) {
166     // Quick and dirty hack to save my hearing...
167     // I'm not too worried about timing, so I'll deal with concurrency later...
168     if (*doIBuzz == 1) {
169       Buzz(1000000, 10);
170     }
171   }
172
173 }
174
175
176
177
178
179 void Keyboard_Listener(ulong_t arg) {
180   ulong_t * doIBuzz = (ulong_t*)arg;
181   Keycode key_press;
182
183   Print("Press F4 to turn on/off the speaker\n");
184
185   while ((key_press = Wait_For_Key())) {    
186     if (key_press == KEY_F4) {
187       Print("\nToggling Speaker Port\n");
188       SerialPrintLevel(100,"\nToggling Speaker Port\n");
189       *doIBuzz = (*doIBuzz + 1) % 2;
190     } else if (key_press == KEY_F5) {
191       Print("\nMachine Restart\n");
192       SerialPrintLevel(100,"\nMachine Restart\n");
193       machine_real_restart();
194     }
195   }
196   return;
197 }
198
199
200
201 extern char BSS_START, BSS_END;
202
203 extern char end;
204
205
206 /* This is an ugly hack to get at the VM  memory */
207 ulong_t vm_range_start;
208 ulong_t vm_range_end;
209 ulong_t guest_kernel_start;
210 ulong_t guest_kernel_end;
211 /* ** */
212
213
214 int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte)
215 {
216   uint_t address;
217
218   for (address=start;address<start+length;address+=PAGE_SIZE) { 
219     void *page;
220     pte_t pte = template_pte;
221     
222     page=Alloc_Page();
223     KASSERT(page);
224     
225     pte.pageBaseAddr=PAGE_ALLIGNED_ADDR(page);
226
227     KASSERT(MapPage((void*)address,&pte,1));
228   }
229   
230   return 0;
231 }
232     
233
234
235 /*
236  * Kernel C code entry point.
237  * Initializes kernel subsystems, mounts filesystems,
238  * and spawns init process.
239  */
240 void Main(struct Boot_Info* bootInfo)
241 {
242   struct Kernel_Thread * key_thread;
243   struct Kernel_Thread * spkr_thread;
244
245   ulong_t doIBuzz = 0;
246
247   Init_BSS();
248   Init_Screen();
249
250
251   Init_Serial();
252   Init_Mem(bootInfo);
253   Init_CRC32();
254   Init_TSS();
255   Init_Interrupts();
256   Init_Scheduler();
257   Init_Traps();
258   Init_Timer();
259   Init_Keyboard();
260   Init_VM(bootInfo);
261   Init_Paging();
262
263   //  Init_IDE();
264
265   // Print("Done; stalling\n");
266
267
268   
269 #if 1
270   SerialPrint("Dumping VM kernel Code (first 128 bytes @ 0x%x)\n", 0x100000);
271   SerialMemDump((unsigned char *)0x100000, 256);
272   /*
273     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
274     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
275   */
276 #endif
277
278 #if 0
279   SerialPrint("Dumping BIOS code f0000-fffff\n\n");
280   SerialMemDump((unsigned char *)0xf0000, 65536);
281   /*
282     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
283     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
284   */
285 #endif
286
287 #if 1
288   SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
289   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
290   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
291
292 #endif
293
294   {
295     struct vmm_os_hooks os_hooks;
296     struct vmm_ctrl_ops vmm_ops;
297     struct guest_info vm_info;
298     addr_t rsp;
299     addr_t rip;
300
301     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
302     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
303     memset(&vm_info, 0, sizeof(struct guest_info));
304
305     os_hooks.print_debug = &PrintBoth;
306     os_hooks.print_info = &Print;
307     os_hooks.print_trace = &SerialPrint;
308     os_hooks.allocate_pages = &Allocate_VMM_Pages;
309     os_hooks.free_page = &Free_VMM_Page;
310     os_hooks.malloc = &VMM_Malloc;
311     os_hooks.free = &VMM_Free;
312     os_hooks.vaddr_to_paddr = &Identity;
313     os_hooks.paddr_to_vaddr = &Identity;
314
315
316     //   DumpGDT();
317     Init_VMM(&os_hooks, &vmm_ops);
318   
319     init_shadow_map(&(vm_info.mem_map));
320     init_shadow_page_state(&(vm_info.shdw_pg_state));
321     vm_info.page_mode = SHADOW_PAGING;
322
323     vm_info.cpu_mode = REAL;
324
325     init_vmm_io_map(&(vm_info.io_map));
326
327     
328     if (0) {
329       
330       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
331       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
332       
333       rip = (ulong_t)(void*)&BuzzVM;
334       //  rip -= 0x10000;
335       //    rip = (addr_t)(void*)&exit_test;
336       //  rip -= 0x2000;
337       vm_info.rip = rip;
338       rsp = (addr_t)Alloc_Page();
339       
340       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
341       
342             
343     } else {
344       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
345       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
346       
347       shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
348       init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
349                                   0x100000, HOST_REGION_PHYSICAL_MEMORY);
350       add_shadow_region(&(vm_info.mem_map),ent);
351
352       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
353       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
354       
355       /*
356       vm_info.cr0 = 0;
357       vm_info.cs.base=0xf000;
358       vm_info.cs.limit=0xffff;
359       */
360       //vm_info.rip = 0xfff0;
361
362       vm_info.rip = 0;
363       vm_info.vm_regs.rsp = 0x0;
364     }
365
366     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
367     (vmm_ops).init_guest(&vm_info);
368     PrintBoth("Starting Guest\n");
369     (vmm_ops).start_guest(&vm_info);
370   }
371
372
373   
374
375
376   TODO("Write a Virtual Machine Monitor");
377   
378
379   Exit(0);
380 }