-
Notifications
You must be signed in to change notification settings - Fork 4
event synchronization
Mathieu Tarral edited this page Jan 12, 2017
·
2 revisions
This page describe how events are reported to the userland component.
First the nitro struct in the kvm_vcpu has 2 synchronization variables :
struct nitro_vcpu{
struct completion k_wait_cv;
struct semaphore n_wait_sem;
struct event event;
};
When a vcpu is created, the struct will be initialized in this way
void nitro_create_vcpu_hook(struct kvm_vcpu *vcpu){
vcpu->nitro.event.present = false;
init_completion(&(vcpu->nitro.k_wait_cv));
sema_init(&(vcpu->nitro.n_wait_sem),0);
}
Then, when the traps are set
if (enabled)
{
kvm->nitro.traps |= NITRO_TRAP_SYSCALL;
init_completion(&vcpu->nitro.k_wait_cv);
}
else
{
kvm->nitro.traps &= ~(NITRO_TRAP_SYSCALL);
complete_all(&(vcpu->nitro.k_wait_cv));
}
When a syscall is trapped, in x86.c:vcpu_run
if(vcpu->nitro.event.present)
nitro_report_event(vcpu);
and nitro_report_event
void nitro_report_event(struct kvm_vcpu *vcpu){
nitro_wait(vcpu);
vcpu->nitro.event.present = false;
}
nitro_wait
like the name suggests, wait for the userland to pick the event with get_event
.
-
up(&(vcpu->nitro.n_wait_sem));
: unlocks the semaphoren_wait_sem
, allowing thenitro_main.c:nitro_report_event
code to continue and load the event -
wait_for_completion_interruptible_timeout
: waits for userland to callcontinue_vm
void nitro_wait(struct kvm_vcpu *vcpu){
long rv;
up(&(vcpu->nitro.n_wait_sem));
rv = wait_for_completion_interruptible_timeout(&(vcpu->nitro.k_wait_cv),msecs_to_jiffies(30000));
if (rv == 0)
printk(KERN_INFO "nitro: %s: wait timed out\n",__FUNCTION__);
else if (rv < 0)
printk(KERN_INFO "nitro: %s: wait interrupted\n",__FUNCTION__);
return;
}
int nitro_ioctl_get_event(struct kvm_vcpu *vcpu, struct event *ev){
int rv;
rv = down_interruptible(&(vcpu->nitro.n_wait_sem));
if (rv == 0) {
ev->direction = vcpu->nitro.event.direction;
ev->type = vcpu->nitro.event.type;
}
return rv;
}
int nitro_ioctl_continue(struct kvm_vcpu *vcpu){
//if no waiters
if(completion_done(&(vcpu->nitro.k_wait_cv)))
return -1;
complete(&(vcpu->nitro.k_wait_cv));
return 0;
}