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);
242 int v3_hvm_ros_reset(reset_type what)
244 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
245 unsigned long long rc;
260 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
263 INFO("Error in request to reset rc=0x%llx\n",rc);
266 // no waiting for completion here
272 int v3_hvm_ros_merge_address_spaces()
274 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
275 unsigned long long rc;
278 a1 = 0x30; // merge address spaces
279 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
281 INFO("Error in request to merge address spaces rc=0x%llx\n",rc);
284 wait_for_completion();
289 int v3_hvm_ros_unmerge_address_spaces()
291 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
292 unsigned long long rc;
295 a1 = 0x31; // merge address spaces
296 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
298 INFO("Error in request to unmerge address spaces rc=0x%llx\n",rc);
301 wait_for_completion();
307 int v3_hvm_ros_invoke_hrt_async(void *buf, int par)
309 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
310 unsigned long long rc;
314 a1 = 0x21; // issue "function" in parallel
316 a1 = 0x20; // issue "function" sequentially
318 a2 = (unsigned long long) buf;
319 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
321 INFO("Error in request to launch %s function rc=0x%llx\n", par ? "parallel" : "", rc);
324 wait_for_completion();
334 Synchronous operation model
339 [1] => completion count
340 [2] => function call ptr
343 2. indicate this is the address for sync
345 4. wait for [1] to match
352 3. wait for [0] to get to cnt
358 static volatile unsigned long long sync_proto[3]={0,0,0};
361 static void wait_for_sync()
363 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
364 struct v3_ros_event event;
366 memset(&event, 1, sizeof(event));
373 a2 = (unsigned long long) &event;
374 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
377 if (event.event_type != ROS_NONE) {
378 handle_ros_event(&event);
385 int v3_hvm_ros_synchronize()
387 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
388 unsigned long long rc;
390 // make sure this address is touched, then zero
391 sync_proto[0]=sync_proto[1]=sync_proto[2]=1;
392 sync_proto[0]=sync_proto[1]=sync_proto[2]=0;
395 a1 = 0x28; // issue sync request setup
396 a2 = (unsigned long long) sync_proto;
397 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
400 INFO("Synchronize call failed with rc=0x%llx\n",rc);
409 int v3_hvm_ros_desynchronize()
411 unsigned long long num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
412 unsigned long long rc;
415 a1 = 0x29; // issue sync request teardown
416 a2 = (unsigned long long) sync_proto;
417 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
420 INFO("Desynchronize call failed with rc=0x%llx\n",rc);
423 wait_for_completion();
428 #define HOW_OFTEN 1000000
430 int v3_hvm_ros_invoke_hrt_sync(void *buf, int ros)
433 sync_proto[2]=(unsigned long long)buf;
437 while (sync_proto[1] != sync_proto[0]) {
439 if (ros && (!i%HOW_OFTEN)) {
440 unsigned long long rc, num, a1=0, a2=0, a3=0, a4=0, a5=0, a6=0, a7=0, a8=0;
441 struct v3_ros_event event;
443 memset(&event, 1, sizeof(event));
447 a2 = (unsigned long long) &event;
448 HCALL(rc,num,a1,a2,a3,a4,a5,a6,a7,a8);
449 if (event.event_type != ROS_NONE) {
450 handle_ros_event(&event);