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
22 #include <arch/lib_helpers.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
))
52 static void wait_for_action_complete(struct cpu_action_queue
*q
,
55 while (!action_completed(q
, a
))
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
))
68 * Keep original address, but use a local copy for async processing.
71 action
= load_acquire_exclusive(&q
->todo
);
73 } while (!store_release_exclusive(&q
->todo
, NULL
));
78 static void queue_action(struct cpu_action_queue
*q
, struct cpu_action
*action
)
81 wait_for_action_queue_slot(q
);
82 if (load_acquire_exclusive(&q
->todo
) != NULL
)
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
);
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
,
103 struct cpu_action_queue
*q
= &ci
->action_queue
;
105 /* Don't run actions on non-online cpus. */
109 if (ci
->id
== smp_processor_id()) {
110 action
->run(action
->arg
);
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. */
119 wait_for_action_complete(q
, action
);
122 static int __arch_run_on_cpu(unsigned int cpu
, struct cpu_action
*action
,
127 if (cpu
>= CONFIG_MAX_CPUS
)
130 ci
= cpu_info_for_cpu(cpu
);
132 action_run_on_cpu(ci
, action
, sync
);
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
)
151 for (i
= 0; i
< CONFIG_MAX_CPUS
; i
++)
152 action_run_on_cpu(cpu_info_for_cpu(i
), action
, sync
);
157 static int __arch_run_on_all_cpus_but_self(struct cpu_action
*action
, int sync
)
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
);
166 action_run_on_cpu(ci
, action
, sync
);
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
;
199 struct cpu_action
*orig
;
200 struct cpu_action action
;
202 orig
= wait_for_action(q
, &action
);
205 action_queue_complete(q
, orig
);