Debug code to see remote kmsgs
[akaros.git] / kern / src / event.c
index 5ec00c0..c89bc2d 100644 (file)
 #include <stdio.h>
 #include <assert.h>
 #include <pmap.h>
+#include <schedule.h>
+
+/* Userspace could give us a vcoreid that causes us to compute a vcpd that is
+ * outside procdata.  If we hit UWLIM, then we've gone farther than we should.
+ * We check the vcoreid, instead of the resulting address, to avoid issues like
+ * address wrap-around. */
+static bool vcoreid_is_safe(uint32_t vcoreid)
+{
+       /* MAX_NUM_VCORES == MAX_NUM_CPUS (check procinfo/procdata) */
+       return vcoreid < MAX_NUM_CPUS;
+}
 
 /* Note these three helpers return the user address of the mbox, not the KVA.
  * Load current to access this, and it will work for any process. */
@@ -93,6 +104,7 @@ static void post_vc_msg(struct proc *p, uint32_t vcoreid,
  * sure it is mapped (slight optimization) */
 static void try_notify(struct proc *p, uint32_t vcoreid, int ev_flags)
 {
+       /* Note this is an unlocked-peek at the vcoremap */
        if ((ev_flags & EVENT_IPI) && vcore_is_mapped(p, vcoreid))
                proc_notify(p, vcoreid);
 }
@@ -228,11 +240,8 @@ static void spam_public_msg(struct proc *p, struct event_msg *ev_msg,
                         * right as another vcore was yielding, and the preempted
                         * message was sent after the last vcore yielded (which caused
                         * us to be WAITING */
-                       if (p->state == PROC_WAITING) {
-                               spin_lock(&p->proc_lock);
-                               __proc_wakeup(p);       /* internally, this double-checks WAITING */
-                               spin_unlock(&p->proc_lock);
-                       }
+                       if (p->state == PROC_WAITING)
+                               proc_wakeup(p); /* internally, this double-checks WAITING */
                        return;
                }
        }
@@ -276,9 +285,9 @@ ultimate_fallback:
        /* The first event to catch the process with no online/bp vcores will need
         * to wake it up.  (We could be RUNNABLE_M here if another event already woke
         * us.) and we didn't get lucky with the penultimate fallback.
-        * __proc_wakeup() will check for WAITING. */
-       __proc_wakeup(p);
+        * proc_wakeup (and __proc_wakeup()) will check for WAITING. */
        spin_unlock(&p->proc_lock);
+       proc_wakeup(p);
        return;
 }
 
@@ -341,12 +350,22 @@ void send_event(struct proc *p, struct event_queue *ev_q, struct event_msg *msg,
        }
        if (!is_user_rwaddr(ev_q, sizeof(struct event_queue))) {
                /* Ought to kill them, just warn for now */
-               warn("[kernel] Illegal addr for ev_q");
+               printk("[kernel] Illegal addr for ev_q\n");
                return;
        }
        /* ev_q is a user pointer, so we need to make sure we're in the right
         * address space */
        old_proc = switch_to(p);
+       /* If we're an _S, just spam vcore0, and wake up if necessary. */
+       if (!__proc_is_mcp(p)) {
+               spam_vcore(p, 0, msg, ev_q->ev_flags);
+               wrmb(); /* don't let the notif_pending write pass the state read */
+               /* using the same pattern as in spam_public (which can have multiple
+                * unblock callbacks */
+               if (p->state == PROC_WAITING)
+                       proc_wakeup(p);
+               goto out;
+       }
        /* Get the vcoreid that we'll message (if appropriate).  For INDIR and
         * SPAMMING, this is the first choice of a vcore, but other vcores might get
         * it.  Common case is !APPRO and !ROUNDROBIN.  Note we are clobbering the
@@ -361,6 +380,11 @@ void send_event(struct proc *p, struct event_queue *ev_q, struct event_msg *msg,
                vcoreid = (ev_q->ev_vcore + 1) % p->procinfo->num_vcores;
                ev_q->ev_vcore = vcoreid;
        }
+       if (!vcoreid_is_safe(vcoreid)) {
+               /* Ought to kill them, just warn for now */
+               printk("[kernel] Vcoreid %d unsafe! (too big?)\n", vcoreid);
+               goto out;
+       }
        /* If we're a SPAM_PUBLIC, they just want us to spam the message.  Note we
         * don't care about the mbox, since it'll go to VCPD public mboxes, and
         * we'll prefer to send it to whatever vcoreid we determined at this point
@@ -387,7 +411,7 @@ void send_event(struct proc *p, struct event_queue *ev_q, struct event_msg *msg,
        /* Even if we're using an mbox in procdata (VCPD), we want a user pointer */
        if (!is_user_rwaddr(ev_mbox, sizeof(struct event_mbox))) {
                /* Ought to kill them, just warn for now */
-               printk("[kernel] Illegal addr for ev_mbox");
+               printk("[kernel] Illegal addr for ev_mbox\n");
                goto out;
        }
        /* We used to support no msgs, but quit being lazy and send a 'msg'.  If the