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.


booting geekos up to the timer initialization
[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
279       // TEMP
280         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
281
282       if (1) {
283         add_shadow_region_passthrough(&vm_info, 0xc7000, 0xc8000, (addr_t)Allocate_VMM_Pages(1));
284         if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
285           PrintDebug("Error adding shadow region\n");
286         }
287       } else {
288         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
289         add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, 0xc8000);
290       }
291
292
293       add_shadow_region_passthrough(&vm_info, 0x100000, 0x2000000, (addr_t)Allocate_VMM_Pages(8192));
294
295
296       print_shadow_map(&(vm_info.mem_map));
297
298       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
299       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
300
301       /*
302         hook_io_port(&(vm_info.io_map), 0x20, &IO_Read, &IO_Write_to_Serial, NULL);
303         hook_io_port(&(vm_info.io_map), 0x21, &IO_Read, &IO_Write_to_Serial, NULL);
304         hook_io_port(&(vm_info.io_map), 0xa0, &IO_Read, &IO_Write_to_Serial, NULL);
305         hook_io_port(&(vm_info.io_map), 0xa1, &IO_Read, &IO_Write_to_Serial, NULL);
306       */
307       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
308       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
309       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);
310       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
311
312       {
313         struct vm_device * nvram = create_nvram();
314         //struct vm_device * timer = create_timer();
315         struct vm_device * pic = create_pic();
316
317         attach_device(&(vm_info), nvram);
318         //attach_device(&(vm_info), timer);
319         attach_device(&(vm_info), pic);
320
321         PrintDebugDevMgr(&(vm_info.dev_mgr));
322       }
323
324       hook_irq(&vm_info, 6);
325       hook_irq(&vm_info, 14);
326       hook_irq(&vm_info, 15);
327
328       vm_info.rip = 0xfff0;
329       vm_info.vm_regs.rsp = 0x0;
330     }
331
332     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
333     (vmm_ops).init_guest(&vm_info);
334     PrintBoth("Starting Guest\n");
335     //Clear_Screen();
336     (vmm_ops).start_guest(&vm_info);
337
338     return 0;
339 }