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.


Minor cleanup (eliminate dead code, correct errno return)
[palacios.git] / gears / services / devfile / devfile_host.c
1 /* 
2    Device File Virtualization Host Module 
3
4    (c) Akhil Guliani and William Gross, 2015
5      
6    Adapted from MPI module (c) 2012 Peter Dinda
7
8  */
9 #include <linux/fs.h>
10 #include <linux/namei.h>
11 #include <linux/version.h>
12 #include <linux/file.h>
13 #include <linux/spinlock.h>
14 #include <linux/uaccess.h>
15 #include <linux/module.h>
16
17 #include <linux/kernel.h>
18 #include <linux/slab.h>
19 #include <linux/mm.h>
20 #include <linux/sched.h>
21
22 #include <linux/syscalls.h>
23 #include <linux/init.h>
24 #include <linux/kmod.h>
25 #include <linux/delay.h>
26 #include <linux/wait.h>
27 #include <linux/poll.h>
28
29 #include <linux/file.h>
30 #include <linux/fcntl.h>
31 #include <linux/device.h>
32 #include <linux/cdev.h>
33
34 #include <asm/uaccess.h>
35
36 #include <asm/page.h>
37
38 #include <palacios/vm_guest_mem.h>
39 #include <interfaces/vmm_host_hypercall.h>
40
41
42 #include "devfile_hc.h"
43
44
45 #define DEEP_DEBUG    1
46 #define SHALLOW_DEBUG 1
47
48 #if DEEP_DEBUG
49 #define DEEP_DEBUG_PRINT(fmt, args...) printk(("devfile: " fmt), ##args)
50 #else
51 #define DEEP_DEBUG_PRINT(fmt, args...) 
52 #endif
53
54 #if SHALLOW_DEBUG
55 #define SHALLOW_DEBUG_PRINT(fmt, args...) printk(("devfile: " fmt), ##args)
56 #else
57 #define SHALLOW_DEBUG_PRINT(fmt, args...) 
58 #endif
59
60
61 #define ERROR(fmt, args...) printk(("devfile: " fmt), ##args)
62 #define INFO(fmt, args...) printk(("devfile: " fmt), ##args)
63
64 #define PRINT_CONSOLE(fmt,args...) printf(("devfile: " fmt),##args)
65
66
67
68
69 // Added to make unique id's for IOCTL
70 #define MY_MACIG 'G'
71 #define INIT_IOCTL _IOR(MY_MACIG, 0, int)
72 #define SHADOW_SYSCALL_DONE _IOW(MY_MACIG, 2, int)
73
74 #define DEVFILE_NAME "v3-devfile"
75
76 static int devfile_major_num = 0;
77 static struct class *devfile_class = 0;
78 static struct cdev devfile_dev;
79
80
81
82 struct devfile_state {
83     void     *shared_mem_va;
84     uint64_t  shared_mem_uva;
85     uint64_t  shared_mem_pa;
86     uint64_t returned_fd;
87
88     wait_queue_head_t user_wait_queue;
89     wait_queue_head_t host_wait_queue;
90
91     enum { WAIT_FOR_INIT, WAIT_ON_GUEST, WAIT_ON_SHADOW} state; 
92 } ;
93
94 // Currently this proof of concept supports a single userland/VM binding
95 // and is serially reusable
96 static struct devfile_state *state=0;
97
98 static inline struct devfile_state *find_matching_state(palacios_core_t core) { return state; } 
99
100
101 /* Hypercall helpers */ 
102
103 static void get_args_64(palacios_core_t core,
104                         struct guest_accessors *acc,
105                         uint64_t *a1,
106                         uint64_t *a2,
107                         uint64_t *a3,
108                         uint64_t *a4,
109                         uint64_t *a5,
110                         uint64_t *a6,
111                         uint64_t *a7,
112                         uint64_t *a8)
113 {
114     *a1 = acc->get_rcx(core);
115     *a2 = acc->get_rdx(core);
116     *a3 = acc->get_rsi(core);
117     *a4 = acc->get_rdi(core);
118     *a5 = acc->get_r8(core);
119     *a6 = acc->get_r9(core);
120     *a7 = acc->get_r10(core);
121     *a8 = acc->get_r11(core);
122 }
123
124 static void get_args_32(palacios_core_t core,
125                         struct guest_accessors *acc,
126                         uint64_t *a1,
127                         uint64_t *a2,
128                         uint64_t *a3,
129                         uint64_t *a4,
130                         uint64_t *a5,
131                         uint64_t *a6,
132                         uint64_t *a7,
133                         uint64_t *a8)
134 {
135     uint64_t rsp;
136     uint32_t temp;
137     
138     
139     rsp = acc->get_rsp(core);
140     
141     acc->read_gva(core,rsp,4,&temp); *a1=temp;
142     acc->read_gva(core,rsp+4,4,&temp); *a2=temp;
143     acc->read_gva(core,rsp+8,4,&temp); *a3=temp;
144     acc->read_gva(core,rsp+12,4,&temp); *a4=temp;
145     acc->read_gva(core,rsp+16,4,&temp); *a5=temp;
146     acc->read_gva(core,rsp+20,4,&temp); *a6=temp;
147     acc->read_gva(core,rsp+24,4,&temp); *a7=temp;
148     acc->read_gva(core,rsp+28,4,&temp); *a8=temp;
149 }
150
151 static void get_args(palacios_core_t core,
152                      struct guest_accessors *acc,
153                      uint64_t *a1,
154                      uint64_t *a2,
155                      uint64_t *a3,
156                      uint64_t *a4,
157                      uint64_t *a5,
158                      uint64_t *a6,
159                      uint64_t *a7,
160                      uint64_t *a8)
161 {
162     uint64_t rbx;
163     uint32_t ebx;
164     
165     rbx=acc->get_rbx(core);
166     ebx=rbx&0xffffffff;
167     
168     switch (ebx) {
169         case 0x64646464:
170             DEEP_DEBUG_PRINT("64 bit hcall\n");
171             return get_args_64(core,acc,a1,a2,a3,a4,a5,a6,a7,a8);
172             break;
173         case 0x32323232:
174             DEEP_DEBUG_PRINT("32 bit hcall\n");
175             return get_args_32(core,acc,a1,a2,a3,a4,a5,a6,a7,a8);
176             break;
177         default:
178             ERROR("UNKNOWN hcall calling convention\n");
179             break;
180     }
181 }
182
183 static void put_return(palacios_core_t core, 
184                        struct guest_accessors *acc,
185                        uint64_t rc,
186                        uint64_t errno)
187 {
188     acc->set_rax(core,rc);
189     acc->set_rbx(core,errno);
190 }
191         
192 /*
193   Convert all hypercall pointer arguments from GVAs to GPAs
194   The host userland is responsible for converting from 
195   GVAs to HVAs. 
196   
197   The assumption here is that any pointer argument
198   points to a structure that does NOT span a page
199   boundary.  The guest userland is responsible for
200   assuring that this is the case.
201 */           
202 static int deref_args(palacios_core_t core, 
203                       struct guest_accessors *acc,
204                       uint64_t* a1, uint64_t* a2, uint64_t* a3, uint64_t* a4, uint64_t* a5,
205                       uint64_t* a6, uint64_t bvec)
206 {
207     if (bvec & 1){
208         uint64_t a1tmp = *a1;
209         acc->gva_to_gpa(core,a1tmp,a1);
210     }
211     if (bvec & 2){
212         uint64_t a2tmp = *a2;
213         acc->gva_to_gpa(core,a2tmp,a2);
214     }
215     if (bvec & 4){
216         uint64_t a3tmp = *a3;
217         acc->gva_to_gpa(core,a3tmp,a3);
218     }
219     if (bvec & 8){
220         uint64_t a4tmp = *a4;
221         acc->gva_to_gpa(core,a4tmp,a4);
222     }
223     if (bvec & 16){
224         uint64_t a5tmp = *a5;
225         acc->gva_to_gpa(core,a5tmp,a5);
226     }
227     if (bvec & 32){
228         uint64_t a6tmp = *a6;
229         acc->gva_to_gpa(core,a6tmp,a6);
230     }
231     return 0; 
232 }
233
234
235
236 static uint64_t devfile_syscall_return(struct devfile_state *s, uint64_t *errno)
237 {
238     uint64_t rc;
239     uint64_t *shared_page = (uint64_t*)(s->shared_mem_va);
240
241     s->state=WAIT_ON_SHADOW;
242
243     // kick the the user if needed
244     //!! IDEA: We can add Usermode Helper to start shadow process instead
245     // and wait for it to send us an ioctl to wake up the module. 
246     wake_up_interruptible(&(s->user_wait_queue));
247     // goto sleep until we see a message received
248     // part of a separate ioctl
249     SHALLOW_DEBUG_PRINT("waiting For Shadow Process\n");
250     while (wait_event_interruptible(s->host_wait_queue, (s->state==WAIT_ON_GUEST)) != 0) {}
251     SHALLOW_DEBUG_PRINT("waiting done\n");
252     // Get the returned value and errno
253     rc     = *(shared_page +8);
254     *errno = *(shared_page +9);
255
256     SHALLOW_DEBUG_PRINT("waiting done %016llu (errno %016llu)\n",rc,*errno);
257     return rc;
258 }
259
260
261 static int devfile_syscall_hcall(struct devfile_state *s, 
262                                  palacios_core_t core,
263                                  uint64_t sys_code,
264                                  uint64_t a1, uint64_t a2,uint64_t a3, 
265                                  uint64_t a4, uint64_t a5, uint64_t a6, 
266                                  uint64_t bit_vec, 
267                                  uint64_t *errno)
268 {
269     //Using shared memory page
270     uint64_t ret;
271     uint64_t *shared_page = (uint64_t*)(s->shared_mem_va);
272
273     *(shared_page +0) = sys_code;
274     *(shared_page +1) = a1;
275     *(shared_page +2) = a2;
276     *(shared_page +3) = a3;
277     *(shared_page +4) = a4;
278     *(shared_page +5) = a5;
279     *(shared_page +6) = a6;
280     *(shared_page +7) = bit_vec;
281
282     SHALLOW_DEBUG_PRINT("Host Module to wait on shadow\n");
283
284     //Now wait for rc and errno to be written to the shared page
285     ret = devfile_syscall_return(s, errno);
286
287     SHALLOW_DEBUG_PRINT("SYSCALL HCALL %016llu (errno %016llu)\n",ret,*errno);
288
289     return ret;
290 }
291
292
293
294 // The main Interface for Hypercalls
295 int devfile_hypercall(palacios_core_t *core,
296                       unsigned int hid,
297                       struct guest_accessors *acc,
298                       void *p)
299 {
300     uint64_t a1,a2,a3,a4,a5,a6,bit_vec,sys_code;
301     uint64_t rc;
302     uint64_t errno;
303     
304     struct devfile_state *s = find_matching_state(core);
305
306     if (s->state == WAIT_FOR_INIT){
307         SHALLOW_DEBUG_PRINT("Shared Memory Not Yet Initialized, returning syscall hypercall\n");
308         return -1;
309     }
310     
311     sys_code = 0;
312     bit_vec = 0;
313     
314     DEEP_DEBUG_PRINT("devfile_hypercall(%p,0x%x,%p,%p)\n",
315                      core,hid,acc,p);
316     
317     get_args(core,acc,&sys_code,&a1,&a2,&a3,&a4,&a5,&a6,&bit_vec);
318
319     DEEP_DEBUG_PRINT("original arguments: %016llu, %016llu, %016llu, %016llu, %016llu, %016llu, %016llu, %016llu\n",
320                      sys_code,a1,a2,a3,a4,a5,a6,bit_vec);
321     
322     // Convert any pointer arguments from GVAs to GPAs
323     deref_args(core,acc,&a1,&a2,&a3,&a4,&a5,&a6,bit_vec);
324
325     DEEP_DEBUG_PRINT("derefed arguments: %016llu, %016llu, %016llu, %016llu, %016llu, %016llu, %016llu, %016llu\n",
326                      sys_code,a1,a2,a3,a4,a5,a6,bit_vec);
327
328     rc = devfile_syscall_hcall(s,core,sys_code,a1,a2,a3,a4,a5,a6,bit_vec,&errno);
329
330     SHALLOW_DEBUG_PRINT("Syscall rc: %016llu errno=%016llu\n",rc,errno);
331
332     put_return(core,acc,rc,errno);
333
334     return 0;
335
336
337
338
339 static int devfile_open(struct inode * inode, struct file * filp) 
340 {
341     struct devfile_state *s = state;
342     
343     if (s) { 
344         ERROR("attempting to open devfile that is already open\n");
345         return -EINVAL;
346     }
347
348     s=(struct devfile_state*)kmalloc(sizeof(struct devfile_state),GFP_KERNEL);
349
350     if (!s) { 
351         ERROR("Failed to allocate space for open\n");
352         return -EINVAL;
353     }
354
355     // This hideousness is here because in this POC we
356     // are simply allowing a single userland to be tied to 
357     // a single VM.   At the same time, we are making 
358     // the rest of the code more flexible for the future
359     state = s;
360
361     memset(s,0,sizeof(*s));
362
363     init_waitqueue_head(&s->user_wait_queue);
364     init_waitqueue_head(&s->host_wait_queue);
365
366     s->state = WAIT_FOR_INIT;
367         
368     filp->private_data = (void*) s;
369
370     return 0;
371 }
372
373 static int devfile_close(struct inode * inode, struct file * filp) 
374 {
375     struct devfile_state *s = filp->private_data;
376     
377     if (s) { 
378         if (s->state==WAIT_ON_SHADOW) { 
379             ERROR("Odd, userland is closing devfile while we are waiting for it\n");
380         }
381         kfree(s);
382         state=0;
383     }
384     
385     return 0;
386
387 }
388
389
390 static long devfile_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 
391 {
392     struct devfile_state *s = filp->private_data;
393
394     switch(cmd) {
395         case INIT_IOCTL:    
396             s->shared_mem_pa = (uint64_t)arg;
397             s->shared_mem_va = __va(s->shared_mem_pa);
398             SHALLOW_DEBUG_PRINT("Shared Memory Physical Address: %016llu\n",s->shared_mem_pa);
399             SHALLOW_DEBUG_PRINT("Shared Memory Kernel VA: %p\n",s->shared_mem_va);
400             //Change State to wait on guest
401             s->state = WAIT_ON_GUEST;
402             break;
403             
404         case SHADOW_SYSCALL_DONE:
405             s->state = WAIT_ON_GUEST;
406             wake_up_interruptible(&(s->host_wait_queue));
407             break;
408
409         default:
410             return -EINVAL;
411     }
412
413     return 0;
414
415 }
416
417
418 static unsigned int devfile_poll(struct file * filp, 
419                                  struct poll_table_struct * poll_tb) 
420 {
421     struct devfile_state *s = filp->private_data;
422
423     SHALLOW_DEBUG_PRINT("poll\n");
424
425     // register ourselves on the user wait queue
426     poll_wait(filp, &(s->user_wait_queue), poll_tb);
427
428     if (s->state==WAIT_ON_SHADOW) { 
429         // Yes, we have a request if you want it!
430         DEEP_DEBUG_PRINT("poll done immediate\n");
431         return  POLLIN | POLLRDNORM;
432     } 
433     // No request yet, so we need to wait for one to show up.
434     DEEP_DEBUG_PRINT("poll delayed\n");
435     // We will get called again when that queue is woken up
436
437     return 0;
438 }
439
440 static struct file_operations devfile_fops = {
441     .open     = devfile_open,
442     .release  = devfile_close,
443     .poll     = devfile_poll,
444     .unlocked_ioctl = devfile_ioctl,
445     .compat_ioctl = devfile_ioctl
446 };
447
448 EXPORT_SYMBOL(devfile_hypercall);
449
450 int init_module(void) 
451 {
452     dev_t dev;
453
454     SHALLOW_DEBUG_PRINT("INIT\n");
455   
456     devfile_class = class_create(THIS_MODULE,"devfile");
457     if (!devfile_class || IS_ERR(devfile_class)) { 
458         ERROR("Cannot register devfile device class\n");
459         return PTR_ERR(devfile_class);
460     }
461
462     dev = MKDEV(0,0);
463
464     if (alloc_chrdev_region(&dev,0,1,"devfile")<0) {
465         ERROR("Failed to alloc chrdev region\n");
466         return -1;
467     }
468
469     devfile_major_num = MAJOR(dev);
470
471     dev = MKDEV(devfile_major_num,1);
472
473     cdev_init(&devfile_dev, &devfile_fops);
474     devfile_dev.owner = THIS_MODULE;
475     devfile_dev.ops = &devfile_fops;
476     cdev_add(&devfile_dev, dev, 1);
477     
478     device_create(devfile_class, NULL, dev, NULL, "v3-devfile");
479
480
481     INFO("inited\n");
482     
483     return 0;
484 }
485
486 void cleanup_module(void) 
487 {
488     dev_t dev = MKDEV(devfile_major_num,1);
489
490     unregister_chrdev_region(MKDEV(devfile_major_num,0),1);
491     cdev_del(&devfile_dev);
492     device_destroy(devfile_class,dev);
493     class_destroy(devfile_class);
494
495     if (state) {
496         kfree(state);
497     }
498
499     INFO("deinited\n");
500 }
501
502
503 MODULE_LICENSE("GPL");