1 #include <smp/start_stop.h>
2 #include <arch/smp/mpspec.h>
3 #include <cpu/p6/apic.h>
6 #include <console/console.h>
7 #include <arch/smp/lapic.h>
11 unsigned long this_processors_id(void)
16 int processor_index(unsigned long apicid)
19 for(i = 0; i < CONFIG_MAX_CPUS; i++) {
20 if (initial_apicid[i] == apicid) {
27 void stop_cpu(unsigned long apicid)
30 unsigned long send_status;
32 /* send an APIC INIT to myself */
33 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
34 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
36 /* wait for the ipi send to finish */
37 printk_spew("Waiting for send to finish...\n");
42 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
43 } while (send_status && (timeout++ < 1000));
44 if (timeout >= 1000) {
45 printk_err("timed out\n");
49 printk_spew("Deasserting INIT.\n");
50 /* Deassert the APIC INIT */
51 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
52 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
54 printk_spew("Waiting for send to finish...\n");
59 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
60 } while (send_status && (timeout++ < 1000));
61 if (timeout >= 1000) {
62 printk_err("timed out\n");
70 /* This is a lot more paranoid now, since Linux can NOT handle
71 * being told there is a CPU when none exists. So any errors
72 * will return 0, meaning no CPU.
74 * We actually handling that case by noting which cpus startup
75 * and not telling anyone about the ones that dont.
77 int start_cpu(unsigned long apicid)
80 unsigned long send_status, accept_status, start_eip;
81 int j, num_starts, maxlvt;
82 extern char _secondary_start[];
85 * Starting actual IPI sequence...
88 printk_spew("Asserting INIT.\n");
91 * Turn INIT on target chip
93 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
99 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
102 printk_spew("Waiting for send to finish...\n");
107 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
108 } while (send_status && (timeout++ < 1000));
109 if (timeout >= 1000) {
110 printk_err("CPU %d: First apic write timed out. Disabling\n",
113 printk_err("ESR is 0x%x\n", apic_read(APIC_ESR));
114 if (apic_read(APIC_ESR)) {
115 printk_err("Try to reset ESR\n");
116 apic_write_around(APIC_ESR, 0);
117 printk_err("ESR is 0x%x\n", apic_read(APIC_ESR));
123 printk_spew("Deasserting INIT.\n");
126 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
129 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
131 printk_spew("Waiting for send to finish...\n");
136 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
137 } while (send_status && (timeout++ < 1000));
138 if (timeout >= 1000) {
139 printk_err("CPU %d: Second apic write timed out. Disabling\n",
145 start_eip = (unsigned long)_secondary_start;
146 printk_spew("start_eip=0x%08lx\n", start_eip);
151 * Run STARTUP IPI loop.
153 printk_spew("#startup loops: %d.\n", num_starts);
157 for (j = 1; j <= num_starts; j++) {
158 printk_spew("Sending STARTUP #%d to %u.\n", j, apicid);
159 apic_read_around(APIC_SPIV);
160 apic_write(APIC_ESR, 0);
162 printk_spew("After apic_write.\n");
169 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
171 /* Boot on the stack */
172 /* Kick the second */
173 apic_write_around(APIC_ICR, APIC_DM_STARTUP
174 | (start_eip >> 12));
177 * Give the other CPU some time to accept the IPI.
181 printk_spew("Startup point 1.\n");
183 printk_spew("Waiting for send to finish...\n");
188 send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
189 } while (send_status && (timeout++ < 1000));
192 * Give the other CPU some time to accept the IPI.
196 * Due to the Pentium erratum 3AP.
199 apic_read_around(APIC_SPIV);
200 apic_write(APIC_ESR, 0);
202 accept_status = (apic_read(APIC_ESR) & 0xEF);
203 if (send_status || accept_status)
206 printk_spew("After Startup.\n");
208 printk_warning("APIC never delivered???\n");
210 printk_warning("APIC delivery error (%lx).\n", accept_status);
211 if (send_status || accept_status)
217 void startup_other_cpus(unsigned long *processor_map)
219 unsigned long apicid = this_processors_id();
222 /* Assume the cpus are densly packed by apicid */
223 for(i = 0; i < CONFIG_MAX_CPUS; i++) {
224 unsigned long cpu_apicid = initial_apicid[i];
225 if (cpu_apicid == -1) {
226 printk_err("CPU %d not found\n",i);
227 processor_map[i] = 0;
230 if (cpu_apicid == apicid ) {
233 if (!start_cpu(cpu_apicid)) {
234 /* Put an error in processor_map[i]? */
235 printk_err("CPU %d/%u would not start!\n",
237 processor_map[i] = 0;