Warning, cross-references for /kernel/smp/intel.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "arch/i386.h"
0023 #include "kernel.h"
0024 #include "mem/mem.h"
0025 #include "smp/smp.h"
0026 #include "smp/intel_mps.h"
0027 #include "smp/apic.h"
0028 #include "smp/spinlock.h"
0029 #include "drivers/pci/pci.h"
0030 #include "util/printf.h"
0031
0032 static int process_mp_fp (struct mp_fp *, bool);
0033 static int process_mp_config (struct mp_config *, bool);
0034 static int add_processor (struct mp_config_processor_entry *);
0035 static struct mp_fp *probe_mp_fp (uint32, uint32);
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 uint32
0059 intel_mps_init(bool pci_irq_only)
0060 {
0061 struct mp_fp *ptr;
0062
0063 if ((ptr = probe_mp_fp (0x9F800, 0xA0000)));
0064 else if ((ptr = probe_mp_fp (0x0040E, 0x0140E)));
0065 else if ((ptr = probe_mp_fp (0xE0000, 0xFFFFF)));
0066 else return 0;
0067
0068 if(ptr)
0069 return process_mp_fp(ptr, pci_irq_only);
0070 else
0071 return 0;
0072 }
0073
0074
0075
0076
0077
0078
0079 static struct mp_fp *
0080 probe_mp_fp (uint32 start, uint32 end)
0081 {
0082 uint32 i;
0083 start &= ~0xF;
0084 for (i = start; i < end; i += 0x10) {
0085 if (*((volatile uint32 *) i) == MP_FP_SIGNATURE) {
0086
0087 return (struct mp_fp *) i;
0088 }
0089 }
0090 return NULL;
0091 }
0092
0093
0094
0095
0096 int
0097 process_mp_fp (struct mp_fp *ptr, bool pci_irq_only)
0098 {
0099 struct mp_config *cfg;
0100
0101
0102 if (ptr == NULL) {
0103 print ("No SMP support detected.\n");
0104 return 1;
0105 }
0106
0107 if (ptr->signature != MP_FP_SIGNATURE) {
0108 print ("MP floating pointer structure signature invalid.\n");
0109 return 1;
0110 }
0111
0112 if (ptr->length != 1) {
0113 print ("MP floating pointer structure reports length != 16 bytes.\n");
0114 return 1;
0115 }
0116
0117 switch (ptr->version) {
0118 case 1:
0119 print ("Intel MP specification v1.1\n");
0120 break;
0121 case 4:
0122 print ("Intel MP specification v1.4\n");
0123 break;
0124 default:
0125 print ("Unknown MP specification reported.\n");
0126 return 1;
0127 }
0128
0129 if (checksum ((uint8 *) ptr, sizeof (struct mp_fp)) != 0) {
0130 print ("MP floating pointer structure failed checksum.\n");
0131 return 1;
0132 }
0133
0134
0135 cfg = (struct mp_config *) ptr->mpconfig_ptr;
0136
0137 process_mp_config (cfg, pci_irq_only);
0138
0139 return mp_num_cpus;
0140 }
0141
0142
0143
0144
0145
0146 #define printf com1_printf
0147 static int
0148 process_mp_config (struct mp_config *cfg, bool pci_irq_only)
0149 {
0150 int i;
0151 uint8 *ptr;
0152 extern uint32 mp_LAPIC_addr, mp_IOAPIC_addr;
0153 extern uint32 mp_num_IOAPICs;
0154 extern mp_IOAPIC_info mp_IOAPICs[];
0155 extern mp_int_override mp_overrides[];
0156 extern uint32 mp_num_overrides;
0157
0158
0159
0160 if (cfg == NULL) {
0161 printf ("MP config pointer is NULL.\n");
0162 return 1;
0163 }
0164
0165 if (cfg->signature != MP_CFG_SIGNATURE) {
0166 printf ("MP config signature invalid.\n");
0167 return 1;
0168 }
0169
0170 if (cfg->specification_revision != 1 && cfg->specification_revision != 4) {
0171 printf ("Unknown MP specification reported by MP config table.\n");
0172 return 1;
0173 }
0174
0175 if (checksum ((uint8 *) cfg, cfg->base_table_length) != 0) {
0176 printf ("MP config table failed checksum.\n");
0177 return 1;
0178 }
0179
0180 printf ("Manufacturer: %.8s Product: %.12s Local APIC: %.8X\n",
0181 cfg->OEM_id, cfg->product_id, cfg->local_APIC);
0182 if (cfg->local_APIC)
0183 mp_LAPIC_addr = cfg->local_APIC;
0184
0185
0186 ptr = (uint8 *) cfg->entries;
0187 for (i = 0; i < cfg->entry_count; i++) {
0188 struct mp_config_entry *entry = (struct mp_config_entry *) ptr;
0189 switch (*ptr) {
0190 case MP_CFG_TYPE_PROCESSOR:
0191 if (!pci_irq_only) {
0192 printf ("Processor APIC-id: %X version: %X %s%s",
0193 entry->processor.APIC_id,
0194 entry->processor.APIC_version,
0195 (entry->processor.flags & 1) ? "(enabled)" : "(disabled)",
0196 (entry->processor.flags & 2) ? " (bootstrap)" : "");
0197
0198 if (add_processor (&entry->processor))
0199 printf (" (booted)");
0200 printf ("\n");
0201 }
0202 ptr += sizeof (struct mp_config_processor_entry);
0203 break;
0204
0205 case MP_CFG_TYPE_BUS:
0206 printf ("Bus entry-id: %X type: %.6s\n",
0207 entry->bus.id, entry->bus.bus_type);
0208 if (entry->bus.bus_type[0] == 'I' &&
0209 entry->bus.bus_type[1] == 'S' && entry->bus.bus_type[2] == 'A') {
0210 mp_ISA_bus_id = entry->bus.id;
0211 }
0212 ptr += sizeof (struct mp_config_bus_entry);
0213 break;
0214
0215 case MP_CFG_TYPE_IO_APIC:
0216 printf ("IO APIC-id: 0x%X version: 0x%X address: 0x%.8X",
0217 entry->IO_APIC.id,
0218 entry->IO_APIC.version, entry->IO_APIC.address);
0219 if (entry->IO_APIC.flags & 1) {
0220 mp_IOAPIC_addr = entry->IO_APIC.address;
0221 printf ("\n");
0222
0223 if (mp_num_IOAPICs == MAX_IOAPICS)
0224 panic ("Too many IO-APICs.");
0225 mp_IOAPICs[mp_num_IOAPICs].id = entry->IO_APIC.id;
0226 mp_IOAPICs[mp_num_IOAPICs].address = entry->IO_APIC.address;
0227
0228 if (mp_num_IOAPICs == 0)
0229 mp_IOAPICs[mp_num_IOAPICs].startGSI = 0;
0230 else
0231 mp_IOAPICs[mp_num_IOAPICs].startGSI =
0232 mp_IOAPICs[mp_num_IOAPICs - 1].startGSI +
0233 mp_IOAPICs[mp_num_IOAPICs - 1].numGSIs;
0234
0235 mp_IOAPICs[mp_num_IOAPICs].numGSIs =
0236 IOAPIC_num_entries();
0237 printf (" startGSI=0x%X numGSIs=%d\n",
0238 mp_IOAPICs[mp_num_IOAPICs].startGSI,
0239 mp_IOAPICs[mp_num_IOAPICs].numGSIs);
0240 mp_num_IOAPICs++;
0241 } else
0242 printf (" (disabled)\n");
0243
0244 ptr += sizeof (struct mp_config_IO_APIC_entry);
0245 break;
0246
0247 case MP_CFG_TYPE_IO_INT:
0248 printf
0249 ("IO interrupt type: %X flags: %X source: (bus: %X irq: %X) dest: (APIC: %X int: %X)\n",
0250 entry->IO_int.int_type, entry->IO_int.flags,
0251 entry->IO_int.source_bus_id, entry->IO_int.source_bus_irq,
0252 entry->IO_int.dest_APIC_id, entry->IO_int.dest_APIC_intin);
0253
0254 if (entry->IO_int.source_bus_irq != entry->IO_int.dest_APIC_intin
0255 && entry->IO_int.int_type == 0
0256
0257 && entry->IO_int.source_bus_id == mp_ISA_bus_id) {
0258
0259 if (mp_num_overrides == MAX_INT_OVERRIDES)
0260 panic ("Too many interrupt overrides.");
0261 mp_overrides[mp_num_overrides].src_bus = entry->IO_int.source_bus_id;
0262 mp_overrides[mp_num_overrides].src_IRQ = entry->IO_int.source_bus_irq;
0263 mp_overrides[mp_num_overrides].dest_GSI =
0264 IOAPIC_lookup (entry->IO_int.dest_APIC_id)->startGSI +
0265 entry->IO_int.dest_APIC_intin;
0266 mp_num_overrides++;
0267 }
0268 if (entry->IO_int.source_bus_id != mp_ISA_bus_id) {
0269
0270 pci_irq_t irq;
0271 irq.bus = entry->IO_int.source_bus_id;
0272
0273
0274
0275 irq.pin = (entry->IO_int.source_bus_irq & 0x03) + 1;
0276 irq.dev = (entry->IO_int.source_bus_irq & 0x7C) >> 2;
0277 irq.gsi =
0278 IOAPIC_lookup (entry->IO_int.dest_APIC_id)->startGSI +
0279 entry->IO_int.dest_APIC_intin;
0280 switch (entry->IO_int.flags & 0x3) {
0281 case 0: irq.polarity = POLARITY_DEFAULT; break;
0282 case 1: irq.polarity = POLARITY_HIGH; break;
0283 case 3: irq.polarity = POLARITY_LOW; break;
0284 }
0285 switch ((entry->IO_int.flags & 0xC) >> 2) {
0286 case 0: irq.trigger = TRIGGER_DEFAULT; break;
0287 case 1: irq.trigger = TRIGGER_EDGE; break;
0288 case 3: irq.trigger = TRIGGER_LEVEL; break;
0289 }
0290 pci_irq_register (&irq);
0291 }
0292 ptr += sizeof (struct mp_config_interrupt_entry);
0293 break;
0294
0295 case MP_CFG_TYPE_LOCAL_INT:
0296 if (!pci_irq_only) {
0297 printf
0298 ("Local interrupt type: %X flags: %X source: (bus: %X irq: %X) dest: (APIC: %X int: %X)\n",
0299 entry->local_int.int_type, entry->local_int.flags,
0300 entry->local_int.source_bus_id, entry->local_int.source_bus_irq,
0301 entry->local_int.dest_APIC_id, entry->local_int.dest_APIC_intin);
0302
0303
0304
0305 }
0306 ptr += sizeof (struct mp_config_interrupt_entry);
0307 break;
0308
0309 default:
0310 printf ("Unknown entry type: %X at address: %p\n", *ptr, ptr);
0311 return 1;
0312 }
0313 }
0314
0315 return mp_num_cpus;
0316 }
0317
0318 #undef printf
0319
0320
0321
0322 static int
0323 add_processor (struct mp_config_processor_entry *proc)
0324 {
0325 #ifndef NO_SMP
0326 uint8 apic_id = proc->APIC_id;
0327
0328 if (!(proc->flags & 1))
0329 return 0;
0330 if (proc->flags & 2)
0331 return 0;
0332
0333 if (smp_boot_cpu (apic_id, proc->APIC_version)) {
0334 CPU_to_APIC[mp_num_cpus] = apic_id;
0335 APIC_to_CPU[apic_id] = mp_num_cpus;
0336 mp_num_cpus++;
0337 return 1;
0338 } else
0339 return 0;
0340 #else
0341 return 0;
0342 #endif
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356