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_merge_address_spaces()
245 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
246 unsigned long long rc;
249 a1 = 0x30; // merge address spaces
250 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
252 INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
255 wait_for_completion();
260 int v3_hvm_ros_unmerge_address_spaces()
262 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
263 unsigned long long rc;
266 a1 = 0x31; // merge address spaces
267 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
269 INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
272 wait_for_completion();
278 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
280 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
281 unsigned long long rc;
285 a1 = 0x21; // issue "function" in parallel
287 a1 = 0x20; // issue "function" sequentially
289 a2 = (unsigned long long) buf;
290 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
292 INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
295 wait_for_completion();
305 Synchronous operation model
310 [1] => completion count
311 [2] => function call ptr
314 2. indicate this is the address for sync
316 4. wait for [1] to match
323 3. wait for [0] to get to cnt
329 static volatile unsigned long long sync_proto[3]={0,0,0};
332 static void wait_for_sync()
334 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
335 struct v3_ros_event event;
337 memset(&event, 1, sizeof(event));
344 a2 = (unsigned long long) &event;
345 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
348 if (event.event_type != ROS_NONE) {
349 handle_ros_event(&event);
356 int v3_hvm_ros_synchronize()
358 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
359 unsigned long long rc;
361 // make sure this address is touched, then zero
362 sync_proto[0]=sync_proto[1]=sync_proto[2]=1;
363 sync_proto[0]=sync_proto[1]=sync_proto[2]=0;
366 a1 = 0x28; // issue sync request setup
367 a2 = (unsigned long long) sync_proto;
368 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
371 INFO("Synchronize call failed with rc=0x%llx\n",rc);
380 int v3_hvm_ros_desynchronize()
382 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
383 unsigned long long rc;
386 a1 = 0x29; // issue sync request teardown
387 a2 = (unsigned long long) sync_proto;
388 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
391 INFO("Desynchronize call failed with rc=0x%llx\n",rc);
394 wait_for_completion();
399 #define HOW_OFTEN 1000000
401 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
404 sync_proto[2]=(unsigned long long)buf;
408 while (sync_proto[1] != sync_proto[0]) {
410 if (ros && (!i%HOW_OFTEN)) {
411 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
412 struct v3_ros_event event;
414 memset(&event, 1, sizeof(event));
418 a2 = (unsigned long long) &event;
419 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
420 if (event.event_type != ROS_NONE) {
421 handle_ros_event(&event);