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.


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