What is a Hypercall?
Hypercall is an explicit call from Virtual Machine (VM) into the underlying VM Moniter (VMM). That is, a hypercall issued from the guest will cause a VM exit from the guest into the VMM. In this sense, it is kinda like syscall, which will result in a trap from userspace into kernel space. Thus, hypercall can serve as a communication approach between the guest and the underlying VMM. The guest can issue hypercalls via VMMCALL instruction on AMD SVM machine or VMCALL on Intel VMX machine.
Adding a Hypercall in Palacios
Palacios maintains a global hypercall map, which maintains the mapping between the unique hypercall number and the hypercall handler. (Each hypercall is associated with a unique hypercall number.). Therefore, to add a hypercal in Palacios, you need to:
- Implement a handler for the hypercall.
- Assign a unique hypercall number for the hypercall.
- Register the hypercall handler and the hypercall number with Palacios.
Sample Example:
static int handle_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data){
unsigned long param1 = *(unsigned long *) &info->vm_regs.rbx;
unsigned long param2 = *(unsigned long *) &info->vm_regs.rcx;
unsigned long param3 = *(unsigned long *) &info->vm_regs.rdx;
V3_Print("param1=%lu param2=%lu param3=%lu\n", param1, parma2, param3);
info->vm_regs.rax = 0; //return value of the hypercall
}
v3_register_hypercall(vm, HCALL_EXAMPLE_ID, handle_hcall, NULL);
Note: The hypercall management APIs in Palacios are contained in palacios/include/palacios/vmm_hypercall.h and palacios/src/palacios/vmm_hypercall.c.
Issuing Hypercalls from Palacios Guest
“Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively. The hypercall number should be placed in rax and the return value will be placed in rax. No other registers will be clobbered unless explicitly stated by the particular hypercall.” (quoted from [1])
For exmaple, on a AMD SVM machine, a hypercall with 3 parameters can be issued via the following code:
#define VMMCALL ".byte 0x0F,0x01,0xD9\r\n" //VMMCALL instruction binary code
int hcall3(unsigned long hcall_id, unsigned long param1, unsigned long param2, unsigned long param3){
int ret;
__asm__ volatile(
VMMCALL
: “=a”(ret)
: “a”(hcall_id), “b”(param1), “c”(param2), “d”(param3)
);
return ret;
}
References:
[1] Linux KVM Hypercall
posted on 2014-11-04 07:59
csgeek? 阅读(717)
评论(0) 编辑 收藏