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 full io support
[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.30 $
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) {
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) {
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) {
121   PrintBoth("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
122   switch (length) {
123
124   case 1:
125     PrintBoth(">0x%.2x\n", *(char*)src);
126     break;
127   case 2:
128     PrintBoth(">0x%.4x\n", *(ushort_t*)src);
129     break;
130   case 4:
131     PrintBoth(">0x%.8x\n", *(uint_t*)src);
132     break;
133   default:
134     break;
135   }
136
137   //  SerialMemDump(src, length);
138   return length;
139 }
140
141
142 void BuzzVM()
143 {
144   int x;
145   int j;
146   unsigned char init;
147
148 #if 0  
149   __asm__ __volatile__ (
150     "popf"
151     );
152     
153 #endif
154     
155   PrintBoth("Starting To Buzz\n");
156
157   init=MyIn_Byte(SPEAKER_PORT);
158
159   while (1) {
160     MyOut_Byte(SPEAKER_PORT, init|0x2);
161     for (j=0;j<1000000;j++) { 
162       x+=j;
163     }
164     MyOut_Byte(SPEAKER_PORT, init);
165     for (j=0;j<1000000;j++) { 
166       x+=j;
167     }
168   }
169 }
170
171
172
173
174
175
176
177
178 void Buzzer(ulong_t arg) {
179   ulong_t *doIBuzz = (ulong_t*)arg;
180   while (1) {
181     // Quick and dirty hack to save my hearing...
182     // I'm not too worried about timing, so I'll deal with concurrency later...
183     if (*doIBuzz == 1) {
184       Buzz(1000000, 10);
185     }
186   }
187
188 }
189
190
191
192
193
194 void Keyboard_Listener(ulong_t arg) {
195   ulong_t * doIBuzz = (ulong_t*)arg;
196   Keycode key_press;
197
198   Print("Press F4 to turn on/off the speaker\n");
199
200   while ((key_press = Wait_For_Key())) {    
201     if (key_press == KEY_F4) {
202       Print("\nToggling Speaker Port\n");
203       SerialPrintLevel(100,"\nToggling Speaker Port\n");
204       *doIBuzz = (*doIBuzz + 1) % 2;
205     } else if (key_press == KEY_F5) {
206       Print("\nMachine Restart\n");
207       SerialPrintLevel(100,"\nMachine Restart\n");
208       machine_real_restart();
209     }
210   }
211   return;
212 }
213
214
215
216 extern char BSS_START, BSS_END;
217
218 extern char end;
219
220
221 /* This is an ugly hack to get at the VM  memory */
222 ulong_t vm_range_start;
223 ulong_t vm_range_end;
224 ulong_t guest_kernel_start;
225 ulong_t guest_kernel_end;
226 /* ** */
227
228
229 int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte)
230 {
231   uint_t address;
232
233   for (address=start;address<start+length;address+=PAGE_SIZE) { 
234     void *page;
235     pte_t pte = template_pte;
236     
237     page=Alloc_Page();
238     KASSERT(page);
239     
240     pte.pageBaseAddr=PAGE_ALLIGNED_ADDR(page);
241
242     KASSERT(MapPage((void*)address,&pte,1));
243   }
244   
245   return 0;
246 }
247     
248
249
250 /*
251  * Kernel C code entry point.
252  * Initializes kernel subsystems, mounts filesystems,
253  * and spawns init process.
254  */
255 void Main(struct Boot_Info* bootInfo)
256 {
257   struct Kernel_Thread * key_thread;
258   struct Kernel_Thread * spkr_thread;
259
260   ulong_t doIBuzz = 0;
261
262   Init_BSS();
263   Init_Screen();
264
265
266   Init_Serial();
267   Init_Mem(bootInfo);
268   Init_CRC32();
269   Init_TSS();
270   Init_Interrupts();
271   Init_Scheduler();
272   Init_Traps();
273   Init_Timer();
274   Init_Keyboard();
275   Init_VM(bootInfo);
276   Init_Paging();
277
278   //  Init_IDE();
279
280   // Print("Done; stalling\n");
281
282
283   
284 #if 1
285   SerialPrint("Dumping VM kernel Code (first 128 bytes @ 0x%x)\n", 0x100000);
286   SerialMemDump((unsigned char *)0x100000, 256);
287   /*
288     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
289     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
290   */
291 #endif
292
293 #if 0
294   SerialPrint("Dumping BIOS code f0000-fffff\n\n");
295   SerialMemDump((unsigned char *)0xf0000, 65536);
296   /*
297     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
298     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
299   */
300 #endif
301
302 #if 1
303   SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
304   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
305   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
306
307 #endif
308
309   {
310     struct vmm_os_hooks os_hooks;
311     struct vmm_ctrl_ops vmm_ops;
312     struct guest_info vm_info;
313     addr_t rsp;
314     addr_t rip;
315
316     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
317     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
318     memset(&vm_info, 0, sizeof(struct guest_info));
319
320     os_hooks.print_debug = &PrintBoth;
321     os_hooks.print_info = &Print;
322     os_hooks.print_trace = &SerialPrint;
323     os_hooks.allocate_pages = &Allocate_VMM_Pages;
324     os_hooks.free_page = &Free_VMM_Page;
325     os_hooks.malloc = &VMM_Malloc;
326     os_hooks.free = &VMM_Free;
327     os_hooks.vaddr_to_paddr = &Identity;
328     os_hooks.paddr_to_vaddr = &Identity;
329
330
331     //   DumpGDT();
332     Init_VMM(&os_hooks, &vmm_ops);
333   
334     init_shadow_map(&(vm_info.mem_map));
335     init_shadow_page_state(&(vm_info.shdw_pg_state));
336     vm_info.page_mode = SHADOW_PAGING;
337
338     vm_info.cpu_mode = REAL;
339
340     init_vmm_io_map(&(vm_info.io_map));
341
342     
343     if (0) {
344       
345       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
346       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
347       
348       rip = (ulong_t)(void*)&BuzzVM;
349       //  rip -= 0x10000;
350       //    rip = (addr_t)(void*)&exit_test;
351       //  rip -= 0x2000;
352       vm_info.rip = rip;
353       rsp = (addr_t)Alloc_Page();
354       
355       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
356       
357             
358     } else {
359       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
360       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
361       
362       shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
363       init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
364                                   0x100000, HOST_REGION_PHYSICAL_MEMORY);
365       add_shadow_region(&(vm_info.mem_map),ent);
366
367       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
368       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
369       
370       /*
371       vm_info.cr0 = 0;
372       vm_info.cs.base=0xf000;
373       vm_info.cs.limit=0xffff;
374       */
375       //vm_info.rip = 0xfff0;
376
377       vm_info.rip = 0;
378       vm_info.vm_regs.rsp = 0x0;
379     }
380
381     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
382     (vmm_ops).init_guest(&vm_info);
383     PrintBoth("Starting Guest\n");
384     (vmm_ops).start_guest(&vm_info);
385   }
386
387
388   
389
390
391   TODO("Write a Virtual Machine Monitor");
392   
393
394   Exit(0);
395 }