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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[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
26 #ifdef __V3VEE__
27 #include <palacios/vmm_mem.h>
28 #include <palacios/vmm_types.h>
29 #include <palacios/vmm_string.h>
30
31
32
33
34 /* utility definitions */
35
36 #define VM_NONE ((struct v3_vm_info *)0)
37 #define VCORE_NONE ((struct guest_info *)0)
38
39 void    *v3_get_host_vm(struct v3_vm_info *);
40 int      v3_get_vcore(struct guest_info *);
41
42 #define V3_Print(vm, vcore, fmt, args...)       \
43   do {                                                          \
44     extern struct v3_os_hooks * os_hooks;                       \
45     if ((os_hooks) && (os_hooks)->print) {                      \
46       (os_hooks)->print(v3_get_host_vm(vm), v3_get_vcore(vcore), (fmt), ##args); \
47     }                                                                   \
48   } while (0)   
49
50
51 #define PrintDebug(vm, vcore, fmt, args...)   V3_Print(vm, vcore, "DEBUG: " fmt, ##args)
52
53 #define PrintError(vm, vcore, fmt, args...)  V3_Print(vm, vcore, "ERROR at %s(%d): " fmt, __FILE__, __LINE__, ##args)
54
55
56
57 /* 4KB-aligned */
58 #define V3_AllocPages(num_pages)                                        \
59     ({                                                                  \
60         extern struct v3_os_hooks * os_hooks;                           \
61         void * ptr = 0;                                                 \
62         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
63             ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB);  \
64         }                                                               \
65         ptr;                                                            \
66     })
67
68
69 #define V3_AllocAlignedPages(num_pages, align)                          \
70     ({                                                                  \
71         extern struct v3_os_hooks * os_hooks;                           \
72         void * ptr = 0;                                                 \
73         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
74             ptr = (os_hooks)->allocate_pages(num_pages,align);          \
75         }                                                               \
76         ptr;                                                            \
77     })
78
79
80 #define V3_FreePages(page, num_pages)                   \
81     do {                                                \
82         extern struct v3_os_hooks * os_hooks;           \
83         if ((os_hooks) && (os_hooks)->free_pages) {     \
84             (os_hooks)->free_pages(page, num_pages);    \
85         }                                               \
86     } while(0)
87
88
89 #define V3_VAddr(addr) ({                                       \
90             extern struct v3_os_hooks * os_hooks;               \
91             void * var = 0;                                     \
92             if ((os_hooks) && (os_hooks)->paddr_to_vaddr) {     \
93                 var = (os_hooks)->paddr_to_vaddr(addr);         \
94             }                                                   \
95             var;                                                \
96         })
97
98
99 #define V3_PAddr(addr) ({                                       \
100             extern struct v3_os_hooks * os_hooks;               \
101             void * var = 0;                                     \
102             if ((os_hooks) && (os_hooks)->vaddr_to_paddr) {     \
103                 var = (os_hooks)->vaddr_to_paddr(addr);         \
104             }                                                   \
105             var;                                                \
106         })
107
108
109
110 #define V3_Malloc(size) ({                              \
111             extern struct v3_os_hooks * os_hooks;       \
112             void * var = 0;                             \
113             if ((os_hooks) && (os_hooks)->malloc) {     \
114                 var = (os_hooks)->malloc(size);         \
115             }                                           \
116             if (!var) PrintError(VM_NONE,VCORE_NONE,"MALLOC FAILURE. Memory LEAK!!\n"); \
117             var;                                        \
118         })
119
120 // We need to check the hook structure at runtime to ensure its SAFE
121 #define V3_Free(addr)                           \
122     do {                                        \
123         extern struct v3_os_hooks * os_hooks;   \
124         if ((os_hooks) && (os_hooks)->free) {   \
125             (os_hooks)->free(addr);             \
126         }                                       \
127     } while (0)
128
129 // uint_t V3_CPU_KHZ();
130 #define V3_CPU_KHZ() ({                                                 \
131             unsigned int khz = 0;                                       \
132             extern struct v3_os_hooks * os_hooks;                       \
133             if ((os_hooks) && (os_hooks)->get_cpu_khz) {                \
134                 khz = (os_hooks)->get_cpu_khz();                        \
135             }                                                           \
136             khz;                                                        \
137         })                                                              \
138         
139
140
141
142 #define V3_Hook_Interrupt(vm, irq) ({                                   \
143             int ret = 0;                                                \
144             extern struct v3_os_hooks * os_hooks;                       \
145             if ((os_hooks) && (os_hooks)->hook_interrupt) {             \
146                 ret = (os_hooks)->hook_interrupt(vm, irq);              \
147             }                                                           \
148             ret;                                                        \
149         })                                                              \
150         
151
152 #define V3_ACK_IRQ(irq)                                         \
153     do {                                                        \
154         extern struct v3_os_hooks * os_hooks;                   \
155         if ((os_hooks) && (os_hooks)->ack_irq) {                \
156             (os_hooks)->ack_irq(irq);                           \
157         }                                                       \
158     } while (0)
159
160
161
162 #define V3_Get_CPU() ({                                                 \
163             int ret = 0;                                                \
164             extern struct v3_os_hooks * os_hooks;                       \
165             if ((os_hooks) && (os_hooks)->get_cpu) {                    \
166                 ret = (os_hooks)->get_cpu();                            \
167             }                                                           \
168             ret;                                                        \
169         })
170
171
172
173
174 #define V3_CREATE_THREAD(fn, arg, name) ({                              \
175             void * thread = NULL;                                       \
176             extern struct v3_os_hooks * os_hooks;                       \
177             if ((os_hooks) && (os_hooks)->start_kernel_thread) {        \
178                 thread = (os_hooks)->start_kernel_thread(fn, arg, name); \
179             }                                                           \
180             thread;                                                     \
181         })
182
183
184
185
186 #define V3_Call_On_CPU(cpu, fn, arg)                    \
187     do {                                                \
188         extern struct v3_os_hooks * os_hooks;           \
189         if ((os_hooks) && (os_hooks)->call_on_cpu) {    \
190             (os_hooks)->call_on_cpu(cpu, fn, arg);      \
191         }                                               \
192     } while (0)
193
194
195
196 #define V3_CREATE_THREAD_ON_CPU(cpu, fn, arg, name) ({                  \
197             void * thread = NULL;                                       \
198             extern struct v3_os_hooks * os_hooks;                       \
199             if ((os_hooks) && (os_hooks)->start_thread_on_cpu) {        \
200                 thread = (os_hooks)->start_thread_on_cpu(cpu, fn, arg, name); \
201             }                                                           \
202             thread;                                                     \
203         })
204
205 #define V3_MOVE_THREAD_TO_CPU(pcpu, thread) ({                          \
206         int ret = -1;                                                   \
207         extern struct v3_os_hooks * os_hooks;                           \
208         if((os_hooks) && (os_hooks)->move_thread_to_cpu) {              \
209             ret = (os_hooks)->move_thread_to_cpu(pcpu, thread);         \
210         }                                                               \
211         ret;                                                            \
212     })
213     
214
215 /* ** */
216
217
218 #define V3_ASSERT(vm, vcore, x)                                         \
219     do {                                                                \
220         extern struct v3_os_hooks * os_hooks;                           \
221         if (!(x)) {                                                     \
222           PrintDebug(vm, vcore, "Failed assertion in %s: %s at %s, line %d, RA=%lx\n", \
223                        __func__, #x, __FILE__, __LINE__,                \
224                        (ulong_t) __builtin_return_address(0));          \
225             while(1){                                                   \
226                 if ((os_hooks) && (os_hooks)->yield_cpu) {              \
227                         (os_hooks)->yield_cpu();                        \
228                 }                                                       \
229             }                                                           \
230         }                                                               \
231     } while(0)                                                          \
232         
233
234
235 #define V3_Yield()                                      \
236     do {                                                \
237         extern struct v3_os_hooks * os_hooks;           \
238         if ((os_hooks) && (os_hooks)->yield_cpu) {      \
239             (os_hooks)->yield_cpu();                    \
240         }                                               \
241     } while (0)                                         \
242
243
244 #define V3_Sleep(usec)                          \
245     do {                                                \
246         extern struct v3_os_hooks * os_hooks;           \
247         if ((os_hooks) && (os_hooks)->sleep_cpu) {\
248             (os_hooks)->sleep_cpu(usec);                \
249         } else {                                        \
250             V3_Yield();                                 \
251         }                                               \
252     }  while (0)                                        \
253
254 #define V3_Wakeup(cpu)                                  \
255     do {                                                \
256         extern struct v3_os_hooks * os_hooks;           \
257         if ((os_hooks) && (os_hooks)->wakeup_cpu) {     \
258             (os_hooks)->wakeup_cpu(cpu);                        \
259         }                                               \
260     } while (0)                                         \
261
262
263 typedef enum v3_vm_class {V3_INVALID_VM, V3_PC_VM, V3_CRAY_VM} v3_vm_class_t;
264
265
266 // Maybe make this a define....
267 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;
268
269
270 v3_cpu_mode_t v3_get_host_cpu_mode();
271
272 void v3_yield(struct guest_info * info, int usec);
273 void v3_yield_cond(struct guest_info * info, int usec);
274 void v3_print_cond(const char * fmt, ...);
275
276 void v3_interrupt_cpu(struct v3_vm_info * vm, int logical_cpu, int vector);
277
278
279
280 v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
281
282
283 int v3_vm_enter(struct guest_info * info);
284 int v3_reset_vm_core(struct guest_info * core, addr_t rip);
285
286
287 #endif /*!__V3VEE__ */
288
289
290
291 struct v3_vm_info;
292
293 /* This will contain function pointers that provide OS services */
294 struct v3_os_hooks {
295   // the vm pointer is the host os's "priv_data" from v3_create_vm
296   // if vm is null, this is a general palacios printout
297   // if vm is not null, and vcore is negative, this is a general print form the vm
298   // if vm is not null, and vcore is non-negative, this is a print from a specific vcore
299     void (*print)(void *vm, int vcore, const char * format, ...)
300         __attribute__ ((format (printf, 3, 4)));
301   
302     void *(*allocate_pages)(int num_pages, unsigned int alignment);
303     void (*free_pages)(void * page, int num_pages);
304
305     void *(*malloc)(unsigned int size);
306     void (*free)(void * addr);
307
308     void *(*paddr_to_vaddr)(void * addr);
309     void *(*vaddr_to_paddr)(void * addr);
310
311     int (*hook_interrupt)(struct v3_vm_info * vm, unsigned int irq);
312     int (*ack_irq)(int irq);
313
314     unsigned int (*get_cpu_khz)(void);
315
316     void (*yield_cpu)(void); 
317     void (*sleep_cpu)(unsigned int usec);
318     void (*wakeup_cpu)(void *cpu);
319
320     void *(*mutex_alloc)(void);
321     void (*mutex_free)(void * mutex);
322     void (*mutex_lock)(void * mutex, int must_spin);
323     void (*mutex_unlock)(void * mutex);
324     void *(*mutex_lock_irqsave)(void * mutex, int must_spin);
325     void (*mutex_unlock_irqrestore)(void * mutex, void *flags);
326
327     unsigned int (*get_cpu)(void);
328
329
330
331     void * (*start_kernel_thread)(int (*fn)(void * arg), void * arg, char * thread_name); 
332     void (*interrupt_cpu)(struct v3_vm_info * vm, int logical_cpu, int vector);
333     void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
334     void * (*start_thread_on_cpu)(int cpu_id, int (*fn)(void * arg), void * arg, char * thread_name);
335     int (*move_thread_to_cpu)(int cpu_id,  void * thread);
336 };
337
338
339 /*
340  *
341  * This is the interrupt state that the VMM's interrupt handlers need to see
342  */
343 struct v3_interrupt {
344     unsigned int irq;
345     unsigned int error;
346
347     unsigned int should_ack;  /* Should the vmm ack this interrupt, or will
348                                * the host OS do it? */
349 };
350
351
352 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;
353 typedef enum {V3_VCORE_UNKNOWN, V3_VCORE_INVALID, V3_VCORE_RUNNING, V3_VCORE_STOPPED} v3_vcore_state_t;
354 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;
355
356 typedef enum {V3_VCORE_MEM_STATE_UNKNOWN, V3_VCORE_MEM_STATE_SHADOW, V3_VCORE_MEM_STATE_NESTED} v3_vcore_mem_state_t;
357 typedef enum {V3_VCORE_MEM_MODE_UNKNOWN, V3_VCORE_MEM_MODE_PHYSICAL, V3_VCORE_MEM_MODE_VIRTUAL} v3_vcore_mem_mode_t;
358
359 struct v3_vcore_state {
360   v3_vcore_state_t state;
361   v3_vcore_cpu_mode_t cpu_mode;
362   v3_vcore_mem_state_t mem_state;
363   v3_vcore_mem_mode_t mem_mode;
364   unsigned long pcore;
365   void *   last_rip;
366   unsigned long long num_exits;
367 };
368
369 struct v3_vm_state {
370   v3_vm_state_t state;
371   void *   mem_base_paddr;
372   unsigned long long  mem_size;
373   unsigned long  num_vcores;
374   struct v3_vcore_state vcore[0];
375 };
376
377 void Init_V3(struct v3_os_hooks * hooks, char * cpus, int num_cpus);
378 void Shutdown_V3( void );
379
380
381 struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name);
382 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
383 int v3_stop_vm(struct v3_vm_info * vm);
384 int v3_pause_vm(struct v3_vm_info * vm);
385 int v3_continue_vm(struct v3_vm_info * vm);
386 int v3_simulate_vm(struct v3_vm_info * vm, unsigned int msecs);
387
388 int v3_save_vm(struct v3_vm_info * vm, char * store, char * url);
389 int v3_load_vm(struct v3_vm_info * vm, char * store, char * url);
390
391 int v3_send_vm(struct v3_vm_info * vm, char * store, char * url);
392 int v3_receive_vm(struct v3_vm_info * vm, char * store, char * url);
393
394 int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu);
395
396 int v3_free_vm(struct v3_vm_info * vm);
397
398 int v3_get_state_vm(struct v3_vm_info *vm, struct v3_vm_state *out);
399
400 int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
401
402
403 #endif