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