arm64: split cpu.c
[coreboot.git] / src / arch / arm64 / cpu.c
blobeb08735292177fbaa0b5194a8bba4161cb4db43c
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2013 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <arch/lib_helpers.h>
23 #include <cpu/cpu.h>
24 #include <console/console.h>
25 #include "cpu-internal.h"
27 struct cpu_info cpu_infos[CONFIG_MAX_CPUS];
28 struct cpu_info *bsp_cpu_info;
30 struct cpu_info *cpu_info(void)
32 return cpu_info_for_cpu(smp_processor_id());
35 static inline int action_queue_empty(struct cpu_action_queue *q)
37 return load_acquire_exclusive(&q->todo) == NULL;
40 static inline int action_completed(struct cpu_action_queue *q,
41 struct cpu_action *action)
43 return load_acquire(&q->completed) == action;
46 static inline void wait_for_action_queue_slot(struct cpu_action_queue *q)
48 while (!action_queue_empty(q))
49 wfe();
52 static void wait_for_action_complete(struct cpu_action_queue *q,
53 struct cpu_action *a)
55 while (!action_completed(q, a))
56 wfe();
59 static struct cpu_action *wait_for_action(struct cpu_action_queue *q,
60 struct cpu_action *local)
62 struct cpu_action *action;
64 while (action_queue_empty(q))
65 wfe();
68 * Keep original address, but use a local copy for async processing.
70 do {
71 action = load_acquire_exclusive(&q->todo);
72 *local = *action;
73 } while (!store_release_exclusive(&q->todo, NULL));
75 return action;
78 static void queue_action(struct cpu_action_queue *q, struct cpu_action *action)
80 do {
81 wait_for_action_queue_slot(q);
82 if (load_acquire_exclusive(&q->todo) != NULL)
83 continue;
84 } while (!store_release_exclusive(&q->todo, action));
87 static void action_queue_complete(struct cpu_action_queue *q,
88 struct cpu_action *action)
90 /* Mark completion and send events to waiters. */
91 store_release(&q->completed, action);
92 sev();
95 static void action_run(struct cpu_action *action)
97 action->run(action->arg);
100 static void action_run_on_cpu(struct cpu_info *ci, struct cpu_action *action,
101 int sync)
103 struct cpu_action_queue *q = &ci->action_queue;
105 /* Don't run actions on non-online cpus. */
106 if (!cpu_online(ci))
107 return;
109 if (ci->id == smp_processor_id()) {
110 action->run(action->arg);
111 return;
114 queue_action(q, action);
115 /* Wait for CPU to pick it up. Empty slot means it was picked up. */
116 wait_for_action_queue_slot(q);
117 /* Wait for completion if requested. */
118 if (sync)
119 wait_for_action_complete(q, action);
122 static int __arch_run_on_cpu(unsigned int cpu, struct cpu_action *action,
123 int sync)
125 struct cpu_info *ci;
127 if (cpu >= CONFIG_MAX_CPUS)
128 return -1;
130 ci = cpu_info_for_cpu(cpu);
132 action_run_on_cpu(ci, action, sync);
134 return 0;
137 int arch_run_on_cpu(unsigned int cpu, struct cpu_action *action)
139 return __arch_run_on_cpu(cpu, action, 1);
142 int arch_run_on_cpu_async(unsigned int cpu, struct cpu_action *action)
144 return __arch_run_on_cpu(cpu, action, 0);
147 static int __arch_run_on_all_cpus(struct cpu_action *action, int sync)
149 int i;
151 for (i = 0; i < CONFIG_MAX_CPUS; i++)
152 action_run_on_cpu(cpu_info_for_cpu(i), action, sync);
154 return 0;
157 static int __arch_run_on_all_cpus_but_self(struct cpu_action *action, int sync)
159 int i;
160 struct cpu_info *me = cpu_info();
162 for (i = 0; i < CONFIG_MAX_CPUS; i++) {
163 struct cpu_info *ci = cpu_info_for_cpu(i);
164 if (ci == me)
165 continue;
166 action_run_on_cpu(ci, action, sync);
169 return 0;
172 int arch_run_on_all_cpus(struct cpu_action *action)
174 return __arch_run_on_all_cpus(action, 1);
177 int arch_run_on_all_cpus_async(struct cpu_action *action)
179 return __arch_run_on_all_cpus(action, 0);
182 int arch_run_on_all_cpus_but_self(struct cpu_action *action)
184 return __arch_run_on_all_cpus_but_self(action, 1);
187 int arch_run_on_all_cpus_but_self_async(struct cpu_action *action)
189 return __arch_run_on_all_cpus_but_self(action, 0);
193 void arch_cpu_wait_for_action(void)
195 struct cpu_info *ci = cpu_info();
196 struct cpu_action_queue *q = &ci->action_queue;
198 while (1) {
199 struct cpu_action *orig;
200 struct cpu_action action;
202 orig = wait_for_action(q, &action);
204 action_run(&action);
205 action_queue_complete(q, orig);