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.


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