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.


*** empty log message ***
[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.14 $
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
30 #include <geekos/debug.h>
31 #include <geekos/vmm.h>
32
33 #include <geekos/gdt.h>
34
35 #include <geekos/vmm_sizes.h>
36 #include <geekos/vmm_stubs.h>
37
38 /*
39   static inline unsigned int cpuid_ecx(unsigned int op)
40   {
41   unsigned int eax, ecx;
42   
43   __asm__("cpuid"
44   : "=a" (eax), "=c" (ecx)
45   : "0" (op)
46   : "bx", "dx" );
47   
48   return ecx;
49   }
50 */
51
52
53
54 extern void Get_MSR(ulong_t msr, unsigned int *val1, unsigned int *val2);
55 extern void Set_MSR(ulong_t msr, ulong_t val1, ulong_t val2);
56 extern uint_t Get_EIP();
57 extern uint_t Get_ESP();
58 extern uint_t Get_EBP();
59
60
61 int foo=42;
62
63 #define SPEAKER_PORT 0x61
64
65
66 void Buzz(unsigned delay, unsigned num)
67 {
68   volatile int x;
69   int i,j;
70   unsigned char init;
71   
72   init=In_Byte(SPEAKER_PORT);
73
74   for (i=0;i<num;i++) { 
75     Out_Byte(SPEAKER_PORT, init|0x2);
76     for (j=0;j<delay;j++) { 
77       x+=j;
78     }
79     Out_Byte(SPEAKER_PORT, init);
80     for (j=0;j<delay;j++) { 
81       x+=j;
82     }
83   }
84 }
85
86 inline void MyOut_Byte(ushort_t port, uchar_t value)
87 {
88     __asm__ __volatile__ (
89         "outb %b0, %w1"
90         :
91         : "a" (value), "Nd" (port)
92     );
93 }
94
95 /*
96  * Read a byte from an I/O port.
97  */
98 inline uchar_t MyIn_Byte(ushort_t port)
99 {
100     uchar_t value;
101
102     __asm__ __volatile__ (
103         "inb %w1, %b0"
104         : "=a" (value)
105         : "Nd" (port)
106     );
107
108     return value;
109 }
110
111
112 extern void MyBuzzVM();
113
114 #define MYBUZZVM_START MyBuzzVM
115 #define MYBUZZVM_LEN   0x3d
116
117 void BuzzVM()
118 {
119   int x;
120   int j;
121   unsigned char init;
122   
123     
124   SerialPrint("Starting To Buzz\n");
125
126   init=MyIn_Byte(SPEAKER_PORT);
127
128   while (1) {
129     MyOut_Byte(SPEAKER_PORT, init|0x2);
130     for (j=0;j<1000000;j++) { 
131       x+=j;
132     }
133     MyOut_Byte(SPEAKER_PORT, init);
134     for (j=0;j<1000000;j++) { 
135       x+=j;
136     }
137   }
138 }
139
140 extern void RunVM();
141
142 int vmRunning = 0;
143
144 void RunVM() {
145   vmRunning = 1;
146
147   while(1);
148 }
149
150
151
152
153
154
155 void Buzzer(ulong_t arg) {
156   ulong_t *doIBuzz = (ulong_t*)arg;
157   while (1) {
158     // Quick and dirty hack to save my hearing...
159     // I'm not too worried about timing, so I'll deal with concurrency later...
160     if (*doIBuzz == 1) {
161       Buzz(1000000, 10);
162     }
163   }
164
165 }
166
167
168
169
170
171 void Hello(ulong_t arg)
172 {
173   char *b="hello ";
174   char byte;
175   short port=0xe9;
176   int i;
177   while(1){
178     for (i=0;i<6;i++) { 
179       byte=b[i];
180       __asm__ __volatile__ ("outb %b0, %w1" : : "a"(byte), "Nd"(port) );
181     }
182   }
183 }
184
185 void Keyboard_Listener(ulong_t arg) {
186   ulong_t * doIBuzz = (ulong_t*)arg;
187   Keycode key_press;
188
189   Print("Press F4 to turn on/off the speaker\n");
190
191   while ((key_press = Wait_For_Key())) {    
192     if (key_press == KEY_F4) {
193       Print("\nToggling Speaker Port\n");
194       SerialPrintLevel(100,"\nToggling Speaker Port\n");
195       *doIBuzz = (*doIBuzz + 1) % 2;
196     } else if (key_press == KEY_F5) {
197       Print("\nMachine Restart\n");
198       SerialPrintLevel(100,"\nMachine Restart\n");
199       machine_real_restart();
200     }
201   }
202   return;
203 }
204
205
206
207 extern char BSS_START, BSS_END;
208
209 extern char end;
210
211 /*
212 void VM_Thread(ulong_t arg) 
213 {
214   int ret;
215   struct VMDescriptor *vm = (struct VMDescriptor *) arg;
216
217   SerialPrintLevel(100,"VM_Thread: Launching VM with (entry_ip=%x, exit_eip=%x, guest_esp=%x)\n",
218               vm->entry_ip, vm->exit_eip, vm->guest_esp);
219
220   SerialPrintLevel(100,"VM_Thread: You should see nothing further from me\n");
221
222
223   ret = VMLaunch(vm);
224
225
226   SerialPrintLevel(100,"VM_Thread: uh oh...");
227
228   switch (ret) { 
229   case VMX_SUCCESS:
230     SerialPrintLevel(100,"Normal VMExit Occurred\n");
231     break;
232   case VMX_FAIL_INVALID:
233     SerialPrintLevel(100,"Possibile invalid VMCS (%.8x)\n", ret);
234     break;
235   case VMX_FAIL_VALID:
236     SerialPrintLevel(100,"Valid VMCS, errorcode recorded in VMCS\n");
237     break;
238   case VMM_ERROR:
239     SerialPrintLevel(100,"VMM Error\n");
240     break;
241   default:
242     SerialPrintLevel(100,"VMLaunch returned unknown error (%.8x)\n", ret);
243     break;
244   }
245   
246   SerialPrintLevel(100,"VM_Thread: Spinning\n");
247   while (1) {}
248     
249 }
250 */
251
252
253
254 int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte)
255 {
256   uint_t address;
257
258   for (address=start;address<start+length;address+=PAGE_SIZE) { 
259     void *page;
260     pte_t pte = template_pte;
261     
262     page=Alloc_Page();
263     KASSERT(page);
264     
265     pte.pageBaseAddr=PAGE_ALLIGNED_ADDR(page);
266
267     KASSERT(MapPage((void*)address,&pte,1));
268   }
269   
270   return 0;
271 }
272     
273
274
275 /*
276  * Kernel C code entry point.
277  * Initializes kernel subsystems, mounts filesystems,
278  * and spawns init process.
279  */
280 void Main(struct Boot_Info* bootInfo)
281 {
282   struct Kernel_Thread * key_thread;
283   struct Kernel_Thread * spkr_thread;
284   // struct Kernel_Thread * vm_thread;
285   // struct VMDescriptor    vm;
286
287   ulong_t doIBuzz = 0;
288
289   Init_BSS();
290   Init_Screen();
291
292
293   Init_Serial();
294   Init_Mem(bootInfo);
295   Init_CRC32();
296   Init_TSS();
297   Init_Interrupts();
298   Init_Scheduler();
299   Init_Traps();
300   Init_Timer();
301   Init_Keyboard();
302   Init_VM(bootInfo);
303   Init_Paging();
304
305   //  Init_IDE();
306
307   Print("Done; stalling\n");
308
309
310   
311 #if 0
312   SerialPrint("Dumping VM kernel Code (first 512 bytes @ 0x%x)\n",VM_KERNEL_START);
313   SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
314   /*
315     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
316     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
317   */
318 #endif
319
320 #if 0
321   SerialPrint("Dumping GUEST KERNEL CODE (first 512*2 bytes @ 0x100000)\n");
322   SerialMemDump((unsigned char *)0x100000, 512*2);
323 #endif
324
325
326
327   {
328     struct vmm_os_hooks os_hooks;
329     struct vmm_ctrl_ops vmm_ops;
330     guest_info_t vm_info;
331     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
332     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
333     memset(&vm_info, 0, sizeof(guest_info_t));
334
335     os_hooks.print_debug = &PrintBoth;
336     os_hooks.print_info = &Print;
337     os_hooks.print_trace = &SerialPrint;
338     os_hooks.Allocate_Pages = &Allocate_VMM_Pages;
339     os_hooks.Free_Page = &Free_VMM_Page;
340     
341     Init_VMM(&os_hooks, &vmm_ops);
342   
343
344
345     vm_info.rip = (ullong_t)(void*)&BuzzVM;
346     vm_info.rsp = (ulong_t)Alloc_Page();
347
348     SerialPrint("Initializing Guest\n");
349     (vmm_ops).init_guest(&vm_info);
350     SerialPrint("Starting Guest\n");
351     (vmm_ops).start_guest(&vm_info);
352     
353   }
354
355
356   SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
357   
358   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
359   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
360
361
362
363
364
365
366   // Try to launch a real VM
367
368
369   // We now map pages of physical memory into where we are going
370   // to slap the vmxassist, bios, and vgabios code
371   /*
372   pte_t template_pte;
373
374   template_pte.present=1;
375   template_pte.flags=VM_WRITE|VM_READ|VM_USER|VM_EXEC;
376   template_pte.accessed=0;
377   template_pte.dirty=0;
378   template_pte.pteAttribute=0;
379   template_pte.globalPage=0;
380   template_pte.kernelInfo=0;
381   
382   SerialPrintLevel(1000,"Allocating Pages for VM kernel\n");
383   
384 #define SEGLEN (1024*64)
385
386   AllocateAndMapPagesForRange(START_OF_VM+0x100000, VM_KERNEL_LENGTH / 512, template_pte);
387 */
388   // Now we should be copying into actual memory
389
390   //SerialPrintLevel(1000,"Copying VM code from %x to %x (%d bytes)\n", VM_KERNEL_START, START_OF_VM+0x100000,VM_KERNEL_LENGTH);
391   //memcpy((char*)(START_OF_VM+0x100000),(char*)VM_KERNEL_START,VM_KERNEL_LENGTH);
392
393   //SerialPrintLevel(1000, "VM copied\n");
394
395   /*
396   // jump into vmxassist
397   vm.entry_ip=(uint_t)0x00107fd0;
398   vm.exit_eip=0;
399   // Put the stack at 512K
400   vm.guest_esp=(uint_t)4096 + 8192 - 4;
401   *(unsigned int *)(vm.guest_esp) = 1024 * 1024;
402   vm.guest_esp -= 4;
403   *(unsigned int *)(vm.guest_esp) = 8;
404   vm.guest_esp -= 4;
405   *(unsigned int *)(vm.guest_esp) = vm.guest_esp + 4;;
406   vm.guest_esp -= 4;
407   *(unsigned int *)(vm.guest_esp) = vm.entry_ip;
408   //  vm.guest_esp -= 4;
409
410  
411   SerialMemDump((unsigned char *)vm.entry_ip, 512);
412   */
413  
414   // vm_thread = Start_Kernel_Thread(VM_Thread, (ulong_t)&vm,PRIORITY_NORMAL,false);
415
416   
417   SerialPrintLevel(1000,"Next: setup GDT\n");
418
419
420
421   TODO("Write a Virtual Machine Monitor");
422   
423   
424   /* Now this thread is done. */
425   Exit(0);
426 }