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.


1f6228e753e69747123ebaa8940d70665d04df71
[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 #define V3_AllocAlignedPages(num_pages, align)                          \
69     ({                                                                  \
70         extern struct v3_os_hooks * os_hooks;                           \
71         void * ptr = 0;                                                 \
72         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
73             ptr = (os_hooks)->allocate_pages(num_pages,align,-1,0);     \
74         }                                                               \
75         ptr;                                                            \
76     })
77
78
79 #define V3_AllocPagesNode(num_pages, node_id)                           \
80     ({                                                                  \
81         extern struct v3_os_hooks * os_hooks;                           \
82         void * ptr = 0;                                                 \
83         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
84             ptr = (os_hooks)->allocate_pages(num_pages, PAGE_SIZE_4KB, node_id,0); \
85         }                                                               \
86         ptr;                                                            \
87     })
88
89 #define V3_AllocPagesExtended(num_pages, align, node_id, constraints)                   \
90     ({                                                                  \
91         extern struct v3_os_hooks * os_hooks;                           \
92         void * ptr = 0;                                                 \
93         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
94             ptr = (os_hooks)->allocate_pages(num_pages, align, node_id,constraints); \
95         }                                                               \
96         ptr;                                                            \
97     })
98
99
100
101 #define V3_FreePages(page, num_pages)                   \
102     do {                                                \
103         extern struct v3_os_hooks * os_hooks;           \
104         if ((os_hooks) && (os_hooks)->free_pages) {     \
105             (os_hooks)->free_pages(page, num_pages);    \
106         }                                               \
107     } while(0)
108
109
110 #define V3_VAddr(addr) ({                                       \
111             extern struct v3_os_hooks * os_hooks;               \
112             void * var = 0;                                     \
113             if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {     \
114                 var = (os_hooks)->paddr_to_vaddr(addr);         \
115             }                                                   \
116             var;                                                \
117         })
118
119
120 #define V3_PAddr(addr) ({                                       \
121             extern struct v3_os_hooks * os_hooks;               \
122             void * var = 0;                                     \
123             if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {     \
124                 var = (os_hooks)->vaddr_to_paddr(addr);         \
125             }                                                   \
126             var;                                                \
127         })
128
129
130
131 #define V3_Malloc(size) ({                              \
132             extern struct v3_os_hooks * os_hooks;       \
133             void * var = 0;                             \
134             if ((os_hooks) && (os_hooks)->malloc) {     \
135                 var = (os_hooks)->malloc(size);         \
136             }                                           \
137             if (!var) PrintError(VM_NONE,VCORE_NONE,"MALLOC FAILURE. Memory LEAK!!\n"); \
138             var;                                        \
139         })
140
141 // We need to check the hook structure at runtime to ensure its SAFE
142 #define V3_Free(addr)                           \
143     do {                                        \
144         extern struct v3_os_hooks * os_hooks;   \
145         if ((os_hooks) && (os_hooks)->free) {   \
146             (os_hooks)->free(addr);             \
147         }                                       \
148     } while (0)
149
150 // uint_t V3_CPU_KHZ();
151 #define V3_CPU_KHZ() ({                                                 \
152             unsigned int khz = 0;                                       \
153             extern struct v3_os_hooks * os_hooks;                       \
154             if ((os_hooks) && (os_hooks)->get_cpu_khz) {                \
155                 khz = (os_hooks)->get_cpu_khz();                        \
156             }                                                           \
157             khz;                                                        \
158         })                                                              \
159         
160
161
162
163 #define V3_Hook_Interrupt(vm, irq) ({                                   \
164             int ret = 0;                                                \
165             extern struct v3_os_hooks * os_hooks;                       \
166             if ((os_hooks) && (os_hooks)->hook_interrupt) {             \
167                 ret = (os_hooks)->hook_interrupt(vm, irq);              \
168             }                                                           \
169             ret;                                                        \
170         })                                                              \
171         
172
173 #define V3_ACK_IRQ(irq)                                         \
174     do {                                                        \
175         extern struct v3_os_hooks * os_hooks;                   \
176         if ((os_hooks) && (os_hooks)->ack_irq) {                \
177             (os_hooks)->ack_irq(irq);                           \
178         }                                                       \
179     } while (0)
180
181
182
183 #define V3_Get_CPU() ({                                                 \
184             int ret = 0;                                                \
185             extern struct v3_os_hooks * os_hooks;                       \
186             if ((os_hooks) && (os_hooks)->get_cpu) {                    \
187                 ret = (os_hooks)->get_cpu();                            \
188             }                                                           \
189             ret;                                                        \
190         })
191
192
193
194
195 #define V3_CREATE_AND_START_THREAD(fn, arg, name)       ({              \
196             void * thread = NULL;                                       \
197             extern struct v3_os_hooks * os_hooks;                       \
198             if ((os_hooks) && (os_hooks)->start_kernel_thread) {        \
199                 thread = (os_hooks)->start_kernel_thread(fn, arg, name); \
200             }                                                           \
201             thread;                                                     \
202         })
203
204
205
206
207 #define V3_Call_On_CPU(cpu, fn, arg)                    \
208     do {                                                \
209         extern struct v3_os_hooks * os_hooks;           \
210         if ((os_hooks) && (os_hooks)->call_on_cpu) {    \
211             (os_hooks)->call_on_cpu(cpu, fn, arg);      \
212         }                                               \
213     } while (0)
214
215
216
217 #define V3_CREATE_THREAD_ON_CPU(cpu, fn, arg, name) ({                  \
218             void * thread = NULL;                                       \
219             extern struct v3_os_hooks * os_hooks;                       \
220             if ((os_hooks) && (os_hooks)->create_thread_on_cpu) {       \
221                 thread = (os_hooks)->create_thread_on_cpu(cpu, fn, arg, name); \
222             }                                                           \
223             thread;                                                     \
224         })
225
226 #define V3_START_THREAD(thread) ({                                      \
227        extern struct v3_os_hooks * os_hooks;                            \
228        if((os_hooks) && (os_hooks)->start_thread){                      \
229            (os_hooks)->start_thread(thread);                            \
230        }                                                                \
231   })
232
233 #define V3_CREATE_AND_START_THREAD_ON_CPU(cpu, fn, arg, name) ({        \
234             void *thread = V3_CREATE_THREAD_ON_CPU(cpu,fn,arg,name);    \
235             if (thread) {                                               \
236                 V3_START_THREAD(thread);                                \
237             }                                                           \
238             thread;                                                     \
239         })
240
241 #define V3_MOVE_THREAD_TO_CPU(pcpu, thread) ({                          \
242         int ret = -1;                                                   \
243         extern struct v3_os_hooks * os_hooks;                           \
244         if((os_hooks) && (os_hooks)->move_thread_to_cpu) {              \
245             ret = (os_hooks)->move_thread_to_cpu(pcpu, thread);         \
246         }                                                               \
247         ret;                                                            \
248     })
249     
250
251 /* ** */
252
253
254 #define V3_ASSERT(vm, vcore, x)                                         \
255     do {                                                                \
256         extern struct v3_os_hooks * os_hooks;                           \
257         if (!(x)) {                                                     \
258           PrintDebug(vm, vcore, "Failed assertion in %s: %s at %s, line %d, RA=%lx\n", \
259                        __func__, #x, __FILE__, __LINE__,                \
260                        (ulong_t) __builtin_return_address(0));          \
261             while(1){                                                   \
262                 if ((os_hooks) && (os_hooks)->yield_cpu) {              \
263                         (os_hooks)->yield_cpu();                        \
264                 }                                                       \
265             }                                                           \
266         }                                                               \
267     } while(0)                                                          \
268         
269
270
271 #define V3_Yield()                                      \
272     do {                                                \
273         extern struct v3_os_hooks * os_hooks;           \
274         if ((os_hooks) && (os_hooks)->yield_cpu) {      \
275             (os_hooks)->yield_cpu();                    \
276         }                                               \
277     } while (0)                                         \
278
279
280 #define V3_Sleep(usec)                          \
281     do {                                                \
282         extern struct v3_os_hooks * os_hooks;           \
283         if ((os_hooks) && (os_hooks)->sleep_cpu) {\
284             (os_hooks)->sleep_cpu(usec);                \
285         } else {                                        \
286             V3_Yield();                                 \
287         }                                               \
288     }  while (0)                                        \
289
290 #define V3_Wakeup(cpu)                                  \
291     do {                                                \
292         extern struct v3_os_hooks * os_hooks;           \
293         if ((os_hooks) && (os_hooks)->wakeup_cpu) {     \
294             (os_hooks)->wakeup_cpu(cpu);                        \
295         }                                               \
296     } while (0)                                         \
297
298
299 typedef enum v3_vm_class {V3_INVALID_VM, V3_PC_VM, V3_CRAY_VM} v3_vm_class_t;
300
301
302 // Maybe make this a define....
303 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;
304
305
306 v3_cpu_mode_t v3_get_host_cpu_mode();
307
308 void v3_yield(struct guest_info * info, int usec);
309 void v3_yield_cond(struct guest_info * info, int usec);
310 void v3_print_cond(const char * fmt, ...);
311
312 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector);
313
314
315
316 v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
317
318
319 int v3_vm_enter(struct guest_info * info);
320 int v3_reset_vm_core(struct guest_info * core, addr_t rip);
321
322
323 #endif /*!__V3VEE__ */
324
325
326
327 struct v3_vm_info;
328
329 /* This will contain function pointers that provide OS services */
330 struct v3_os_hooks {
331     // the vm pointer is the host os's "priv_data" from v3_create_vm
332     // if vm is null, this is a general palacios printout
333     // if vm is not null, and vcore is negative, this is a general print form the vm
334     // if vm is not null, and vcore is non-negative, this is a print from a specific vcore
335     void (*print)(void *vm, int vcore, const char * format, ...)
336         __attribute__ ((format (printf, 3, 4)));
337
338     // For page allocation:
339     //   - node_id -1 => any node, otherwise the numa node we want to alloc from
340     //   - constraint = 0 => no constraints, otherwise a bitwise-or of the following flags
341 #define V3_ALLOC_PAGES_CONSTRAINT_4GB  1
342     void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id, int constraint);
343     void (*free_pages)(void * page, int num_pages);
344
345     void *(*malloc)(unsigned int size);
346     void (*free)(void * addr);
347
348     void *(*paddr_to_vaddr)(void * addr);
349     void *(*vaddr_to_paddr)(void * addr);
350
351     int (*hook_interrupt)(struct v3_vm_info * vm, unsigned int irq);
352     int (*ack_irq)(int irq);
353
354     unsigned int (*get_cpu_khz)(void);
355
356     void (*yield_cpu)(void); 
357     void (*sleep_cpu)(unsigned int usec);
358     void (*wakeup_cpu)(void *cpu);
359
360     void *(*mutex_alloc)(void);
361     void (*mutex_free)(void * mutex);
362     void (*mutex_lock)(void * mutex, int must_spin);
363     void (*mutex_unlock)(void * mutex);
364     void *(*mutex_lock_irqsave)(void * mutex, int must_spin);
365     void (*mutex_unlock_irqrestore)(void * mutex, void *flags);
366
367     unsigned int (*get_cpu)(void);
368
369     void * (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name); 
370     void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector);
371     void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
372     void * (*create_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name);
373     void (*start_thread)(void * core_thread);
374     int (*move_thread_to_cpu)(int cpu_id,  void * thread);
375 };
376
377
378 /*
379  *
380  * This is the interrupt state that the VMM's interrupt handlers need to see
381  */
382 struct v3_interrupt {
383     unsigned int irq;
384     unsigned int error;
385
386     unsigned int should_ack;  /* Should the vmm ack this interrupt, or will
387                                * the host OS do it? */
388 };
389
390
391 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;
392 typedef enum {V3_VCORE_UNKNOWN, V3_VCORE_INVALID, V3_VCORE_RUNNING, V3_VCORE_STOPPED} v3_vcore_state_t;
393 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;
394
395 typedef enum {V3_VCORE_MEM_STATE_UNKNOWN, V3_VCORE_MEM_STATE_SHADOW, V3_VCORE_MEM_STATE_NESTED} v3_vcore_mem_state_t;
396 typedef enum {V3_VCORE_MEM_MODE_UNKNOWN, V3_VCORE_MEM_MODE_PHYSICAL, V3_VCORE_MEM_MODE_VIRTUAL} v3_vcore_mem_mode_t;
397
398
399 struct v3_vm_base_state {
400     v3_vm_state_t       state;
401 };
402
403 struct v3_vm_vcore_state {
404   v3_vcore_state_t state;
405   v3_vcore_cpu_mode_t cpu_mode;
406   v3_vcore_mem_state_t mem_state;
407   v3_vcore_mem_mode_t mem_mode;
408   unsigned long pcore;
409   void *   last_rip;
410   unsigned long long num_exits;
411 };
412
413 struct v3_vm_core_state {
414     unsigned long         num_vcores;
415     struct v3_vm_vcore_state vcore[];
416 };
417
418 struct v3_vm_mem_region {
419     void               *host_paddr;
420     unsigned long long  size;
421     int                 swapped;
422     int                 pinned;
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, unsigned int cpu_mask);
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