2 Copyright (c) 2015 Peter Dinda
5 #include <sys/syscall.h>
14 #include "v3_hvm_ros_user.h"
17 #define DEBUG_OUTPUT 0
21 #define DEBUG(...) fprintf(stderr,__VA_ARGS__)
27 #define INFO(...) fprintf(stdout,__VA_ARGS__)
34 typedef unsigned char uchar_t;
36 #define rdtscll(val) \
40 asm volatile("rdtsc" : "=a" (a), "=d" (d)); \
41 *(uint32_t *)&(tsc) = a; \
42 *(uint32_t *)(((uchar_t *)&tsc) + 4) = d; \
48 This convention match the definition in palacios/include/palacios/vmm_hvm.h
54 rbx = 0x6464646464646464...
67 arguments on stack in C order (first argument is TOS)
68 arguments are also 32 bit
70 #define HCALL64(rc,id,a,b,c,d,e,f,g,h) \
71 asm volatile ("movq %1, %%rax; " \
73 "movq $0x6464646464646464, %%rbx; " \
87 "m"(a), "m"(b), "m"(c), "m"(d), \
88 "m"(e), "m"(f), "m"(g), "m"(h) \
89 : "%rax","%rcx","%rdx","%rsi","%rdi", \
90 "%r8","%r9","%r10","%r11" \
93 #define HCALL32(rc,id,a,b,c,d,e,f,g,h) \
94 asm volatile ("movl %1, %%eax; " \
96 "movl $0x32323232, %%ebx; " \
107 "addl $32, %%esp; " \
111 "m"(a), "m"(b), "m"(c), "m"(d), \
112 "m"(e), "m"(f), "m"(g), "m"(h) \
117 #define HCALL(rc,id,a,b,c,d,e,f,g,h) HCALL64(rc,id,a,b,c,d,e,f,g,h)
119 #define HCALL(rc,id,a,b,c,d,e,f,g,h) HCALL32(rc,id,a,b,c,d,e,f,g,h)
123 /* This must match the definition in palacios/include/palacios/vmm_hvm.h" */
124 struct v3_ros_event {
125 enum { ROS_NONE=0, ROS_PAGE_FAULT=1, ROS_SYSCALL=2 } event_type;
126 uint64_t last_ros_event_result; // valid when ROS_NONE
128 struct { // valid when ROS_PAGE_FAULT
131 enum {ROS_READ, ROS_WRITE} action;
133 struct { // valid when ROS_SYSCALL
140 int v3_hvm_ros_user_init()
142 // currently nothing to do
146 int v3_hvm_ros_user_deinit()
148 // currently nothing to do
152 static void handle_ros_event(struct v3_ros_event *event)
154 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
157 switch (event->event_type) {
159 // force the ros kernel to the PTE
160 if (event->page_fault.action==ROS_READ) {
161 DEBUG("Handling page fault read for %p\n", (volatile char*)(event->page_fault.cr2));
162 t=*(volatile char*)(event->page_fault.cr2);
163 t=t; // avoid wanting for this throwaway
164 } else if (event->page_fault.action==ROS_WRITE) {
165 DEBUG("Handling page fault writefor %p\n", (volatile char*)(event->page_fault.cr2));
166 *(volatile char*)(event->page_fault.cr2) = *(volatile char *)(event->page_fault.cr2);
170 DEBUG("Done - doing hypercall\n");
174 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
176 DEBUG("Completed.\n");
181 DEBUG("Doing system call: syscall(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
182 event->syscall.args[0],
183 event->syscall.args[1],
184 event->syscall.args[2],
185 event->syscall.args[3],
186 event->syscall.args[4],
187 event->syscall.args[5],
188 event->syscall.args[6],
189 event->syscall.args[7]);
191 rc = syscall(event->syscall.args[0],
192 event->syscall.args[1],
193 event->syscall.args[2],
194 event->syscall.args[3],
195 event->syscall.args[4],
196 event->syscall.args[5],
197 event->syscall.args[6],
198 event->syscall.args[7]);
201 DEBUG("syscall failed");
204 DEBUG("Return = 0x%llx, doing hypercall\n", rc);
208 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
209 DEBUG("Completed\n");
213 DEBUG( "Unknown ROS event 0x%x\n", event->event_type);
220 static void wait_for_completion()
222 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
223 struct v3_ros_event event;
225 memset(&event, 1, sizeof(event));
232 a2 = (unsigned long long) &event;
233 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
236 if (event.event_type != ROS_NONE) {
237 handle_ros_event(&event);
244 int v3_hvm_ros_install_hrt_image(void *image, uint64_t size)
246 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
247 unsigned long long i;
248 volatile long long sum=0;
251 a1 = 0x8; // install image
252 a2 = (unsigned long long) image;
255 // touch the whoel image to make it has ptes
256 for (i=0;i<size;i++) {
257 sum+=((char*)image)[i];
260 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
269 int v3_hvm_ros_reset(reset_type what)
271 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
272 unsigned long long rc;
287 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
290 INFO("Error in request to reset rc=0x%llx\n",rc);
293 // no waiting for completion here
299 int v3_hvm_ros_merge_address_spaces()
301 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
302 unsigned long long rc;
305 a1 = 0x30; // merge address spaces
306 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
308 INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
311 wait_for_completion();
316 int v3_hvm_ros_unmerge_address_spaces()
318 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
319 unsigned long long rc;
322 a1 = 0x31; // merge address spaces
323 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
325 INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
328 wait_for_completion();
334 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
336 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
337 unsigned long long rc;
341 a1 = 0x21; // issue "function" in parallel
343 a1 = 0x20; // issue "function" sequentially
345 a2 = (unsigned long long) buf;
346 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
348 INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
351 wait_for_completion();
361 Synchronous operation model
366 [1] => completion count
367 [2] => function call ptr
370 2. indicate this is the address for sync
372 4. wait for [1] to match
379 3. wait for [0] to get to cnt
385 static volatile unsigned long long sync_proto[3]={0,0,0};
388 static void wait_for_sync()
390 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
391 struct v3_ros_event event;
393 memset(&event, 1, sizeof(event));
400 a2 = (unsigned long long) &event;
401 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
404 if (event.event_type != ROS_NONE) {
405 handle_ros_event(&event);
412 int v3_hvm_ros_synchronize()
414 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
415 unsigned long long rc;
417 // make sure this address is touched, then zero
418 sync_proto[0]=sync_proto[1]=sync_proto[2]=1;
419 sync_proto[0]=sync_proto[1]=sync_proto[2]=0;
422 a1 = 0x28; // issue sync request setup
423 a2 = (unsigned long long) sync_proto;
424 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
427 INFO("Synchronize call failed with rc=0x%llx\n",rc);
436 int v3_hvm_ros_desynchronize()
438 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
439 unsigned long long rc;
442 a1 = 0x29; // issue sync request teardown
443 a2 = (unsigned long long) sync_proto;
444 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
447 INFO("Desynchronize call failed with rc=0x%llx\n",rc);
450 wait_for_completion();
455 #define HOW_OFTEN 1000000
457 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
460 sync_proto[2]=(unsigned long long)buf;
464 while (sync_proto[1] != sync_proto[0]) {
466 if (ros && (!i%HOW_OFTEN)) {
467 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
468 struct v3_ros_event event;
470 memset(&event, 1, sizeof(event));
474 a2 = (unsigned long long) &event;
475 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
476 if (event.event_type != ROS_NONE) {
477 handle_ros_event(&event);
484 extern void *__v3_hvm_ros_signal_handler_stub;
486 void (*__v3_hvm_ros_signal_handler)(uint64_t) = 0;
487 static void *__v3_hvm_ros_signal_handler_stack = 0;
488 static uint64_t __v3_hvm_ros_signal_handler_stack_size=0;
490 int v3_hvm_ros_register_signal(void (*h)(uint64_t), void *stack, uint64_t stack_size )
492 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
494 if (mlock(stack,stack_size)) {
495 INFO("Can't pin stack - proceeding\n");
498 // clear it and touch it
499 memset(stack,0,stack_size);
501 __v3_hvm_ros_signal_handler_stack = stack;
502 __v3_hvm_ros_signal_handler_stack_size = stack_size;
503 __v3_hvm_ros_signal_handler = h;
505 // Attempt to install
509 a2 = (unsigned long long) &__v3_hvm_ros_signal_handler_stub;
510 a3 = (unsigned long long) stack + stack_size - 8; // put us at the top of the stack
512 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
514 INFO("Failed to install HVM signal handler\n");
521 int v3_hvm_ros_unregister_signal()
523 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
525 // an unregister boils down to setting handler to null
528 a2 = (unsigned long long) 0;
529 a3 = (unsigned long long) 0;
531 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
534 INFO("Failed to uninstall HVM signal handler\n");
537 // and now do user space cleanup
539 __v3_hvm_ros_signal_handler = 0;
541 if (__v3_hvm_ros_signal_handler_stack) {
542 munlock(__v3_hvm_ros_signal_handler_stack,__v3_hvm_ros_signal_handler_stack_size);
543 __v3_hvm_ros_signal_handler_stack = 0;
544 __v3_hvm_ros_signal_handler_stack_size = 0;
555 int v3_hvm_hrt_signal_ros(uint64_t code)
557 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
561 a2 = (unsigned long long) code;
563 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);