4fac486633003b259307b702e9ac10fc8d3f2253
[akaros.git] / kern / src / trap.c
1 /* Copyright (c) 2012 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Arch-independent trap handling and kernel messaging */
6
7 #include <arch/arch.h>
8 #include <smp.h>
9 #include <trap.h>
10 #include <stdio.h>
11 #include <slab.h>
12 #include <assert.h>
13 #include <kdebug.h>
14 #include <kmalloc.h>
15
16 void reflect_unhandled_trap(unsigned int trap_nr, unsigned int err,
17                             unsigned long aux)
18 {
19         uint32_t coreid = core_id();
20         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
21         struct proc *p = pcpui->cur_proc;
22         uint32_t vcoreid = pcpui->owning_vcoreid;
23         struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
24         struct hw_trapframe *hw_tf = &pcpui->cur_ctx->tf.hw_tf;
25         assert(p);
26         assert(pcpui->cur_ctx && (pcpui->cur_ctx->type == ROS_HW_CTX));
27         if (!(p->procinfo->is_mcp)) {
28                 printk("Unhandled SCP trap\n");
29                 goto error_out;
30         }
31         if (vcpd->notif_disabled) {
32                 printk("Unhandled MCP trap in vcore context\n");
33                 goto error_out;
34         }
35         /* need to store trap_nr, err code, and aux into the tf so that it can get
36          * extracted on the other end, and we need to flag the TF in some way so we
37          * can tell it was reflected.  for example, on a PF, we need some number (14
38          * on x86), the prot violation (write, read, etc), and the virt addr (aux).
39          * parlib will know how to extract this info. */
40         __arch_reflect_trap_hwtf(hw_tf, trap_nr, err, aux);
41         /* the guts of a __notify */
42         vcpd->notif_disabled = TRUE;
43         vcpd->uthread_ctx = *pcpui->cur_ctx;
44         memset(pcpui->cur_ctx, 0, sizeof(struct user_context));
45         proc_init_ctx(pcpui->cur_ctx, vcoreid, p->env_entry,
46                       vcpd->transition_stack, vcpd->vcore_tls_desc);
47         return;
48 error_out:
49         print_trapframe(hw_tf);
50         enable_irq();
51         printk("err 0x%x, aux %p\n", err, aux);
52         debug_addr_proc(p, get_hwtf_pc(hw_tf));
53         proc_destroy(p);
54 }
55
56 struct kmem_cache *kernel_msg_cache;
57
58 void kernel_msg_init(void)
59 {
60         kernel_msg_cache = kmem_cache_create("kernel_msgs",
61                            sizeof(struct kernel_message), ARCH_CL_SIZE, 0, 0, 0);
62 }
63
64 uint32_t send_kernel_message(uint32_t dst, amr_t pc, long arg0, long arg1,
65                              long arg2, int type)
66 {
67         kernel_message_t *k_msg;
68         assert(pc);
69         // note this will be freed on the destination core
70         k_msg = kmem_cache_alloc(kernel_msg_cache, 0);
71         k_msg->srcid = core_id();
72         k_msg->dstid = dst;
73         k_msg->pc = pc;
74         k_msg->arg0 = arg0;
75         k_msg->arg1 = arg1;
76         k_msg->arg2 = arg2;
77         switch (type) {
78                 case KMSG_IMMEDIATE:
79                         spin_lock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
80                         STAILQ_INSERT_TAIL(&per_cpu_info[dst].immed_amsgs, k_msg, link);
81                         spin_unlock_irqsave(&per_cpu_info[dst].immed_amsg_lock);
82                         break;
83                 case KMSG_ROUTINE:
84                         spin_lock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
85                         STAILQ_INSERT_TAIL(&per_cpu_info[dst].routine_amsgs, k_msg, link);
86                         spin_unlock_irqsave(&per_cpu_info[dst].routine_amsg_lock);
87                         break;
88                 default:
89                         panic("Unknown type of kernel message!");
90         }
91         /* since we touched memory the other core will touch (the lock), we don't
92          * need an wmb_f() */
93         /* if we're sending a routine message locally, we don't want/need an IPI */
94         if ((dst != k_msg->srcid) || (type == KMSG_IMMEDIATE))
95                 send_ipi(dst, I_KERNEL_MSG);
96         return 0;
97 }
98
99 /* Kernel message IPI/IRQ handler.
100  *
101  * This processes immediate messages, and that's it (it used to handle routines
102  * too, if it came in from userspace).  Routine messages will get processed when
103  * the kernel has a chance (right before popping to userspace or in smp_idle
104  * before halting).
105  *
106  * Note that all of this happens from interrupt context, and interrupts are
107  * disabled. */
108 void handle_kmsg_ipi(struct hw_trapframe *hw_tf, void *data)
109 {
110         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
111         struct kernel_message *kmsg_i, *temp;
112         /* Avoid locking if the list appears empty (lockless peek is okay) */
113         if (STAILQ_EMPTY(&pcpui->immed_amsgs))
114                 return;
115         /* The lock serves as a cmb to force a re-read of the head of the list */
116         spin_lock_irqsave(&pcpui->immed_amsg_lock);
117         STAILQ_FOREACH_SAFE(kmsg_i, &pcpui->immed_amsgs, link, temp) {
118                 pcpui_trace_kmsg(pcpui, (uintptr_t)kmsg_i->pc);
119                 kmsg_i->pc(kmsg_i->srcid, kmsg_i->arg0, kmsg_i->arg1, kmsg_i->arg2);
120                 STAILQ_REMOVE(&pcpui->immed_amsgs, kmsg_i, kernel_message, link);
121                 kmem_cache_free(kernel_msg_cache, (void*)kmsg_i);
122         }
123         spin_unlock_irqsave(&pcpui->immed_amsg_lock);
124 }
125
126 bool has_routine_kmsg(void)
127 {
128         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
129         /* lockless peek */
130         return !STAILQ_EMPTY(&pcpui->routine_amsgs);
131 }
132
133 /* Helper function, gets the next routine KMSG (RKM).  Returns 0 if the list was
134  * empty. */
135 static kernel_message_t *get_next_rkmsg(struct per_cpu_info *pcpui)
136 {
137         struct kernel_message *kmsg;
138         /* Avoid locking if the list appears empty (lockless peek is okay) */
139         if (STAILQ_EMPTY(&pcpui->routine_amsgs))
140                 return 0;
141         /* The lock serves as a cmb to force a re-read of the head of the list.
142          * IRQs are disabled by our caller. */
143         spin_lock(&pcpui->routine_amsg_lock);
144         kmsg = STAILQ_FIRST(&pcpui->routine_amsgs);
145         if (kmsg)
146                 STAILQ_REMOVE_HEAD(&pcpui->routine_amsgs, link);
147         spin_unlock(&pcpui->routine_amsg_lock);
148         return kmsg;
149 }
150
151 /* Runs routine kernel messages.  This might not return.  In the past, this
152  * would also run immediate messages, but this is unnecessary.  Immediates will
153  * run whenever we reenable IRQs.  We could have some sort of ordering or
154  * guarantees between KMSG classes, but that's not particularly useful at this
155  * point.
156  *
157  * Note this runs from normal context, with interruptes disabled.  However, a
158  * particular RKM could enable interrupts - for instance __launch_kthread() will
159  * restore an old kthread that may have had IRQs on. */
160 void process_routine_kmsg(void)
161 {
162         uint32_t pcoreid = core_id();
163         struct per_cpu_info *pcpui = &per_cpu_info[pcoreid];
164         struct kernel_message msg_cp, *kmsg;
165
166         /* Important that callers have IRQs disabled.  When sending cross-core RKMs,
167          * the IPI is used to keep the core from going to sleep - even though RKMs
168          * aren't handled in the kmsg handler.  Check smp_idle() for more info. */
169         assert(!irq_is_enabled());
170         while ((kmsg = get_next_rkmsg(pcpui))) {
171                 /* Copy in, and then free, in case we don't return */
172                 msg_cp = *kmsg;
173                 kmem_cache_free(kernel_msg_cache, (void*)kmsg);
174                 assert(msg_cp.dstid == pcoreid);        /* caught a brutal bug with this */
175                 set_rkmsg(pcpui);                                       /* we're now in early RKM ctx */
176                 /* The kmsg could block.  If it does, we want the kthread code to know
177                  * it's not running on behalf of a process, and we're actually spawning
178                  * a kernel task.  While we do have a syscall that does work in an RKM
179                  * (change_to), it's not really the rest of the syscall context. */
180                 pcpui->cur_kthread->is_ktask = TRUE;
181                 pcpui_trace_kmsg(pcpui, (uintptr_t)msg_cp.pc);
182                 msg_cp.pc(msg_cp.srcid, msg_cp.arg0, msg_cp.arg1, msg_cp.arg2);
183                 /* And if we make it back, be sure to unset this.  If we never return,
184                  * but the kthread exits via some other way (smp_idle()), then
185                  * smp_idle() will deal with the flag.  The default state is "off".  For
186                  * an example of an RKM that does this, check out the
187                  * monitor->mon_bin_run.  Finally, if the kthread gets swapped out of
188                  * pcpui, such as in __launch_kthread(), the next time the kthread is
189                  * reused, is_ktask will be reset. */
190                 pcpui->cur_kthread->is_ktask = FALSE;
191                 /* If we aren't still in early RKM, it is because the KMSG blocked
192                  * (thus leaving early RKM, finishing in default context) and then
193                  * returned.  This is a 'detached' RKM.  Must idle in this scenario,
194                  * since we might have migrated or otherwise weren't meant to PRKM
195                  * (can't return twice).  Also note that this may involve a core
196                  * migration, so we need to reread pcpui.*/
197                 cmb();
198                 pcpui = &per_cpu_info[core_id()];
199                 if (!in_early_rkmsg_ctx(pcpui))
200                         smp_idle();
201                 clear_rkmsg(pcpui);
202                 /* Some RKMs might turn on interrupts (perhaps in the future) and then
203                  * return. */
204                 disable_irq();
205         }
206 }
207
208 /* extremely dangerous and racy: prints out the immed and routine kmsgs for a
209  * specific core (so possibly remotely) */
210 void print_kmsgs(uint32_t coreid)
211 {
212         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
213         void __print_kmsgs(struct kernel_msg_list *list, char *type)
214         {
215                 char *fn_name;
216                 struct kernel_message *kmsg_i;
217                 STAILQ_FOREACH(kmsg_i, list, link) {
218                         fn_name = get_fn_name((long)kmsg_i->pc);
219                         printk("%s KMSG on %d from %d to run %p(%s)\n", type,
220                                kmsg_i->dstid, kmsg_i->srcid, kmsg_i->pc, fn_name); 
221                         kfree(fn_name);
222                 }
223         }
224         __print_kmsgs(&pcpui->immed_amsgs, "Immedte");
225         __print_kmsgs(&pcpui->routine_amsgs, "Routine");
226 }
227
228 /* Debugging stuff */
229 void kmsg_queue_stat(void)
230 {
231         struct kernel_message *kmsg;
232         bool immed_emp, routine_emp;
233         for (int i = 0; i < num_cpus; i++) {
234                 spin_lock_irqsave(&per_cpu_info[i].immed_amsg_lock);
235                 immed_emp = STAILQ_EMPTY(&per_cpu_info[i].immed_amsgs);
236                 spin_unlock_irqsave(&per_cpu_info[i].immed_amsg_lock);
237                 spin_lock_irqsave(&per_cpu_info[i].routine_amsg_lock);
238                 routine_emp = STAILQ_EMPTY(&per_cpu_info[i].routine_amsgs);
239                 spin_unlock_irqsave(&per_cpu_info[i].routine_amsg_lock);
240                 printk("Core %d's immed_emp: %d, routine_emp %d\n", i, immed_emp,
241                routine_emp);
242                 if (!immed_emp) {
243                         kmsg = STAILQ_FIRST(&per_cpu_info[i].immed_amsgs);
244                         printk("Immed msg on core %d:\n", i);
245                         printk("\tsrc:  %d\n", kmsg->srcid);
246                         printk("\tdst:  %d\n", kmsg->dstid);
247                         printk("\tpc:   %p\n", kmsg->pc);
248                         printk("\targ0: %p\n", kmsg->arg0);
249                         printk("\targ1: %p\n", kmsg->arg1);
250                         printk("\targ2: %p\n", kmsg->arg2);
251                 }
252                 if (!routine_emp) {
253                         kmsg = STAILQ_FIRST(&per_cpu_info[i].routine_amsgs);
254                         printk("Routine msg on core %d:\n", i);
255                         printk("\tsrc:  %d\n", kmsg->srcid);
256                         printk("\tdst:  %d\n", kmsg->dstid);
257                         printk("\tpc:   %p\n", kmsg->pc);
258                         printk("\targ0: %p\n", kmsg->arg0);
259                         printk("\targ1: %p\n", kmsg->arg1);
260                         printk("\targ2: %p\n", kmsg->arg2);
261                 }
262                         
263         }
264 }
265
266 void print_kctx_depths(const char *str)
267 {
268         uint32_t coreid = core_id();
269         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
270         
271         if (!str)
272                 str = "(none)";
273         printk("%s: Core %d, irq depth %d, ktrap depth %d, irqon %d\n", str, coreid,
274                irq_depth(pcpui), ktrap_depth(pcpui), irq_is_enabled());
275 }
276
277 void print_user_ctx(struct user_context *ctx)
278 {
279         if (ctx->type == ROS_SW_CTX)
280                 print_swtrapframe(&ctx->tf.sw_tf);
281         else if (ctx->type == ROS_HW_CTX)
282                 print_trapframe(&ctx->tf.hw_tf);
283         else
284                 printk("Bad TF %p type %d!\n", ctx, ctx->type);
285 }