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