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.


75714c43e5da30640e4c7b38eba75390e0a7ad39
[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 #include <devices/simple_pic.h>
11 #include <devices/8259a.h>
12 #include <palacios/vmm_intr.h>
13
14
15 #define SPEAKER_PORT 0x61
16
17
18
19
20 inline void VM_Out_Byte(ushort_t port, uchar_t value)
21 {
22     __asm__ __volatile__ (
23         "outb %b0, %w1"
24         :
25         : "a" (value), "Nd" (port)
26     );
27 }
28
29 /*
30  * Read a byte from an I/O port.
31  */
32 inline uchar_t VM_In_Byte(ushort_t port)
33 {
34     uchar_t value;
35
36     __asm__ __volatile__ (
37         "inb %w1, %b0"
38         : "=a" (value)
39         : "Nd" (port)
40     );
41
42     return value;
43 }
44
45
46
47 int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
48
49   if (length != 1) {
50     return 0;
51   }
52
53   *(uchar_t*)dst = VM_In_Byte(port);    
54   return 1;
55 }
56
57
58
59 int IO_Write(ushort_t port, void * src, uint_t length, void * priv_data) {
60
61   if (length != 1) {
62     return 0;
63   }
64
65   VM_Out_Byte(port, *(uchar_t *)src);    
66
67   return 1;
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
165
166     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
167     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
168     memset(&vm_info, 0, sizeof(struct guest_info));
169
170     os_hooks.print_debug = &SerialPrint;
171     os_hooks.print_info = &Print;
172     os_hooks.print_trace = &SerialPrint;
173     os_hooks.allocate_pages = &Allocate_VMM_Pages;
174     os_hooks.free_page = &Free_VMM_Page;
175     os_hooks.malloc = &VMM_Malloc;
176     os_hooks.free = &VMM_Free;
177     os_hooks.vaddr_to_paddr = &Identity;
178     os_hooks.paddr_to_vaddr = &Identity;
179
180  
181     //   DumpGDT();
182     Init_VMM(&os_hooks, &vmm_ops);
183   
184     init_shadow_map(&(vm_info.mem_map));
185     init_shadow_page_state(&(vm_info.shdw_pg_state));
186     vm_info.page_mode = SHADOW_PAGING;
187
188     vm_info.cpu_mode = REAL;
189
190     //init_irq_map(&(vm_info.irq_map));
191     init_vmm_io_map(&(vm_info.io_map));
192     init_interrupt_state(&vm_info);
193
194     dev_mgr_init(&(vm_info.dev_mgr));
195     
196     if (0) {
197       
198       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
199       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
200       
201       rip = (ulong_t)(void*)&BuzzVM;
202       //  rip -= 0x10000;
203       //    rip = (addr_t)(void*)&exit_test;
204       //  rip -= 0x2000;
205       vm_info.rip = rip;
206       rsp = (addr_t)Alloc_Page();
207       
208       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
209       
210             
211     } else if (0) {
212       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
213       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
214       
215       /*
216         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
217         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
218         0x100000, HOST_REGION_PHYSICAL_MEMORY);
219         add_shadow_region(&(vm_info.mem_map),ent);
220       */
221
222       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
223
224       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
225       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
226       
227       /*
228         vm_info.cr0 = 0;
229         vm_info.cs.base=0xf000;
230         vm_info.cs.limit=0xffff;
231       */
232       //vm_info.rip = 0xfff0;
233
234       vm_info.rip = 0;
235       vm_info.vm_regs.rsp = 0x0;
236     } else {
237       int i;
238       void * region_start;
239
240  
241       PrintDebug("Guest Size: %lu\n", bootInfo->guest_size);
242
243       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
244
245       if (layout->magic != MAGIC_CODE) {
246         PrintDebug("Layout Magic Mismatch (0x%x)\n", layout->magic);
247       }
248
249       PrintDebug("%d layout regions\n", layout->num_regions);
250
251       region_start = (void *)&(layout->regions[layout->num_regions]);
252
253       PrintDebug("region start = 0x%x\n", region_start);
254
255       for (i = 0; i < layout->num_regions; i++) {
256         struct layout_region * reg = &(layout->regions[i]);
257         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
258         void * guest_mem = Allocate_VMM_Pages(num_pages);
259
260         PrintDebug("Layout Region %d bytes\n", reg->length);
261         memcpy(guest_mem, region_start, reg->length);
262         
263         SerialMemDump((unsigned char *)(guest_mem), 16);
264
265         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
266
267         PrintDebug("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
268
269         region_start += reg->length;
270       }
271       
272       add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
273       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
274       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
275       if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
276         PrintDebug("Error adding shadow region\n");
277       }
278
279
280       print_shadow_map(&(vm_info.mem_map));
281
282       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
283       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
284
285       /*
286         hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial, NULL);
287         hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial, NULL);
288         hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial, NULL);
289         hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial, NULL);
290       */
291       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
292       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
293       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);
294       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
295
296       {
297         //struct vm_device * nvram = create_nvram();
298         //struct vm_device * timer = create_timer();
299         struct vm_device * pic = create_pic();
300
301         //attach_device(&(vm_info), nvram);
302         //attach_device(&(vm_info), timer);
303         attach_device(&(vm_info), pic);
304
305         PrintDebugDevMgr(&(vm_info.dev_mgr));
306       }
307
308
309       hook_irq(&vm_info, 6);
310
311       vm_info.rip = 0xfff0;
312       vm_info.vm_regs.rsp = 0x0;
313     }
314
315     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
316     (vmm_ops).init_guest(&vm_info);
317     PrintBoth("Starting Guest\n");
318     //Clear_Screen();
319     (vmm_ops).start_guest(&vm_info);
320
321     return 0;
322 }