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.


HRT image replacement from ROS application
[palacios.git] / guest / linux / hvm-ros / v3_hvm_ros_user.c
1 /*
2   Copyright (c) 2015 Peter Dinda
3 */
4
5 #include <sys/syscall.h>
6 #include <unistd.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11
12
13 #include "v3_hvm_ros_user.h"
14
15
16 #define DEBUG_OUTPUT 0
17 #define INFO_OUTPUT 0
18
19 #if DEBUG_OUTPUT
20 #define DEBUG(...) fprintf(stderr,__VA_ARGS__)
21 #else
22 #define DEBUG(...)
23 #endif
24
25 #if INFO_OUTPUT
26 #define INFO(...) fprintf(stdout,__VA_ARGS__)
27 #else
28 #define INFO(...)
29 #endif
30
31
32
33 typedef unsigned char uchar_t;
34
35 #define rdtscll(val)                                    \
36     do {                                                \
37         uint64_t tsc;                                   \
38         uint32_t a, d;                                  \
39         asm volatile("rdtsc" : "=a" (a), "=d" (d));     \
40         *(uint32_t *)&(tsc) = a;                        \
41         *(uint32_t *)(((uchar_t *)&tsc) + 4) = d;       \
42         val = tsc;                                      \
43     } while (0)                                 
44
45
46 /*
47   This convention match the definition in palacios/include/palacios/vmm_hvm.h
48
49   Calling convention:
50
51 64 bit:
52   rax = hcall number
53   rbx = 0x6464646464646464...
54   rcx = 1st arg
55   rdx = 2nd arg
56   rsi = 3rd arg
57   rdi = 4th arg
58   r8  = 5th arg
59   r9  = 6th arg
60   r10 = 7th arg
61   r11 = 8th arg
62
63 32 bit:
64   eax = hcall number
65   ebx = 0x32323232
66   arguments on stack in C order (first argument is TOS)
67      arguments are also 32 bit
68 */
69 #define HCALL64(rc,id,a,b,c,d,e,f,g,h)                \
70   asm volatile ("movq %1, %%rax; "                    \
71                 "pushq %%rbx; "                       \
72                 "movq $0x6464646464646464, %%rbx; "   \
73                 "movq %2, %%rcx; "                    \
74                 "movq %3, %%rdx; "                    \
75                 "movq %4, %%rsi; "                    \
76                 "movq %5, %%rdi; "                    \
77                 "movq %6, %%r8 ; "                    \
78                 "movq %7, %%r9 ; "                    \
79                 "movq %8, %%r10; "                    \
80                 "movq %9, %%r11; "                    \
81                 "vmmcall ;       "                    \
82                 "movq %%rax, %0; "                    \
83                 "popq %%rbx; "                        \
84                 : "=m"(rc)                            \
85                 : "m"(id),                            \
86                   "m"(a), "m"(b), "m"(c), "m"(d),     \
87                   "m"(e), "m"(f), "m"(g), "m"(h)      \
88                 : "%rax","%rcx","%rdx","%rsi","%rdi", \
89                   "%r8","%r9","%r10","%r11"           \
90                 )
91
92 #define HCALL32(rc,id,a,b,c,d,e,f,g,h)                \
93   asm volatile ("movl %1, %%eax; "                    \
94                 "pushl %%ebx; "                       \
95                 "movl $0x32323232, %%ebx; "           \
96                 "pushl %9;"                           \
97                 "pushl %8;"                           \
98                 "pushl %7;"                           \
99                 "pushl %6;"                           \
100                 "pushl %5;"                           \
101                 "pushl %4;"                           \
102                 "pushl %3;"                           \
103                 "pushl %2;"                           \
104                 "vmmcall ;       "                    \
105                 "movl %%eax, %0; "                    \
106                 "addl $32, %%esp; "                   \
107                 "popl %%ebx; "                        \
108                 : "=r"(rc)                            \
109                 : "m"(id),                            \
110                   "m"(a), "m"(b), "m"(c), "m"(d),     \
111                 "m"(e), "m"(f), "m"(g), "m"(h)        \
112                 : "%eax"                              \
113                 )
114
115 #ifdef __x86_64__
116 #define HCALL(rc,id,a,b,c,d,e,f,g,h)  HCALL64(rc,id,a,b,c,d,e,f,g,h)
117 #else
118 #define HCALL(rc,id,a,b,c,d,e,f,g,h)  HCALL32(rc,id,a,b,c,d,e,f,g,h)   
119 #endif
120
121
122 /* This must match the definition in palacios/include/palacios/vmm_hvm.h" */
123 struct v3_ros_event {
124     enum { ROS_NONE=0, ROS_PAGE_FAULT=1, ROS_SYSCALL=2 } event_type;
125     uint64_t       last_ros_event_result; // valid when ROS_NONE
126     union {
127         struct {   // valid when ROS_PAGE_FAULT
128             uint64_t rip;
129             uint64_t cr2;
130             enum {ROS_READ, ROS_WRITE} action;
131         } page_fault;
132         struct { // valid when ROS_SYSCALL
133             uint64_t args[8];
134         } syscall;
135     };
136 };
137
138
139 int v3_hvm_ros_user_init()
140 {
141     // currently nothing to do
142     return 0;
143 }
144
145 int v3_hvm_ros_user_deinit()
146 {
147     // currently nothing to do
148     return 0;
149 }
150
151 static void handle_ros_event(struct v3_ros_event *event)
152 {
153     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
154     char t;
155
156     switch (event->event_type) { 
157         case ROS_PAGE_FAULT: 
158             // force the ros kernel to the PTE
159             if (event->page_fault.action==ROS_READ) { 
160                 DEBUG("Handling page fault read for %p\n", (volatile char*)(event->page_fault.cr2));
161                 t=*(volatile char*)(event->page_fault.cr2);
162                 t=t; // avoid wanting for this throwaway
163             } else if (event->page_fault.action==ROS_WRITE) { 
164                 DEBUG("Handling page fault writefor %p\n", (volatile char*)(event->page_fault.cr2));
165                 *(volatile char*)(event->page_fault.cr2) = *(volatile char *)(event->page_fault.cr2);
166             } else {
167                 INFO("Huh?\n");
168             }
169             DEBUG("Done - doing hypercall\n");
170             num = 0xf00d;
171             a1 = 0x1f;
172             a2 = 0; // success
173             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
174             // completed
175             DEBUG("Completed.\n");
176
177             break;
178             
179         case ROS_SYSCALL:
180             DEBUG("Doing system call: syscall(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
181                     event->syscall.args[0],
182                     event->syscall.args[1],
183                     event->syscall.args[2],
184                     event->syscall.args[3],
185                     event->syscall.args[4],
186                     event->syscall.args[5],
187                     event->syscall.args[6],
188                     event->syscall.args[7]);
189
190             rc = syscall(event->syscall.args[0],
191                          event->syscall.args[1],
192                          event->syscall.args[2],
193                          event->syscall.args[3],
194                          event->syscall.args[4],
195                          event->syscall.args[5],
196                          event->syscall.args[6],
197                          event->syscall.args[7]);
198
199             if ((int)rc<0) {
200                 DEBUG("syscall failed");
201             }
202
203             DEBUG("Return = 0x%llx, doing hypercall\n", rc);
204             num = 0xf00d;
205             a1 = 0x1f;
206             a2 = rc;
207             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
208             DEBUG("Completed\n");
209
210             break;
211         default:
212             DEBUG( "Unknown ROS event 0x%x\n", event->event_type);
213             break;
214     }
215 }
216     
217     
218
219 static void wait_for_completion()
220 {
221   unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
222   struct v3_ros_event event;
223
224   memset(&event, 1, sizeof(event));
225
226   rc = 1;
227
228   while (rc) { 
229     num = 0xf00d;
230     a1 = 0xf;
231     a2 = (unsigned long long) &event;
232     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
233     if (rc) { 
234         //      usleep(100);
235         if (event.event_type != ROS_NONE) { 
236             handle_ros_event(&event);
237         }
238     }
239   }
240 }
241
242
243 int v3_hvm_ros_install_hrt_image(void *image, uint64_t size)
244 {
245     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
246     unsigned long long i;
247     volatile long long sum=0;
248
249     num = 0xf00d;
250     a1 = 0x8; // install image
251     a2 = (unsigned long long) image;
252     a3 = size;
253
254     // touch the whoel image to make it has ptes
255     for (i=0;i<size;i++) { 
256         sum+=((char*)image)[i];
257     }
258
259     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
260
261     if (rc) { 
262         return -1;
263     } else {
264         return 0;
265     }
266 }
267
268 int v3_hvm_ros_reset(reset_type what)
269 {
270     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
271     unsigned long long rc;
272     
273     num=0xf00d;
274     switch (what) { 
275         case RESET_ROS:
276             a1 = 0x1;
277             break;
278         case RESET_HRT:
279             a1 = 0x2;
280             break;
281         case RESET_BOTH:
282             a1 = 0x3;
283             break;
284     }
285     
286     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
287     
288     if (rc) {
289         INFO("Error in request to reset rc=0x%llx\n",rc);
290         return -1;
291     } else {
292         // no waiting for completion here
293         return 0;
294     }
295 }
296
297
298 int v3_hvm_ros_merge_address_spaces()
299 {
300     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
301     unsigned long long rc;
302
303     num=0xf00d;
304     a1 = 0x30; // merge address spaces
305     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
306     if (rc) {
307       INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
308       return -1;
309     } else {
310       wait_for_completion();
311       return 0;
312     }
313 }
314
315 int v3_hvm_ros_unmerge_address_spaces()
316 {
317     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
318     unsigned long long rc;
319
320     num=0xf00d;
321     a1 = 0x31; // merge address spaces
322     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
323     if (rc) {
324       INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
325       return -1;
326     } else {
327       wait_for_completion();
328       return 0;
329     }
330 }
331
332
333 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
334 {
335     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
336     unsigned long long rc;
337
338     num=0xf00d;
339     if (par) { 
340         a1 = 0x21; // issue "function" in parallel
341     } else {
342         a1 = 0x20; // issue "function" sequentially
343     }
344     a2 = (unsigned long long) buf;
345     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
346     if (rc) { 
347         INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
348         return -1;
349     } else {
350         wait_for_completion();
351         return 0;
352     }
353 }
354
355
356
357
358
359 /*
360   Synchronous operation model 
361
362   On ROS:
363
364   [0] => issue count
365   [1] => completion count
366   [2] => function call ptr
367
368   1. merge
369   2. indicate this is the address for sync
370   3. ++[0]
371   4. wait for [1] to match
372   5. goto 3
373
374   On HRT:
375
376   1. merge
377   2. cnt=1;
378   3. wait for [0] to get to cnt
379   4. exec
380   5. ++[1]   ++cnt
381   6. goto 3
382 */
383
384 static volatile unsigned long long sync_proto[3]={0,0,0};
385
386
387 static void wait_for_sync()
388 {
389   unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
390   struct v3_ros_event event;
391
392   memset(&event, 1, sizeof(event));
393   
394   rc = 1;
395
396   while (rc!=4) { 
397     num = 0xf00d;
398     a1 = 0xf;
399     a2 = (unsigned long long) &event;
400     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
401     if (rc!=4) { 
402         //      usleep(100);
403         if (event.event_type != ROS_NONE) { 
404             handle_ros_event(&event);
405         }
406     }
407   }
408 }
409
410
411 int v3_hvm_ros_synchronize()
412 {
413     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
414     unsigned long long rc;
415
416     // make sure this address is touched, then zero
417     sync_proto[0]=sync_proto[1]=sync_proto[2]=1;
418     sync_proto[0]=sync_proto[1]=sync_proto[2]=0;
419
420     num=0xf00d;
421     a1 = 0x28; // issue sync request setup
422     a2 = (unsigned long long) sync_proto;
423     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
424     
425     if (rc) { 
426         INFO("Synchronize call failed with rc=0x%llx\n",rc);
427         return -1;
428     } else {
429         wait_for_sync();
430         return 0;
431     }
432 }
433
434
435 int v3_hvm_ros_desynchronize()
436 {
437     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
438     unsigned long long rc;
439
440     num=0xf00d;
441     a1 = 0x29; // issue sync request teardown
442     a2 = (unsigned long long) sync_proto;
443     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
444
445     if (rc) { 
446         INFO("Desynchronize call failed with rc=0x%llx\n",rc);
447         return -1;
448     } else {
449         wait_for_completion();
450         return 0;
451     }
452 }
453
454 #define HOW_OFTEN 1000000
455
456 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
457 {
458     int i;
459     sync_proto[2]=(unsigned long long)buf;
460     sync_proto[0]++;
461
462     i=0;
463     while (sync_proto[1] != sync_proto[0]) {
464         i++;
465         if (ros && (!i%HOW_OFTEN)) { 
466             unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
467             struct v3_ros_event event;
468
469             memset(&event, 1, sizeof(event));
470
471             num = 0xf00d;
472             a1 = 0xf;
473             a2 = (unsigned long long) &event;
474             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
475             if (event.event_type != ROS_NONE) { 
476                 handle_ros_event(&event);
477             }
478         }
479     }   
480     return 0;
481 }
482