blob: c52a898a2ef78c952c8c8b80b8f404b6bb5a72c8 [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Yinghai Lu72ee9b02005-12-14 02:39:33 +00002
Aaron Durbin029aaf62013-10-10 12:41:49 -05003#include <cpu/x86/cr.h>
Kyösti Mälkkibae775a2014-12-18 10:36:33 +02004#include <cpu/x86/gdt.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00005#include <cpu/x86/lapic.h>
Kyösti Mälkkic4fdb7b2019-08-10 15:51:59 +03006#include <cpu/x86/smi_deprecated.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07007#include <acpi/acpi.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00008#include <delay.h>
Stefan Reinauer75dbc382012-10-15 15:19:43 -07009#include <lib.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000010#include <string.h>
Julius Wernerec5e5e02014-08-20 15:29:56 -070011#include <symbols.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000012#include <console/console.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000013#include <device/device.h>
14#include <device/path.h>
15#include <smp/atomic.h>
16#include <smp/spinlock.h>
17#include <cpu/cpu.h>
Stefan Reinauer2bdfb482012-04-03 16:17:11 -070018#include <cpu/intel/speedstep.h>
Elyes HAOUASdda17fa2019-10-27 13:09:37 +010019#include <smp/node.h>
Elyes HAOUAS845652b2019-06-23 06:55:41 +020020#include <stdlib.h>
Aaron Durbin38c326d2013-05-06 12:22:23 -050021#include <thread.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000022
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000023/* This is a lot more paranoid now, since Linux can NOT handle
Zheng Baod4c5c442010-02-20 09:38:16 +000024 * being told there is a CPU when none exists. So any errors
25 * will return 0, meaning no CPU.
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000026 *
27 * We actually handling that case by noting which cpus startup
Martin Roth4c3ab732013-07-08 16:23:54 -060028 * and not telling anyone about the ones that don't.
Zheng Baod4c5c442010-02-20 09:38:16 +000029 */
Kyösti Mälkki63539bb2012-07-05 06:31:15 +030030
31/* Start-UP IPI vector must be 4kB aligned and below 1MB. */
32#define AP_SIPI_VECTOR 0x1000
Yinghai Lu72ee9b02005-12-14 02:39:33 +000033
Kyösti Mälkkia16cd9c2016-06-16 00:40:16 +030034static char *lowmem_backup;
35static char *lowmem_backup_ptr;
36static int lowmem_backup_size;
Rudolf Mareka572f832009-04-13 17:57:44 +000037
Aaron Durbina146d582013-02-08 16:56:51 -060038static inline void setup_secondary_gdt(void)
39{
40 u16 *gdt_limit;
Patrick Rudolphadcf7822020-08-27 20:50:18 +020041#if ENV_X86_64
Stefan Reinauere021dea2015-06-18 01:15:27 -070042 u64 *gdt_base;
43#else
Aaron Durbina146d582013-02-08 16:56:51 -060044 u32 *gdt_base;
Stefan Reinauere021dea2015-06-18 01:15:27 -070045#endif
Aaron Durbina146d582013-02-08 16:56:51 -060046
47 gdt_limit = (void *)&_secondary_gdt_addr;
48 gdt_base = (void *)&gdt_limit[1];
49
Stefan Reinauere021dea2015-06-18 01:15:27 -070050 *gdt_limit = (uintptr_t)&gdt_end - (uintptr_t)&gdt - 1;
51 *gdt_base = (uintptr_t)&gdt;
Aaron Durbina146d582013-02-08 16:56:51 -060052}
Myles Watson6e235762009-09-29 14:56:15 +000053
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -070054static void copy_secondary_start_to_lowest_1M(void)
Yinghai Lu72ee9b02005-12-14 02:39:33 +000055{
Zheng Baod4c5c442010-02-20 09:38:16 +000056 unsigned long code_size;
Yinghai Lu72ee9b02005-12-14 02:39:33 +000057
Aaron Durbina146d582013-02-08 16:56:51 -060058 /* Fill in secondary_start's local gdt. */
59 setup_secondary_gdt();
60
Lee Leahyc5917072017-03-15 16:38:51 -070061 code_size = (unsigned long)_secondary_start_end
62 - (unsigned long)_secondary_start;
Yinghai Lu72ee9b02005-12-14 02:39:33 +000063
Kyösti Mälkkia16cd9c2016-06-16 00:40:16 +030064 if (acpi_is_wakeup_s3()) {
65 /* need to save it for RAM resume */
66 lowmem_backup_size = code_size;
67 lowmem_backup = malloc(code_size);
68 lowmem_backup_ptr = (char *)AP_SIPI_VECTOR;
Zheng Baod4c5c442010-02-20 09:38:16 +000069
Kyösti Mälkkia16cd9c2016-06-16 00:40:16 +030070 if (lowmem_backup == NULL)
71 die("Out of backup memory\n");
Rudolf Mareka572f832009-04-13 17:57:44 +000072
Kyösti Mälkkia16cd9c2016-06-16 00:40:16 +030073 memcpy(lowmem_backup, lowmem_backup_ptr, lowmem_backup_size);
74 }
75
Elyes HAOUAS585d1a02016-07-28 19:15:34 +020076 /* copy the _secondary_start to the RAM below 1M*/
Lee Leahyc5917072017-03-15 16:38:51 -070077 memcpy((unsigned char *)AP_SIPI_VECTOR,
78 (unsigned char *)_secondary_start, code_size);
Yinghai Lu72ee9b02005-12-14 02:39:33 +000079
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -070080 printk(BIOS_DEBUG, "start_eip=0x%08lx, code_size=0x%08lx\n",
Lee Leahydfc8a5602017-03-15 16:47:33 -070081 (unsigned long int)AP_SIPI_VECTOR, code_size);
Yinghai Lu72ee9b02005-12-14 02:39:33 +000082}
83
Kyösti Mälkkia16cd9c2016-06-16 00:40:16 +030084static void recover_lowest_1M(void)
85{
86 if (acpi_is_wakeup_s3())
87 memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
88}
89
Kyösti Mälkki68fe11b2021-05-30 10:17:52 +030090static uint32_t wait_for_ipi_completion(const int timeout_ms)
91{
92 int loops = timeout_ms * 10;
93 uint32_t send_status;
94
95 /* wait for the ipi send to finish */
96 printk(BIOS_SPEW, "Waiting for send to finish...\n");
97 do {
98 printk(BIOS_SPEW, "+");
99 udelay(100);
100 send_status = lapic_busy();
101 } while (send_status && (--loops > 0));
102
103 return send_status;
104}
105
Sven Schnelle51676b12012-07-29 19:18:03 +0200106static int lapic_start_cpu(unsigned long apicid)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000107{
Kyösti Mälkki68fe11b2021-05-30 10:17:52 +0300108 const int timeout_100ms = 100;
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +0100109 uint32_t send_status, accept_status;
Ronald G. Minnichb5e777c2013-07-22 20:17:18 +0200110 int j, maxlvt;
Zheng Baod4c5c442010-02-20 09:38:16 +0000111
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000112 /*
113 * Starting actual IPI sequence...
114 */
115
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000116 printk(BIOS_SPEW, "Asserting INIT.\n");
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000117
Sven Schnelle51676b12012-07-29 19:18:03 +0200118 /*
119 * Turn INIT on target chip
120 */
Arthur Heymans6f77ff72021-05-21 09:32:45 +0200121 lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, apicid);
Sven Schnelle51676b12012-07-29 19:18:03 +0200122
Kyösti Mälkki68fe11b2021-05-30 10:17:52 +0300123 send_status = wait_for_ipi_completion(timeout_100ms);
124 if (send_status) {
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700125 printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
126 "Disabling\n", apicid);
Zheng Baod4c5c442010-02-20 09:38:16 +0000127 // too bad.
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +0100128 printk(BIOS_ERR, "ESR is 0x%x\n", lapic_read(LAPIC_ESR));
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000129 if (lapic_read(LAPIC_ESR)) {
Sven Schnelle51676b12012-07-29 19:18:03 +0200130 printk(BIOS_ERR, "Try to reset ESR\n");
Kyösti Mälkkib31b0332021-05-31 14:41:15 +0300131 lapic_write(LAPIC_ESR, 0);
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +0100132 printk(BIOS_ERR, "ESR is 0x%x\n",
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700133 lapic_read(LAPIC_ESR));
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000134 }
135 return 0;
136 }
Sven Schnelle51676b12012-07-29 19:18:03 +0200137 mdelay(10);
Yinghai Lu9a791df2006-04-03 20:38:34 +0000138
Sven Schnelle51676b12012-07-29 19:18:03 +0200139 printk(BIOS_SPEW, "Deasserting INIT.\n");
Sven Schnelle042c1462012-06-17 10:32:55 +0200140
Arthur Heymans6f77ff72021-05-21 09:32:45 +0200141 lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);
Sven Schnelle042c1462012-06-17 10:32:55 +0200142
Kyösti Mälkki68fe11b2021-05-30 10:17:52 +0300143 send_status = wait_for_ipi_completion(timeout_100ms);
144 if (send_status) {
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200145 printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700146 "Disabling\n", apicid);
Sven Schnelle51676b12012-07-29 19:18:03 +0200147 // too bad.
148 return 0;
149 }
150
Sven Schnelle042c1462012-06-17 10:32:55 +0200151 /*
Sven Schnelle51676b12012-07-29 19:18:03 +0200152 * Run STARTUP IPI loop.
Sven Schnelle042c1462012-06-17 10:32:55 +0200153 */
Ronald G. Minnichb5e777c2013-07-22 20:17:18 +0200154 printk(BIOS_SPEW, "#startup loops: %d.\n", CONFIG_NUM_IPI_STARTS);
Sven Schnelle51676b12012-07-29 19:18:03 +0200155
156 maxlvt = 4;
157
Ronald G. Minnichb5e777c2013-07-22 20:17:18 +0200158 for (j = 1; j <= CONFIG_NUM_IPI_STARTS; j++) {
Sven Schnelle51676b12012-07-29 19:18:03 +0200159 printk(BIOS_SPEW, "Sending STARTUP #%d to %lu.\n", j, apicid);
Kyösti Mälkki08f45262021-05-31 10:53:18 +0300160 lapic_read(LAPIC_SPIV);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000161 lapic_write(LAPIC_ESR, 0);
Sven Schnelle51676b12012-07-29 19:18:03 +0200162 lapic_read(LAPIC_ESR);
163 printk(BIOS_SPEW, "After apic_write.\n");
Sven Schnelle042c1462012-06-17 10:32:55 +0200164
Sven Schnelle51676b12012-07-29 19:18:03 +0200165 /*
166 * STARTUP IPI
167 */
168
Arthur Heymans6f77ff72021-05-21 09:32:45 +0200169 lapic_send_ipi(LAPIC_DM_STARTUP | (AP_SIPI_VECTOR >> 12), apicid);
Sven Schnelle51676b12012-07-29 19:18:03 +0200170
171 /*
172 * Give the other CPU some time to accept the IPI.
173 */
174 udelay(300);
175
176 printk(BIOS_SPEW, "Startup point 1.\n");
177
Kyösti Mälkki68fe11b2021-05-30 10:17:52 +0300178 send_status = wait_for_ipi_completion(timeout_100ms);
Sven Schnelle51676b12012-07-29 19:18:03 +0200179
180 /*
181 * Give the other CPU some time to accept the IPI.
182 */
183 udelay(200);
184 /*
185 * Due to the Pentium erratum 3AP.
186 */
187 if (maxlvt > 3) {
Kyösti Mälkki08f45262021-05-31 10:53:18 +0300188 lapic_read(LAPIC_SPIV);
Sven Schnelle51676b12012-07-29 19:18:03 +0200189 lapic_write(LAPIC_ESR, 0);
190 }
191 accept_status = (lapic_read(LAPIC_ESR) & 0xEF);
192 if (send_status || accept_status)
193 break;
194 }
195 printk(BIOS_SPEW, "After Startup.\n");
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000196 if (send_status)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000197 printk(BIOS_WARNING, "APIC never delivered???\n");
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000198 if (accept_status)
Patrick Rudolphfc57d6c2019-11-12 16:30:14 +0100199 printk(BIOS_WARNING, "APIC delivery error (%x).\n",
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700200 accept_status);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000201 if (send_status || accept_status)
202 return 0;
203 return 1;
204}
205
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000206/* Number of cpus that are currently running in coreboot */
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000207static atomic_t active_cpus = ATOMIC_INIT(1);
208
Sven Schnelle51676b12012-07-29 19:18:03 +0200209/* start_cpu_lock covers last_cpu_index and secondary_stack.
Elyes HAOUASd82be922016-07-28 18:58:27 +0200210 * Only starting one CPU at a time let's me remove the logic
Sven Schnelle51676b12012-07-29 19:18:03 +0200211 * for select the stack from assembly language.
212 *
Elyes HAOUASd82be922016-07-28 18:58:27 +0200213 * In addition communicating by variables to the CPU I
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700214 * am starting allows me to verify it has started before
Sven Schnelle51676b12012-07-29 19:18:03 +0200215 * start_cpu returns.
216 */
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000217
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300218DECLARE_SPIN_LOCK(start_cpu_lock);
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700219static unsigned int last_cpu_index = 0;
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700220static void *stacks[CONFIG_MAX_CPUS];
Sven Schnelle51676b12012-07-29 19:18:03 +0200221volatile unsigned long secondary_stack;
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700222volatile unsigned int secondary_cpu_index;
Sven Schnelle51676b12012-07-29 19:18:03 +0200223
Kyösti Mälkki67d07a62021-05-29 21:10:51 +0300224static int start_cpu(struct device *cpu)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000225{
Sven Schnelle51676b12012-07-29 19:18:03 +0200226 struct cpu_info *info;
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +0300227 uintptr_t stack_top;
228 uintptr_t stack_base;
Sven Schnelle51676b12012-07-29 19:18:03 +0200229 unsigned long apicid;
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700230 unsigned int index;
Sven Schnelle51676b12012-07-29 19:18:03 +0200231 unsigned long count;
232 int result;
233
234 spin_lock(&start_cpu_lock);
235
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700236 /* Get the CPU's apicid */
Sven Schnelle51676b12012-07-29 19:18:03 +0200237 apicid = cpu->path.apic.apic_id;
238
239 /* Get an index for the new processor */
240 index = ++last_cpu_index;
241
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +0300242 /* Find boundaries of the new processor's stack */
243 stack_top = ALIGN_DOWN((uintptr_t)_estack, CONFIG_STACK_SIZE);
244 stack_top -= (CONFIG_STACK_SIZE*index);
245 stack_base = stack_top - CONFIG_STACK_SIZE;
246 stack_top -= sizeof(struct cpu_info);
247 printk(BIOS_SPEW, "CPU%d: stack_base %p, stack_top %p\n", index,
248 (void *)stack_base, (void *)stack_top);
Kyösti Mälkkia706ad52018-05-23 01:13:27 +0300249 stacks[index] = (void *)stack_base;
250
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700251 /* Record the index and which CPU structure we are using */
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +0300252 info = (struct cpu_info *)stack_top;
Sven Schnelle51676b12012-07-29 19:18:03 +0200253 info->index = index;
254 info->cpu = cpu;
Subrata Banike091d0e2019-05-10 12:35:42 +0530255 cpu_add_map_entry(info->index);
Sven Schnelle51676b12012-07-29 19:18:03 +0200256
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700257 /* Advertise the new stack and index to start_cpu */
Kyösti Mälkki2fbb6772018-05-15 19:50:20 +0300258 secondary_stack = stack_top;
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700259 secondary_cpu_index = index;
Sven Schnelle51676b12012-07-29 19:18:03 +0200260
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700261 /* Until the CPU starts up report the CPU is not enabled */
Sven Schnelle51676b12012-07-29 19:18:03 +0200262 cpu->enabled = 0;
263 cpu->initialized = 0;
264
Elyes HAOUASd82be922016-07-28 18:58:27 +0200265 /* Start the CPU */
Sven Schnelle51676b12012-07-29 19:18:03 +0200266 result = lapic_start_cpu(apicid);
267
268 if (result) {
269 result = 0;
Elyes HAOUASd82be922016-07-28 18:58:27 +0200270 /* Wait 1s or until the new CPU calls in */
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200271 for (count = 0; count < 100000; count++) {
Sven Schnelle51676b12012-07-29 19:18:03 +0200272 if (secondary_stack == 0) {
273 result = 1;
274 break;
275 }
276 udelay(10);
Jonathan A. Kollasch98fc2e92015-07-15 11:27:18 -0500277 }
Sven Schnelle51676b12012-07-29 19:18:03 +0200278 }
279 secondary_stack = 0;
280 spin_unlock(&start_cpu_lock);
281 return result;
282}
283
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000284/* C entry point of secondary cpus */
Lee Leahydfc8a5602017-03-15 16:47:33 -0700285asmlinkage void secondary_cpu_init(unsigned int index)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000286{
Sven Schnelle042c1462012-06-17 10:32:55 +0200287 atomic_inc(&active_cpus);
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +0300288
Kyösti Mälkki176989a2021-05-29 22:22:57 +0300289 spin_lock(&start_cpu_lock);
Sven Schnelle51676b12012-07-29 19:18:03 +0200290
291#ifdef __SSE3__
292 /*
293 * Seems that CR4 was cleared when AP start via lapic_start_cpu()
294 * Turn on CR4.OSFXSR and CR4.OSXMMEXCPT when SSE options enabled
295 */
Elyes HAOUAS63f98f22019-06-26 20:17:50 +0200296 CRx_TYPE cr4_val;
Aaron Durbin029aaf62013-10-10 12:41:49 -0500297 cr4_val = read_cr4();
298 cr4_val |= (CR4_OSFXSR | CR4_OSXMMEXCPT);
299 write_cr4(cr4_val);
Sven Schnelle51676b12012-07-29 19:18:03 +0200300#endif
Kyösti Mälkki9ec72272021-10-17 08:34:31 +0300301
302 /* Ensure the local APIC is enabled */
303 enable_lapic();
304 setup_lapic_interrupts();
305
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700306 cpu_initialize(index);
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +0300307
Kyösti Mälkki176989a2021-05-29 22:22:57 +0300308 spin_unlock(&start_cpu_lock);
Sven Schnelle51676b12012-07-29 19:18:03 +0200309
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000310 atomic_dec(&active_cpus);
Sven Schnelle51676b12012-07-29 19:18:03 +0200311
312 stop_this_cpu();
313}
314
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100315static void start_other_cpus(struct bus *cpu_bus, struct device *bsp_cpu)
Sven Schnelle51676b12012-07-29 19:18:03 +0200316{
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100317 struct device *cpu;
Sven Schnelle51676b12012-07-29 19:18:03 +0200318 /* Loop through the cpus once getting them started */
319
Elyes HAOUAS90ba1892016-10-02 10:23:01 +0200320 for (cpu = cpu_bus->children; cpu; cpu = cpu->sibling) {
Lee Leahya15d8af2017-03-15 14:49:35 -0700321 if (cpu->path.type != DEVICE_PATH_APIC)
Sven Schnelle51676b12012-07-29 19:18:03 +0200322 continue;
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +0300323
Lee Leahya15d8af2017-03-15 14:49:35 -0700324 if (!cpu->enabled)
Sven Schnelle51676b12012-07-29 19:18:03 +0200325 continue;
Sven Schnelle51676b12012-07-29 19:18:03 +0200326
Lee Leahya15d8af2017-03-15 14:49:35 -0700327 if (cpu->initialized)
Sven Schnelle51676b12012-07-29 19:18:03 +0200328 continue;
Sven Schnelle51676b12012-07-29 19:18:03 +0200329
Lee Leahya15d8af2017-03-15 14:49:35 -0700330 if (!start_cpu(cpu))
Sven Schnelle51676b12012-07-29 19:18:03 +0200331 /* Record the error in cpu? */
332 printk(BIOS_ERR, "CPU 0x%02x would not start!\n",
333 cpu->path.apic.apic_id);
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +0300334
Kyösti Mälkki176989a2021-05-29 22:22:57 +0300335 udelay(10);
Sven Schnelle51676b12012-07-29 19:18:03 +0200336 }
Yinghai Lu9a8e36d2006-05-18 17:02:17 +0000337}
338
339static void wait_other_cpus_stop(struct bus *cpu_bus)
340{
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100341 struct device *cpu;
Yinghai Lu9a8e36d2006-05-18 17:02:17 +0000342 int old_active_count, active_count;
Stefan Reinauer2bdfb482012-04-03 16:17:11 -0700343 long loopcount = 0;
Ronald G. Minnich000bf83c2012-06-06 13:00:24 -0700344 int i;
Stefan Reinauer2bdfb482012-04-03 16:17:11 -0700345
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000346 /* Now loop until the other cpus have finished initializing */
347 old_active_count = 1;
348 active_count = atomic_read(&active_cpus);
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200349 while (active_count > 1) {
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000350 if (active_count != old_active_count) {
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700351 printk(BIOS_INFO, "Waiting for %d CPUS to stop\n",
352 active_count - 1);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000353 old_active_count = active_count;
354 }
355 udelay(10);
356 active_count = atomic_read(&active_cpus);
Stefan Reinauer2bdfb482012-04-03 16:17:11 -0700357 loopcount++;
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000358 }
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200359 for (cpu = cpu_bus->children; cpu; cpu = cpu->sibling) {
Lee Leahya15d8af2017-03-15 14:49:35 -0700360 if (cpu->path.type != DEVICE_PATH_APIC)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000361 continue;
Lee Leahya15d8af2017-03-15 14:49:35 -0700362 if (cpu->path.apic.apic_id == SPEEDSTEP_APIC_MAGIC)
Stefan Reinauer2bdfb482012-04-03 16:17:11 -0700363 continue;
Lee Leahya15d8af2017-03-15 14:49:35 -0700364 if (!cpu->initialized)
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000365 printk(BIOS_ERR, "CPU 0x%02x did not initialize!\n",
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000366 cpu->path.apic.apic_id);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000367 }
Stefan Reinauer2bdfb482012-04-03 16:17:11 -0700368 printk(BIOS_DEBUG, "All AP CPUs stopped (%ld loops)\n", loopcount);
Timothy Pearson6b6c6532015-09-05 19:31:20 -0500369 checkstack(_estack, 0);
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300370 for (i = 1; i < CONFIG_MAX_CPUS && i <= last_cpu_index; i++)
Stefan Reinauer75dbc382012-10-15 15:19:43 -0700371 checkstack((void *)stacks[i] + CONFIG_STACK_SIZE, i);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000372}
373
Eric Biederman7003ba42004-10-16 06:20:29 +0000374void initialize_cpus(struct bus *cpu_bus)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000375{
376 struct device_path cpu_path;
Sven Schnelle51676b12012-07-29 19:18:03 +0200377 struct cpu_info *info;
378
Elyes HAOUASd82be922016-07-28 18:58:27 +0200379 /* Find the info struct for this CPU */
Sven Schnelle51676b12012-07-29 19:18:03 +0200380 info = cpu_info();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000381
Kyösti Mälkki4cf65e92021-06-06 12:03:27 +0300382 /* Ensure the local APIC is enabled */
Kyösti Mälkki9ec72272021-10-17 08:34:31 +0300383 if (is_smp_boot()) {
Kyösti Mälkkiff284f62017-08-18 12:11:16 +0300384 enable_lapic();
Kyösti Mälkki9ec72272021-10-17 08:34:31 +0300385 setup_lapic_interrupts();
Kyösti Mälkki707e5452022-02-10 07:13:29 +0200386 } else {
387 disable_lapic();
Kyösti Mälkki9ec72272021-10-17 08:34:31 +0300388 }
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000389
Kyösti Mälkki4cf65e92021-06-06 12:03:27 +0300390 /* Get the device path of the boot CPU */
391 cpu_path.type = DEVICE_PATH_APIC;
392 cpu_path.apic.apic_id = lapicid();
Stefan Reinauer00a889c2008-10-29 04:48:44 +0000393
Elyes HAOUASd82be922016-07-28 18:58:27 +0200394 /* Find the device structure for the boot CPU */
Sven Schnelle51676b12012-07-29 19:18:03 +0200395 info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
Subrata Banike091d0e2019-05-10 12:35:42 +0530396 cpu_add_map_entry(info->index);
Sven Schnelle51676b12012-07-29 19:18:03 +0200397
Stefan Reinauer1bfbbc02012-06-07 14:00:07 -0700398 // why here? In case some day we can start core1 in amd_sibling_init
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300399 if (is_smp_boot())
400 copy_secondary_start_to_lowest_1M();
Stefan Reinauer00a889c2008-10-29 04:48:44 +0000401
Kyösti Mälkki894f6f82022-01-29 14:05:58 +0200402 if (CONFIG(SMM_LEGACY_ASEG))
403 smm_init();
Stefan Reinauer00a889c2008-10-29 04:48:44 +0000404
Zheng Baod4c5c442010-02-20 09:38:16 +0000405 /* Initialize the bootstrap processor */
Ronald G. Minnich8b930592012-06-05 14:41:27 -0700406 cpu_initialize(0);
Yinghai Lu9a8e36d2006-05-18 17:02:17 +0000407
Kyösti Mälkki176989a2021-05-29 22:22:57 +0300408 if (is_smp_boot())
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +0300409 start_other_cpus(cpu_bus, info->cpu);
Sven Schnelle51676b12012-07-29 19:18:03 +0200410
Kyösti Mälkkifdca6552018-04-26 20:09:54 +0300411 /* Now wait the rest of the cpus stop*/
412 if (is_smp_boot())
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300413 wait_other_cpus_stop(cpu_bus);
Damien Zammit149c4c52015-11-28 21:27:05 +1100414
Kyösti Mälkki894f6f82022-01-29 14:05:58 +0200415 if (CONFIG(SMM_LEGACY_ASEG))
416 smm_init_completion();
Kyösti Mälkki2e501422017-04-21 08:43:09 +0300417
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300418 if (is_smp_boot())
419 recover_lowest_1M();
420}