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.12 $
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   init=MyIn_Byte(SPEAKER_PORT);
125
126   while (1) {
127     MyOut_Byte(SPEAKER_PORT, init|0x2);
128     for (j=0;j<1000000;j++) { 
129       x+=j;
130     }
131     MyOut_Byte(SPEAKER_PORT, init);
132     for (j=0;j<1000000;j++) { 
133       x+=j;
134     }
135   }
136 }
137
138 extern void RunVM();
139
140 int vmRunning = 0;
141
142 void RunVM() {
143   vmRunning = 1;
144
145   while(1);
146 }
147
148
149
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
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
251
252 int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte)
253 {
254   uint_t address;
255
256   for (address=start;address<start+length;address+=PAGE_SIZE) { 
257     void *page;
258     pte_t pte = template_pte;
259     
260     page=Alloc_Page();
261     KASSERT(page);
262     
263     pte.pageBaseAddr=PAGE_ALLIGNED_ADDR(page);
264
265     KASSERT(MapPage((void*)address,&pte,1));
266   }
267   
268   return 0;
269 }
270     
271
272
273 /*
274  * Kernel C code entry point.
275  * Initializes kernel subsystems, mounts filesystems,
276  * and spawns init process.
277  */
278 void Main(struct Boot_Info* bootInfo)
279 {
280   struct Kernel_Thread * key_thread;
281   struct Kernel_Thread * spkr_thread;
282   // struct Kernel_Thread * vm_thread;
283   // struct VMDescriptor    vm;
284
285   ulong_t doIBuzz = 0;
286
287   Init_BSS();
288   Init_Screen();
289
290
291   Init_Serial();
292   Init_Mem(bootInfo);
293   Init_CRC32();
294   Init_TSS();
295   Init_Interrupts();
296   Init_Scheduler();
297   Init_Traps();
298   Init_Timer();
299   Init_Keyboard();
300   Init_VM(bootInfo);
301   Init_Paging();
302
303   //  Init_IDE();
304
305   Print("Done; stalling\n");
306
307
308   
309 #if 0
310   SerialPrint("Dumping VM kernel Code (first 512 bytes @ 0x%x)\n",VM_KERNEL_START);
311   SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
312   /*
313     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
314     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
315   */
316 #endif
317
318 #if 1
319   SerialPrint("Dumping GUEST KERNEL CODE (first 512*2 bytes @ 0x100000)\n");
320   SerialMemDump((unsigned char *)0x100000, 512*2);
321 #endif
322
323
324
325   
326   struct vmm_os_hooks os_hooks;
327   os_hooks.print_debug = &PrintBoth;
328   os_hooks.print_info = &Print;
329   os_hooks.print_trace = &SerialPrint;
330   os_hooks.Allocate_Pages = &Allocate_VMM_Pages;
331   os_hooks.Free_Page = &Free_VMM_Page;
332
333   Init_VMM(&os_hooks);
334
335   
336   SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
337   
338   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
339   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
340
341
342
343
344
345
346   // Try to launch a real VM
347
348
349   // We now map pages of physical memory into where we are going
350   // to slap the vmxassist, bios, and vgabios code
351   /*
352   pte_t template_pte;
353
354   template_pte.present=1;
355   template_pte.flags=VM_WRITE|VM_READ|VM_USER|VM_EXEC;
356   template_pte.accessed=0;
357   template_pte.dirty=0;
358   template_pte.pteAttribute=0;
359   template_pte.globalPage=0;
360   template_pte.kernelInfo=0;
361   
362   SerialPrintLevel(1000,"Allocating Pages for VM kernel\n");
363   
364 #define SEGLEN (1024*64)
365
366   AllocateAndMapPagesForRange(START_OF_VM+0x100000, VM_KERNEL_LENGTH / 512, template_pte);
367 */
368   // Now we should be copying into actual memory
369
370   //SerialPrintLevel(1000,"Copying VM code from %x to %x (%d bytes)\n", VM_KERNEL_START, START_OF_VM+0x100000,VM_KERNEL_LENGTH);
371   //memcpy((char*)(START_OF_VM+0x100000),(char*)VM_KERNEL_START,VM_KERNEL_LENGTH);
372
373   //SerialPrintLevel(1000, "VM copied\n");
374
375   /*
376   // jump into vmxassist
377   vm.entry_ip=(uint_t)0x00107fd0;
378   vm.exit_eip=0;
379   // Put the stack at 512K
380   vm.guest_esp=(uint_t)4096 + 8192 - 4;
381   *(unsigned int *)(vm.guest_esp) = 1024 * 1024;
382   vm.guest_esp -= 4;
383   *(unsigned int *)(vm.guest_esp) = 8;
384   vm.guest_esp -= 4;
385   *(unsigned int *)(vm.guest_esp) = vm.guest_esp + 4;;
386   vm.guest_esp -= 4;
387   *(unsigned int *)(vm.guest_esp) = vm.entry_ip;
388   //  vm.guest_esp -= 4;
389
390  
391   SerialMemDump((unsigned char *)vm.entry_ip, 512);
392   */
393  
394   // vm_thread = Start_Kernel_Thread(VM_Thread, (ulong_t)&vm,PRIORITY_NORMAL,false);
395
396   
397   SerialPrintLevel(1000,"Next: setup GDT\n");
398
399
400
401   TODO("Write a Virtual Machine Monitor");
402   
403   
404   /* Now this thread is done. */
405   Exit(0);
406 }