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