Allow ev_qs to not have INDIR throttling (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. */
218         /* TODO: need a ONLINE_ONLY flag or something, for preempt messages */
219         if (try_alert_vcore(p, ev_q, vcoreid))
220                 return;
221         /* If the process is WAITING, let's just jump to the fallback */
222         if (p->state == PROC_WAITING)
223                 goto ultimate_fallback;
224         /* If we're here, the desired vcore is unreachable, but the process is
225          * probably RUNNING_M (online_vs) or RUNNABLE_M (bulk preempted or recently
226          * woken up), so we'll need to find another vcore. */
227         if (__alert_list_member(&p->online_vcs, p, ev_q))
228                 return;
229         if (__alert_list_member(&p->bulk_preempted_vcs, p, ev_q))
230                 return;
231         /* Last chance, let's check the head of the inactives.  It might be
232          * alertable (the kernel set it earlier due to an event, or it was a
233          * bulk_preempt that didn't restart), and we can avoid grabbing the
234          * proc_lock. */
235         vc = TAILQ_FIRST(&p->inactive_vcs);
236         if (vc) {       /* might be none in rare circumstances */
237                 if (try_alert_vcore(p, ev_q, vcore2vcoreid(p, vc))) {
238                         /* Need to ensure the proc wakes up, but only if it was WAITING.
239                          * One way for this to happen is if a normal vcore was preempted
240                          * right as another vcore was yielding, and the preempted
241                          * message was sent after the last vcore yielded (which caused
242                          * us to be WAITING */
243                         if (p->state == PROC_WAITING) {
244                                 spin_lock(&p->proc_lock);
245                                 __proc_wakeup(p);       /* internally, this double-checks WAITING */
246                                 spin_unlock(&p->proc_lock);
247                         }
248                         return;
249                 }
250         }
251 ultimate_fallback:
252         /* At this point, we can't find one.  This could be due to a (hopefully
253          * rare) weird yield/request storm, or more commonly because the lists were
254          * empty and the process is simply WAITING (yielded all of its vcores and is
255          * waiting on an event).  Time for the ultimate fallback: locking.  Note
256          * that when we __alert_vcore(), there is a chance we need to mmap, which
257          * grabs the mm_lock. */
258         spin_lock(&p->proc_lock);
259         if (p->state != PROC_WAITING) {
260                 /* We need to check the online and bulk_preempt lists again, now that we are
261                  * sure no one is messing with them.  If we're WAITING, we can skip
262                  * these (or assert they are empty!). */
263                 vc = TAILQ_FIRST(&p->online_vcs);
264                 if (vc) {
265                         /* there's an online vcore, so just alert it (we know it isn't going
266                          * anywhere), and return */
267                         __alert_vcore(p, ev_q, vcore2vcoreid(p, vc));
268                         spin_unlock(&p->proc_lock);
269                         return;
270                 }
271                 vc = TAILQ_FIRST(&p->bulk_preempted_vcs);
272                 if (vc) {
273                         /* the process is bulk preempted, similar deal to above */
274                         __alert_vcore(p, ev_q, vcore2vcoreid(p, vc));
275                         spin_unlock(&p->proc_lock);
276                         return;
277                 }
278         }
279         /* At this point, we're sure all vcores are yielded, though we might not be
280          * WAITING.  Post to the first on the inactive list (which is the one that
281          * will definitely be woken up) */
282         vc = TAILQ_FIRST(&p->inactive_vcs);
283         assert(vc);
284         __alert_vcore(p, ev_q, vcore2vcoreid(p, vc));
285         /* Set the vcore's alertable flag, to short circuit our last ditch effort
286          * above */
287         set_vcore_alertable(vcore2vcoreid(p, vc));
288         /* The first event to catch the process with no online/bp vcores will need
289          * to wake it up.  (We could be RUNNABLE_M here if another event already woke
290          * us.) and we didn't get lucky with the penultimate fallback.
291          * __proc_wakeup() will check for WAITING. */
292         __proc_wakeup(p);
293         spin_unlock(&p->proc_lock);
294         return;
295 }
296
297 /* Send an event to ev_q, based on the parameters in ev_q's flag.  We don't
298  * accept null ev_qs, since the caller ought to be checking before bothering to
299  * make a msg and send it to the event_q.  Vcoreid is who the kernel thinks the
300  * message ought to go to (for IPIs).  Appropriate for things like
301  * EV_PREEMPT_PENDING, where we tell the affected vcore.  To have the message go
302  * where the kernel suggests, set EVENT_VCORE_APPRO(priate). */
303 void send_event(struct proc *p, struct event_queue *ev_q, struct event_msg *msg,
304                 uint32_t vcoreid)
305 {
306         struct proc *old_proc;
307         struct event_mbox *ev_mbox = 0;
308         assert(p);
309         printd("[kernel] sending msg to proc %08p, ev_q %08p\n", p, ev_q);
310         if (!ev_q) {
311                 warn("[kernel] Null ev_q - kernel code should check before sending!");
312                 return;
313         }
314         if (!is_user_rwaddr(ev_q, sizeof(struct event_queue))) {
315                 /* Ought to kill them, just warn for now */
316                 warn("[kernel] Illegal addr for ev_q");
317                 return;
318         }
319         /* ev_q is a user pointer, so we need to make sure we're in the right
320          * address space */
321         old_proc = switch_to(p);
322         /* Get the mbox and vcoreid */
323         /* If we're going with APPRO, we use the kernel's suggested vcore's ev_mbox.
324          * vcoreid is already what the kernel suggests. */
325         if (ev_q->ev_flags & EVENT_VCORE_APPRO) {
326                 ev_mbox = get_proc_ev_mbox(vcoreid);
327         } else {        /* common case */
328                 ev_mbox = ev_q->ev_mbox;
329                 vcoreid = ev_q->ev_vcore;
330         }
331         /* Check on the style, which could affect our mbox selection.  Other styles
332          * would go here (or in similar functions we call to).  Important thing is
333          * we come out knowing which vcore to send to in the event of an IPI/INDIR,
334          * and we know what mbox to post to. */
335         if (ev_q->ev_flags & EVENT_ROUNDROBIN) {
336                 /* Pick a vcore, and if we don't have a mbox yet, pick that vcore's
337                  * default mbox.  Assuming ev_vcore was the previous one used.  Note
338                  * that round-robin overrides the passed-in vcoreid. */
339                 vcoreid = (ev_q->ev_vcore + 1) % p->procinfo->num_vcores;
340                 ev_q->ev_vcore = vcoreid;
341                 /* Note that the style of not having a specific ev_mbox may go away.  I
342                  * can't think of legitimate uses of this for now, since things that are
343                  * RR probably are non-vcore-business, and thus inappropriate for a VCPD
344                  * ev_mbox. */
345                 if (!ev_mbox)
346                         ev_mbox = get_proc_ev_mbox(vcoreid);
347         }
348         /* At this point, we ought to have the right mbox to send the msg to, and
349          * which vcore to send an IPI to (if we send one).  The mbox could be the
350          * vcore's vcpd ev_mbox.  The vcoreid only matters for IPIs and INDIRs. */
351         if (!ev_mbox) {
352                 /* this is a process error */
353                 warn("[kernel] ought to have an mbox by now!");
354                 goto out;
355         }
356         /* Even if we're using an mbox in procdata (VCPD), we want a user pointer */
357         if (!is_user_rwaddr(ev_mbox, sizeof(struct event_mbox))) {
358                 /* Ought to kill them, just warn for now */
359                 warn("[kernel] Illegal addr for ev_mbox");
360                 goto out;
361         }
362         /* We used to support no msgs, but quit being lazy and send a 'msg'.  If the
363          * ev_q is a NOMSG, we won't actually memcpy or anything, it'll just be a
364          * vehicle for sending the ev_type. */
365         assert(msg);
366         post_ev_msg(ev_mbox, msg, ev_q->ev_flags);
367         /* Help out userspace a bit by checking for a potentially confusing bug */
368         if ((ev_mbox == get_proc_ev_mbox(vcoreid)) &&
369             (ev_q->ev_flags & EVENT_INDIR))
370                 printk("[kernel] User-bug: ev_q has an INDIR with a VCPD ev_mbox!\n");
371         /* Prod/alert a vcore with an IPI or INDIR, if desired */
372         if ((ev_q->ev_flags & (EVENT_IPI | EVENT_INDIR)))
373                 alert_vcore(p, ev_q, vcoreid);
374         /* Fall through */
375 out:
376         /* Return to the old address space. */
377         switch_back(p, old_proc);
378 }
379
380 /* Send an event for the kernel event ev_num.  These are the "one sided" kernel
381  * initiated events, that require a lookup of the ev_q in procdata.  This is
382  * roughly equivalent to the old "proc_notify()" */
383 void send_kernel_event(struct proc *p, struct event_msg *msg, uint32_t vcoreid)
384 {
385         uint16_t ev_num = msg->ev_type;
386         assert(ev_num < MAX_NR_EVENT);          /* events start at 0 */
387         struct event_queue *ev_q = p->procdata->kernel_evts[ev_num];
388         if (ev_q)
389                 send_event(p, ev_q, msg, vcoreid);
390 }
391
392 /* Writes the msg to the vcpd/default mbox of the vcore.  Needs to load current,
393  * but doesn't need to care about what the process wants.  Note this isn't
394  * commonly used - just the monitor and sys_self_notify(). */
395 void post_vcore_event(struct proc *p, struct event_msg *msg, uint32_t vcoreid)
396 {
397         /* Need to set p as current to post the event */
398         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
399         struct proc *old_proc = switch_to(p);
400         /* *ev_mbox is the user address of the vcpd mbox */
401         post_ev_msg(get_proc_ev_mbox(vcoreid), msg, 0); /* no chance for a NOMSG */
402         switch_back(p, old_proc);
403 }