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.


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