Alias "e" to monitor's "exit"
[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_CORES];
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         /* Treat the startup threads as ktasks.  This will last until smp_idle when
102          * they clear it, either in anticipation of being a user-backing kthread or
103          * to handle an RKM. */
104         kthread->is_ktask = TRUE;
105         per_cpu_info[coreid].spare = 0;
106         /* Init relevant lists */
107         spinlock_init_irqsave(&per_cpu_info[coreid].immed_amsg_lock);
108         STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
109         spinlock_init_irqsave(&per_cpu_info[coreid].routine_amsg_lock);
110         STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
111         /* Initialize the per-core timer chain */
112         init_timer_chain(&per_cpu_info[coreid].tchain, set_pcpu_alarm_interrupt);
113 #ifdef CONFIG_KTHREAD_POISON
114         *kstack_bottom_addr(kthread->stacktop) = 0xdeadbeef;
115 #endif /* CONFIG_KTHREAD_POISON */
116         /* Init generic tracing ring */
117         trace_buf = kpage_alloc_addr();
118         assert(trace_buf);
119         trace_ring_init(&pcpui->traces, trace_buf, PGSIZE,
120                         sizeof(struct pcpu_trace_event));
121         for (int i = 0; i < NR_CPU_STATES; i++)
122                 pcpui->state_ticks[i] = 0;
123         pcpui->last_tick_cnt = read_tsc();
124         /* Core 0 is in the KERNEL state, called from smp_boot.  The other cores are
125          * too, at least on x86, where we were called from asm (woken by POKE). */
126         pcpui->cpu_state = CPU_STATE_KERNEL;
127         /* Enable full lock debugging, after all pcpui work is done */
128         pcpui->__lock_checking_enabled = 1;
129 }
130
131 /* it's actually okay to set the state to the existing state.  originally, it
132  * was a bug in the state tracking, but it is possible, at least on x86, to have
133  * a halted core (state IDLE) get woken up by an IRQ that does not trigger the
134  * IRQ handling state.  for example, there is the I_POKE_CORE ipi.  smp_idle
135  * will just sleep again, and reset the state from IDLE to IDLE. */
136 void __set_cpu_state(struct per_cpu_info *pcpui, int state)
137 {
138         uint64_t now_ticks;
139         assert(!irq_is_enabled());
140         /* TODO: could put in an option to enable/disable state tracking. */
141         now_ticks = read_tsc();
142         pcpui->state_ticks[pcpui->cpu_state] += now_ticks - pcpui->last_tick_cnt;
143         /* TODO: if the state was user, we could account for the vcore's time,
144          * similar to the total_ticks in struct vcore.  the difference is that the
145          * total_ticks tracks the vcore's virtual time, while this tracks user time.
146          * something like vcore->user_ticks. */
147         pcpui->cpu_state = state;
148         pcpui->last_tick_cnt = now_ticks;
149 }
150
151 void reset_cpu_state_ticks(int coreid)
152 {
153         struct per_cpu_info *pcpui = &per_cpu_info[coreid];
154         uint64_t now_ticks;
155         if (coreid >= num_cores)
156                 return;
157         /* need to update last_tick_cnt, so the current value doesn't get added in
158          * next time we update */
159         now_ticks = read_tsc();
160         for (int i = 0; i < NR_CPU_STATES; i++) {
161                 pcpui->state_ticks[i] = 0;
162                 pcpui->last_tick_cnt = now_ticks;
163         }
164 }
165
166 /* PCPUI Trace Rings: */
167
168 static void pcpui_trace_kmsg_handler(void *event, void *data)
169 {
170         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
171         char *func_name;
172         uintptr_t addr;
173         addr = te->arg1;
174         func_name = get_fn_name(addr);
175         printk("\tKMSG %p: %s\n", addr, func_name);
176         kfree(func_name);
177 }
178
179 static void pcpui_trace_locks_handler(void *event, void *data)
180 {
181         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
182         char *func_name;
183         uintptr_t lock_addr = te->arg1;
184         if (lock_addr > KERN_LOAD_ADDR)
185                 func_name = get_fn_name(lock_addr);
186         else
187                 func_name = "Dynamic lock";
188         printk("Time %uus, lock %p (%s)\n", te->arg0, lock_addr, func_name);
189         printk("\t");
190         spinlock_debug((spinlock_t*)lock_addr);
191         if (lock_addr > KERN_LOAD_ADDR)
192                 kfree(func_name);
193 }
194
195 /* Add specific trace handlers here: */
196 trace_handler_t pcpui_tr_handlers[PCPUI_NR_TYPES] = {
197                                   0,
198                                   pcpui_trace_kmsg_handler,
199                                   pcpui_trace_locks_handler,
200                                   };
201
202 /* Generic handler for the pcpui ring.  Will switch out to the appropriate
203  * type's handler */
204 static void pcpui_trace_fn(void *event, void *data)
205 {
206         struct pcpu_trace_event *te = (struct pcpu_trace_event*)event;
207         int desired_type = (int)(long)data;
208         if (te->type >= PCPUI_NR_TYPES)
209                 printk("Bad trace type %d\n", te->type);
210         /* desired_type == 0 means all types */
211         if (desired_type && desired_type != te->type)
212                 return;
213         if (pcpui_tr_handlers[te->type])
214                 pcpui_tr_handlers[te->type](event, data);
215 }
216
217 void pcpui_tr_foreach(int coreid, int type)
218 {
219         struct trace_ring *tr = &per_cpu_info[coreid].traces;
220         assert(tr);
221         printk("\n\nTrace Ring on Core %d\n--------------\n", coreid);
222         trace_ring_foreach(tr, pcpui_trace_fn, (void*)(long)type);
223 }
224
225 void pcpui_tr_foreach_all(int type)
226 {
227         for (int i = 0; i < num_cores; i++)
228                 pcpui_tr_foreach(i, type);
229 }
230
231 void pcpui_tr_reset_all(void)
232 {
233         for (int i = 0; i < num_cores; i++)
234                 trace_ring_reset(&per_cpu_info[i].traces);
235 }
236
237 void pcpui_tr_reset_and_clear_all(void)
238 {
239         for (int i = 0; i < num_cores; i++)
240                 trace_ring_reset_and_clear(&per_cpu_info[i].traces);
241 }