2 Copyright (c) 2015 Peter Dinda
5 #include <sys/syscall.h>
13 #include "v3_hvm_ros_user.h"
16 #define DEBUG_OUTPUT 0
20 #define DEBUG(...) fprintf(stderr,__VA_ARGS__)
26 #define INFO(...) fprintf(stdout,__VA_ARGS__)
33 typedef unsigned char uchar_t;
35 #define rdtscll(val) \
39 asm volatile("rdtsc" : "=a" (a), "=d" (d)); \
40 *(uint32_t *)&(tsc) = a; \
41 *(uint32_t *)(((uchar_t *)&tsc) + 4) = d; \
47 This convention match the definition in palacios/include/palacios/vmm_hvm.h
53 rbx = 0x6464646464646464...
66 arguments on stack in C order (first argument is TOS)
67 arguments are also 32 bit
69 #define HCALL64(rc,id,a,b,c,d,e,f,g,h) \
70 asm volatile ("movq %1, %%rax; " \
72 "movq $0x6464646464646464, %%rbx; " \
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" \
92 #define HCALL32(rc,id,a,b,c,d,e,f,g,h) \
93 asm volatile ("movl %1, %%eax; " \
95 "movl $0x32323232, %%ebx; " \
106 "addl $32, %%esp; " \
110 "m"(a), "m"(b), "m"(c), "m"(d), \
111 "m"(e), "m"(f), "m"(g), "m"(h) \
116 #define HCALL(rc,id,a,b,c,d,e,f,g,h) HCALL64(rc,id,a,b,c,d,e,f,g,h)
118 #define HCALL(rc,id,a,b,c,d,e,f,g,h) HCALL32(rc,id,a,b,c,d,e,f,g,h)
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
127 struct { // valid when ROS_PAGE_FAULT
130 enum {ROS_READ, ROS_WRITE} action;
132 struct { // valid when ROS_SYSCALL
139 int v3_hvm_ros_user_init()
141 // currently nothing to do
145 int v3_hvm_ros_user_deinit()
147 // currently nothing to do
151 static void handle_ros_event(struct v3_ros_event *event)
153 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
156 switch (event->event_type) {
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);
169 DEBUG("Done - doing hypercall\n");
173 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
175 DEBUG("Completed.\n");
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]);
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]);
200 DEBUG("syscall failed");
203 DEBUG("Return = 0x%llx, doing hypercall\n", rc);
207 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
208 DEBUG("Completed\n");
212 DEBUG( "Unknown ROS event 0x%x\n", event->event_type);
219 static void wait_for_completion()
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;
224 memset(&event, 1, sizeof(event));
231 a2 = (unsigned long long) &event;
232 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
235 if (event.event_type != ROS_NONE) {
236 handle_ros_event(&event);
243 int v3_hvm_ros_install_hrt_image(void *image, uint64_t size)
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;
250 a1 = 0x8; // install image
251 a2 = (unsigned long long) image;
254 // touch the whoel image to make it has ptes
255 for (i=0;i<size;i++) {
256 sum+=((char*)image)[i];
259 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
268 int v3_hvm_ros_reset(reset_type what)
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;
286 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
289 INFO("Error in request to reset rc=0x%llx\n",rc);
292 // no waiting for completion here
298 int v3_hvm_ros_merge_address_spaces()
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;
304 a1 = 0x30; // merge address spaces
305 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
307 INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
310 wait_for_completion();
315 int v3_hvm_ros_unmerge_address_spaces()
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;
321 a1 = 0x31; // merge address spaces
322 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
324 INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
327 wait_for_completion();
333 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
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;
340 a1 = 0x21; // issue "function" in parallel
342 a1 = 0x20; // issue "function" sequentially
344 a2 = (unsigned long long) buf;
345 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
347 INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
350 wait_for_completion();
360 Synchronous operation model
365 [1] => completion count
366 [2] => function call ptr
369 2. indicate this is the address for sync
371 4. wait for [1] to match
378 3. wait for [0] to get to cnt
384 static volatile unsigned long long sync_proto[3]={0,0,0};
387 static void wait_for_sync()
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;
392 memset(&event, 1, sizeof(event));
399 a2 = (unsigned long long) &event;
400 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
403 if (event.event_type != ROS_NONE) {
404 handle_ros_event(&event);
411 int v3_hvm_ros_synchronize()
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;
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;
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);
426 INFO("Synchronize call failed with rc=0x%llx\n",rc);
435 int v3_hvm_ros_desynchronize()
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;
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);
446 INFO("Desynchronize call failed with rc=0x%llx\n",rc);
449 wait_for_completion();
454 #define HOW_OFTEN 1000000
456 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
459 sync_proto[2]=(unsigned long long)buf;
463 while (sync_proto[1] != sync_proto[0]) {
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;
469 memset(&event, 1, sizeof(event));
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);