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 #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     os_hooks.hook_interrupt = &hook_irq_stub;
180     os_hooks.ack_irq = &ack_irq;
181  
182     //   DumpGDT();
183     Init_VMM(&os_hooks, &vmm_ops);
184   
185     init_shadow_map(&(vm_info.mem_map));
186     init_shadow_page_state(&(vm_info.shdw_pg_state));
187     vm_info.page_mode = SHADOW_PAGING;
188
189     vm_info.cpu_mode = REAL;
190
191     //init_irq_map(&(vm_info.irq_map));
192     init_vmm_io_map(&(vm_info.io_map));
193     init_interrupt_state(&vm_info);
194
195     dev_mgr_init(&(vm_info.dev_mgr));
196     
197     if (0) {
198       
199       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
200       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
201       
202       rip = (ulong_t)(void*)&BuzzVM;
203       //  rip -= 0x10000;
204       //    rip = (addr_t)(void*)&exit_test;
205       //  rip -= 0x2000;
206       vm_info.rip = rip;
207       rsp = (addr_t)Alloc_Page();
208       
209       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
210       
211             
212     } else if (0) {
213       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
214       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
215       
216       /*
217         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
218         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
219         0x100000, HOST_REGION_PHYSICAL_MEMORY);
220         add_shadow_region(&(vm_info.mem_map),ent);
221       */
222
223       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
224
225       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
226       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
227       
228       /*
229         vm_info.cr0 = 0;
230         vm_info.cs.base=0xf000;
231         vm_info.cs.limit=0xffff;
232       */
233       //vm_info.rip = 0xfff0;
234
235       vm_info.rip = 0;
236       vm_info.vm_regs.rsp = 0x0;
237     } else {
238       int i;
239       void * region_start;
240
241  
242       PrintDebug("Guest Size: %lu\n", bootInfo->guest_size);
243
244       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
245
246       if (layout->magic != MAGIC_CODE) {
247         PrintDebug("Layout Magic Mismatch (0x%x)\n", layout->magic);
248       }
249
250       PrintDebug("%d layout regions\n", layout->num_regions);
251
252       region_start = (void *)&(layout->regions[layout->num_regions]);
253
254       PrintDebug("region start = 0x%x\n", region_start);
255
256       for (i = 0; i < layout->num_regions; i++) {
257         struct layout_region * reg = &(layout->regions[i]);
258         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
259         void * guest_mem = Allocate_VMM_Pages(num_pages);
260
261         PrintDebug("Layout Region %d bytes\n", reg->length);
262         memcpy(guest_mem, region_start, reg->length);
263         
264         SerialMemDump((unsigned char *)(guest_mem), 16);
265
266         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
267
268         PrintDebug("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
269
270         region_start += reg->length;
271       }
272       
273       //     
274       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
275       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
276       
277
278       if (1) {
279         add_shadow_region_passthrough(&vm_info, 0xc7000, 0xc8000, (addr_t)Allocate_VMM_Pages(1));
280         if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
281           PrintDebug("Error adding shadow region\n");
282         }
283       } else {
284         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
285         add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, 0xc8000);
286       }
287
288
289       print_shadow_map(&(vm_info.mem_map));
290
291       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
292       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
293
294       /*
295         hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial, NULL);
296         hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial, NULL);
297         hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial, NULL);
298         hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial, NULL);
299       */
300       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
301       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
302       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);
303       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
304
305       {
306         struct vm_device * nvram = create_nvram();
307         //struct vm_device * timer = create_timer();
308         struct vm_device * pic = create_pic();
309
310         attach_device(&(vm_info), nvram);
311         //attach_device(&(vm_info), timer);
312         attach_device(&(vm_info), pic);
313
314         PrintDebugDevMgr(&(vm_info.dev_mgr));
315       }
316
317       hook_irq(&vm_info, 6);
318       hook_irq(&vm_info, 14);
319       hook_irq(&vm_info, 15);
320
321       vm_info.rip = 0xfff0;
322       vm_info.vm_regs.rsp = 0x0;
323     }
324
325     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
326     (vmm_ops).init_guest(&vm_info);
327     PrintBoth("Starting Guest\n");
328     //Clear_Screen();
329     (vmm_ops).start_guest(&vm_info);
330
331     return 0;
332 }