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.


added the framework for interupt delivery
[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
187     
188     if (0) {
189       
190       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
191       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
192       
193       rip = (ulong_t)(void*)&BuzzVM;
194       //  rip -= 0x10000;
195       //    rip = (addr_t)(void*)&exit_test;
196       //  rip -= 0x2000;
197       vm_info.rip = rip;
198       rsp = (addr_t)Alloc_Page();
199       
200       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
201       
202             
203     } else if (0) {
204       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
205       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
206       
207       /*
208         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
209         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
210         0x100000, HOST_REGION_PHYSICAL_MEMORY);
211         add_shadow_region(&(vm_info.mem_map),ent);
212       */
213
214       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
215
216       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
217       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
218       
219       /*
220         vm_info.cr0 = 0;
221         vm_info.cs.base=0xf000;
222         vm_info.cs.limit=0xffff;
223       */
224       //vm_info.rip = 0xfff0;
225
226       vm_info.rip = 0;
227       vm_info.vm_regs.rsp = 0x0;
228     } else {
229       int i;
230       void * region_start;
231
232  
233       PrintDebug("Guest Size: %lu\n", bootInfo->guest_size);
234
235       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
236
237       if (layout->magic != MAGIC_CODE) {
238         PrintDebug("Layout Magic Mismatch (0x%x)\n", layout->magic);
239       }
240
241       PrintDebug("%d layout regions\n", layout->num_regions);
242
243       region_start = (void *)&(layout->regions[layout->num_regions]);
244
245       PrintDebug("region start = 0x%x\n", region_start);
246
247       for (i = 0; i < layout->num_regions; i++) {
248         struct layout_region * reg = &(layout->regions[i]);
249         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
250         void * guest_mem = Allocate_VMM_Pages(num_pages);
251
252         PrintDebug("Layout Region %d bytes\n", reg->length);
253         memcpy(guest_mem, region_start, reg->length);
254         
255         SerialMemDump((unsigned char *)(guest_mem), 16);
256
257         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
258
259         PrintDebug("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
260
261         region_start += reg->length;
262       }
263       
264       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
265       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
266       if (add_shadow_region_passthrough(&vm_info, 0xc7000, 0xf0000, (addr_t)Allocate_VMM_Pages(41)) == -1) {
267         PrintDebug("Error adding shadow region\n");
268       }
269
270       print_shadow_map(&(vm_info.mem_map));
271
272       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write);
273       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial);
274
275       hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial);
276       hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial);
277       hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial);
278       hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial);
279
280       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial);
281       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial);
282       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug);
283       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial);
284
285       vm_info.rip = 0xfff0;
286       vm_info.vm_regs.rsp = 0x0;
287     }
288
289     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
290     (vmm_ops).init_guest(&vm_info);
291     PrintBoth("Starting Guest\n");
292     Clear_Screen();
293     (vmm_ops).start_guest(&vm_info);
294
295     return 0;
296
297 }