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.


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