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.


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