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.


Extensions to HVM ROS userspace library corresponding to HVM enhancements
[palacios.git] / guest / linux / hvm-ros / v3_hvm_ros_user.c
1 /*
2   Copyright (c) 2015 Peter Dinda
3 */
4
5 #include <unistd.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <syscall.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include <sys/mman.h>
14
15 #include "v3_hvm_ros_user.h"
16
17
18 #define HRT_FAIL_VEC 0x1d
19
20 static FILE *log = NULL;
21
22
23 #if DEBUG_ENABLE==1
24 #define DEBUG(fmt, args...) if (log) { fprintf(log, "DEBUG: " fmt, ##args); }
25 #else
26 #define DEBUG(...)
27 #endif
28
29 #if INFO_ENABLE==1
30 #define INFO(fmt, args...) if (log) {  fprintf(log, fmt, ##args); }
31         fprintf(stdout, fmt, ##args); \
32     }
33 #else
34 #define INFO(...)
35 #endif
36
37
38
39 typedef unsigned char uchar_t;
40
41 #define rdtscll(val)                                    \
42     do {                                                \
43         uint64_t tsc;                                   \
44         uint32_t a, d;                                  \
45         asm volatile("rdtsc" : "=a" (a), "=d" (d));     \
46         *(uint32_t *)&(tsc) = a;                        \
47         *(uint32_t *)(((uchar_t *)&tsc) + 4) = d;       \
48         val = tsc;                                      \
49     } while (0)                                 
50
51
52 /*
53   This convention match the definition in palacios/include/palacios/vmm_hvm.h
54
55   Calling convention:
56
57 64 bit:
58   rax = hcall number
59   rbx = 0x6464646464646464...
60   rcx = 1st arg
61   rdx = 2nd arg
62   rsi = 3rd arg
63   rdi = 4th arg
64   r8  = 5th arg
65   r9  = 6th arg
66   r10 = 7th arg
67   r11 = 8th arg
68
69 32 bit:
70   eax = hcall number
71   ebx = 0x32323232
72   arguments on stack in C order (first argument is TOS)
73      arguments are also 32 bit
74 */
75 #define HCALL64(rc,id,a,b,c,d,e,f,g,h)                \
76   asm volatile ("movq %1, %%rax; "                    \
77                 "pushq %%rbx; "                       \
78                 "movq $0x6464646464646464, %%rbx; "   \
79                 "movq %2, %%rcx; "                    \
80                 "movq %3, %%rdx; "                    \
81                 "movq %4, %%rsi; "                    \
82                 "movq %5, %%rdi; "                    \
83                 "movq %6, %%r8 ; "                    \
84                 "movq %7, %%r9 ; "                    \
85                 "movq %8, %%r10; "                    \
86                 "movq %9, %%r11; "                    \
87                 "vmmcall ;       "                    \
88                 "movq %%rax, %0; "                    \
89                 "popq %%rbx; "                        \
90                 : "=m"(rc)                            \
91                 : "m"(id),                            \
92                   "m"(a), "m"(b), "m"(c), "m"(d),     \
93                   "m"(e), "m"(f), "m"(g), "m"(h)      \
94                 : "%rax","%rcx","%rdx","%rsi","%rdi", \
95                   "%r8","%r9","%r10","%r11"           \
96                 )
97
98 #define HCALL32(rc,id,a,b,c,d,e,f,g,h)                \
99   asm volatile ("movl %1, %%eax; "                    \
100                 "pushl %%ebx; "                       \
101                 "movl $0x32323232, %%ebx; "           \
102                 "pushl %9;"                           \
103                 "pushl %8;"                           \
104                 "pushl %7;"                           \
105                 "pushl %6;"                           \
106                 "pushl %5;"                           \
107                 "pushl %4;"                           \
108                 "pushl %3;"                           \
109                 "pushl %2;"                           \
110                 "vmmcall ;       "                    \
111                 "movl %%eax, %0; "                    \
112                 "addl $32, %%esp; "                   \
113                 "popl %%ebx; "                        \
114                 : "=r"(rc)                            \
115                 : "m"(id),                            \
116                   "m"(a), "m"(b), "m"(c), "m"(d),     \
117                 "m"(e), "m"(f), "m"(g), "m"(h)        \
118                 : "%eax"                              \
119                 )
120
121 #ifdef __x86_64__
122 #define HCALL(rc,id,a,b,c,d,e,f,g,h)  HCALL64(rc,id,a,b,c,d,e,f,g,h)
123 #else
124 #define HCALL(rc,id,a,b,c,d,e,f,g,h)  HCALL32(rc,id,a,b,c,d,e,f,g,h)   
125 #endif
126
127 static inline uint64_t 
128 Syscall (uint64_t num, 
129                  uint64_t a1,
130                  uint64_t a2,
131                  uint64_t a3,
132                  uint64_t a4,
133                  uint64_t a5,
134                  uint64_t a6)
135 {
136     uint64_t rc;
137
138     __asm__ __volatile__ ("movq %1, %%rax; "
139                           "movq %2, %%rdi; "
140                           "movq %3, %%rsi; "
141                           "movq %4, %%rdx; "
142                           "movq %5, %%r10; "
143                           "movq %6, %%r8; "
144                           "movq %7, %%r9; "
145                           "syscall; "
146                           "movq %%rax, %0; "
147                           : "=m"(rc)
148                           : "m"(num), "m"(a1), "m"(a2), "m"(a3), "m"(a4), "m"(a5), "m"(a6)
149                           : "%rax", "%rdi", "%rcx", "%rsi", "%rdx", "%r10", "%r8", "%r9", "%r11", "memory");
150
151     return rc;
152 }
153
154
155 /* This must match the definition in palacios/include/palacios/vmm_hvm.h" */
156 struct v3_ros_event {
157     enum { ROS_NONE=0, ROS_PAGE_FAULT=1, ROS_SYSCALL=2, HRT_EXCEPTION=3, HRT_THREAD_EXIT=4, ROS_DONE=5} event_type;
158     uint64_t       last_ros_event_result; // valid when ROS_NONE
159     union {
160         struct {   // valid when ROS_PAGE_FAULT
161             uint64_t rip;
162             uint64_t cr2;
163             enum {ROS_READ, ROS_WRITE} action;
164         } page_fault;
165         struct { // valid when ROS_SYSCALL
166             uint64_t args[8];
167         } syscall;
168     struct { // valid when HRT_EXCEPTION
169         uint64_t rip;
170         uint64_t vector;
171     } excp;
172     struct { // valid when HRT_THREAD_EXIT
173         uint64_t nktid;
174     } thread_exit;
175     };
176 };
177
178
179 int v3_hvm_ros_user_init()
180 {
181     log = stderr;
182     return 0;
183 }
184
185
186 int v3_hvm_ros_user_set_log(FILE *l)
187 {
188     log = l;
189     return 0;
190 }
191
192 int v3_hvm_ros_user_deinit()
193 {
194     log = NULL;
195     return 0;
196 }
197
198
199 int v3_hvm_handle_ros_event_nohcall(struct v3_ros_event *event)
200 {
201     uint64_t rc;
202     char t;
203     
204     switch (event->event_type) { 
205         case ROS_PAGE_FAULT: 
206             // force the ros kernel to the PTE
207             if (event->page_fault.action==ROS_READ) { 
208                 DEBUG("EVENT [PF READ] : %p\n", (volatile char*)(event->page_fault.cr2));
209                 t=*(volatile char*)(event->page_fault.cr2);
210                 t=t; // avoid wanting for this throwaway
211             } else if (event->page_fault.action==ROS_WRITE) { 
212                 DEBUG("EVENT [PF WRITE] : %p\n", (volatile char*)(event->page_fault.cr2));
213                 
214                 // stash the old contents
215                 char tmp = *((volatile char *)event->page_fault.cr2);
216                 
217                 // force a write
218                 *((volatile char*)event->page_fault.cr2) = 0xa;
219                 
220                 // put the old value back
221                 *((volatile char*)event->page_fault.cr2) = tmp;
222                 
223             } else {
224                 INFO("Huh?\n");
225             }
226             
227             DEBUG("Done.");
228             event->last_ros_event_result = 0;
229             //event->event_type            = ROS_DONE;
230             event->event_type            = ROS_NONE;
231             // completed
232             DEBUG("[OK]\n");
233             
234             break;
235             
236         case ROS_SYSCALL:
237             DEBUG("EVENT [SYSCALL] : syscall(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
238                   event->syscall.args[0],
239                   event->syscall.args[1],
240                   event->syscall.args[2],
241                   event->syscall.args[3],
242                   event->syscall.args[4],
243                   event->syscall.args[5],
244                   event->syscall.args[6],
245                   event->syscall.args[7]);
246             
247             rc = Syscall(event->syscall.args[0],
248                          event->syscall.args[1],
249                          event->syscall.args[2],
250                          event->syscall.args[3],
251                          event->syscall.args[4],
252                          event->syscall.args[5],
253                          event->syscall.args[6]);
254             
255             if ((long int)rc<0) {
256                 DEBUG("Syscall (num=0x%llx) failed (rc=0x%llx)\n", (unsigned long long)event->syscall.args[0], (unsigned long long)rc);
257             }
258             
259             DEBUG("Return = 0x%lx...", rc);
260             event->last_ros_event_result = rc;
261             //event->event_type            = ROS_DONE;
262             event->event_type            = ROS_NONE;
263             DEBUG("[OK]\n");
264             
265             break;
266             
267         case HRT_EXCEPTION:
268             DEBUG("EVENT [EXCEPTION] : (tid=%lx) at %p vector=0x%lx...", syscall(SYS_gettid), (void*)event->excp.rip, event->excp.vector);
269             if (event->excp.vector == HRT_FAIL_VEC) {
270                 INFO("HRT execution failed due to exception in HRT\n");
271             } else {
272                 INFO("HRT execution failed due to exception in ROS (vec=0x%lx)\n", event->excp.vector);
273             }
274             
275             event->last_ros_event_result = 0;
276             //event->event_type            = ROS_DONE;
277             event->event_type            = ROS_NONE;
278             DEBUG("[OK]\n");
279             exit(EXIT_FAILURE);
280             break;
281
282         default:
283             DEBUG( "Unknown ROS event 0x%x\n", event->event_type);
284             break;
285     }
286     
287     return 0;
288 }
289
290
291 int v3_hvm_handle_ros_event(struct v3_ros_event *event)
292 {
293     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
294     char t;
295
296     switch (event->event_type) { 
297         case ROS_PAGE_FAULT: 
298             // force the ros kernel to the PTE
299             if (event->page_fault.action==ROS_READ) { 
300                 DEBUG("Handling page fault read for %p\n", (volatile char*)(event->page_fault.cr2));
301                 t=*(volatile char*)(event->page_fault.cr2);
302                 t=t; // avoid wanting for this throwaway
303             } else if (event->page_fault.action==ROS_WRITE) { 
304                 DEBUG("Handling page fault write for %p\n", (volatile char*)(event->page_fault.cr2));
305                 
306                 // stash the old contents
307                 char tmp = *((volatile char *)event->page_fault.cr2);
308                 
309                 // force a write
310                 *((volatile char*)event->page_fault.cr2) = 0xa;
311                 
312                 // put the old value back
313                 *((volatile char*)event->page_fault.cr2) = tmp;
314                 
315             } else {
316                 INFO("Huh?\n");
317             }
318             
319             DEBUG("Done - doing hypercall...");
320             num = 0xf00d;
321             a1 = 0x1f;
322             a2 = 0; // success
323             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
324             // completed
325             DEBUG("[OK]\n");
326             
327             break;
328             
329         case ROS_SYSCALL:
330             DEBUG("Doing system call: syscall(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
331                   event->syscall.args[0],
332                   event->syscall.args[1],
333                   event->syscall.args[2],
334                   event->syscall.args[3],
335                   event->syscall.args[4],
336                   event->syscall.args[5],
337                   event->syscall.args[6],
338                   event->syscall.args[7]);
339             
340             rc = Syscall(event->syscall.args[0],
341                          event->syscall.args[1],
342                          event->syscall.args[2],
343                          event->syscall.args[3],
344                          event->syscall.args[4],
345                          event->syscall.args[5],
346                          event->syscall.args[6]);
347             
348             if ((long int)rc<0) {
349                 DEBUG("Syscall (num=0x%llx) failed (rc=0x%llx)\n", (unsigned long long)event->syscall.args[0], (unsigned long long)rc);
350             }
351             
352             DEBUG("Return = 0x%llx, doing hypercall...", rc);
353             num = 0xf00d;
354             a1 = 0x1f;
355             a2 = rc;
356             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
357             DEBUG("[OK]\n");
358             
359             break;
360
361         case HRT_EXCEPTION:
362             DEBUG("Handling exception (tid=%lx) at %p vector=0x%lx...", syscall(SYS_gettid), (void*)event->excp.rip, event->excp.vector);
363             if (event->excp.vector == HRT_FAIL_VEC) {
364                 INFO("HRT execution failed due to exception in HRT\n");
365             } else {
366                 INFO("HRT execution failed due to exception in ROS (vec=0x%lx)\n", event->excp.vector);
367             }
368             
369             num = 0xf00d;
370             a1 = 0x1f;
371             a2 = rc;
372             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
373             DEBUG("[OK]\n");
374             exit(EXIT_FAILURE);
375             break;
376             
377         default:
378             DEBUG( "Unknown ROS event 0x%x\n", event->event_type);
379             break;
380     }
381     
382     return 0;
383 }
384
385 static void wait_for_merge_completion()
386 {
387     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
388     struct v3_ros_event event;
389     
390     memset(&event, 1, sizeof(event));
391     
392     rc = 1;
393     
394     while (rc) { 
395         num = 0xf00d;
396         a1 = 0xf;
397         a2 = (unsigned long long) &event;
398         HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
399     }
400     
401 }
402
403
404 static void wait_for_completion()
405 {
406   unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
407   struct v3_ros_event event;
408
409   memset(&event, 1, sizeof(event));
410
411   rc = 1;
412
413   while (rc) { 
414     num = 0xf00d;
415     a1 = 0xf;
416     a2 = (unsigned long long) &event;
417     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
418     if (rc) { 
419         //      usleep(100);
420         if (event.event_type != ROS_NONE) { 
421             v3_hvm_handle_ros_event(&event);
422         }
423     }
424   }
425 }
426
427
428 int v3_hvm_ros_install_hrt_image(void *image, uint64_t size)
429 {
430     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
431     unsigned long long i;
432     volatile long long sum=0;
433
434     num = 0xf00d;
435     a1 = 0x8; // install image
436     a2 = (unsigned long long) image;
437     a3 = size;
438
439     // touch the whoel image to make it has ptes
440     for (i=0;i<size;i++) { 
441         sum+=((char*)image)[i];
442     }
443
444     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
445
446     if (rc) { 
447         return -1;
448     } else {
449         return 0;
450     }
451 }
452
453 int v3_hvm_ros_reset(reset_type what)
454 {
455     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
456     unsigned long long rc;
457     
458     num=0xf00d;
459     switch (what) { 
460         case RESET_ROS:
461             a1 = 0x1;
462             break;
463         case RESET_HRT:
464             a1 = 0x2;
465             break;
466         case RESET_BOTH:
467             a1 = 0x3;
468             break;
469     }
470     
471     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
472     
473     if (rc) {
474         INFO("Error in request to reset rc=0x%llx\n",rc);
475         return -1;
476     } else {
477         // no waiting for completion here
478         return 0;
479     }
480 }
481
482
483 int v3_hvm_ros_merge_address_spaces()
484 {
485     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
486     unsigned long long rc;
487
488     num=0xf00d;
489     a1 = 0x30; // merge address spaces
490     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
491     if (rc) {
492       INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
493       return -1;
494     } else {
495       wait_for_merge_completion();
496       return 0;
497     }
498 }
499
500 int v3_hvm_ros_unmerge_address_spaces()
501 {
502     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
503     unsigned long long rc;
504
505     num=0xf00d;
506     a1 = 0x31; // merge address spaces
507     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
508     if (rc) {
509       INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
510       return -1;
511     } else {
512       wait_for_completion();
513       return 0;
514     }
515 }
516
517
518 int v3_hvm_ros_mirror_gdt(uint64_t fsbase, uint64_t cpu)
519 {
520     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
521     unsigned long long rc;
522
523     num=0xf00d;
524     a1 = 0x51; // mirror the ROS FS and GS on the HRT side
525     a2 = fsbase;
526     a3 = cpu;
527     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
528     if (rc) {
529       INFO("Error in request to mirror GDT (rc=0x%llx)\n", rc);
530       return -1;
531     } else {
532       wait_for_completion();
533       return 0;
534     }
535
536 }
537
538 int v3_hvm_ros_unmirror_gdt()
539 {
540     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
541     unsigned long long rc;
542
543     num=0xf00d;
544     a1 = 0x53; // unmirror GDT and the rest
545     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
546     if (rc) {
547       INFO("Error in request to unmirror GDT (rc=0x%llx)\n", rc);
548       return -1;
549     } else {
550       wait_for_completion();
551       return 0;
552     }
553 }
554
555
556 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
557 {
558     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
559     unsigned long long rc;
560
561     num=0xf00d;
562     if (par) { 
563         a1 = 0x21; // issue "function" in parallel
564     } else {
565         a1 = 0x20; // issue "function" sequentially
566     }
567     a2 = (unsigned long long) buf;
568     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
569     if (rc) { 
570         INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
571         return -1;
572     } else {
573         wait_for_completion();
574         return 0;
575     }
576 }
577
578 int v3_hvm_ros_invoke_hrt_async_nowait(void *buf, int par)
579 {
580     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
581     unsigned long long rc;
582
583     num=0xf00d;
584     if (par) { 
585         a1 = 0x21; // issue "function" in parallel
586     } else {
587         a1 = 0x20; // issue "function" sequentially
588     }
589     a2 = (unsigned long long) buf;
590     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
591     return 0;
592 }
593
594
595
596
597
598 /*
599   Synchronous operation model 
600
601   On ROS:
602
603   [0] => issue count
604   [1] => completion count
605   [2] => function call ptr
606
607   1. merge
608   2. indicate this is the address for sync
609   3. ++[0]
610   4. wait for [1] to match
611   5. goto 3
612
613   On HRT:
614
615   1. merge
616   2. cnt=1;
617   3. wait for [0] to get to cnt
618   4. exec
619   5. ++[1]   ++cnt
620   6. goto 3
621 */
622
623 static volatile unsigned long long sync_proto[3]={0,0,0};
624
625
626 static void wait_for_sync()
627 {
628   unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
629   struct v3_ros_event event;
630
631   memset(&event, 1, sizeof(event));
632   
633   rc = 1;
634
635   while (rc!=4) { 
636     num = 0xf00d;
637     a1 = 0xf;
638     a2 = (unsigned long long) &event;
639     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
640     if (rc!=4) { 
641         //      usleep(100);
642         if (event.event_type != ROS_NONE) { 
643             v3_hvm_handle_ros_event(&event);
644         }
645     }
646   }
647 }
648
649
650 int v3_hvm_ros_synchronize()
651 {
652     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
653     unsigned long long rc;
654
655     // make sure this address is touched, then zero
656     sync_proto[0]=sync_proto[1]=sync_proto[2]=1;
657     sync_proto[0]=sync_proto[1]=sync_proto[2]=0;
658
659     num=0xf00d;
660     a1 = 0x28; // issue sync request setup
661     a2 = (unsigned long long) sync_proto;
662     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
663     
664     if (rc) { 
665         INFO("Synchronize call failed with rc=0x%llx\n",rc);
666         return -1;
667     } else {
668         wait_for_sync();
669         return 0;
670     }
671 }
672
673
674 int v3_hvm_ros_desynchronize()
675 {
676     unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
677     unsigned long long rc;
678
679     num=0xf00d;
680     a1 = 0x29; // issue sync request teardown
681     a2 = (unsigned long long) sync_proto;
682     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
683
684     if (rc) { 
685         INFO("Desynchronize call failed with rc=0x%llx\n",rc);
686         return -1;
687     } else {
688         wait_for_completion();
689         return 0;
690     }
691 }
692
693 #define HOW_OFTEN 1000000
694
695 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
696 {
697     int i;
698     sync_proto[2]=(unsigned long long)buf;
699     sync_proto[0]++;
700
701     i=0;
702     while (sync_proto[1] != sync_proto[0]) {
703         i++;
704         if (ros && (!i%HOW_OFTEN)) { 
705             unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
706             struct v3_ros_event event;
707
708             memset(&event, 1, sizeof(event));
709
710             num = 0xf00d;
711             a1 = 0xf;
712             a2 = (unsigned long long) &event;
713             HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
714             if (event.event_type != ROS_NONE) { 
715                 v3_hvm_handle_ros_event(&event);
716             }
717         }
718     }   
719     return 0;
720 }
721
722 extern void *__v3_hvm_ros_signal_handler_stub;
723
724 void (*__v3_hvm_ros_signal_handler)(uint64_t) = 0;
725 static void *__v3_hvm_ros_signal_handler_stack = 0;
726 static uint64_t __v3_hvm_ros_signal_handler_stack_size=0;
727
728 int v3_hvm_ros_register_signal(void (*h)(uint64_t), void *stack, uint64_t stack_size)
729 {
730     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
731
732     if (mlock(stack,stack_size)) { 
733         INFO("Can't pin stack - proceeding\n");
734     }
735
736     // clear it and touch it
737     memset(stack,0,stack_size);
738
739     __v3_hvm_ros_signal_handler_stack = stack;
740     __v3_hvm_ros_signal_handler_stack_size = stack_size;
741     __v3_hvm_ros_signal_handler = h;
742
743     // Attempt to install
744     
745     num = 0xf00d;
746     a1 = 0x40;
747     a2 = (unsigned long long) &__v3_hvm_ros_signal_handler_stub;
748     a3 = (unsigned long long) stack + stack_size - 16; // put us at the top of the stack, and 16 byte aligned
749
750     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
751     if (rc) {
752         INFO("Failed to install HVM signal handler\n");
753         return -1;
754     } 
755
756     return 0;
757 }
758
759 int v3_hvm_ros_unregister_signal()
760 {
761     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
762
763     // an unregister boils down to setting handler to null
764     num = 0xf00d;
765     a1 = 0x40;
766     a2 = (unsigned long long) 0;
767     a3 = (unsigned long long) 0; 
768
769     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
770
771     if (rc) {
772         INFO("Failed to uninstall HVM signal handler\n");
773     } 
774
775     // and now do user space cleanup
776
777     __v3_hvm_ros_signal_handler = 0;
778
779     if (__v3_hvm_ros_signal_handler_stack) { 
780         munlock(__v3_hvm_ros_signal_handler_stack,__v3_hvm_ros_signal_handler_stack_size);
781         __v3_hvm_ros_signal_handler_stack = 0;
782         __v3_hvm_ros_signal_handler_stack_size = 0;
783     }
784     
785     if (rc) { 
786         return -1;
787     } else {
788         return 0;
789     }
790 }
791
792
793 int  v3_hvm_hrt_signal_ros(uint64_t code)
794 {
795     unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
796
797     num = 0xf00d;
798     a1 = 0x41;
799     a2 = (unsigned long long) code;
800
801     HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
802
803     return rc ? -1 : rc;
804
805 }
806
807