Merged in all of the recent changes for compiling on sparc
[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 <ros/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         cprintf("Cores, report in!\n");
24         time_for_smp_init = 1;
25
26         while(*(volatile uint8_t*)&num_cpus < num_cores());
27
28         cprintf("All cores reporting!\n");
29 }
30
31 void
32 smp_init(void)
33 {
34         static spinlock_t report_in_lock = 0;
35
36         cprintf("Good morning, Vietnam! (core id = %d)\n",core_id());
37
38         spin_lock(&report_in_lock);
39         num_cpus++;
40         spin_unlock(&report_in_lock);
41
42         smp_idle();
43 }
44
45 handler_wrapper_t
46 wrapper_pool[MAX_NUM_CPUS*8] = {{0},0};
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                 while(send_active_message(i,(amr_t)smp_call_wrapper,
98                                           (uint32_t)handler,(uint32_t)wrapper,
99                                           (uint32_t)data) != 0);
100         }
101
102         // send to me
103         while(send_active_message(core_id(),(amr_t)smp_call_wrapper,
104                                   (uint32_t)handler,(uint32_t)wrapper,
105                                   (uint32_t)data) != 0);
106
107         cpu_relax(); // wait to get the interrupt
108
109         disable_irqsave(&state);
110
111         return 0;
112 }
113
114 int smp_call_function_single(uint32_t dest, isr_t handler, void* data,
115                              handler_wrapper_t** wait_wrapper)
116 {
117         int8_t state = 0;
118         handler_wrapper_t* wrapper = 0;
119         if(wait_wrapper)
120         {
121                 wrapper = *wait_wrapper = smp_make_wrapper();
122                 if(!wrapper)
123                         return -ENOMEM;
124                 wrapper->wait_list[dest] = 1;
125         }
126
127         enable_irqsave(&state);
128
129         while(send_active_message(dest,(amr_t)smp_call_wrapper,
130                                   (uint32_t)handler,(uint32_t)wrapper,
131                                   (uint32_t)data) != 0);
132
133         cpu_relax(); // wait to get the interrupt, if it's to this core
134
135         disable_irqsave(&state);
136
137         return 0;
138 }
139
140 int smp_call_wait(handler_wrapper_t* wrapper)
141 {
142         int i;
143         for(i = 0; i < num_cores(); i++)
144                 while(wrapper->wait_list[i]);
145
146         spin_unlock(&wrapper->lock);
147         return 0;
148 }