parlib: Add a syscall lookup table (XCC)
[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 = vm->gths[gpcoreid];
27         gpci = &vm->gpcis[gpcoreid];
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 the
36          * 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.  If the notif was already set, then a previous thread
41          * poked the guest and signaled the CV. */
42         if (!GET_BITMASK_BIT(gpci->posted_irq_desc, VMX_POSTED_OUTSTANDING_NOTIF)) {
43                 SET_BITMASK_BIT_ATOMIC(gpci->posted_irq_desc,
44                                        VMX_POSTED_OUTSTANDING_NOTIF);
45                 ros_syscall(SYS_vmm_poke_guest, gpcoreid, 0, 0, 0, 0, 0);
46                 uth_cond_var_signal(gth->halt_cv);
47         }
48         uth_mutex_unlock(gth->halt_mtx);
49         return 0;
50 }