proc: fix refcounting bug in proc_get_set()
[akaros.git] / user / vmm / vmm.c
1 /* Copyright (c) 2016 Google Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Helper functions for virtual machines */
6
7 #include <vmm/vmm.h>
8 #include <errno.h>
9 #include <parlib/bitmask.h>
10 #include <parlib/uthread.h>
11 #include <sys/syscall.h>
12
13 /* Sends an interrupt with @vector to guest pcore @gpcoreid.  Returns 0 on
14  * success, -1 with errstr set o/w. */
15 int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
16                         unsigned int vector)
17 {
18         struct guest_thread *gth;
19         struct vmm_gpcore_init *gpci;
20
21         if (gpcoreid >= vm->nr_gpcs) {
22                 werrstr("Guest pcoreid %d out of range (%d gpcs)", gpcoreid,
23                         vm->nr_gpcs);
24                 return -1;
25         }
26         gth = gpcid_to_gth(vm, gpcoreid);
27         gpci = gth_to_gpci(gth);
28         /* The OUTSTANDING_NOTIF bit (256) is one greater than the last valid
29          * descriptor */
30         if (vector >= VMX_POSTED_OUTSTANDING_NOTIF) {
31                 werrstr("Interrupt vector %d too high (max %d)", vector,
32                         VMX_POSTED_OUTSTANDING_NOTIF - 1);
33                 return -1;
34         }
35         /* Syncing with halting guest threads.  The Mutex protects changes to
36          * the posted irq descriptor. */
37         uth_mutex_lock(gth->halt_mtx);
38         SET_BITMASK_BIT_ATOMIC(gpci->posted_irq_desc, vector);
39         /* Atomic op provides the mb() btw writing the vector and mucking with
40          * OUTSTANDING_NOTIF.
41          *
42          * If we set notif, it's on us to inject the IRQ.  Either way, notif
43          * will be set and we must kick the CV, unconditionally. */
44         if (!GET_BITMASK_BIT(gpci->posted_irq_desc,
45                              VMX_POSTED_OUTSTANDING_NOTIF)) {
46                 SET_BITMASK_BIT_ATOMIC(gpci->posted_irq_desc,
47                                        VMX_POSTED_OUTSTANDING_NOTIF);
48                 ros_syscall(SYS_vmm_poke_guest, gpcoreid, 0, 0, 0, 0, 0);
49         }
50         uth_cond_var_signal(gth->halt_cv);
51         uth_mutex_unlock(gth->halt_mtx);
52         return 0;
53 }