7589f6a9b8eb99d48515c6ca171596cf1be69b7e
[akaros.git] / kern / src / event.c
1 /* Copyright (c) 2011 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Kernel utility functions for sending events and notifications (IPIs) to
6  * processes. */
7
8 #include <ucq.h>
9 #include <bitmask.h>
10 #include <event.h>
11 #include <atomic.h>
12 #include <process.h>
13 #include <smp.h>
14 #include <umem.h>
15 #include <stdio.h>
16 #include <assert.h>
17 #include <pmap.h>
18
19 /* Note these three helpers return the user address of the mbox, not the KVA.
20  * Load current to access this, and it will work for any process. */
21 static struct event_mbox *get_vcpd_mbox_priv(uint32_t vcoreid)
22 {
23         return &__procdata.vcore_preempt_data[vcoreid].ev_mbox_private;
24 }
25
26 static struct event_mbox *get_vcpd_mbox_pub(uint32_t vcoreid)
27 {
28         return &__procdata.vcore_preempt_data[vcoreid].ev_mbox_public;
29 }
30
31 static struct event_mbox *get_vcpd_mbox(uint32_t vcoreid, int ev_flags)
32 {
33         if (ev_flags & EVENT_VCORE_PRIVATE)
34                 return get_vcpd_mbox_priv(vcoreid);
35         else
36                 return get_vcpd_mbox_pub(vcoreid);
37 }
38
39 /* Can we message the vcore?  (Will it check its messages).  Note this checks
40  * procdata via the user pointer. */
41 static bool can_msg_vcore(uint32_t vcoreid)
42 {
43         struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
44         return vcpd->can_rcv_msg;
45 }
46
47 /* Says a vcore can be messaged.  Only call this once you are sure this is true
48  * (holding the proc_lock, etc). */
49 static void set_vcore_msgable(uint32_t vcoreid)
50 {
51         struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
52         vcpd->can_rcv_msg = TRUE;
53 }
54
55 /* Posts a message to the mbox, subject to flags.  Feel free to send 0 for the
56  * flags if you don't want to give them the option of EVENT_NOMSG (which is what
57  * we do when sending an indirection event).  Make sure that if mbox is a user
58  * pointer, that you've checked it *and* have that processes address space
59  * loaded.  This can get called with a KVA for mbox. */
60 static void post_ev_msg(struct proc *p, struct event_mbox *mbox,
61                         struct event_msg *msg, int ev_flags)
62 {
63         printd("[kernel] Sending event type %d to mbox %08p\n", msg->ev_type, mbox);
64         /* Sanity check */
65         assert(p);
66         /* If they just want a bit (NOMSG), just set the bit */
67         if (ev_flags & EVENT_NOMSG) {
68                 SET_BITMASK_BIT_ATOMIC(mbox->ev_bitmap, msg->ev_type);
69                 wmb();
70                 mbox->ev_check_bits = TRUE;
71         } else {
72                 send_ucq_msg(&mbox->ev_msgs, p, msg);
73         }
74 }
75
76 /* Helper: use this when sending a message to a VCPD mbox.  It just posts to the
77  * ev_mbox and sets notif pending.  Note this uses a userspace address for the
78  * VCPD (though not a user's pointer). */
79 static void post_vc_msg(struct proc *p, uint32_t vcoreid,
80                         struct event_mbox *ev_mbox, struct event_msg *ev_msg,
81                         int ev_flags)
82 {
83         struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
84         post_ev_msg(p, ev_mbox, ev_msg, ev_flags);
85         /* Set notif pending so userspace doesn't miss the message while yielding */
86         wmb(); /* Ensure ev_msg write is before notif_pending */
87         /* proc_notify() also sets this, but the ev_q might not have requested an
88          * IPI, so we have to do it here too. */
89         vcpd->notif_pending = TRUE;
90 }
91
92 /* Helper: will IPI / proc_notify if the flags say so.  We also check to make
93  * sure it is mapped (slight optimization) */
94 static void try_notify(struct proc *p, uint32_t vcoreid, int ev_flags)
95 {
96         if ((ev_flags & EVENT_IPI) && vcore_is_mapped(p, vcoreid))
97                 proc_notify(p, vcoreid);
98 }
99
100 /* Helper: sends the message and an optional IPI to the vcore.  Sends to the
101  * public mbox.  This is meant for spammy messages. */
102 static void spam_vcore(struct proc *p, uint32_t vcoreid,
103                        struct event_msg *ev_msg, int ev_flags)
104 {
105         post_vc_msg(p, vcoreid, get_vcpd_mbox_pub(vcoreid), ev_msg, ev_flags);
106         try_notify(p, vcoreid, ev_flags);
107 }
108
109 /* Attempts to message a vcore that may or may not have 'can_rcv_msg' set.  If
110  * so, we'll post the message and the message will eventually get dealt with
111  * (when the vcore runs or when it is preempte-recovered). */
112 static bool try_spam_vcore(struct proc *p, uint32_t vcoreid,
113                            struct event_msg *ev_msg, int ev_flags)
114 {
115         /* Not sure if we can or not, so check before spamming.  Technically, the
116          * only critical part is that we __alert, then check can_alert. */
117         if (can_msg_vcore(vcoreid)) {
118                 spam_vcore(p, vcoreid, ev_msg, ev_flags);
119                 wrmb(); /* prev write (notif_pending) must come before following reads*/
120                 if (can_msg_vcore(vcoreid))
121                         return TRUE;
122         }
123         return FALSE;
124 }
125
126 /* Helper: will try to message (INDIR/IPI) a list member (lists of vcores).  We
127  * use this on the online and bulk_preempted vcore lists.  If this succeeds in
128  * alerting a vcore on the list, it'll return TRUE.  We need to be careful here,
129  * since we're reading a list that could be concurrently modified.  The
130  * important thing is that we can always fail if we're unsure (such as with
131  * lists being temporarily empty).  The caller will be able to deal with it via
132  * the ultimate fallback. */
133 static bool spam_list_member(struct vcore_tailq *list, struct proc *p,
134                              struct event_msg *ev_msg, int ev_flags)
135 {
136         struct vcore *vc, *vc_first;
137         uint32_t vcoreid;
138         int loops = 0;
139         vc = TAILQ_FIRST(list);
140         /* If the list appears empty, we'll bail out (failing) after the loop. */
141         while (vc) {
142                 vcoreid = vcore2vcoreid(p, vc);
143                 /* post the alert.  Not using the try_spam_vcore() helper since I want
144                  * something more customized for the lists. */
145                 spam_vcore(p, vcoreid, ev_msg, ev_flags);
146                 wrmb(); /* prev write (notif_pending) must come before following reads*/
147                 /* if they are still alertable after we sent the msg, then they'll get
148                  * it before yielding (racing with userspace yield here).  This check is
149                  * not as critical as the next one, but will allow us to alert vcores
150                  * that happen to concurrently be moved from the active to the
151                  * bulk_preempt list. */
152                 if (can_msg_vcore(vcoreid))
153                         return TRUE;
154                 /* As a backup, if they are still the first on the list, then they are
155                  * still going to get the message.  For the online list, proc_yield()
156                  * will return them to userspace (where they will get the message)
157                  * because __alert_vcore() set notif_pending.  For the BP list, they
158                  * will either be turned on later, or have a preempt message sent about
159                  * their demise.
160                  *
161                  * We race on list membership (and not exclusively 'can_rcv_msg', so
162                  * that when it fails we can get a new vcore to try (or know WHP there
163                  * are none). */
164                 vc_first = TAILQ_FIRST(list);
165                 if (vc == vc_first)
166                         return TRUE;
167                 /* At this point, the list has changed and the vcore we tried yielded,
168                  * so we try the *new* list head.  Track loops for sanity reasons. */
169                 if (loops++ > 10) {
170                         warn("Too many (%d) attempts to find a vcore, failing!", loops);
171                         return FALSE;   /* always safe to fail! */
172                 }
173                 /* Get set up for your attack run! */
174                 vc = vc_first;
175         }
176         return FALSE;
177 }
178
179 /* This makes sure ev_msg is sent to some vcore, preferring vcoreid.
180  *
181  * One of the goals of FALLBACK (and this func) is to allow processes to yield
182  * cores without fear of losing messages.  Even when yielding and getting
183  * preempted, if your message is spammed, it will get to some vcore.  If
184  * MUST_RUN is set, it'll get to a running vcore.  Messages that you send like
185  * this must be able to handle spurious reads, since more than one vcore is
186  * likely to get the message and handle it.
187  *
188  * We try the desired vcore, using 'can_rcv_msg'.  Failing that, we'll search
189  * the online and then the bulk_preempted lists.  These lists serve as a way to
190  * find likely messageable vcores.  spam_list_member() helps us with them,
191  * failing if anything seems to go wrong.  At which point we just lock and try
192  * to deal with things.  In that scenario, we most likely would need to lock
193  * anyway to wake up the process (was WAITING).
194  *
195  * One tricky thing with sending to the bulk_preempt list is that we may want to
196  * send a message about a (bulk) preemption to someone on that list.  This works
197  * since a given vcore that was preempted will be removed from that list before
198  * we try to send_event() (in theory, there isn't code that can send that event
199  * yet).  Someone else will get the event and wake up the preempted vcore. */
200 static void spam_public_msg(struct proc *p, struct event_msg *ev_msg,
201                                                         uint32_t vcoreid, int ev_flags)
202 {
203         struct vcore *vc;
204         /* First, try posting to the desired vcore (so long as we don't have to send
205          * it to a vcore that will run, like we do for preempt messages). */
206         if (!(ev_flags & EVENT_VCORE_MUST_RUN) &&
207            (try_spam_vcore(p, vcoreid, ev_msg, ev_flags)))
208                 return;
209         /* If the process is WAITING, let's just jump to the fallback */
210         if (p->state == PROC_WAITING)
211                 goto ultimate_fallback;
212         /* If we're here, the desired vcore is unreachable, but the process is
213          * probably RUNNING_M (online_vs) or RUNNABLE_M (bulk preempted or recently
214          * woken up), so we'll need to find another vcore. */
215         if (spam_list_member(&p->online_vcs, p, ev_msg, ev_flags))
216                 return;
217         if (spam_list_member(&p->bulk_preempted_vcs, p, ev_msg, ev_flags))
218                 return;
219         /* Last chance, let's check the head of the inactives.  It might be
220          * alertable (the kernel set it earlier due to an event, or it was a
221          * bulk_preempt that didn't restart), and we can avoid grabbing the
222          * proc_lock. */
223         vc = TAILQ_FIRST(&p->inactive_vcs);
224         if (vc) {       /* might be none in rare circumstances */
225                 if (try_spam_vcore(p, vcore2vcoreid(p, vc), ev_msg, ev_flags)) {
226                         /* Need to ensure the proc wakes up, but only if it was WAITING.
227                          * One way for this to happen is if a normal vcore was preempted
228                          * right as another vcore was yielding, and the preempted
229                          * message was sent after the last vcore yielded (which caused
230                          * us to be WAITING */
231                         if (p->state == PROC_WAITING) {
232                                 spin_lock(&p->proc_lock);
233                                 __proc_wakeup(p);       /* internally, this double-checks WAITING */
234                                 spin_unlock(&p->proc_lock);
235                         }
236                         return;
237                 }
238         }
239 ultimate_fallback:
240         /* At this point, we can't find one.  This could be due to a (hopefully
241          * rare) weird yield/request storm, or more commonly because the lists were
242          * empty and the process is simply WAITING (yielded all of its vcores and is
243          * waiting on an event).  Time for the ultimate fallback: locking.  Note
244          * that when we __alert_vcore(), there is a chance we need to mmap, which
245          * grabs the mm_lock. */
246         spin_lock(&p->proc_lock);
247         if (p->state != PROC_WAITING) {
248                 /* We need to check the online and bulk_preempt lists again, now that we are
249                  * sure no one is messing with them.  If we're WAITING, we can skip
250                  * these (or assert they are empty!). */
251                 vc = TAILQ_FIRST(&p->online_vcs);
252                 if (vc) {
253                         /* there's an online vcore, so just alert it (we know it isn't going
254                          * anywhere), and return */
255                         spam_vcore(p, vcore2vcoreid(p, vc), ev_msg, ev_flags);
256                         spin_unlock(&p->proc_lock);
257                         return;
258                 }
259                 vc = TAILQ_FIRST(&p->bulk_preempted_vcs);
260                 if (vc) {
261                         /* the process is bulk preempted, similar deal to above */
262                         spam_vcore(p, vcore2vcoreid(p, vc), ev_msg, ev_flags);
263                         spin_unlock(&p->proc_lock);
264                         return;
265                 }
266         }
267         /* At this point, we're sure all vcores are yielded, though we might not be
268          * WAITING.  Post to the first on the inactive list (which is the one that
269          * will definitely be woken up) */
270         vc = TAILQ_FIRST(&p->inactive_vcs);
271         assert(vc);
272         spam_vcore(p, vcore2vcoreid(p, vc), ev_msg, ev_flags);
273         /* Set the vcore's alertable flag, to short circuit our last ditch effort
274          * above */
275         set_vcore_msgable(vcore2vcoreid(p, vc));
276         /* The first event to catch the process with no online/bp vcores will need
277          * to wake it up.  (We could be RUNNABLE_M here if another event already woke
278          * us.) and we didn't get lucky with the penultimate fallback.
279          * __proc_wakeup() will check for WAITING. */
280         __proc_wakeup(p);
281         spin_unlock(&p->proc_lock);
282         return;
283 }
284
285 /* Helper: sends an indirection event for an ev_q, preferring vcoreid */
286 static void send_indir(struct proc *p, struct event_queue *ev_q,
287                        uint32_t vcoreid)
288 {
289         struct event_msg local_msg = {0};
290         /* If an alert is already pending and they don't want repeats, just return.
291          * One of the few uses of NOTHROTTLE will be for preempt_msg ev_qs.  Ex: an
292          * INDIR was already sent to the preempted vcore, then alert throttling
293          * would stop another vcore from getting the message about the original
294          * vcore. */
295         if (!(ev_q->ev_flags & EVENT_NOTHROTTLE) && (ev_q->ev_alert_pending))
296                 return;
297         /* We'll eventually get an INDIR through, so don't send any more til
298          * userspace toggles this.  Regardless of other writers to this flag, we
299          * eventually send an alert that causes userspace to turn throttling off
300          * again (before handling all of the ev_q's events).
301          *
302          * This will also squelch IPIs, since there's no reason to send the IPI if
303          * the INDIR is still un-acknowledged.  The vcore is either in vcore
304          * context, attempting to deal with the INDIR, or offline.  This statement
305          * is probably true. */
306         ev_q->ev_alert_pending = TRUE;
307         wmb();  /* force this write to happen before any event writes */
308         local_msg.ev_type = EV_EVENT;
309         local_msg.ev_arg3 = ev_q;
310         /* Don't care about FALLBACK, just send and be done with it.  TODO:
311          * considering getting rid of FALLBACK as an option and making it mandatory
312          * when you want an INDIR.  Having trouble thinking of when you'd want an
313          * INDIR but not a FALLBACK. */
314         if (!(ev_q->ev_flags & EVENT_FALLBACK)) {
315                 printk("[kernel] INDIR requested without FALLBACK, prob a bug.\n");
316                 spam_vcore(p, vcoreid, &local_msg, ev_q->ev_flags);
317                 return;
318         }
319         /* At this point, we actually want to send an INDIR (with FALLBACK).
320          * This will guarantee the message makes it to some vcore.  For flags, we
321          * only want to send flags relevant to spamming messages. */
322         spam_public_msg(p, &local_msg, vcoreid, ev_q->ev_flags & EVENT_SPAM_FLAGS);
323 }
324
325 /* Helper that alerts a vcore, by IPI and/or INDIR, that it needs to check the
326  * ev_q.  send_indir() eventually Handles FALLBACK and other tricky things. 
327  * alerted. */
328 static void alert_vcore(struct proc *p, struct event_queue *ev_q,
329                         uint32_t vcoreid)
330 {
331         /* INDIR will also call try_notify (IPI) later */
332         if (ev_q->ev_flags & EVENT_INDIR) {
333                 send_indir(p, ev_q, vcoreid);
334         } else {
335                 /* they may want an IPI despite not wanting an INDIR */
336                 try_notify(p, vcoreid, ev_q->ev_flags);
337         }
338 }
339
340 /* Send an event to ev_q, based on the parameters in ev_q's flag.  We don't
341  * accept null ev_qs, since the caller ought to be checking before bothering to
342  * make a msg and send it to the event_q.  Vcoreid is who the kernel thinks the
343  * message ought to go to (for IPIs).  Appropriate for things like
344  * EV_PREEMPT_PENDING, where we tell the affected vcore.  To have the message go
345  * where the kernel suggests, set EVENT_VCORE_APPRO(priate). */
346 void send_event(struct proc *p, struct event_queue *ev_q, struct event_msg *msg,
347                 uint32_t vcoreid)
348 {
349         struct proc *old_proc;
350         struct event_mbox *ev_mbox = 0;
351         assert(p);
352         printd("[kernel] sending msg to proc %08p, ev_q %08p\n", p, ev_q);
353         if (!ev_q) {
354                 warn("[kernel] Null ev_q - kernel code should check before sending!");
355                 return;
356         }
357         if (!is_user_rwaddr(ev_q, sizeof(struct event_queue))) {
358                 /* Ought to kill them, just warn for now */
359                 warn("[kernel] Illegal addr for ev_q");
360                 return;
361         }
362         /* ev_q is a user pointer, so we need to make sure we're in the right
363          * address space */
364         old_proc = switch_to(p);
365         /* Get the mbox and vcoreid */
366         /* If we're going with APPRO, we use the kernel's suggested vcore's ev_mbox.
367          * vcoreid is already what the kernel suggests. */
368         if (ev_q->ev_flags & EVENT_VCORE_APPRO) {
369                 /* flags determine if it's private (like a preempt pending) or not */
370                 ev_mbox = get_vcpd_mbox(vcoreid, ev_q->ev_flags);
371         } else {        /* common case */
372                 ev_mbox = ev_q->ev_mbox;
373                 vcoreid = ev_q->ev_vcore;
374         }
375         /* Check on the style, which could affect our mbox selection.  Other styles
376          * would go here (or in similar functions we call to).  Important thing is
377          * we come out knowing which vcore to send to in the event of an IPI/INDIR,
378          * and we know what mbox to post to. */
379         if (ev_q->ev_flags & EVENT_ROUNDROBIN) {
380                 /* Pick a vcore, and if we don't have a mbox yet, pick that vcore's
381                  * default mbox.  Assuming ev_vcore was the previous one used.  Note
382                  * that round-robin overrides the passed-in vcoreid. */
383                 vcoreid = (ev_q->ev_vcore + 1) % p->procinfo->num_vcores;
384                 ev_q->ev_vcore = vcoreid;
385                 /* Note that the style of not having a specific ev_mbox may go away.  I
386                  * can't think of legitimate uses of this for now, since things that are
387                  * RR probably are non-vcore-business, and thus inappropriate for a VCPD
388                  * ev_mbox. */
389                 if (!ev_mbox)
390                         ev_mbox = get_vcpd_mbox(vcoreid, ev_q->ev_flags);
391         }
392         /* At this point, we ought to have the right mbox to send the msg to, and
393          * which vcore to send an IPI to (if we send one).  The mbox could be the
394          * vcore's vcpd ev_mbox.  The vcoreid only matters for IPIs and INDIRs. */
395         if (!ev_mbox) {
396                 /* this is a process error */
397                 warn("[kernel] ought to have an mbox by now!");
398                 goto out;
399         }
400         /* Even if we're using an mbox in procdata (VCPD), we want a user pointer */
401         if (!is_user_rwaddr(ev_mbox, sizeof(struct event_mbox))) {
402                 /* Ought to kill them, just warn for now */
403                 warn("[kernel] Illegal addr for ev_mbox");
404                 goto out;
405         }
406         /* We used to support no msgs, but quit being lazy and send a 'msg'.  If the
407          * ev_q is a NOMSG, we won't actually memcpy or anything, it'll just be a
408          * vehicle for sending the ev_type. */
409         assert(msg);
410         post_ev_msg(p, ev_mbox, msg, ev_q->ev_flags);
411         wmb();  /* ensure ev_msg write is before alert_vcore() */
412         /* Help out userspace a bit by checking for a potentially confusing bug */
413         if ((ev_mbox == get_vcpd_mbox_pub(vcoreid)) &&
414             (ev_q->ev_flags & EVENT_INDIR))
415                 printk("[kernel] User-bug: ev_q has an INDIR with a VCPD ev_mbox!\n");
416         /* Prod/alert a vcore with an IPI or INDIR, if desired */
417         if ((ev_q->ev_flags & (EVENT_IPI | EVENT_INDIR)))
418                 alert_vcore(p, ev_q, vcoreid);
419         /* Fall through */
420 out:
421         /* Return to the old address space. */
422         switch_back(p, old_proc);
423 }
424
425 /* Send an event for the kernel event ev_num.  These are the "one sided" kernel
426  * initiated events, that require a lookup of the ev_q in procdata.  This is
427  * roughly equivalent to the old "proc_notify()" */
428 void send_kernel_event(struct proc *p, struct event_msg *msg, uint32_t vcoreid)
429 {
430         uint16_t ev_num = msg->ev_type;
431         assert(ev_num < MAX_NR_EVENT);          /* events start at 0 */
432         struct event_queue *ev_q = p->procdata->kernel_evts[ev_num];
433         /* linux would put a rmb_depends() here too, i think. */
434         if (ev_q)
435                 send_event(p, ev_q, msg, vcoreid);
436 }
437
438 /* Writes the msg to the vcpd mbox of the vcore.  If you want the private mbox,
439  * send in the ev_flag EVENT_VCORE_PRIVATE.  If not, the message could
440  * be received by other vcores if the given vcore is offline/preempted/etc.
441  * Whatever other flags you pass in will get sent to post_ev_msg.  Currently,
442  * the only one that will get looked at is NO_MSG (set a bit).
443  *
444  * This needs to load current (switch_to), but doesn't need to care about what
445  * the process wants.  Note this isn't commonly used - just the monitor and
446  * sys_self_notify(). */
447 void post_vcore_event(struct proc *p, struct event_msg *msg, uint32_t vcoreid,
448                       int ev_flags)
449 {
450         /* Need to set p as current to post the event */
451         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
452         struct proc *old_proc = switch_to(p);
453         /* *ev_mbox is the user address of the vcpd mbox */
454         post_vc_msg(p, vcoreid, get_vcpd_mbox(vcoreid, ev_flags), msg, ev_flags);
455         switch_back(p, old_proc);
456 }