Remove page coloring
[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 #include <arch/arch.h>
8 #include <atomic.h>
9 #include <smp.h>
10 #include <error.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <assert.h>
14 #include <pmap.h>
15 #include <process.h>
16 #include <schedule.h>
17 #include <trap.h>
18 #include <trace.h>
19 #include <kdebug.h>
20 #include <kmalloc.h>
21 #include <core_set.h>
22 #include <completion.h>
23
24 struct all_cpu_work {
25         struct completion comp;
26         void (*func)(void *);
27         void *opaque;
28 };
29
30 struct per_cpu_info per_cpu_info[MAX_NUM_CORES];
31
32 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
33 atomic_t outstanding_calls = 0;
34
35 /* Helper for running a proc (if we should).  Lots of repetition with
36  * proc_restartcore */
37 static void try_run_proc(void)
38 {
39         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
40         /* There was a process running here, and we should return to it. */
41         if (pcpui->owning_proc) {
42                 assert(!pcpui->cur_kthread->sysc);
43                 assert(pcpui->cur_ctx);
44                 __proc_startcore(pcpui->owning_proc, pcpui->cur_ctx);
45                 assert(0);
46         } else {
47                 /* Make sure we have abandoned core.  It's possible to have an owner
48                  * without a current (smp_idle, __startcore, __death). */
49                 abandon_core();
50         }
51 }
52
53 /* All cores end up calling this whenever there is nothing left to do or they
54  * don't know explicitly what to do.  Non-zero cores call it when they are done
55  * booting.  Other cases include after getting a DEATH IPI.
56  *
57  * All cores attempt to run the context of any owning proc.  Barring that, they
58  * halt and wake up when interrupted, do any work on their work queue, then halt
59  * again.  In between, the ksched gets a chance to tell it to do something else,
60  * or perhaps to halt in another manner. */
61 static void __attribute__((noinline, noreturn)) __smp_idle(void)
62 {
63         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
64
65         disable_irq();  /* might not be needed - need to look at KMSGs closely */
66         clear_rkmsg(pcpui);
67         pcpui->cur_kthread->flags = KTH_DEFAULT_FLAGS;
68         enable_irq();   /* one-shot change to get any IRQs before we halt later */
69         while (1) {
70                 disable_irq();
71                 process_routine_kmsg();
72                 try_run_proc();
73                 cpu_bored();            /* call out to the ksched */
74                 /* cpu_halt() atomically turns on interrupts and halts the core.
75                  * Important to do this, since we could have a RKM come in via an
76                  * interrupt right while PRKM is returning, and we wouldn't catch
77                  * it. */
78                 __set_cpu_state(pcpui, CPU_STATE_IDLE);
79                 cpu_halt();
80                 /* interrupts are back on now (given our current semantics) */
81         }
82         assert(0);
83 }
84
85 void smp_idle(void)
86 {
87         /* FP must be zeroed before SP.  Ideally, we'd do both atomically.  If we
88          * take an IRQ/NMI in between and set SP first, then a backtrace would be
89          * confused since FP points *below* the SP that the *IRQ handler* is now
90          * using.  By zeroing FP first, at least we won't BT at all (though FP is
91          * still out of sync with SP). */
92         set_frame_pointer(0);
93         set_stack_pointer(get_stack_top());
94         __smp_idle();
95 }
96
97 /* Arch-independent per-cpu initialization.  This will call the arch dependent
98  * init first. */
99 void smp_percpu_init(void)
100 {
101         uint32_t coreid = core_id();
102         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
103         void *trace_buf;
104         struct kthread *kthread;
105         /* Don't initialize __ctx_depth here, since it is already 1 (at least on
106          * x86), since this runs in irq context. */
107         /* Do this first */
108         __arch_pcpu_init(coreid);
109         /* init our kthread (tracks our currently running context) */
110         kthread = __kthread_zalloc();
111         kthread->stacktop = get_stack_top();    /* assumes we're on the 1st page */
112         pcpui->cur_kthread = kthread;
113         /* Treat the startup threads as ktasks.  This will last until smp_idle when
114          * they clear it, either in anticipation of being a user-backing kthread or
115          * to handle an RKM. */
116         kthread->flags = KTH_KTASK_FLAGS;
117         per_cpu_info[coreid].spare = 0;
118         /* Init relevant lists */
119         spinlock_init_irqsave(&per_cpu_info[coreid].immed_amsg_lock);
120         STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
121         spinlock_init_irqsave(&per_cpu_info[coreid].routine_amsg_lock);
122         STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
123         /* Initialize the per-core timer chain */
124         init_timer_chain(&per_cpu_info[coreid].tchain, set_pcpu_alarm_interrupt);
125 #ifdef CONFIG_KTHREAD_POISON
126         *kstack_bottom_addr(kthread->stacktop) = 0xdeadbeef;
127 #endif /* CONFIG_KTHREAD_POISON */
128         /* Init generic tracing ring */
129         trace_buf = kpage_alloc_addr();
130         assert(trace_buf);
131         trace_ring_init(&pcpui->traces, trace_buf, PGSIZE,
132                         sizeof(struct pcpu_trace_event));
133         for (int i = 0; i < NR_CPU_STATES; i++)
134                 pcpui->state_ticks[i] = 0;
135         pcpui->last_tick_cnt = read_tsc();
136         /* Core 0 is in the KERNEL state, called from smp_boot.  The other cores are
137          * too, at least on x86, where we were called from asm (woken by POKE). */
138         pcpui->cpu_state = CPU_STATE_KERNEL;
139         /* Enable full lock debugging, after all pcpui work is done */
140         pcpui->__lock_checking_enabled = 1;
141 }
142
143 /* it's actually okay to set the state to the existing state.  originally, it
144  * was a bug in the state tracking, but it is possible, at least on x86, to have
145  * a halted core (state IDLE) get woken up by an IRQ that does not trigger the
146  * IRQ handling state.  for example, there is the I_POKE_CORE ipi.  smp_idle
147  * will just sleep again, and reset the state from IDLE to IDLE. */
148 void __set_cpu_state(struct per_cpu_info *pcpui, int state)
149 {
150         uint64_t now_ticks;
151         assert(!irq_is_enabled());
152         /* TODO: could put in an option to enable/disable state tracking. */
153         now_ticks = read_tsc();
154         pcpui->state_ticks[pcpui->cpu_state] += now_ticks - pcpui->last_tick_cnt;
155         /* TODO: if the state was user, we could account for the vcore's time,
156          * similar to the total_ticks in struct vcore.  the difference is that the
157          * total_ticks tracks the vcore's virtual time, while this tracks user time.
158          * something like vcore->user_ticks. */
159         pcpui->cpu_state = state;
160         pcpui->last_tick_cnt = now_ticks;
161 }
162
163 void reset_cpu_state_ticks(int coreid)
164 {
165         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
166         uint64_t now_ticks;
167         if (coreid >= num_cores)
168                 return;
169         /* need to update last_tick_cnt, so the current value doesn't get added in
170          * next time we update */
171         now_ticks = read_tsc();
172         for (int i = 0; i < NR_CPU_STATES; i++) {
173                 pcpui->state_ticks[i] = 0;
174                 pcpui->last_tick_cnt = now_ticks;
175         }
176 }
177
178 /* PCPUI Trace Rings: */
179
180 static void pcpui_trace_kmsg_handler(void *event, void *data)
181 {
182         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
183         char *func_name;
184         uintptr_t addr;
185         addr = te->arg1;
186         func_name = get_fn_name(addr);
187         printk("\tKMSG %p: %s\n", addr, func_name);
188         kfree(func_name);
189 }
190
191 static void pcpui_trace_locks_handler(void *event, void *data)
192 {
193         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
194         char *func_name;
195         uintptr_t lock_addr = te->arg1;
196         if (lock_addr > KERN_LOAD_ADDR)
197                 func_name = get_fn_name(lock_addr);
198         else
199                 func_name = "Dynamic lock";
200         printk("Time %uus, lock %p (%s)\n", te->arg0, lock_addr, func_name);
201         printk("\t");
202         spinlock_debug((spinlock_t*)lock_addr);
203         if (lock_addr > KERN_LOAD_ADDR)
204                 kfree(func_name);
205 }
206
207 /* Add specific trace handlers here: */
208 trace_handler_t pcpui_tr_handlers[PCPUI_NR_TYPES] = {
209                                   0,
210                                   pcpui_trace_kmsg_handler,
211                                   pcpui_trace_locks_handler,
212                                   };
213
214 /* Generic handler for the pcpui ring.  Will switch out to the appropriate
215  * type's handler */
216 static void pcpui_trace_fn(void *event, void *data)
217 {
218         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
219         int desired_type = (int)(long)data;
220         if (te->type >= PCPUI_NR_TYPES)
221                 printk("Bad trace type %d\n", te->type);
222         /* desired_type == 0 means all types */
223         if (desired_type && desired_type != te->type)
224                 return;
225         if (pcpui_tr_handlers[te->type])
226                 pcpui_tr_handlers[te->type](event, data);
227 }
228
229 void pcpui_tr_foreach(int coreid, int type)
230 {
231         struct trace_ring *tr = &per_cpu_info[coreid].traces;
232         assert(tr);
233         printk("\n\nTrace Ring on Core %d\n--------------\n", coreid);
234         trace_ring_foreach(tr, pcpui_trace_fn, (void*)(long)type);
235 }
236
237 void pcpui_tr_foreach_all(int type)
238 {
239         for (int i = 0; i < num_cores; i++)
240                 pcpui_tr_foreach(i, type);
241 }
242
243 void pcpui_tr_reset_all(void)
244 {
245         for (int i = 0; i < num_cores; i++)
246                 trace_ring_reset(&per_cpu_info[i].traces);
247 }
248
249 void pcpui_tr_reset_and_clear_all(void)
250 {
251         for (int i = 0; i < num_cores; i++)
252                 trace_ring_reset_and_clear(&per_cpu_info[i].traces);
253 }
254
255 static void smp_do_core_work(uint32_t srcid, long a0, long a1, long a2)
256 {
257         struct all_cpu_work *acw = (struct all_cpu_work *) a0;
258
259         acw->func(acw->opaque);
260         completion_complete(&acw->comp, 1);
261 }
262
263 void smp_do_in_cores(const struct core_set *cset, void (*func)(void *),
264                                          void *opaque)
265 {
266         int cpu = core_id();
267         struct all_cpu_work acw;
268
269         memset(&acw, 0, sizeof(acw));
270         completion_init(&acw.comp, core_set_remote_count(cset));
271         acw.func = func;
272         acw.opaque = opaque;
273
274         for (int i = 0; i < num_cores; i++) {
275                 if (core_set_getcpu(cset, i)) {
276                         if (i == cpu)
277                                 func(opaque);
278                         else
279                                 send_kernel_message(i, smp_do_core_work, (long) &acw, 0, 0,
280                                                                         KMSG_ROUTINE);
281                 }
282         }
283         completion_wait(&acw.comp);
284 }