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