Fixes errno value for opens without O_CREATE
[akaros.git] / kern / src / smp.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7 #ifdef __SHARC__
8 #pragma nosharc
9 #endif
10
11 #include <arch/arch.h>
12 #include <atomic.h>
13 #include <smp.h>
14 #include <error.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <assert.h>
18 #include <pmap.h>
19 #include <process.h>
20 #include <schedule.h>
21 #include <trap.h>
22 #include <trace.h>
23 #include <kdebug.h>
24 #include <kmalloc.h>
25
26 struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
27
28 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
29 atomic_t outstanding_calls = 0;
30
31 /* Helper for running a proc (if we should).  Lots of repetition with
32  * proc_restartcore */
33 static void try_run_proc(void)
34 {
35         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
36         /* There was a process running here, and we should return to it. */
37         if (pcpui->owning_proc) {
38                 assert(!pcpui->cur_kthread->sysc);
39                 assert(pcpui->cur_ctx);
40                 __proc_startcore(pcpui->owning_proc, pcpui->cur_ctx);
41                 assert(0);
42         } else {
43                 /* Make sure we have abandoned core.  It's possible to have an owner
44                  * without a current (smp_idle, __startcore, __death). */
45                 abandon_core();
46         }
47 }
48
49 /* All cores end up calling this whenever there is nothing left to do or they
50  * don't know explicitly what to do.  Non-zero cores call it when they are done
51  * booting.  Other cases include after getting a DEATH IPI.
52  *
53  * All cores attempt to run the context of any owning proc.  Barring that, they
54  * halt and wake up when interrupted, do any work on their work queue, then halt
55  * again.  In between, the ksched gets a chance to tell it to do something else,
56  * or perhaps to halt in another manner. */
57 static void __attribute__((noinline, noreturn)) __smp_idle(void)
58 {
59         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
60         clear_rkmsg(pcpui);
61         pcpui->cur_kthread->is_ktask = FALSE;
62         enable_irq();   /* one-shot change to get any IRQs before we halt later */
63         while (1) {
64                 disable_irq();
65                 process_routine_kmsg();
66                 try_run_proc();
67                 cpu_bored();            /* call out to the ksched */
68                 /* cpu_halt() atomically turns on interrupts and halts the core.
69                  * Important to do this, since we could have a RKM come in via an
70                  * interrupt right while PRKM is returning, and we wouldn't catch
71                  * it. */
72                 cpu_halt();
73                 /* interrupts are back on now (given our current semantics) */
74         }
75         assert(0);
76 }
77
78 void smp_idle(void)
79 {
80         #ifdef CONFIG_RESET_STACKS
81         set_stack_pointer(get_stack_top());
82         set_frame_pointer(0);
83         #endif /* CONFIG_RESET_STACKS */
84         __smp_idle();
85         assert(0);
86 }
87
88 /* Arch-independent per-cpu initialization.  This will call the arch dependent
89  * init first. */
90 void smp_percpu_init(void)
91 {
92         uint32_t coreid = core_id();
93         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
94         void *trace_buf;
95         struct kthread *kthread;
96         /* Don't initialize __ctx_depth here, since it is already 1 (at least on
97          * x86), since this runs in irq context. */
98         /* Do this first */
99         __arch_pcpu_init(coreid);
100         /* init our kthread (tracks our currently running context) */
101         kthread = __kthread_zalloc();
102         kthread->stacktop = get_stack_top();    /* assumes we're on the 1st page */
103         pcpui->cur_kthread = kthread;
104         per_cpu_info[coreid].spare = 0;
105         /* Init relevant lists */
106         spinlock_init_irqsave(&per_cpu_info[coreid].immed_amsg_lock);
107         STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
108         spinlock_init_irqsave(&per_cpu_info[coreid].routine_amsg_lock);
109         STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
110         /* Initialize the per-core timer chain */
111         init_timer_chain(&per_cpu_info[coreid].tchain, set_pcpu_alarm_interrupt);
112 #ifdef CONFIG_KTHREAD_POISON
113         *kstack_bottom_addr(kthread->stacktop) = 0xdeadbeef;
114 #endif /* CONFIG_KTHREAD_POISON */
115         /* Init generic tracing ring */
116         trace_buf = kpage_alloc_addr();
117         assert(trace_buf);
118         trace_ring_init(&pcpui->traces, trace_buf, PGSIZE,
119                         sizeof(struct pcpu_trace_event));
120         /* Enable full lock debugging, after all pcpui work is done */
121         pcpui->__lock_checking_enabled = 1;
122 }
123
124 /* PCPUI Trace Rings: */
125
126 static void pcpui_trace_kmsg_handler(void *event, void *data)
127 {
128         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
129         char *func_name;
130         uintptr_t addr;
131         addr = te->arg1;
132         func_name = get_fn_name(addr);
133         printk("\tKMSG %p: %s\n", addr, func_name);
134         kfree(func_name);
135 }
136
137 static void pcpui_trace_locks_handler(void *event, void *data)
138 {
139         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
140         char *func_name;
141         uintptr_t lock_addr = te->arg1;
142         if (lock_addr > KERN_LOAD_ADDR)
143                 func_name = get_fn_name(lock_addr);
144         else
145                 func_name = "Dynamic lock";
146         printk("Time %uus, lock %p (%s)\n", te->arg0, lock_addr, func_name);
147         printk("\t");
148         spinlock_debug((spinlock_t*)lock_addr);
149         if (lock_addr > KERN_LOAD_ADDR)
150                 kfree(func_name);
151 }
152
153 /* Add specific trace handlers here: */
154 trace_handler_t pcpui_tr_handlers[PCPUI_NR_TYPES] = {
155                                   0,
156                                   pcpui_trace_kmsg_handler,
157                                   pcpui_trace_locks_handler,
158                                   };
159
160 /* Generic handler for the pcpui ring.  Will switch out to the appropriate
161  * type's handler */
162 static void pcpui_trace_fn(void *event, void *data)
163 {
164         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
165         int desired_type = (int)(long)data;
166         if (te->type >= PCPUI_NR_TYPES)
167                 printk("Bad trace type %d\n", te->type);
168         /* desired_type == 0 means all types */
169         if (desired_type && desired_type != te->type)
170                 return;
171         if (pcpui_tr_handlers[te->type])
172                 pcpui_tr_handlers[te->type](event, data);
173 }
174
175 void pcpui_tr_foreach(int coreid, int type)
176 {
177         struct trace_ring *tr = &per_cpu_info[coreid].traces;
178         assert(tr);
179         printk("\n\nTrace Ring on Core %d\n--------------\n", coreid);
180         trace_ring_foreach(tr, pcpui_trace_fn, (void*)(long)type);
181 }
182
183 void pcpui_tr_foreach_all(int type)
184 {
185         for (int i = 0; i < num_cpus; i++)
186                 pcpui_tr_foreach(i, type);
187 }
188
189 void pcpui_tr_reset_all(void)
190 {
191         for (int i = 0; i < num_cpus; i++)
192                 trace_ring_reset(&per_cpu_info[i].traces);
193 }
194
195 void pcpui_tr_reset_and_clear_all(void)
196 {
197         for (int i = 0; i < num_cpus; i++)
198                 trace_ring_reset_and_clear(&per_cpu_info[i].traces);
199 }