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.


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