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