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.


Main now launches a separate thread that spins - this results in halt exits not resum...
[palacios.git] / palacios / src / geekos / vm.c
1 #include <geekos/vmm_stubs.h>
2 #include <palacios/vmm.h>
3 #include <geekos/debug.h>
4 #include <geekos/serial.h>
5 #include <geekos/vm.h>
6 #include <geekos/screen.h>
7
8 #include <devices/generic.h>
9 #include <devices/nvram.h>
10 #include <devices/timer.h>
11 #include <devices/simple_pic.h>
12 #include <devices/8259a.h>
13 #include <devices/8254.h>
14 #include <devices/keyboard.h>
15 #include <devices/serial.h>
16
17 #include <palacios/vmm_intr.h>
18 #include <palacios/vmm_dev_mgr.h>
19 #include <palacios/vmm_time.h>
20
21 #define SPEAKER_PORT 0x61
22
23 static inline void VM_Out_Byte(ushort_t port, uchar_t value)
24 {
25     __asm__ __volatile__ (
26         "outb %b0, %w1"
27         :
28         : "a" (value), "Nd" (port)
29     );
30 }
31
32 /*
33  * Read a byte from an I/O port.
34  */
35 static inline uchar_t VM_In_Byte(ushort_t port)
36 {
37     uchar_t value;
38
39     __asm__ __volatile__ (
40         "inb %w1, %b0"
41         : "=a" (value)
42         : "Nd" (port)
43     );
44
45     return value;
46 }
47
48
49
50
51 int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
52
53   if (length != 1) {
54     return 0;
55   }
56
57   *(uchar_t*)dst = VM_In_Byte(port);    
58   return 1;
59 }
60
61
62
63 int IO_Write(ushort_t port, void * src, uint_t length, void * priv_data) {
64
65   if (length != 1) {
66     return 0;
67   }
68
69   VM_Out_Byte(port, *(uchar_t *)src);    
70
71   return 1;
72 }
73
74
75 int IO_Read_to_Serial(ushort_t port, void * dst, uint_t length, void * priv_data) {
76   PrintBoth("Input from Guest on port %d (0x%x) Length=%d\n", port, port, length);
77   
78   return 0;
79 }
80
81
82 char * bochs_debug_buf = NULL;
83 int bochs_debug_offset = 0;
84
85 char * bochs_info_buf = NULL;
86 int bochs_info_offset = 0;
87
88
89 int IO_BOCHS_debug(ushort_t port, void * src, uint_t length, void * priv_data) {
90   if (!bochs_debug_buf) {
91     bochs_debug_buf = (char*)Malloc(1024);
92   }
93
94   bochs_debug_buf[bochs_debug_offset++] = *(char*)src;
95
96   if ((*(char*)src == 0xa) ||  (bochs_debug_offset == 1023)) {
97     SerialPrint("BOCHSDEBUG>%s", bochs_debug_buf);
98     memset(bochs_debug_buf, 0, 1024);
99     bochs_debug_offset = 0;
100   }
101
102   return length;
103 }
104
105 int IO_BOCHS_info(ushort_t port, void * src, uint_t length, void * priv_data) {
106   if (!bochs_info_buf) {
107     bochs_info_buf = (char*)Malloc(1024);
108   }
109
110   bochs_info_buf[bochs_info_offset++] = *(char*)src;
111
112   if ((*(char*)src == 0xa) ||  (bochs_info_offset == 1023)) {
113     SerialPrint("BOCHSINFO>%s", bochs_info_buf);
114     memset(bochs_info_buf, 0, 1024);
115     bochs_info_offset = 0;
116   }
117
118   return length;
119 }
120
121
122 int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, void * priv_data) {
123  SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
124   switch (length) {
125
126   case 1:
127     SerialPrint(">0x%.2x\n", *(char*)src);
128     break;
129   case 2:
130     SerialPrint(">0x%.4x\n", *(ushort_t*)src);
131     break;
132   case 4:
133     SerialPrint(">0x%.8x\n", *(uint_t*)src);
134     break;
135   default:
136     break;
137   }
138
139   //  SerialMemDump(src, length);
140   return length;
141 }
142
143
144
145 void BuzzVM()
146 {
147   int x;
148   int j;
149   unsigned char init;
150
151 #if 0  
152   __asm__ __volatile__ (
153     "popf"
154     );
155     
156 #endif
157     
158   PrintBoth("Starting To Buzz\n");
159
160   init=VM_In_Byte(SPEAKER_PORT);
161
162   while (1) {
163     VM_Out_Byte(SPEAKER_PORT, init|0x2);
164     for (j=0;j<1000000;j++) { 
165       x+=j;
166     }
167     VM_Out_Byte(SPEAKER_PORT, init);
168     for (j=0;j<1000000;j++) { 
169       x+=j;
170     }
171   }
172 }
173
174
175
176 int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
177   memcpy(dst, (void*)guest_addr, length);
178   return length;
179 }
180
181 int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
182   memcpy((void*)guest_addr, src, length);
183   return length;
184 }
185
186
187
188 /* We need a configuration mechanism, so we can wrap this completely inside the VMM code, 
189  * with no pollution into the HOST OS
190  */
191
192 int RunVMM(struct Boot_Info * bootInfo) {
193
194     struct vmm_os_hooks os_hooks;
195     struct vmm_ctrl_ops vmm_ops;
196     struct guest_info vm_info;
197     addr_t rsp;
198     addr_t rip;
199
200
201
202     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
203     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
204     memset(&vm_info, 0, sizeof(struct guest_info));
205
206     os_hooks.print_debug = &SerialPrint;
207     os_hooks.print_info = &Print;
208     os_hooks.print_trace = &SerialPrint;
209     os_hooks.allocate_pages = &Allocate_VMM_Pages;
210     os_hooks.free_page = &Free_VMM_Page;
211     os_hooks.malloc = &VMM_Malloc;
212     os_hooks.free = &VMM_Free;
213     os_hooks.vaddr_to_paddr = &Identity;
214     os_hooks.paddr_to_vaddr = &Identity;
215     os_hooks.hook_interrupt = &hook_irq_stub;
216     os_hooks.ack_irq = &ack_irq;
217     os_hooks.get_cpu_khz = &get_cpu_khz;
218
219     Init_VMM(&os_hooks, &vmm_ops);
220   
221
222     /* MOVE THIS TO AN INIT GUEST ROUTINE */
223    
224     
225     v3_init_time(&(vm_info.time_state));
226     init_shadow_map(&(vm_info.mem_map));
227
228     if ((vmm_ops).has_nested_paging()) {
229       vm_info.shdw_pg_mode = NESTED_PAGING;
230     } else {
231       init_shadow_page_state(&(vm_info.shdw_pg_state));
232       vm_info.shdw_pg_mode = SHADOW_PAGING;
233     }
234
235     vm_info.cpu_mode = REAL;
236     vm_info.mem_mode = PHYSICAL_MEM;
237
238     //init_irq_map(&(vm_info.irq_map));
239     init_vmm_io_map(&(vm_info.io_map));
240     init_interrupt_state(&vm_info);
241
242     dev_mgr_init(&(vm_info.dev_mgr));
243     /* ** */
244     
245     if (0) {
246       
247       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
248       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
249       
250       rip = (ulong_t)(void*)&BuzzVM;
251       //  rip -= 0x10000;
252       //    rip = (addr_t)(void*)&exit_test;
253       //  rip -= 0x2000;
254       vm_info.rip = rip;
255       rsp = (addr_t)Alloc_Page();
256       
257       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
258       
259             
260     } else if (0) {
261       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
262       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
263       
264       /*
265         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
266         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
267         0x100000, HOST_REGION_PHYSICAL_MEMORY);
268         add_shadow_region(&(vm_info.mem_map),ent);
269       */
270
271       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
272
273       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
274       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
275       
276       /*
277         vm_info.cr0 = 0;
278         vm_info.cs.base=0xf000;
279         vm_info.cs.limit=0xffff;
280       */
281       //vm_info.rip = 0xfff0;
282
283       vm_info.rip = 0;
284       vm_info.vm_regs.rsp = 0x0;
285     } else {
286       int i;
287       void * region_start;
288
289  
290       PrintBoth("Guest Size: %lu\n", bootInfo->guest_size);
291
292       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
293
294       if (layout->magic != MAGIC_CODE) {
295         PrintBoth("Layout Magic Mismatch (0x%x)\n", layout->magic);
296       }
297
298       PrintBoth("%d layout regions\n", layout->num_regions);
299
300       region_start = (void *)&(layout->regions[layout->num_regions]);
301
302       PrintBoth("region start = 0x%x\n", region_start);
303
304       for (i = 0; i < layout->num_regions; i++) {
305         struct layout_region * reg = &(layout->regions[i]);
306         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
307         void * guest_mem = Allocate_VMM_Pages(num_pages);
308
309         PrintBoth("Layout Region %d bytes\n", reg->length);
310         memcpy(guest_mem, region_start, reg->length);
311         
312         SerialMemDump((unsigned char *)(guest_mem), 16);
313
314         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
315
316         PrintBoth("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
317
318         region_start += reg->length;
319       }
320       
321       //     
322       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
323       
324       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
325       //hook_guest_mem(&vm_info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL);
326
327
328       // TEMP
329       //add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
330
331       if (1) {
332         add_shadow_region_passthrough(&vm_info, 0xc7000, 0xc8000, (addr_t)Allocate_VMM_Pages(1));
333         if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
334           PrintBoth("Error adding shadow region\n");
335         }
336       } else {
337         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
338         add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, 0xc8000);
339       }
340
341
342       //add_shadow_region_passthrough(&vm_info, 0x100000, 0x2000000, (addr_t)Allocate_VMM_Pages(8192));
343       add_shadow_region_passthrough(&vm_info, 0x100000, 0x1000000, (addr_t)Allocate_VMM_Pages(4096));
344
345       // test - give linux accesss to PCI space - PAD
346       add_shadow_region_passthrough(&vm_info, 0xc0000000,0xffffffff,0xc0000000);
347
348
349       print_shadow_map(&(vm_info.mem_map));
350
351       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
352       //hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
353
354
355       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
356       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
357       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_info, NULL);
358       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_BOCHS_debug, NULL);
359
360       {
361         
362         struct vm_device * nvram = create_nvram();
363         //struct vm_device * timer = create_timer();
364         struct vm_device * pic = create_pic();
365         struct vm_device * keyboard = create_keyboard();
366         struct vm_device * pit = create_pit(); 
367         //struct vm_device * serial = create_serial();
368
369
370 #define GENERIC 1
371
372 #if GENERIC
373         generic_port_range_type range[] = {
374 #if 0
375           {0x00, 0x07, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channels 0,1,2,3 (address, counter)
376           {0xc0, 0xc7, GENERIC_PRINT_AND_
377 IGNORE},   // DMA 2 channels 4,5,6,7 (address, counter)
378           {0x87, 0x87, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 0 page register
379           {0x83, 0x83, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 1 page register
380           {0x81, 0x81, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 2 page register
381           {0x82, 0x82, GENERIC_PRINT_AND_IGNORE},   // DMA 1 channel 3 page register
382           {0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 4 page register
383           {0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 5 page register
384           {0x89, 0x89, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 6 page register
385           {0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE},   // DMA 2 channel 7 page register
386           {0x08, 0x0f, GENERIC_PRINT_AND_IGNORE},   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
387           {0xd0, 0xde, GENERIC_PRINT_AND_IGNORE},   // DMA 2 misc registers
388 #endif
389
390           
391           {0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 1
392           {0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE},      // COM 2
393           {0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 3
394           {0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE},      // COM 4
395           
396 #if 0
397             {0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
398             {0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 1
399             {0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 0
400             {0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH}, // IDE 0
401 #endif
402
403
404 #if 0
405           {0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (base,statusa/statusb,DOR)
406           {0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (mainstat/datarate,data)
407           {0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE}, // Primary floppy controller (DIR)
408           {0x370, 0x372, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (base,statusa/statusb,DOR)
409           {0x374, 0x375, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (mainstat/datarate,data)
410           {0x377, 0x377, GENERIC_PRINT_AND_IGNORE}, // Secondary floppy controller (DIR)
411
412 #endif
413
414           //      {0x378, 0x400, GENERIC_PRINT_AND_IGNORE}
415
416           {0,0,0},  // sentinal - must be last
417
418         };
419
420         struct vm_device * generic = create_generic(range,NULL,NULL);
421
422 #endif
423
424         attach_device(&(vm_info), nvram);
425         //attach_device(&(vm_info), timer);
426         attach_device(&(vm_info), pic);
427         attach_device(&(vm_info), pit);
428         attach_device(&(vm_info), keyboard);
429         // attach_device(&(vm_info), serial);
430
431
432 #if GENERIC
433         // Important that this be attached last!
434         attach_device(&(vm_info), generic);
435
436 #endif
437
438         PrintDebugDevMgr(&(vm_info.dev_mgr));
439       }
440
441       // give keyboard interrupts to vm
442       // no longer needed since we have a keyboard device
443       //hook_irq(&vm_info, 1);
444       
445 #if 1
446       // give floppy controller to vm
447       hook_irq(&vm_info, 6);
448 #endif
449
450       //primary ide
451       hook_irq(&vm_info, 14);
452
453       // secondary ide
454       hook_irq(&vm_info, 15);
455
456
457
458       vm_info.rip = 0xfff0;
459       vm_info.vm_regs.rsp = 0x0;
460     }
461
462
463     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
464     (vmm_ops).init_guest(&vm_info);
465     PrintBoth("Starting Guest\n");
466     //Clear_Screen();
467     (vmm_ops).start_guest(&vm_info);
468
469     return 0;
470 }