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.


lots of changes...
[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/nvram.h>
9 #include <devices/timer.h>
10 #include <devices/simple_pic.h>
11 #include <devices/8259a.h>
12
13 #include <palacios/vmm_intr.h>
14 #include <palacios/vmm_dev_mgr.h>
15
16 #define SPEAKER_PORT 0x61
17
18
19
20
21 inline void VM_Out_Byte(ushort_t port, uchar_t value)
22 {
23     __asm__ __volatile__ (
24         "outb %b0, %w1"
25         :
26         : "a" (value), "Nd" (port)
27     );
28 }
29
30 /*
31  * Read a byte from an I/O port.
32  */
33 inline uchar_t VM_In_Byte(ushort_t port)
34 {
35     uchar_t value;
36
37     __asm__ __volatile__ (
38         "inb %w1, %b0"
39         : "=a" (value)
40         : "Nd" (port)
41     );
42
43     return value;
44 }
45
46
47
48 int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
49
50   if (length != 1) {
51     return 0;
52   }
53
54   *(uchar_t*)dst = VM_In_Byte(port);    
55   return 1;
56 }
57
58
59
60 int IO_Write(ushort_t port, void * src, uint_t length, void * priv_data) {
61
62   if (length != 1) {
63     return 0;
64   }
65
66   VM_Out_Byte(port, *(uchar_t *)src);    
67
68   return 1;
69 }
70
71
72 int IO_Read_to_Serial(ushort_t port, void * dst, uint_t length, void * priv_data) {
73   PrintBoth("Input from Guest on port %d (0x%x) Length=%d\n", port, port, length);
74   
75   return 0;
76 }
77
78
79 char * bochs_debug_buf = NULL;
80 int bochs_debug_offset = 0;
81
82
83 int IO_BOCHS_debug(ushort_t port, void * src, uint_t length, void * priv_data) {
84   if (!bochs_debug_buf) {
85     bochs_debug_buf = (char*)Malloc(1024);
86   }
87
88   bochs_debug_buf[bochs_debug_offset++] = *(char*)src;
89
90   if ((*(char*)src == 0xa) ||  (bochs_debug_offset == 1023)) {
91     SerialPrint("BOCHS>%s", bochs_debug_buf);
92     memset(bochs_debug_buf, 0, 1024);
93     bochs_debug_offset = 0;
94   }
95
96   return length;
97 }
98
99
100 int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, void * priv_data) {
101  SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
102   switch (length) {
103
104   case 1:
105     SerialPrint(">0x%.2x\n", *(char*)src);
106     break;
107   case 2:
108     SerialPrint(">0x%.4x\n", *(ushort_t*)src);
109     break;
110   case 4:
111     SerialPrint(">0x%.8x\n", *(uint_t*)src);
112     break;
113   default:
114     break;
115   }
116
117   //  SerialMemDump(src, length);
118   return length;
119 }
120
121
122
123 void BuzzVM()
124 {
125   int x;
126   int j;
127   unsigned char init;
128
129 #if 0  
130   __asm__ __volatile__ (
131     "popf"
132     );
133     
134 #endif
135     
136   PrintBoth("Starting To Buzz\n");
137
138   init=VM_In_Byte(SPEAKER_PORT);
139
140   while (1) {
141     VM_Out_Byte(SPEAKER_PORT, init|0x2);
142     for (j=0;j<1000000;j++) { 
143       x+=j;
144     }
145     VM_Out_Byte(SPEAKER_PORT, init);
146     for (j=0;j<1000000;j++) { 
147       x+=j;
148     }
149   }
150 }
151
152
153
154
155 /* We need a configuration mechanism, so we can wrap this completely inside the VMM code, 
156  * with no pollution into the HOST OS
157  */
158
159 int RunVMM(struct Boot_Info * bootInfo) {
160
161     struct vmm_os_hooks os_hooks;
162     struct vmm_ctrl_ops vmm_ops;
163     struct guest_info vm_info;
164     addr_t rsp;
165     addr_t rip;
166
167
168
169     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
170     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
171     memset(&vm_info, 0, sizeof(struct guest_info));
172
173     os_hooks.print_debug = &SerialPrint;
174     os_hooks.print_info = &Print;
175     os_hooks.print_trace = &SerialPrint;
176     os_hooks.allocate_pages = &Allocate_VMM_Pages;
177     os_hooks.free_page = &Free_VMM_Page;
178     os_hooks.malloc = &VMM_Malloc;
179     os_hooks.free = &VMM_Free;
180     os_hooks.vaddr_to_paddr = &Identity;
181     os_hooks.paddr_to_vaddr = &Identity;
182     os_hooks.hook_interrupt = &hook_irq_stub;
183     os_hooks.ack_irq = &ack_irq;
184  
185
186     Init_VMM(&os_hooks, &vmm_ops);
187   
188
189     /* MOVE THIS TO AN INIT GUEST ROUTINE */
190     init_shadow_map(&(vm_info.mem_map));
191     init_shadow_page_state(&(vm_info.shdw_pg_state));
192     vm_info.page_mode = SHADOW_PAGING;
193
194     vm_info.cpu_mode = REAL;
195
196     //init_irq_map(&(vm_info.irq_map));
197     init_vmm_io_map(&(vm_info.io_map));
198     init_interrupt_state(&vm_info);
199
200     dev_mgr_init(&(vm_info.dev_mgr));
201     /* ** */
202     
203     if (0) {
204       
205       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
206       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
207       
208       rip = (ulong_t)(void*)&BuzzVM;
209       //  rip -= 0x10000;
210       //    rip = (addr_t)(void*)&exit_test;
211       //  rip -= 0x2000;
212       vm_info.rip = rip;
213       rsp = (addr_t)Alloc_Page();
214       
215       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
216       
217             
218     } else if (0) {
219       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
220       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
221       
222       /*
223         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
224         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
225         0x100000, HOST_REGION_PHYSICAL_MEMORY);
226         add_shadow_region(&(vm_info.mem_map),ent);
227       */
228
229       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
230
231       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
232       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
233       
234       /*
235         vm_info.cr0 = 0;
236         vm_info.cs.base=0xf000;
237         vm_info.cs.limit=0xffff;
238       */
239       //vm_info.rip = 0xfff0;
240
241       vm_info.rip = 0;
242       vm_info.vm_regs.rsp = 0x0;
243     } else {
244       int i;
245       void * region_start;
246
247  
248       PrintBoth("Guest Size: %lu\n", bootInfo->guest_size);
249
250       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
251
252       if (layout->magic != MAGIC_CODE) {
253         PrintBoth("Layout Magic Mismatch (0x%x)\n", layout->magic);
254       }
255
256       PrintBoth("%d layout regions\n", layout->num_regions);
257
258       region_start = (void *)&(layout->regions[layout->num_regions]);
259
260       PrintBoth("region start = 0x%x\n", region_start);
261
262       for (i = 0; i < layout->num_regions; i++) {
263         struct layout_region * reg = &(layout->regions[i]);
264         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
265         void * guest_mem = Allocate_VMM_Pages(num_pages);
266
267         PrintBoth("Layout Region %d bytes\n", reg->length);
268         memcpy(guest_mem, region_start, reg->length);
269         
270         SerialMemDump((unsigned char *)(guest_mem), 16);
271
272         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
273
274         PrintBoth("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
275
276         region_start += reg->length;
277       }
278       
279       //     
280       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
281       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
282       
283
284
285       // TEMP
286       //add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
287
288       if (1) {
289         add_shadow_region_passthrough(&vm_info, 0xc7000, 0xc8000, (addr_t)Allocate_VMM_Pages(1));
290         if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
291           PrintBoth("Error adding shadow region\n");
292         }
293       } else {
294         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
295         add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, 0xc8000);
296       }
297
298
299       //add_shadow_region_passthrough(&vm_info, 0x100000, 0x2000000, (addr_t)Allocate_VMM_Pages(8192));
300       add_shadow_region_passthrough(&vm_info, 0x100000, 0x1000000, (addr_t)Allocate_VMM_Pages(4096));
301
302
303       print_shadow_map(&(vm_info.mem_map));
304
305       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
306       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
307
308
309       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
310       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
311       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);
312       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
313
314       {
315         struct vm_device * nvram = create_nvram();
316         //struct vm_device * timer = create_timer();
317         struct vm_device * pic = create_pic();
318
319         attach_device(&(vm_info), nvram);
320         //attach_device(&(vm_info), timer);
321         attach_device(&(vm_info), pic);
322
323         PrintDebugDevMgr(&(vm_info.dev_mgr));
324       }
325
326       hook_irq(&vm_info, 6);
327       hook_irq(&vm_info, 14);
328       hook_irq(&vm_info, 15);
329
330
331       vm_info.rip = 0xfff0;
332       vm_info.vm_regs.rsp = 0x0;
333     }
334
335     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
336     (vmm_ops).init_guest(&vm_info);
337     PrintBoth("Starting Guest\n");
338     //Clear_Screen();
339     (vmm_ops).start_guest(&vm_info);
340
341     return 0;
342 }