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