1201_ht_bus0_dev0_fidvid_core.diff
[coreboot.git] / src / cpu / x86 / lapic / lapic_cpu_init.c
1 #include <cpu/x86/lapic.h>
2 #include <delay.h>
3 #include <string.h>
4 #include <console/console.h>
5 #include <arch/hlt.h>
6 #include <device/device.h>
7 #include <device/path.h>
8 #include <smp/atomic.h>
9 #include <smp/spinlock.h>
10 #include <cpu/cpu.h>
11
12
13 #if CONFIG_SMP == 1
14
15 /* This is a lot more paranoid now, since Linux can NOT handle
16  * being told there is a CPU when none exists. So any errors 
17  * will return 0, meaning no CPU. 
18  *
19  * We actually handling that case by noting which cpus startup
20  * and not telling anyone about the ones that dont.
21  */ 
22 static int lapic_start_cpu(unsigned long apicid)
23 {
24         int timeout;
25         unsigned long send_status, accept_status, start_eip;
26         int j, num_starts, maxlvt;
27         extern char _secondary_start[];
28                 
29         /*
30          * Starting actual IPI sequence...
31          */
32
33         printk_spew("Asserting INIT.\n");
34
35         /*
36          * Turn INIT on target chip
37          */
38         lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
39
40         /*
41          * Send IPI
42          */
43         
44         lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT
45                                 | LAPIC_DM_INIT);
46
47         printk_spew("Waiting for send to finish...\n");
48         timeout = 0;
49         do {
50                 printk_spew("+");
51                 udelay(100);
52                 send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
53         } while (send_status && (timeout++ < 1000));
54         if (timeout >= 1000) {
55                 printk_err("CPU %d: First apic write timed out. Disabling\n",
56                          apicid);
57                 // too bad. 
58                 printk_err("ESR is 0x%x\n", lapic_read(LAPIC_ESR));
59                 if (lapic_read(LAPIC_ESR)) {
60                         printk_err("Try to reset ESR\n");
61                         lapic_write_around(LAPIC_ESR, 0);
62                         printk_err("ESR is 0x%x\n", lapic_read(LAPIC_ESR));
63                 }
64                 return 0;
65         }
66         mdelay(10);
67
68         printk_spew("Deasserting INIT.\n");
69
70         /* Target chip */
71         lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
72
73         /* Send IPI */
74         lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);
75         
76         printk_spew("Waiting for send to finish...\n");
77         timeout = 0;
78         do {
79                 printk_spew("+");
80                 udelay(100);
81                 send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
82         } while (send_status && (timeout++ < 1000));
83         if (timeout >= 1000) {
84                 printk_err("CPU %d: Second apic write timed out. Disabling\n",
85                          apicid);
86                 // too bad. 
87                 return 0;
88         }
89
90         start_eip = (unsigned long)_secondary_start;
91         printk_spew("start_eip=0x%08lx\n", start_eip);
92        
93         num_starts = 2;
94
95         /*
96          * Run STARTUP IPI loop.
97          */
98         printk_spew("#startup loops: %d.\n", num_starts);
99
100         maxlvt = 4;
101
102         for (j = 1; j <= num_starts; j++) {
103                 printk_spew("Sending STARTUP #%d to %u.\n", j, apicid);
104                 lapic_read_around(LAPIC_SPIV);
105                 lapic_write(LAPIC_ESR, 0);
106                 lapic_read(LAPIC_ESR);
107                 printk_spew("After apic_write.\n");
108
109                 /*
110                  * STARTUP IPI
111                  */
112
113                 /* Target chip */
114                 lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
115
116                 /* Boot on the stack */
117                 /* Kick the second */
118                 lapic_write_around(LAPIC_ICR, LAPIC_DM_STARTUP
119                                         | (start_eip >> 12));
120
121                 /*
122                  * Give the other CPU some time to accept the IPI.
123                  */
124                 udelay(300);
125
126                 printk_spew("Startup point 1.\n");
127
128                 printk_spew("Waiting for send to finish...\n");
129                 timeout = 0;
130                 do {
131                         printk_spew("+");
132                         udelay(100);
133                         send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
134                 } while (send_status && (timeout++ < 1000));
135
136                 /*
137                  * Give the other CPU some time to accept the IPI.
138                  */
139                 udelay(200);
140                 /*
141                  * Due to the Pentium erratum 3AP.
142                  */
143                 if (maxlvt > 3) {
144                         lapic_read_around(LAPIC_SPIV);
145                         lapic_write(LAPIC_ESR, 0);
146                 }
147                 accept_status = (lapic_read(LAPIC_ESR) & 0xEF);
148                 if (send_status || accept_status)
149                         break;
150         }
151         printk_spew("After Startup.\n");
152         if (send_status)
153                 printk_warning("APIC never delivered???\n");
154         if (accept_status)
155                 printk_warning("APIC delivery error (%lx).\n", accept_status);
156         if (send_status || accept_status)
157                 return 0;
158         return 1;
159 }
160
161 /* Number of cpus that are currently running in linuxbios */
162 static atomic_t active_cpus = ATOMIC_INIT(1);
163
164 /* start_cpu_lock covers last_cpu_index and secondary_stack.
165  * Only starting one cpu at a time let's me remove the logic
166  * for select the stack from assembly language.
167  *
168  * In addition communicating by variables to the cpu I
169  * am starting allows me to veryify it has started before
170  * start_cpu returns.
171  */
172
173 static spinlock_t start_cpu_lock = SPIN_LOCK_UNLOCKED;
174 static unsigned last_cpu_index = 0;
175 volatile unsigned long secondary_stack;
176
177 int start_cpu(device_t cpu)
178 {
179         extern unsigned char _estack[];
180         struct cpu_info *info;
181         unsigned long stack_end;
182         unsigned long apicid;
183         unsigned long index;
184         unsigned long count;
185         int result;
186
187         spin_lock(&start_cpu_lock);
188
189         /* Get the cpu's apicid */
190         apicid = cpu->path.u.apic.apic_id;
191
192         /* Get an index for the new processor */
193         index = ++last_cpu_index;
194         
195         /* Find end of the new processors stack */
196         stack_end = ((unsigned long)_estack) - (STACK_SIZE*index) - sizeof(struct cpu_info);
197         
198         /* Record the index and which cpu structure we are using */
199         info = (struct cpu_info *)stack_end;
200         info->index = index;
201         info->cpu   = cpu;
202
203         /* Advertise the new stack to start_cpu */
204         secondary_stack = stack_end;
205
206         /* Until the cpu starts up report the cpu is not enabled */
207         cpu->enabled = 0;
208         cpu->initialized = 0;
209
210         /* Start the cpu */
211         result = lapic_start_cpu(apicid);
212
213         if (result) {
214                 result = 0;
215                 /* Wait 1s or until the new the new cpu calls in */
216                 for(count = 0; count < 100000 ; count++) {
217                         if (secondary_stack == 0) {
218                                 result = 1;
219                                 break;
220                         }
221                         udelay(10);
222                 }
223         }
224         secondary_stack = 0;
225         spin_unlock(&start_cpu_lock);
226         return result;
227 }
228
229 /* C entry point of secondary cpus */
230 void secondary_cpu_init(void)
231 {
232         atomic_inc(&active_cpus);
233 #if SERIAL_CPU_INIT == 1
234   #if CONFIG_MAX_CPUS>2
235         spin_lock(&start_cpu_lock);
236   #endif
237 #endif
238         cpu_initialize();
239 #if SERIAL_CPU_INIT == 1
240   #if CONFIG_MAX_CPUS>2
241         spin_unlock(&start_cpu_lock);
242   #endif
243 #endif
244
245         atomic_dec(&active_cpus);
246         stop_this_cpu();
247 }
248
249 static void initialize_other_cpus(struct bus *cpu_bus)
250 {
251         int old_active_count, active_count;
252         device_t cpu;
253         /* Loop through the cpus once getting them started */
254         for(cpu = cpu_bus->children; cpu ; cpu = cpu->sibling) {
255                 if (cpu->path.type != DEVICE_PATH_APIC) {
256                         continue;
257                 }
258
259                 if (!cpu->enabled) {
260                         continue;
261                 }
262
263                 if (cpu->initialized) {
264                         continue;
265                 }
266
267                 if (!start_cpu(cpu)) {
268                         /* Record the error in cpu? */
269                         printk_err("CPU  %u would not start!\n",
270                                 cpu->path.u.apic.apic_id);
271                 }
272 #if SERIAL_CPU_INIT == 1
273   #if CONFIG_MAX_CPUS>2
274                 udelay(10);
275   #endif
276 #endif
277         }
278
279         /* Now loop until the other cpus have finished initializing */
280         old_active_count = 1;
281         active_count = atomic_read(&active_cpus);
282         while(active_count > 1) {
283                 if (active_count != old_active_count) {
284                         printk_info("Waiting for %d CPUS to stop\n", active_count - 1);
285                         old_active_count = active_count;
286                 }
287                 udelay(10);
288                 active_count = atomic_read(&active_cpus);
289         }
290         for(cpu = cpu_bus->children; cpu; cpu = cpu->sibling) {
291                 if (cpu->path.type != DEVICE_PATH_APIC) {
292                         continue;
293                 }
294                 if (!cpu->initialized) {
295                         printk_err("CPU %u did not initialize!\n", 
296                                 cpu->path.u.apic.apic_id);
297 #warning "FIXME do I need a mainboard_cpu_fixup function?"
298                 }
299         }
300         printk_debug("All AP CPUs stopped\n");
301 }
302
303 #else /* CONFIG_SMP */
304 #define initialize_other_cpus(root) do {} while(0)
305 #endif /* CONFIG_SMP */
306
307 void initialize_cpus(struct bus *cpu_bus)
308 {
309         struct device_path cpu_path;
310         struct cpu_info *info;
311
312         /* Find the info struct for this cpu */
313         info = cpu_info();
314
315 #if NEED_LAPIC == 1
316         /* Ensure the local apic is enabled */
317         enable_lapic();
318
319         /* Get the device path of the boot cpu */
320         cpu_path.type           = DEVICE_PATH_APIC;
321         cpu_path.u.apic.apic_id = lapicid();
322 #else
323         /* Get the device path of the boot cpu */
324         cpu_path.type           = DEVICE_PATH_CPU;
325         cpu_path.u.cpu.id       = 0;
326 #endif
327         
328         /* Find the device structure for the boot cpu */
329         info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
330         
331         /* Initialize the bootstrap processor */
332         cpu_initialize();
333
334         /* Now initialize the rest of the cpus */
335         initialize_other_cpus(cpu_bus);
336 }
337