Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / mpparse.c
1 /*
2  *      Intel Multiprocessor Specification 1.1 and 1.4
3  *      compliant MP-table parsing routines.
4  *
5  *      (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
6  *      (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
7  *
8  *      Fixes
9  *              Erich Boleyn    :       MP v1.4 and additional changes.
10  *              Alan Cox        :       Added EBDA scanning
11  *              Ingo Molnar     :       various cleanups and rewrites
12  *              Maciej W. Rozycki:      Bits for default MP configurations
13  *              Paul Diefenbaugh:       Added full ACPI support
14  */
15
16 #include <lwk/smp.h>
17 #include <lwk/init.h>
18 #include <lwk/bootmem.h>
19 #include <lwk/cpuinfo.h>
20 #include <lwk/params.h>
21 #include <arch/io.h>
22 #include <arch/mpspec.h>
23 #include <arch/proto.h>
24 #include <arch/io_apic.h>
25
26 /**
27  * Points to the MP table, once and if it is found.
28  * This gets initialized by find_mp_table().
29  */
30 static struct intel_mp_floating *mpf_found;
31
32 /**
33  * Physical CPU ID of the bootstrap CPU (the BP).
34  */
35 unsigned int __initdata boot_phys_cpu_id = -1U;
36
37 /**
38  * The number of CPUs in the system.
39  */
40 unsigned int __initdata num_cpus = 0;
41
42 /**
43  * Map of all CPUs present.
44  * Bits set represent physical CPU IDs present.
45  */
46 physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
47
48 /**
49  * Version information for every Local APIC in the system.
50  * The array is indexed by APIC ID.
51  */
52 unsigned char apic_version[MAX_APICS];
53
54 /**
55  * MP Bus information
56  */
57 static int    mp_current_pci_id = 0;
58 unsigned char mp_bus_id_to_type    [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
59 int           mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
60
61 /**
62  * MP IO APIC information
63  */
64 int nr_ioapics = 0;
65 struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
66
67 /**
68  * MP IRQ information
69  */
70 int mp_irq_entries = 0;
71 struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
72
73
74 /* TODO: move these */
75 int pic_mode;
76
77 /**
78  * Computes the checksum of an MP configuration block.
79  */
80 static int __init
81 mpf_checksum(unsigned char *mp, int len)
82 {
83         int sum = 0;
84         while (len--)
85                 sum += *mp++;
86         return sum & 0xFF;
87 }
88
89 /**
90  * Parses an MP table CPU entry.
91  */
92 static void __init
93 MP_processor_info(struct mpc_config_processor *m)
94 {
95         int cpu;
96         int is_bp;
97         unsigned char ver;
98         cpumask_t tmp_map;
99
100         if (!(m->mpc_cpuflag & CPU_ENABLED))
101                 panic("A disabled CPU was encountered\n");
102
103         /* Count the new CPU */
104         if (++num_cpus > NR_CPUS)
105                 panic("NR_CPUS limit of %i reached.\n", NR_CPUS);
106
107         /*
108          * Determine if this is the bootstrap processor...
109          * the one responsible for booting the other CPUs.
110          */
111         is_bp = (m->mpc_cpuflag & CPU_BOOTPROCESSOR);
112
113         /*
114          * Assign a logical CPU ID.
115          * The bootstrap CPU is always assigned logical ID 0.
116          * All other CPUs are assigned the lowest ID available.
117          */
118         if (is_bp) {
119                 cpu = 0;
120         } else {
121                 cpus_complement(tmp_map, cpu_present_map);
122                 cpu = first_cpu(tmp_map);
123         }
124
125         /* Validate APIC version, fixing up if necessary. */
126         ver = m->mpc_apicver;
127         if (ver == 0x0) {
128                 printk(KERN_ERR "BIOS bug, APIC version is 0 for PhysCPU#%d! "
129                                 "fixing up to 0x10. (tell your hw vendor)\n",
130                                 m->mpc_apicid);
131                 ver = 0x10;
132         }
133
134         /* Remember the APIC's version */
135         apic_version[m->mpc_apicid] = ver;
136
137         /* Add the CPU to the map of physical CPU IDs present. */
138         physid_set(m->mpc_apicid, phys_cpu_present_map);
139
140         /* Remember the physical CPU ID of the bootstrap CPU. */
141         if (is_bp)
142                 boot_phys_cpu_id = m->mpc_apicid;
143
144         /* Add the CPU to the map of logical CPU IDs present. */
145         cpu_set(cpu, cpu_present_map);
146
147         /* Store ID information. */
148         cpu_info[cpu].logical_id   = cpu;
149         cpu_info[cpu].physical_id  = m->mpc_apicid;
150         cpu_info[cpu].arch.apic_id = m->mpc_apicid;
151
152         printk(KERN_DEBUG
153           "Physical CPU #%d -> Logical CPU #%d, %d:%d APIC version %d%s\n",
154                 m->mpc_apicid,
155                 cpu,
156                (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
157                (m->mpc_cpufeature & CPU_MODEL_MASK)  >> 4,
158                 ver,
159                 is_bp ? " (Bootstrap CPU)" : "");
160 }
161
162 /**
163  * Parses an MP table BUS entry.
164  */
165 static void __init
166 MP_bus_info(struct mpc_config_bus *m)
167 {
168         char str[7];
169
170         memcpy(str, m->mpc_bustype, 6);
171         str[6] = 0;
172         printk(KERN_DEBUG "Bus #%d is %s\n", m->mpc_busid, str);
173
174         if (strncmp(str, "ISA", 3) == 0) {
175                 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
176         } else if (strncmp(str, "EISA", 4) == 0) {
177                 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
178         } else if (strncmp(str, "PCI", 3) == 0) {
179                 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
180                 mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
181                 mp_current_pci_id++;
182         } else if (strncmp(str, "MCA", 3) == 0) {
183                 mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
184         } else {
185                 printk(KERN_ERR "Unknown bustype %s\n", str);
186         }
187 }
188
189 /**
190  * Parses an MP table BUS entry.
191  */
192 static void __init
193 MP_ioapic_info(struct mpc_config_ioapic *m)
194 {
195         if (!(m->mpc_flags & MPC_APIC_USABLE)) {
196                 printk(KERN_DEBUG "Encountered unusable APIC, ignoring it.\n");
197                 return;
198         }
199
200         printk(KERN_DEBUG "I/O APIC #%d Version %d at 0x%X\n",
201                 m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
202         if (nr_ioapics >= MAX_IO_APICS) {
203                 printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
204                         MAX_IO_APICS, nr_ioapics);
205                 panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
206         }
207         if (!m->mpc_apicaddr) {
208                 printk(KERN_ERR "WARNING: bogus zero I/O APIC address"
209                         " found in MP table, skipping!\n");
210                 return;
211         }
212         mp_ioapics[nr_ioapics] = *m;
213         nr_ioapics++;
214
215         ioapic_id[ioapic_num]        = m->mpc_apicid;
216         ioapic_phys_addr[ioapic_num] = m->mpc_apicaddr;
217         ioapic_num++;
218 }
219
220 /**
221  * Parses an MP table IRQ source entry.
222  */
223 static void __init
224 MP_intsrc_info(struct mpc_config_intsrc *m)
225 {
226         mp_irqs [mp_irq_entries] = *m;
227         printk(KERN_DEBUG
228                 "Int: type %d, pol %d, trig %d, bus %d,"
229                 " IRQ %02x, APIC ID %x, APIC INT %02x\n",
230                         m->mpc_irqtype, m->mpc_irqflag & 3,
231                         (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
232                         m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
233         if (++mp_irq_entries >= MAX_IRQ_SOURCES)
234                 panic("Max # of irq sources exceeded!!\n");
235 }
236
237 /**
238  * Parses an MP table LINT entry.
239  */
240 static void __init
241 MP_lintsrc_info (struct mpc_config_lintsrc *m)
242 {
243         printk(KERN_DEBUG
244                 "Lint: type %d, pol %d, trig %d, bus %d,"
245                 " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
246                         m->mpc_irqtype, m->mpc_irqflag & 3,
247                         (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
248                         m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
249         /*
250          * Well it seems all SMP boards in existence
251          * use ExtINT/LVT1 == LINT0 and
252          * NMI/LVT2 == LINT1 - the following check
253          * will show us if this assumptions is false.
254          * Until then we do not have to add baggage.
255          */
256         if ((m->mpc_irqtype == mp_ExtINT) &&
257                 (m->mpc_destapiclint != 0))
258                         BUG();
259         if ((m->mpc_irqtype == mp_NMI) &&
260                 (m->mpc_destapiclint != 1))
261                         BUG();
262 }
263
264 /**
265  * Parses the input MP table, storing various bits of information in global
266  * variables as it goes.
267  */
268 static int __init
269 read_mpc(struct mp_config_table *mpc)
270 {
271         char str[16];
272         int count=sizeof(*mpc);
273         unsigned char *mpt=((unsigned char *)mpc)+count;
274
275         if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
276                 printk(KERN_ERR "SMP mptable: bad signature [%c%c%c%c]!\n",
277                         mpc->mpc_signature[0],
278                         mpc->mpc_signature[1],
279                         mpc->mpc_signature[2],
280                         mpc->mpc_signature[3]);
281                 return -1;
282         }
283         if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
284                 printk(KERN_ERR "SMP mptable: checksum error!\n");
285                 return -1;
286         }
287         if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
288                 printk(KERN_ERR "SMP mptable: bad table version (%d)!\n",
289                         mpc->mpc_spec);
290                 return -1;
291         }
292         if (!mpc->mpc_lapic) {
293                 printk(KERN_ERR "SMP mptable: null local APIC address!\n");
294                 return -1;
295         }
296         memcpy(str, mpc->mpc_oem, 8);
297         str[8]=0;
298         printk(KERN_DEBUG "    OEM ID: %s\n", str);
299
300         memcpy(str, mpc->mpc_productid, 12);
301         str[12]=0;
302         printk(KERN_DEBUG "    Product ID: %s\n", str);
303
304         printk(KERN_DEBUG "    APIC at: 0x%X\n", mpc->mpc_lapic);
305
306         /* Save the local APIC address, it might be non-default. */
307         lapic_phys_addr = mpc->mpc_lapic;
308
309         /* Now process all of the configuration blocks in the table. */
310         while (count < mpc->mpc_length) {
311                 switch(*mpt) {
312                         case MP_PROCESSOR:
313                         {
314                                 struct mpc_config_processor *m=
315                                         (struct mpc_config_processor *)mpt;
316                                 MP_processor_info(m);
317                                 mpt += sizeof(*m);
318                                 count += sizeof(*m);
319                                 break;
320                         }
321                         case MP_BUS:
322                         {
323                                 struct mpc_config_bus *m=
324                                         (struct mpc_config_bus *)mpt;
325                                 MP_bus_info(m);
326                                 mpt += sizeof(*m);
327                                 count += sizeof(*m);
328                                 break;
329                         }
330                         case MP_IOAPIC:
331                         {
332                                 struct mpc_config_ioapic *m=
333                                         (struct mpc_config_ioapic *)mpt;
334                                 MP_ioapic_info(m);
335                                 mpt+=sizeof(*m);
336                                 count+=sizeof(*m);
337                                 break;
338                         }
339                         case MP_INTSRC:
340                         {
341                                 struct mpc_config_intsrc *m=
342                                         (struct mpc_config_intsrc *)mpt;
343
344                                 MP_intsrc_info(m);
345                                 mpt+=sizeof(*m);
346                                 count+=sizeof(*m);
347                                 break;
348                         }
349                         case MP_LINTSRC:
350                         {
351                                 struct mpc_config_lintsrc *m=
352                                         (struct mpc_config_lintsrc *)mpt;
353                                 MP_lintsrc_info(m);
354                                 mpt+=sizeof(*m);
355                                 count+=sizeof(*m);
356                                 break;
357                         }
358                 }
359         }
360         //clustered_apic_check();
361         if (!num_cpus)
362                 printk(KERN_ERR "SMP mptable: no CPUs registered!\n");
363         return 0;
364 }
365
366 /**
367  * Determines the multiprocessor configuration.
368  * The configuration information is stored in global variables so nothing is
369  * returned.  find_mp_config() must be called before this function.
370  */
371 void __init
372 get_mp_config(void)
373 {
374         struct intel_mp_floating *mpf = mpf_found;
375         if (!mpf) {
376                 printk(KERN_WARNING "Assuming 1 CPU.\n");
377                 num_cpus = 1;
378                 /* Assign the only CPU logical=physical ID 0 */
379                 cpu_set(0, cpu_present_map);
380                 physid_set(0, phys_cpu_present_map);
381                 cpu_info[0].logical_id   = 0;
382                 cpu_info[0].physical_id  = 0;
383                 cpu_info[0].arch.apic_id = 0;
384                 return;
385         }
386
387         printk(KERN_DEBUG "Intel MultiProcessor Specification v1.%d\n",
388                mpf->mpf_specification);
389         if (mpf->mpf_feature2 & (1<<7)) {
390                 printk(KERN_DEBUG "    IMCR and PIC compatibility mode.\n");
391                 pic_mode = 1;
392         } else {
393                 printk(KERN_DEBUG "    Virtual Wire compatibility mode.\n");
394                 pic_mode = 0;
395         }
396
397         /*
398          * We don't support the default MP configuration.
399          * All supported multi-CPU systems must provide a full MP table.
400          */
401         if (mpf->mpf_feature1 != 0)
402                 BUG();
403         if (!mpf->mpf_physptr)
404                 BUG();
405
406         /*
407          * Set this early so we don't allocate CPU0 if the
408          * MADT list doesn't list the bootstrap processor first.
409          * The bootstrap processor has to be logical ID 0... which
410          * we are reserving here.
411          */
412         cpu_set(0, cpu_present_map);
413
414         /*
415          * Parse the MP configuration
416          */
417         if (read_mpc(phys_to_virt(mpf->mpf_physptr)))
418                 panic("BIOS bug, MP table errors detected! (tell your hw vendor)\n");
419 }
420
421 /**
422  * Scans a region of memory for the MP table.
423  */
424 static int __init
425 scan(unsigned long base, unsigned long length)
426 {
427         unsigned int *bp = phys_to_virt(base);
428         struct intel_mp_floating *mpf;
429
430         printk(KERN_DEBUG "Scan for MP table from 0x%p for %ld bytes\n",
431                           bp, length);
432
433         while (length > 0) {
434                 mpf = (struct intel_mp_floating *)bp;
435                 if ((*bp == SMP_MAGIC_IDENT) &&
436                         (mpf->mpf_length == 1) &&
437                         !mpf_checksum((unsigned char *)bp, 16) &&
438                         ((mpf->mpf_specification == 1)
439                                 || (mpf->mpf_specification == 4)) ) {
440
441                         reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
442                         if (mpf->mpf_physptr)
443                                 reserve_bootmem(mpf->mpf_physptr, PAGE_SIZE);
444                         mpf_found = mpf;
445                         printk(KERN_DEBUG "Found MP table at:     0x%p\n", mpf);
446                         return 1;
447                 }
448                 bp += 4;
449                 length -= 16;
450         }
451         return 0;
452 }
453
454 /**
455  * Locates the MP table, if there is one.
456  * This does not parse the MP table... get_mp_config() does that.
457  */
458 void __init
459 find_mp_config(void)
460 {
461         /* 
462          * 1) Scan the bottom 1K for a signature
463          * 2) Scan the top 1K of base RAM
464          * 3) Scan the 64K of bios
465          */
466         if (scan(0x0,0x400) ||
467                 scan(639*0x400,0x400) ||
468                         scan(0xF0000,0x10000))
469                 return;
470
471         /*
472          * If it is an MP machine we should know now.
473          *
474          * If not, make a final effort and scan the
475          * Extended BIOS Data Area. 
476          *
477          * NOTE! There are Linux loaders that will corrupt the EBDA
478          * area, and as such this kind of MP config may be less
479          * trustworthy, simply because the MP table may have been
480          * stomped on during early boot. These loaders are buggy and
481          * should be fixed.
482          */
483         if (scan(ebda_addr, 0x1000)) {
484                 printk(KERN_WARNING "MP table found in EBDA\n");
485                 return;
486         }
487
488         /* If we have come this far, we did not find an MP table */
489         printk(KERN_DEBUG "No MP table found.\n");
490 }
491