942bc40a37aa017156879be28c4a44d4d4405ee0
[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 __DEPUTY__
11 #pragma nodeputy
12 #endif
13
14 void
15 smp_boot(void)
16 {
17         extern int time_for_smp_init;
18         num_cpus = 1;
19         cprintf("Cores, report in!\n");
20         time_for_smp_init = 1;
21
22         while(*(volatile uint8_t*)&num_cpus < num_cores());
23
24         cprintf("All cores reporting!\n");
25 }
26
27 void
28 smp_init(void)
29 {
30         static spinlock_t report_in_lock = 0;
31
32         cprintf("Good morning, Vietnam! (core id = %d)\n",core_id());
33
34         spin_lock(&report_in_lock);
35         num_cpus++;
36         spin_unlock(&report_in_lock);
37
38         smp_idle();
39 }
40
41 handler_wrapper_t
42 wrapper_pool[MAX_NUM_CPUS*8] = {{0},0};
43
44 handler_wrapper_t*
45 smp_make_wrapper()
46 {
47         int i;
48         for(i = 0; i < sizeof(wrapper_pool)/sizeof(wrapper_pool[0]); i++)
49                 if(spin_trylock(&wrapper_pool[i].lock) == 0)
50                         return &wrapper_pool[i];
51         return NULL;
52 }
53
54 void
55 smp_call_wrapper(trapframe_t* tf, uint32_t src, isr_t handler,
56                  handler_wrapper_t* wrapper,void* data)
57 {
58         if(wrapper)
59                 wrapper->wait_list[core_id()] = 0;
60         handler(tf,data);
61 }
62
63 int smp_call_function_self(isr_t handler, void* data,
64                            handler_wrapper_t** wait_wrapper)
65 {
66         return smp_call_function_single(core_id(),handler,data,wait_wrapper);
67 }
68
69 int smp_call_function_all(isr_t handler, void* data,
70                           handler_wrapper_t** wait_wrapper)
71 {
72         int8_t state = 0;
73         int i;
74         handler_wrapper_t* wrapper = 0;
75         if(wait_wrapper)
76         {
77                 wrapper = *wait_wrapper = smp_make_wrapper();
78                 if(!wrapper)
79                         return -ENOMEM;
80
81                 for(i = 0; i < num_cores(); i++)
82                         wrapper->wait_list[i] = 1;
83         }
84
85         enable_irqsave(&state);
86
87         // send to others
88         for(i = 0; i < num_cores(); i++)
89         {
90                 if(i == core_id())
91                         continue;
92
93                 while(send_active_message(i,(amr_t)smp_call_wrapper,
94                                           (uint32_t)handler,(uint32_t)wrapper,
95                                           (uint32_t)data) != 0);
96         }
97
98         // send to me
99         while(send_active_message(core_id(),(amr_t)smp_call_wrapper,
100                                   (uint32_t)handler,(uint32_t)wrapper,
101                                   (uint32_t)data) != 0);
102
103         cpu_relax(); // wait to get the interrupt
104
105         disable_irqsave(&state);
106
107         return 0;
108 }
109
110 int smp_call_function_single(uint8_t dest, isr_t handler, void* data,
111                              handler_wrapper_t** wait_wrapper)
112 {
113         int8_t state = 0;
114         handler_wrapper_t* wrapper = 0;
115         if(wait_wrapper)
116         {
117                 wrapper = *wait_wrapper = smp_make_wrapper();
118                 if(!wrapper)
119                         return -ENOMEM;
120                 wrapper->wait_list[dest] = 1;
121         }
122
123         enable_irqsave(&state);
124
125         while(send_active_message(dest,(amr_t)smp_call_wrapper,
126                                   (uint32_t)handler,(uint32_t)wrapper,
127                                   (uint32_t)data) != 0);
128
129         cpu_relax(); // wait to get the interrupt, if it's to this core
130
131         disable_irqsave(&state);
132
133         return 0;
134 }
135
136 int smp_call_wait(handler_wrapper_t* wrapper)
137 {
138         int i;
139         for(i = 0; i < num_cores(); i++)
140                 while(wrapper->wait_list[i]);
141
142         spin_unlock(&wrapper->lock);
143         return 0;
144 }