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.


Added generic device, some keyboard fixes (still in progress)
[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
8 #include <devices/generic.h>
9 #include <devices/nvram.h>
10 #include <devices/timer.h>
11 #include <devices/simple_pic.h>
12 #include <devices/8259a.h>
13 #include <devices/8254.h>
14 #include <devices/keyboard.h>
15
16 #include <palacios/vmm_intr.h>
17 #include <palacios/vmm_dev_mgr.h>
18 #include <palacios/vmm_time.h>
19
20 #define SPEAKER_PORT 0x61
21
22 static inline void VM_Out_Byte(ushort_t port, uchar_t value)
23 {
24     __asm__ __volatile__ (
25         "outb %b0, %w1"
26         :
27         : "a" (value), "Nd" (port)
28     );
29 }
30
31 /*
32  * Read a byte from an I/O port.
33  */
34 static inline uchar_t VM_In_Byte(ushort_t port)
35 {
36     uchar_t value;
37
38     __asm__ __volatile__ (
39         "inb %w1, %b0"
40         : "=a" (value)
41         : "Nd" (port)
42     );
43
44     return value;
45 }
46
47
48
49
50 int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
51
52   if (length != 1) {
53     return 0;
54   }
55
56   *(uchar_t*)dst = VM_In_Byte(port);    
57   return 1;
58 }
59
60
61
62 int IO_Write(ushort_t port, void * src, uint_t length, void * priv_data) {
63
64   if (length != 1) {
65     return 0;
66   }
67
68   VM_Out_Byte(port, *(uchar_t *)src);    
69
70   return 1;
71 }
72
73
74 int IO_Read_to_Serial(ushort_t port, void * dst, uint_t length, void * priv_data) {
75   PrintBoth("Input from Guest on port %d (0x%x) Length=%d\n", port, port, length);
76   
77   return 0;
78 }
79
80
81 char * bochs_debug_buf = NULL;
82 int bochs_debug_offset = 0;
83
84
85 int IO_BOCHS_debug(ushort_t port, void * src, uint_t length, void * priv_data) {
86   if (!bochs_debug_buf) {
87     bochs_debug_buf = (char*)Malloc(1024);
88   }
89
90   bochs_debug_buf[bochs_debug_offset++] = *(char*)src;
91
92   if ((*(char*)src == 0xa) ||  (bochs_debug_offset == 1023)) {
93     SerialPrint("BOCHS>%s", bochs_debug_buf);
94     memset(bochs_debug_buf, 0, 1024);
95     bochs_debug_offset = 0;
96   }
97
98   return length;
99 }
100
101
102 int IO_Write_to_Serial(ushort_t port, void * src, uint_t length, void * priv_data) {
103  SerialPrint("Output from Guest on port %d (0x%x) Length=%d\n", port, port, length);
104   switch (length) {
105
106   case 1:
107     SerialPrint(">0x%.2x\n", *(char*)src);
108     break;
109   case 2:
110     SerialPrint(">0x%.4x\n", *(ushort_t*)src);
111     break;
112   case 4:
113     SerialPrint(">0x%.8x\n", *(uint_t*)src);
114     break;
115   default:
116     break;
117   }
118
119   //  SerialMemDump(src, length);
120   return length;
121 }
122
123
124
125 void BuzzVM()
126 {
127   int x;
128   int j;
129   unsigned char init;
130
131 #if 0  
132   __asm__ __volatile__ (
133     "popf"
134     );
135     
136 #endif
137     
138   PrintBoth("Starting To Buzz\n");
139
140   init=VM_In_Byte(SPEAKER_PORT);
141
142   while (1) {
143     VM_Out_Byte(SPEAKER_PORT, init|0x2);
144     for (j=0;j<1000000;j++) { 
145       x+=j;
146     }
147     VM_Out_Byte(SPEAKER_PORT, init);
148     for (j=0;j<1000000;j++) { 
149       x+=j;
150     }
151   }
152 }
153
154
155
156
157 /* We need a configuration mechanism, so we can wrap this completely inside the VMM code, 
158  * with no pollution into the HOST OS
159  */
160
161 int RunVMM(struct Boot_Info * bootInfo) {
162
163     struct vmm_os_hooks os_hooks;
164     struct vmm_ctrl_ops vmm_ops;
165     struct guest_info vm_info;
166     addr_t rsp;
167     addr_t rip;
168
169
170
171     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
172     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
173     memset(&vm_info, 0, sizeof(struct guest_info));
174
175     os_hooks.print_debug = &SerialPrint;
176     os_hooks.print_info = &Print;
177     os_hooks.print_trace = &SerialPrint;
178     os_hooks.allocate_pages = &Allocate_VMM_Pages;
179     os_hooks.free_page = &Free_VMM_Page;
180     os_hooks.malloc = &VMM_Malloc;
181     os_hooks.free = &VMM_Free;
182     os_hooks.vaddr_to_paddr = &Identity;
183     os_hooks.paddr_to_vaddr = &Identity;
184     os_hooks.hook_interrupt = &hook_irq_stub;
185     os_hooks.ack_irq = &ack_irq;
186     os_hooks.get_cpu_khz = &get_cpu_khz;
187
188     Init_VMM(&os_hooks, &vmm_ops);
189   
190
191     /* MOVE THIS TO AN INIT GUEST ROUTINE */
192     init_shadow_map(&(vm_info.mem_map));
193     init_shadow_page_state(&(vm_info.shdw_pg_state));
194     v3_init_time(&(vm_info.time_state));
195     vm_info.page_mode = SHADOW_PAGING;
196
197     vm_info.cpu_mode = REAL;
198
199     //init_irq_map(&(vm_info.irq_map));
200     init_vmm_io_map(&(vm_info.io_map));
201     init_interrupt_state(&vm_info);
202
203     dev_mgr_init(&(vm_info.dev_mgr));
204     /* ** */
205     
206     if (0) {
207       
208       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x800000, 0x10000);    
209       //    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
210       
211       rip = (ulong_t)(void*)&BuzzVM;
212       //  rip -= 0x10000;
213       //    rip = (addr_t)(void*)&exit_test;
214       //  rip -= 0x2000;
215       vm_info.rip = rip;
216       rsp = (addr_t)Alloc_Page();
217       
218       vm_info.vm_regs.rsp = (rsp +4092 );// - 0x2000;
219       
220             
221     } else if (0) {
222       //add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x1000, 0x100000);
223       //      add_shared_mem_range(&(vm_info.mem_layout), 0x0, 0x100000, 0x0);
224       
225       /*
226         shadow_region_t *ent = Malloc(sizeof(shadow_region_t));;
227         init_shadow_region_physical(ent,0,0x100000,GUEST_REGION_PHYSICAL_MEMORY,
228         0x100000, HOST_REGION_PHYSICAL_MEMORY);
229         add_shadow_region(&(vm_info.mem_map),ent);
230       */
231
232       add_shadow_region_passthrough(&vm_info, 0x0, 0x100000, 0x100000);
233
234       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
235       hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
236       
237       /*
238         vm_info.cr0 = 0;
239         vm_info.cs.base=0xf000;
240         vm_info.cs.limit=0xffff;
241       */
242       //vm_info.rip = 0xfff0;
243
244       vm_info.rip = 0;
245       vm_info.vm_regs.rsp = 0x0;
246     } else {
247       int i;
248       void * region_start;
249
250  
251       PrintBoth("Guest Size: %lu\n", bootInfo->guest_size);
252
253       struct guest_mem_layout * layout = (struct guest_mem_layout *)0x100000;
254
255       if (layout->magic != MAGIC_CODE) {
256         PrintBoth("Layout Magic Mismatch (0x%x)\n", layout->magic);
257       }
258
259       PrintBoth("%d layout regions\n", layout->num_regions);
260
261       region_start = (void *)&(layout->regions[layout->num_regions]);
262
263       PrintBoth("region start = 0x%x\n", region_start);
264
265       for (i = 0; i < layout->num_regions; i++) {
266         struct layout_region * reg = &(layout->regions[i]);
267         uint_t num_pages = (reg->length / PAGE_SIZE) + ((reg->length % PAGE_SIZE) ? 1 : 0);
268         void * guest_mem = Allocate_VMM_Pages(num_pages);
269
270         PrintBoth("Layout Region %d bytes\n", reg->length);
271         memcpy(guest_mem, region_start, reg->length);
272         
273         SerialMemDump((unsigned char *)(guest_mem), 16);
274
275         add_shadow_region_passthrough(&vm_info, reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
276
277         PrintBoth("Adding Shadow Region (0x%x-0x%x) -> 0x%x\n", reg->final_addr, reg->final_addr + (num_pages * PAGE_SIZE), guest_mem);
278
279         region_start += reg->length;
280       }
281       
282       //     
283       add_shadow_region_passthrough(&vm_info, 0x0, 0xa0000, (addr_t)Allocate_VMM_Pages(160));
284       add_shadow_region_passthrough(&vm_info, 0xa0000, 0xc0000, 0xa0000); 
285       
286
287
288       // TEMP
289       //add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
290
291       if (1) {
292         add_shadow_region_passthrough(&vm_info, 0xc7000, 0xc8000, (addr_t)Allocate_VMM_Pages(1));
293         if (add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, (addr_t)Allocate_VMM_Pages(40)) == -1) {
294           PrintBoth("Error adding shadow region\n");
295         }
296       } else {
297         add_shadow_region_passthrough(&vm_info, 0xc0000, 0xc8000, 0xc0000);
298         add_shadow_region_passthrough(&vm_info, 0xc8000, 0xf0000, 0xc8000);
299       }
300
301
302       //add_shadow_region_passthrough(&vm_info, 0x100000, 0x2000000, (addr_t)Allocate_VMM_Pages(8192));
303       add_shadow_region_passthrough(&vm_info, 0x100000, 0x1000000, (addr_t)Allocate_VMM_Pages(4096));
304
305
306       print_shadow_map(&(vm_info.mem_map));
307
308       hook_io_port(&(vm_info.io_map), 0x61, &IO_Read, &IO_Write, NULL);
309       //hook_io_port(&(vm_info.io_map), 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
310
311
312       hook_io_port(&(vm_info.io_map), 0x400, &IO_Read, &IO_Write_to_Serial, NULL);
313       hook_io_port(&(vm_info.io_map), 0x401, &IO_Read, &IO_Write_to_Serial, NULL);
314       hook_io_port(&(vm_info.io_map), 0x402, &IO_Read, &IO_BOCHS_debug, NULL);
315       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
316
317       {
318         
319         struct vm_device * nvram = create_nvram();
320         //struct vm_device * timer = create_timer();
321         struct vm_device * pic = create_pic();
322         //struct vm_device * keyboard = create_keyboard();
323         struct vm_device * pit = create_pit();
324
325         //generic_port_range_type range = {0,1024} ; // hook first 1024 ports if not already hooked
326
327         //struct vm_device * generic = create_generic(&range,1,NULL,0,NULL,0);
328         
329
330         attach_device(&(vm_info), nvram);
331         //attach_device(&(vm_info), timer);
332         attach_device(&(vm_info), pic);
333         attach_device(&(vm_info), pit);
334         //attach_device(&(vm_info), keyboard);
335
336         // Important that this be attached last!
337         //attach_device(&(vm_info), generic);
338
339         PrintDebugDevMgr(&(vm_info.dev_mgr));
340       }
341
342       // give keyboard interrupts to vm
343       //hook_irq(&vm_info, 1);
344       
345       // give floppy controller to vm
346       hook_irq(&vm_info, 6);
347
348       // primary ide
349       hook_irq(&vm_info, 14);
350
351       // secondary ide
352       hook_irq(&vm_info, 15);
353
354
355       vm_info.rip = 0xfff0;
356       vm_info.vm_regs.rsp = 0x0;
357     }
358
359     PrintBoth("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", (uint_t)vm_info.rip,(uint_t)vm_info.vm_regs.rsp);
360     (vmm_ops).init_guest(&vm_info);
361     PrintBoth("Starting Guest\n");
362     //Clear_Screen();
363     (vmm_ops).start_guest(&vm_info);
364
365     return 0;
366 }