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.


2b02058d9ce885bc7466a7174478d30481d919c0
[palacios.git] / palacios / include / palacios / vmm.h
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifndef __VMM_H__
21 #define __VMM_H__
22
23
24
25 #ifdef __V3VEE__
26 #include <palacios/vmm_mem.h>
27 #include <palacios/vmm_types.h>
28 #include <palacios/vmm_string.h>
29
30
31
32
33 /* utility definitions */
34
35 #define VM_NONE ((struct v3_vm_info *)0)
36 #define VCORE_NONE ((struct guest_info *)0)
37
38 void    *v3_get_host_vm(struct v3_vm_info *);
39 int      v3_get_vcore(struct guest_info *);
40
41 #define V3_Print(vm, vcore, fmt, args...)       \
42   do {                                                          \
43     extern struct v3_os_hooks * os_hooks;                       \
44     if ((os_hooks) && (os_hooks)->print) {                      \
45       (os_hooks)->print(v3_get_host_vm(vm), v3_get_vcore(vcore), (fmt), ##args); \
46     }                                                                   \
47   } while (0)   
48
49
50 #define PrintDebug(vm, vcore, fmt, args...)   V3_Print(vm, vcore, "DEBUG: " fmt, ##args)
51
52 #define PrintError(vm, vcore, fmt, args...)  V3_Print(vm, vcore, "ERROR at %s(%d): " fmt, __FILE__, __LINE__, ##args)
53
54
55
56 /* 4KB-aligned */
57 #define V3_AllocPages(num_pages)                                        \
58     ({                                                                  \
59         extern struct v3_os_hooks * os_hooks;                           \
60         void * ptr = 0;                                                 \
61         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
62             ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,0); \
63         }                                                               \
64         ptr;                                                            \
65     })
66
67
68 // Use 32 bit constraints if the vm uses 32bit shadow paging at any point
69 // Should be used for shadow page tables and any physical memory
70 // mapped into the vm
71 #define V3_AllocShadowSafePages(vm,num_pages)                           \
72     ({                                                                  \
73         extern struct v3_os_hooks * os_hooks;                           \
74         void * ptr = 0;                                                 \
75         int c; int shadow=0;                                            \
76         for (c=0;c<(vm)->num_cores && !shadow;c++) {                    \
77             shadow|=vm->cores[c].shdw_pg_mode==SHADOW_PAGING;           \
78         }                                                               \
79         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
80             ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,\
81                     shadow ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);        \
82         }                                                               \
83         ptr;                                                            \
84     })
85
86 #define V3_AllocAlignedPages(num_pages, align)                          \
87     ({                                                                  \
88         extern struct v3_os_hooks * os_hooks;                           \
89         void * ptr = 0;                                                 \
90         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
91             ptr = (os_hooks)->allocate_pages(num_pages,align,-1,0);     \
92         }                                                               \
93         ptr;                                                            \
94     })
95
96
97 #define V3_AllocPagesNode(num_pages, node_id)                           \
98     ({                                                                  \
99         extern struct v3_os_hooks * os_hooks;                           \
100         void * ptr = 0;                                                 \
101         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
102             ptr = (os_hooks)->allocate_pages(num_pages, PAGE_SIZE_4KB, node_id,0); \
103         }                                                               \
104         ptr;                                                            \
105     })
106
107 #define V3_AllocPagesExtended(num_pages, align, node_id, constraints)                   \
108     ({                                                                  \
109         extern struct v3_os_hooks * os_hooks;                           \
110         void * ptr = 0;                                                 \
111         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
112             ptr = (os_hooks)->allocate_pages(num_pages, align, node_id,constraints); \
113         }                                                               \
114         ptr;                                                            \
115     })
116
117
118
119 #define V3_FreePages(page, num_pages)                   \
120     do {                                                \
121         extern struct v3_os_hooks * os_hooks;           \
122         if ((os_hooks) && (os_hooks)->free_pages) {     \
123             (os_hooks)->free_pages(page, num_pages);    \
124         }                                               \
125     } while(0)
126
127
128 #define V3_VAddr(addr) ({                                       \
129             extern struct v3_os_hooks * os_hooks;               \
130             void * var = 0;                                     \
131             if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {     \
132                 var = (os_hooks)->paddr_to_vaddr(addr);         \
133             }                                                   \
134             var;                                                \
135         })
136
137
138 #define V3_PAddr(addr) ({                                       \
139             extern struct v3_os_hooks * os_hooks;               \
140             void * var = 0;                                     \
141             if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {     \
142                 var = (os_hooks)->vaddr_to_paddr(addr);         \
143             }                                                   \
144             var;                                                \
145         })
146
147
148
149 #define V3_Malloc(size) ({                              \
150             extern struct v3_os_hooks * os_hooks;       \
151             void * var = 0;                             \
152             if ((os_hooks) && (os_hooks)->malloc) {     \
153                 var = (os_hooks)->malloc(size);         \
154             }                                           \
155             if (!var) PrintError(VM_NONE,VCORE_NONE,"MALLOC FAILURE. Memory LEAK!!\n"); \
156             var;                                        \
157         })
158
159 // We need to check the hook structure at runtime to ensure its SAFE
160 #define V3_Free(addr)                           \
161     do {                                        \
162         extern struct v3_os_hooks * os_hooks;   \
163         if ((os_hooks) && (os_hooks)->free) {   \
164             (os_hooks)->free(addr);             \
165         }                                       \
166     } while (0)
167
168 // uint_t V3_CPU_KHZ();
169 #define V3_CPU_KHZ() ({                                                 \
170             unsigned int khz = 0;                                       \
171             extern struct v3_os_hooks * os_hooks;                       \
172             if ((os_hooks) && (os_hooks)->get_cpu_khz) {                \
173                 khz = (os_hooks)->get_cpu_khz();                        \
174             }                                                           \
175             khz;                                                        \
176         })                                                              \
177         
178
179
180
181 #define V3_Hook_Interrupt(vm, irq) ({                                   \
182             int ret = 0;                                                \
183             extern struct v3_os_hooks * os_hooks;                       \
184             if ((os_hooks) && (os_hooks)->hook_interrupt) {             \
185                 ret = (os_hooks)->hook_interrupt(vm, irq);              \
186             }                                                           \
187             ret;                                                        \
188         })                                                              \
189         
190
191 #define V3_ACK_IRQ(irq)                                         \
192     do {                                                        \
193         extern struct v3_os_hooks * os_hooks;                   \
194         if ((os_hooks) && (os_hooks)->ack_irq) {                \
195             (os_hooks)->ack_irq(irq);                           \
196         }                                                       \
197     } while (0)
198
199
200
201 #define V3_Get_CPU() ({                                                 \
202             int ret = 0;                                                \
203             extern struct v3_os_hooks * os_hooks;                       \
204             if ((os_hooks) && (os_hooks)->get_cpu) {                    \
205                 ret = (os_hooks)->get_cpu();                            \
206             }                                                           \
207             ret;                                                        \
208         })
209
210
211
212
213 #define V3_CREATE_THREAD(fn, arg, name) ({                              \
214             void * thread = NULL;                                       \
215             extern struct v3_os_hooks * os_hooks;                       \
216             if ((os_hooks) && (os_hooks)->start_kernel_thread) {        \
217                 thread = (os_hooks)->start_kernel_thread(fn, arg, name); \
218             }                                                           \
219             thread;                                                     \
220         })
221
222
223
224
225 #define V3_Call_On_CPU(cpu, fn, arg)                    \
226     do {                                                \
227         extern struct v3_os_hooks * os_hooks;           \
228         if ((os_hooks) && (os_hooks)->call_on_cpu) {    \
229             (os_hooks)->call_on_cpu(cpu, fn, arg);      \
230         }                                               \
231     } while (0)
232
233
234
235 #define V3_CREATE_THREAD_ON_CPU(cpu, fn, arg, name) ({                  \
236             void * thread = NULL;                                       \
237             extern struct v3_os_hooks * os_hooks;                       \
238             if ((os_hooks) && (os_hooks)->start_thread_on_cpu) {        \
239                 thread = (os_hooks)->start_thread_on_cpu(cpu, fn, arg, name); \
240             }                                                           \
241             thread;                                                     \
242         })
243
244 #define V3_MOVE_THREAD_TO_CPU(pcpu, thread) ({                          \
245         int ret = -1;                                                   \
246         extern struct v3_os_hooks * os_hooks;                           \
247         if((os_hooks) && (os_hooks)->move_thread_to_cpu) {              \
248             ret = (os_hooks)->move_thread_to_cpu(pcpu, thread);         \
249         }                                                               \
250         ret;                                                            \
251     })
252     
253
254 /* ** */
255
256
257 #define V3_ASSERT(vm, vcore, x)                                         \
258     do {                                                                \
259         extern struct v3_os_hooks * os_hooks;                           \
260         if (!(x)) {                                                     \
261           PrintDebug(vm, vcore, "Failed assertion in %s: %s at %s, line %d, RA=%lx\n", \
262                        __func__, #x, __FILE__, __LINE__,                \
263                        (ulong_t) __builtin_return_address(0));          \
264             while(1){                                                   \
265                 if ((os_hooks) && (os_hooks)->yield_cpu) {              \
266                         (os_hooks)->yield_cpu();                        \
267                 }                                                       \
268             }                                                           \
269         }                                                               \
270     } while(0)                                                          \
271         
272
273
274 #define V3_Yield()                                      \
275     do {                                                \
276         extern struct v3_os_hooks * os_hooks;           \
277         if ((os_hooks) && (os_hooks)->yield_cpu) {      \
278             (os_hooks)->yield_cpu();                    \
279         }                                               \
280     } while (0)                                         \
281
282
283 #define V3_Sleep(usec)                          \
284     do {                                                \
285         extern struct v3_os_hooks * os_hooks;           \
286         if ((os_hooks) && (os_hooks)->sleep_cpu) {\
287             (os_hooks)->sleep_cpu(usec);                \
288         } else {                                        \
289             V3_Yield();                                 \
290         }                                               \
291     }  while (0)                                        \
292
293 #define V3_Wakeup(cpu)                                  \
294     do {                                                \
295         extern struct v3_os_hooks * os_hooks;           \
296         if ((os_hooks) && (os_hooks)->wakeup_cpu) {     \
297             (os_hooks)->wakeup_cpu(cpu);                        \
298         }                                               \
299     } while (0)                                         \
300
301
302 typedef enum v3_vm_class {V3_INVALID_VM, V3_PC_VM, V3_CRAY_VM} v3_vm_class_t;
303
304
305 // Maybe make this a define....
306 typedef enum v3_cpu_arch {V3_INVALID_CPU, V3_SVM_CPU, V3_SVM_REV3_CPU, V3_VMX_CPU, V3_VMX_EPT_CPU, V3_VMX_EPT_UG_CPU} v3_cpu_arch_t;
307
308
309 v3_cpu_mode_t v3_get_host_cpu_mode();
310
311 void v3_yield(struct guest_info * info, int usec);
312 void v3_yield_cond(struct guest_info * info, int usec);
313 void v3_print_cond(const char * fmt, ...);
314
315 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector);
316
317
318
319 v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
320
321
322 int v3_vm_enter(struct guest_info * info);
323 int v3_reset_vm_core(struct guest_info * core, addr_t rip);
324
325
326 #endif /*!__V3VEE__ */
327
328
329
330 struct v3_vm_info;
331
332 /* This will contain function pointers that provide OS services */
333 struct v3_os_hooks {
334     // the vm pointer is the host os's "priv_data" from v3_create_vm
335     // if vm is null, this is a general palacios printout
336     // if vm is not null, and vcore is negative, this is a general print form the vm
337     // if vm is not null, and vcore is non-negative, this is a print from a specific vcore
338     void (*print)(void *vm, int vcore, const char * format, ...)
339         __attribute__ ((format (printf, 3, 4)));
340
341     // For page allocation:
342     //   - node_id -1 => any node, otherwise the numa node we want to alloc from
343     //   - constraint = 0 => no constraints, otherwise a bitwise-or of the following flags
344 #define V3_ALLOC_PAGES_CONSTRAINT_4GB  1
345     void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id, int constraint);
346     void (*free_pages)(void * page, int num_pages);
347
348     void *(*malloc)(unsigned int size);
349     void (*free)(void * addr);
350
351     void *(*paddr_to_vaddr)(void * addr);
352     void *(*vaddr_to_paddr)(void * addr);
353
354     int (*hook_interrupt)(struct v3_vm_info * vm, unsigned int irq);
355     int (*ack_irq)(int irq);
356
357     unsigned int (*get_cpu_khz)(void);
358
359     void (*yield_cpu)(void); 
360     void (*sleep_cpu)(unsigned int usec);
361     void (*wakeup_cpu)(void *cpu);
362
363     void *(*mutex_alloc)(void);
364     void (*mutex_free)(void * mutex);
365     void (*mutex_lock)(void * mutex, int must_spin);
366     void (*mutex_unlock)(void * mutex);
367     void *(*mutex_lock_irqsave)(void * mutex, int must_spin);
368     void (*mutex_unlock_irqrestore)(void * mutex, void *flags);
369
370     unsigned int (*get_cpu)(void);
371
372     void * (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name); 
373     void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector);
374     void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
375     void * (*start_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name);
376     int (*move_thread_to_cpu)(int cpu_id,  void * thread);
377 };
378
379
380 /*
381  *
382  * This is the interrupt state that the VMM's interrupt handlers need to see
383  */
384 struct v3_interrupt {
385     unsigned int irq;
386     unsigned int error;
387
388     unsigned int should_ack;  /* Should the vmm ack this interrupt, or will
389                                * the host OS do it? */
390 };
391
392
393 typedef enum {V3_VM_UNKNOWN, V3_VM_INVALID, V3_VM_RUNNING, V3_VM_STOPPED, V3_VM_PAUSED, V3_VM_ERROR, V3_VM_SIMULATING} v3_vm_state_t;
394 typedef enum {V3_VCORE_UNKNOWN, V3_VCORE_INVALID, V3_VCORE_RUNNING, V3_VCORE_STOPPED} v3_vcore_state_t;
395 typedef enum {V3_VCORE_CPU_UNKNOWN, V3_VCORE_CPU_REAL, V3_VCORE_CPU_PROTECTED, V3_VCORE_CPU_PROTECTED_PAE, V3_VCORE_CPU_LONG, V3_VCORE_CPU_LONG_32_COMPAT, V3_VCORE_CPU_LONG_16_COMPAT} v3_vcore_cpu_mode_t;
396
397 typedef enum {V3_VCORE_MEM_STATE_UNKNOWN, V3_VCORE_MEM_STATE_SHADOW, V3_VCORE_MEM_STATE_NESTED} v3_vcore_mem_state_t;
398 typedef enum {V3_VCORE_MEM_MODE_UNKNOWN, V3_VCORE_MEM_MODE_PHYSICAL, V3_VCORE_MEM_MODE_VIRTUAL} v3_vcore_mem_mode_t;
399
400
401 struct v3_vm_base_state {
402     v3_vm_state_t       state;
403 };
404
405 struct v3_vm_vcore_state {
406   v3_vcore_state_t state;
407   v3_vcore_cpu_mode_t cpu_mode;
408   v3_vcore_mem_state_t mem_state;
409   v3_vcore_mem_mode_t mem_mode;
410   unsigned long pcore;
411   void *   last_rip;
412   unsigned long long num_exits;
413 };
414
415 struct v3_vm_core_state {
416     unsigned long         num_vcores;
417     struct v3_vm_vcore_state vcore[];
418 };
419
420 struct v3_vm_mem_region {
421     void               *host_paddr;
422     unsigned long long  size;
423 };
424
425 struct v3_vm_mem_state {
426     unsigned long long      mem_size;
427     unsigned long           num_regions;
428     struct v3_vm_mem_region region[]; 
429 };
430
431 char *v3_lookup_option(char *name);
432 void Init_V3(struct v3_os_hooks * hooks, char * cpus, int num_cpus, char *options);
433 void Shutdown_V3( void );
434
435
436 struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name);
437 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
438 int v3_stop_vm(struct v3_vm_info * vm);
439 int v3_pause_vm(struct v3_vm_info * vm);
440 int v3_continue_vm(struct v3_vm_info * vm);
441 int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs);
442
443 int v3_save_vm(struct v3_vm_info * vm, char * store, char * url, unsigned long long opts);
444 int v3_load_vm(struct v3_vm_info * vm, char * store, char * url, unsigned long long opts);
445
446 int v3_send_vm(struct v3_vm_info * vm, char * store, char * url, unsigned long long opts);
447 int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url, unsigned long long opts);
448
449 int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu);
450 int v3_move_vm_mem(struct v3_vm_info * vm, void *gpa, int target_cpu);
451
452 int v3_free_vm(struct v3_vm_info * vm);
453
454 int v3_get_state_vm(struct v3_vm_info        *vm, 
455                     struct v3_vm_base_state  *base,
456                     struct v3_vm_core_state  *core,
457                     struct v3_vm_mem_state   *mem);
458
459 char *v3_lookup_option(char *key);
460
461 int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
462
463
464 #endif