proc messages are routine instead of immediate
[akaros.git] / kern / arch / sparc / smp.c
1 #include <smp.h>
2 #include <arch/arch.h>
3 #include <arch/smp.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <error.h>
7 #include <assert.h>
8 #include <atomic.h>
9
10 #ifdef __SHARC__
11 #pragma nosharc
12 #endif
13
14 #ifdef __DEPUTY__
15 #pragma nodeputy
16 #endif
17
18 void
19 smp_boot(void)
20 {
21         extern int time_for_smp_init;
22         num_cpus = 1;
23         printd("Cores, report in!\n");
24         time_for_smp_init = 1;
25
26         while(*(volatile uint32_t*)&num_cpus < num_cores());
27
28         printd("%d cores reporting!\n",num_cpus);
29 }
30
31 void
32 smp_init(void)
33 {
34         static spinlock_t report_in_lock = SPINLOCK_INITIALIZER;
35
36         spin_lock(&report_in_lock);
37         num_cpus++;
38         spin_unlock(&report_in_lock);
39
40         printd("Good morning, Vietnam! (core id = %d)\n",core_id());
41
42         smp_idle();
43 }
44
45 handler_wrapper_t
46 wrapper_pool[MAX_NUM_CPUS*8] = {{{0},SPINLOCK_INITIALIZER}};
47
48 handler_wrapper_t*
49 smp_make_wrapper()
50 {
51         int i;
52         for(i = 0; i < sizeof(wrapper_pool)/sizeof(wrapper_pool[0]); i++)
53                 if(spin_trylock(&wrapper_pool[i].lock) == 0)
54                         return &wrapper_pool[i];
55         return NULL;
56 }
57
58 void
59 smp_call_wrapper(trapframe_t* tf, uint32_t src, isr_t handler,
60                  handler_wrapper_t* wrapper,void* data)
61 {
62         if(wrapper)
63                 wrapper->wait_list[core_id()] = 0;
64         handler(tf,data);
65 }
66
67 int smp_call_function_self(isr_t handler, void* data,
68                            handler_wrapper_t** wait_wrapper)
69 {
70         return smp_call_function_single(core_id(),handler,data,wait_wrapper);
71 }
72
73 int smp_call_function_all(isr_t handler, void* data,
74                           handler_wrapper_t** wait_wrapper)
75 {
76         int8_t state = 0;
77         int i;
78         handler_wrapper_t* wrapper = 0;
79         if(wait_wrapper)
80         {
81                 wrapper = *wait_wrapper = smp_make_wrapper();
82                 if(!wrapper)
83                         return -ENOMEM;
84
85                 for(i = 0; i < num_cores(); i++)
86                         wrapper->wait_list[i] = 1;
87         }
88
89         enable_irqsave(&state);
90
91         // send to others
92         for(i = 0; i < num_cores(); i++)
93         {
94                 if(i == core_id())
95                         continue;
96
97                 send_kernel_message(i,(amr_t)smp_call_wrapper,
98                                           handler, wrapper, data, KMSG_IMMEDIATE);
99         }
100
101         // send to me
102         send_kernel_message(core_id(),(amr_t)smp_call_wrapper,
103                                   handler,wrapper,data, KMSG_IMMEDIATE);
104
105         cpu_relax(); // wait to get the interrupt
106
107         disable_irqsave(&state);
108
109         return 0;
110 }
111
112 int smp_call_function_single(uint32_t dest, isr_t handler, void* data,
113                              handler_wrapper_t** wait_wrapper)
114 {
115         int8_t state = 0;
116         handler_wrapper_t* wrapper = 0;
117         if(wait_wrapper)
118         {
119                 wrapper = *wait_wrapper = smp_make_wrapper();
120                 if(!wrapper)
121                         return -ENOMEM;
122                 wrapper->wait_list[dest] = 1;
123         }
124
125         enable_irqsave(&state);
126
127         send_kernel_message(dest,(amr_t)smp_call_wrapper,
128                                   handler,wrapper,data, KMSG_IMMEDIATE);
129
130         cpu_relax(); // wait to get the interrupt, if it's to this core
131
132         disable_irqsave(&state);
133
134         return 0;
135 }
136
137 int smp_call_wait(handler_wrapper_t* wrapper)
138 {
139         int i;
140         for(i = 0; i < num_cores(); i++)
141                 while(wrapper->wait_list[i]);
142
143         spin_unlock(&wrapper->lock);
144         return 0;
145 }
146
147 /* Perform any initialization needed by per_cpu_info.  Right now, this just
148  * inits the amsg list (which sparc will probably also want).  Make sure every
149  * core calls this at some point in the smp_boot process. */
150 void smp_percpu_init(void)
151 {
152         uint32_t coreid = core_id();
153         spinlock_init(&per_cpu_info[coreid].immed_amsg_lock);
154         STAILQ_INIT(&per_cpu_info[coreid].immed_amsgs);
155         spinlock_init(&per_cpu_info[coreid].routine_amsg_lock);
156         STAILQ_INIT(&per_cpu_info[coreid].routine_amsgs);
157 }