|  | /* 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; | 
|  | } |