blob: 0a3a1d3df4a02516a7686a4d0eedab6b788e32ca [file] [log] [blame]
/* Copyright (c) 2016 Google Inc.
* Barret Rhoden <brho@cs.berkeley.edu>
* See LICENSE for details.
*
* Helper functions for virtual machines */
#include <vmm/vmm.h>
#include <errno.h>
#include <parlib/bitmask.h>
#include <parlib/uthread.h>
#include <sys/syscall.h>
/* Sends an interrupt with @vector to guest pcore @gpcoreid. Returns 0 on
* success, -1 with errstr set o/w. */
int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
unsigned int vector)
{
struct guest_thread *gth;
struct vmm_gpcore_init *gpci;
if (gpcoreid >= vm->nr_gpcs) {
werrstr("Guest pcoreid %d out of range (%d gpcs)", gpcoreid,
vm->nr_gpcs);
return -1;
}
gth = gpcid_to_gth(vm, gpcoreid);
gpci = gth_to_gpci(gth);
/* The OUTSTANDING_NOTIF bit (256) is one greater than the last valid
* descriptor */
if (vector >= VMX_POSTED_OUTSTANDING_NOTIF) {
werrstr("Interrupt vector %d too high (max %d)", vector,
VMX_POSTED_OUTSTANDING_NOTIF - 1);
return -1;
}
/* Syncing with halting guest threads. The Mutex protects changes to
* the posted irq descriptor. */
uth_mutex_lock(gth->halt_mtx);
SET_BITMASK_BIT_ATOMIC(gpci->posted_irq_desc, vector);
/* Atomic op provides the mb() btw writing the vector and mucking with
* OUTSTANDING_NOTIF.
*
* If we set notif, it's on us to inject the IRQ. Either way, notif
* will be set and we must kick the CV, unconditionally. */
if (!GET_BITMASK_BIT(gpci->posted_irq_desc,
VMX_POSTED_OUTSTANDING_NOTIF)) {
SET_BITMASK_BIT_ATOMIC(gpci->posted_irq_desc,
VMX_POSTED_OUTSTANDING_NOTIF);
ros_syscall(SYS_vmm_poke_guest, gpcoreid, 0, 0, 0, 0, 0);
}
uth_cond_var_signal(gth->halt_cv);
uth_mutex_unlock(gth->halt_mtx);
return 0;
}