File indexing completed on 2025-05-11 08:23:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 #define _SMP_IMPS_C
0048
0049
0050
0051
0052 #if 0
0053 #define IMPS_DEBUG
0054 #endif
0055
0056 #include <bsp/apic.h>
0057 #include <bsp/smp-imps.h>
0058 #include <bsp/irq.h>
0059 #include <rtems/score/smpimpl.h>
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 #if 0
0070 #define KERNEL_PRINT(x)
0071 #define CMOS_WRITE_BYTE(x,y)
0072 #define CMOS_READ_BYTE(x)
0073 #define PHYS_TO_VIRTUAL(x)
0074 #define VIRTUAL_TO_PHYS(x)
0075 #define UDELAY(x)
0076 #define READ_MSR_LO(x)
0077 #else
0078 #include <string.h>
0079 #include <unistd.h>
0080 #include <rtems.h>
0081 #include <rtems/bspIo.h>
0082 #include <rtems/score/cpu.h>
0083 #include <assert.h>
0084
0085 extern void _pc386_delay(void);
0086 extern uint32_t* gdtdesc;
0087
0088 static int lapic_dummy = 0;
0089 unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
0090
0091
0092
0093 static void CMOS_WRITE_BYTE(
0094 unsigned int offset,
0095 unsigned char value
0096 )
0097 {
0098 if ( offset < 128 ) {
0099 outport_byte( 0x70, offset );
0100 outport_byte( 0x71, value );
0101 } else {
0102 outport_byte( 0x72, offset );
0103 outport_byte( 0x73, value );
0104 }
0105 }
0106
0107 static unsigned char CMOS_READ_BYTE(
0108 unsigned int offset
0109 )
0110 {
0111 unsigned char value;
0112 if ( offset < 128 ) {
0113 outport_byte( 0x70, offset );
0114 inport_byte( 0x71, value );
0115 } else {
0116 outport_byte( 0x72, offset );
0117 inport_byte( 0x73, value );
0118 }
0119 return value;
0120 }
0121
0122 #define PHYS_TO_VIRTUAL(_x) _x
0123 #define VIRTUAL_TO_PHYS(_x) _x
0124 static void UDELAY(int x)
0125 { int _i = x;
0126 while ( _i-- )
0127 _pc386_delay();
0128 }
0129
0130 #define READ_MSR_LO(_x) \
0131 (unsigned int)(read_msr(_x) & 0xffffffff)
0132
0133 static inline unsigned long long read_msr(unsigned int msr)
0134 {
0135 unsigned long long value;
0136
0137 asm volatile("rdmsr" : "=A" (value) : "c" (msr));
0138 return value;
0139 }
0140 #endif
0141
0142
0143
0144
0145 #define EBDA_SEG_ADDR 0x40E
0146 #define BIOS_RESET_VECTOR 0x467
0147 #define LAPIC_ADDR_DEFAULT 0xFEE00000uL
0148 #define IOAPIC_ADDR_DEFAULT 0xFEC00000uL
0149 #define CMOS_RESET_CODE 0xF
0150 #define CMOS_RESET_JUMP 0xa
0151 #define CMOS_BASE_MEMORY 0x15
0152
0153
0154
0155
0156
0157 #define DEF_ENTRIES 23
0158
0159 static struct {
0160 imps_processor proc[2];
0161 imps_bus bus[2];
0162 imps_ioapic ioapic;
0163 imps_interrupt intin[16];
0164 imps_interrupt lintin[2];
0165 } defconfig = {
0166 { { IMPS_BCT_PROCESSOR, 0, 0, 0, 0, 0},
0167 { IMPS_BCT_PROCESSOR, 1, 0, 0, 0, 0} },
0168 { { IMPS_BCT_BUS, 0, {'E', 'I', 'S', 'A', ' ', ' '}},
0169 { 255, 1, {'P', 'C', 'I', ' ', ' ', ' '}} },
0170 { IMPS_BCT_IOAPIC, 0, 0, IMPS_FLAG_ENABLED, IOAPIC_ADDR_DEFAULT },
0171 { { IMPS_BCT_IO_INTERRUPT, IMPS_INT_EXTINT, 0, 0, 0, 0xFF, 0},
0172 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 1, 0xFF, 1},
0173 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 0, 0xFF, 2},
0174 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 3, 0xFF, 3},
0175 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 4, 0xFF, 4},
0176 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 5, 0xFF, 5},
0177 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 6, 0xFF, 6},
0178 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 7, 0xFF, 7},
0179 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 8, 0xFF, 8},
0180 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 9, 0xFF, 9},
0181 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 10, 0xFF, 10},
0182 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 11, 0xFF, 11},
0183 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 12, 0xFF, 12},
0184 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 13, 0xFF, 13},
0185 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 14, 0xFF, 14},
0186 { IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 15, 0xFF, 15} },
0187 { { IMPS_BCT_LOCAL_INTERRUPT, IMPS_INT_EXTINT, 0, 0, 15, 0xFF, 0},
0188 { IMPS_BCT_LOCAL_INTERRUPT, IMPS_INT_NMI, 0, 0, 15, 0xFF, 1} }
0189 };
0190
0191
0192
0193
0194
0195 volatile int imps_release_cpus = 0;
0196 int imps_enabled = 0;
0197 int imps_num_cpus = 1;
0198 unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
0199 unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
0200
0201
0202 extern unsigned imps_lapic_addr;
0203
0204 static void secondary_cpu_initialize(void);
0205
0206
0207
0208
0209
0210
0211 static int
0212 get_checksum(unsigned start, int length)
0213 {
0214 unsigned sum = 0;
0215
0216 while (length-- > 0) {
0217 sum += *((unsigned char *) (start++));
0218 }
0219
0220 return (sum&0xFF);
0221 }
0222
0223
0224
0225
0226 int
0227 send_ipi(unsigned int dst, unsigned int v)
0228 {
0229 int to, send_status, apicid;
0230
0231 apicid = imps_cpu_apic_map[dst];
0232
0233 IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (apicid << 24));
0234 IMPS_LAPIC_WRITE(LAPIC_ICR, v);
0235
0236
0237 to = 0;
0238 do {
0239 UDELAY(100);
0240 send_status = IMPS_LAPIC_READ(LAPIC_ICR) & LAPIC_ICR_STATUS_PEND;
0241 } while (send_status && (to++ < 1000));
0242
0243 return (to < 1000);
0244 }
0245
0246
0247
0248
0249
0250
0251
0252 static int
0253 boot_cpu(imps_processor *proc)
0254 {
0255 int apicid = proc->apic_id, success = 1;
0256 int cpuid;
0257 unsigned bootaddr;
0258 unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
0259
0260 cpuid = imps_apic_cpu_map[apicid];
0261
0262
0263
0264
0265
0266
0267
0268
0269 volatile uint32_t *reset;
0270
0271 bootaddr = (512-64)*1024;
0272 reset= (volatile uint32_t *)bootaddr;
0273
0274 memcpy(
0275 (char *) bootaddr,
0276 _binary_appstart_bin_start,
0277 (size_t)_binary_appstart_bin_size
0278 );
0279
0280
0281
0282 reset[1] = (uint32_t)secondary_cpu_initialize;
0283 reset[2] = (uint32_t)_Per_CPU_Get_by_index(cpuid)->interrupt_stack_high;
0284 memcpy(
0285 (char*) &reset[3],
0286 &gdtdesc,
0287 6);
0288
0289
0290
0291
0292
0293 CMOS_WRITE_BYTE(CMOS_RESET_CODE, CMOS_RESET_JUMP);
0294 *((volatile unsigned *) bios_reset_vector) = ((bootaddr & 0xFF000) << 12);
0295
0296
0297 IMPS_LAPIC_WRITE(LAPIC_ESR, 0);
0298 IMPS_LAPIC_READ(LAPIC_ESR);
0299
0300
0301 send_ipi(
0302 cpuid,
0303 LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
0304 );
0305 UDELAY(10000);
0306
0307
0308 send_ipi(cpuid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT);
0309
0310 UDELAY(10000);
0311
0312
0313
0314
0315
0316 if (proc->apic_ver >= APIC_VER_NEW) {
0317 int i;
0318 for (i = 1; i <= 2; i++) {
0319 send_ipi(cpuid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF));
0320 UDELAY(1000);
0321 }
0322 }
0323
0324
0325
0326
0327 while (reset[2] != 0);
0328
0329
0330
0331
0332
0333
0334 IMPS_LAPIC_WRITE(LAPIC_ESR, 0);
0335 IMPS_LAPIC_READ(LAPIC_ESR);
0336
0337
0338 CMOS_WRITE_BYTE(CMOS_RESET_CODE, 0);
0339 *((volatile unsigned *) bios_reset_vector) = 0;
0340
0341 return success;
0342 }
0343
0344
0345
0346
0347 static void
0348 add_processor(imps_processor *proc)
0349 {
0350 int apicid = proc->apic_id;
0351
0352 printk(" Processor [APIC id %d ver %d]: ", apicid, proc->apic_ver);
0353 if (!(proc->flags & IMPS_FLAG_ENABLED)) {
0354 printk("DISABLED\n");
0355 return;
0356 }
0357 if (proc->flags & (IMPS_CPUFLAG_BOOT)) {
0358 printk("#0 BootStrap Processor (BSP)\n");
0359 return;
0360 }
0361
0362
0363
0364
0365 imps_cpu_apic_map[imps_num_cpus] = apicid;
0366 imps_apic_cpu_map[apicid] = imps_num_cpus;
0367 if (boot_cpu(proc)) {
0368
0369
0370
0371
0372 imps_num_cpus++;
0373 printk("#%d Application Processor (AP)\n", imps_apic_cpu_map[apicid]);
0374 }
0375 }
0376
0377
0378 static void
0379 add_bus(imps_bus *bus)
0380 {
0381 char str[8];
0382
0383 memcpy(str, bus->bus_type, 6);
0384 str[6] = 0;
0385 printk(" Bus id %d is %s\n", bus->id, str);
0386
0387
0388 }
0389
0390 static void
0391 add_ioapic(imps_ioapic *ioapic)
0392 {
0393 printk(" I/O APIC id %d ver %d, address: 0x%x ",
0394 ioapic->id, ioapic->ver, ioapic->addr);
0395 if (!(ioapic->flags & IMPS_FLAG_ENABLED)) {
0396 printk("DISABLED\n");
0397 return;
0398 }
0399 printk("\n");
0400
0401
0402 }
0403
0404 static void
0405 imps_read_config_table(unsigned start, int count)
0406 {
0407 while (count-- > 0) {
0408 switch (*((unsigned char *)start)) {
0409 case IMPS_BCT_PROCESSOR:
0410 if ( imps_num_cpus < rtems_configuration_get_maximum_processors() ) {
0411 if (_SMP_Should_start_processor((uint32_t) imps_num_cpus)) {
0412 add_processor((imps_processor *)start);
0413 }
0414 } else
0415 imps_num_cpus++;
0416 start += 12;
0417 break;
0418 case IMPS_BCT_BUS:
0419 add_bus((imps_bus *)start);
0420 break;
0421 case IMPS_BCT_IOAPIC:
0422 add_ioapic((imps_ioapic *)start);
0423 break;
0424 #if 0
0425 case IMPS_BCT_IO_INTERRUPT:
0426 add_io_interrupt((imps_interrupt *)start);
0427 break;
0428 #endif
0429 #if 0
0430 case IMPS_BCT_LOCAL_INTERRUPT:
0431 add_local_interupt((imps_interrupt *)start);
0432 break;
0433 #endif
0434 default:
0435 break;
0436 }
0437 start += 8;
0438 }
0439 if ( imps_num_cpus > rtems_configuration_get_maximum_processors() ) {
0440 printk(
0441 "WARNING!! Found more CPUs (%d) than configured for (%d)!!\n",
0442 imps_num_cpus - 1,
0443 rtems_configuration_get_maximum_processors()
0444 );
0445 imps_num_cpus = rtems_configuration_get_maximum_processors();
0446 return;
0447 }
0448 }
0449
0450 static int
0451 imps_bad_bios(imps_fps *fps_ptr)
0452 {
0453 int sum;
0454 imps_cth *local_cth_ptr
0455 = (imps_cth *) PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
0456
0457 if (fps_ptr->feature_info[0] > IMPS_FPS_DEFAULT_MAX) {
0458 printk(" Invalid MP System Configuration type %d\n",
0459 fps_ptr->feature_info[0]);
0460 return 1;
0461 }
0462
0463 if (fps_ptr->cth_ptr) {
0464 sum = get_checksum((unsigned)local_cth_ptr,
0465 local_cth_ptr->base_length);
0466 if (local_cth_ptr->sig != IMPS_CTH_SIGNATURE || sum) {
0467 printk(
0468 " Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",
0469 (unsigned)(fps_ptr->cth_ptr),
0470 sum
0471 );
0472 return 1;
0473 }
0474 if (local_cth_ptr->spec_rev != fps_ptr->spec_rev) {
0475 printk(
0476 " Bad MP Config Table sub-revision # %d\n",
0477 local_cth_ptr->spec_rev
0478 );
0479 return 1;
0480 }
0481 if (local_cth_ptr->extended_length) {
0482 sum = (get_checksum(((unsigned)local_cth_ptr)
0483 + local_cth_ptr->base_length,
0484 local_cth_ptr->extended_length)
0485 + local_cth_ptr->extended_checksum) & 0xFF;
0486 if (sum) {
0487 printk(" Bad Extended MP Config Table checksum 0x%x\n", sum);
0488 return 1;
0489 }
0490 }
0491 } else if (!fps_ptr->feature_info[0]) {
0492 printk(" Missing configuration information\n");
0493 return 1;
0494 }
0495
0496 return 0;
0497 }
0498
0499 static void
0500 imps_read_bios(imps_fps *fps_ptr)
0501 {
0502 int apicid;
0503 unsigned cth_start, cth_count;
0504 imps_cth *local_cth_ptr
0505 = (imps_cth *)PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
0506 char *str_ptr;
0507
0508 printk("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
0509 fps_ptr->spec_rev);
0510
0511
0512
0513
0514
0515 if (imps_bad_bios(fps_ptr)) {
0516 printk(" Disabling MPS support\n");
0517 return;
0518 }
0519
0520 if (fps_ptr->feature_info[1] & IMPS_FPS_IMCRP_BIT) {
0521 str_ptr = "IMCR and PIC";
0522 } else {
0523 str_ptr = "Virtual Wire";
0524 }
0525 if (fps_ptr->cth_ptr) {
0526 imps_lapic_addr = local_cth_ptr->lapic_addr;
0527 } else {
0528 imps_lapic_addr = LAPIC_ADDR_DEFAULT;
0529 }
0530 printk(" APIC config: \"%s mode\" Local APIC address: 0x%x\n",
0531 str_ptr, imps_lapic_addr);
0532 if (imps_lapic_addr != (READ_MSR_LO(0x1b) & 0xFFFFF000)) {
0533 printk("Inconsistent Local APIC address, Disabling SMP support\n");
0534 return;
0535 }
0536 imps_lapic_addr = PHYS_TO_VIRTUAL(imps_lapic_addr);
0537
0538
0539
0540
0541 apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
0542 IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
0543 apicid = APIC_ID(IMPS_LAPIC_READ(LAPIC_ID));
0544 imps_cpu_apic_map[0] = apicid;
0545 imps_apic_cpu_map[apicid] = 0;
0546
0547 if (fps_ptr->cth_ptr) {
0548 char str1[16], str2[16];
0549 memcpy(str1, local_cth_ptr->oem_id, 8);
0550 str1[8] = 0;
0551 memcpy(str2, local_cth_ptr->prod_id, 12);
0552 str2[12] = 0;
0553 printk(" OEM id: %s Product id: %s\n", str1, str2);
0554 cth_start = ((unsigned) local_cth_ptr) + sizeof(imps_cth);
0555 cth_count = local_cth_ptr->entry_count;
0556 } else {
0557 *((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_ID;
0558 defconfig.ioapic.id
0559 = APIC_ID(*((volatile unsigned *)
0560 (IOAPIC_ADDR_DEFAULT+IOAPIC_RW)));
0561 *((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_VER;
0562 defconfig.ioapic.ver
0563 = APIC_VERSION(*((volatile unsigned *)
0564 (IOAPIC_ADDR_DEFAULT+IOAPIC_RW)));
0565 defconfig.proc[apicid].flags
0566 = IMPS_FLAG_ENABLED|IMPS_CPUFLAG_BOOT;
0567 defconfig.proc[!apicid].flags = IMPS_FLAG_ENABLED;
0568 imps_num_cpus = 2;
0569 if (fps_ptr->feature_info[0] == 1
0570 || fps_ptr->feature_info[0] == 5) {
0571 memcpy(defconfig.bus[0].bus_type, "ISA ", 6);
0572 }
0573 if (fps_ptr->feature_info[0] == 4
0574 || fps_ptr->feature_info[0] == 7) {
0575 memcpy(defconfig.bus[0].bus_type, "MCA ", 6);
0576 }
0577 if (fps_ptr->feature_info[0] > 4) {
0578 defconfig.proc[0].apic_ver = 0x10;
0579 defconfig.proc[1].apic_ver = 0x10;
0580 defconfig.bus[1].type = IMPS_BCT_BUS;
0581 }
0582 if (fps_ptr->feature_info[0] == 2) {
0583 defconfig.intin[2].type = 255;
0584 defconfig.intin[13].type = 255;
0585 }
0586 if (fps_ptr->feature_info[0] == 7) {
0587 defconfig.intin[0].type = 255;
0588 }
0589 cth_start = (unsigned) &defconfig;
0590 cth_count = DEF_ENTRIES;
0591 }
0592 imps_read_config_table(cth_start, cth_count);
0593
0594
0595
0596 imps_enabled = 1;
0597 }
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613 static int
0614 imps_scan(unsigned start, unsigned length)
0615 {
0616 printk("Scanning from 0x%x for %d bytes\n", start, length);
0617
0618 while (length > 0) {
0619 imps_fps *fps_ptr = (imps_fps *) PHYS_TO_VIRTUAL(start);
0620
0621 if (fps_ptr->sig == IMPS_FPS_SIGNATURE
0622 && fps_ptr->length == 1
0623 && (fps_ptr->spec_rev == 1 || fps_ptr->spec_rev == 4)
0624 && !get_checksum(start, 16)) {
0625 printk("Found MP Floating Structure Pointer at %x\n", start);
0626 imps_read_bios(fps_ptr);
0627 return 1;
0628 }
0629
0630 length -= 16;
0631 start += 16;
0632 }
0633
0634 return 0;
0635 }
0636
0637 #if !defined(__rtems__)
0638
0639
0640
0641
0642 int
0643 imps_force(int ncpus)
0644 {
0645 int apicid, i;
0646 imps_processor p;
0647
0648 printk("Intel MultiProcessor \"Force\" Support\n");
0649
0650 imps_lapic_addr = (READ_MSR_LO(0x1b) & 0xFFFFF000);
0651 imps_lapic_addr = PHYS_TO_VIRTUAL(imps_lapic_addr);
0652
0653
0654
0655
0656 apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
0657 IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
0658 apicid = APIC_ID(IMPS_LAPIC_READ(LAPIC_ID));
0659 imps_cpu_apic_map[0] = apicid;
0660 imps_apic_cpu_map[apicid] = 0;
0661
0662 p.type = 0;
0663 p.apic_ver = 0x10;
0664 p.signature = p.features = 0;
0665
0666 for (i = 0; i < ncpus; i++) {
0667 if (apicid == i) {
0668 p.flags = IMPS_FLAG_ENABLED | IMPS_CPUFLAG_BOOT;
0669 } else {
0670 p.flags = IMPS_FLAG_ENABLED;
0671 }
0672 p.apic_id = i;
0673 add_processor(&p);
0674 }
0675
0676 return imps_num_cpus;
0677 }
0678 #endif
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708 int
0709 imps_probe(void)
0710 {
0711
0712
0713
0714 unsigned ebda_addr = *((unsigned short *)
0715 PHYS_TO_VIRTUAL(EBDA_SEG_ADDR)) << 4;
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 unsigned mem_lower = ((CMOS_READ_BYTE(CMOS_BASE_MEMORY+1) << 8)
0726 | CMOS_READ_BYTE(CMOS_BASE_MEMORY)) << 10;
0727
0728 #ifdef IMPS_DEBUG
0729 imps_enabled = 0;
0730 imps_num_cpus = 1;
0731 #endif
0732
0733
0734
0735
0736
0737 if (mem_lower < 512*1024 || mem_lower > 640*1024) {
0738 return 0;
0739 }
0740
0741 if (ebda_addr > mem_lower - 1024
0742 || ebda_addr + *((unsigned char *) PHYS_TO_VIRTUAL(ebda_addr))
0743 * 1024 > mem_lower) {
0744 ebda_addr = 0;
0745 }
0746
0747 if (((ebda_addr && imps_scan(ebda_addr, 1024))
0748 || (!ebda_addr && imps_scan(mem_lower - 1024, 1024))
0749 || imps_scan(0xF0000, 0x10000)) && imps_enabled) {
0750 return imps_num_cpus;
0751 }
0752
0753
0754
0755
0756
0757 return 0;
0758 }
0759
0760
0761
0762
0763 static void smp_apic_ack(void)
0764 {
0765 (void) IMPS_LAPIC_READ(LAPIC_SPIV);
0766 IMPS_LAPIC_WRITE(LAPIC_EOI, 0 );
0767 }
0768
0769 static void bsp_inter_processor_interrupt(void *arg)
0770 {
0771 (void) arg;
0772
0773 smp_apic_ack();
0774
0775
0776
0777
0778 __asm__ __volatile__("cli");
0779
0780 _SMP_Inter_processor_interrupt_handler(_Per_CPU_Get());
0781
0782
0783
0784
0785 __asm__ __volatile__("sti");
0786 }
0787
0788 void
0789 ipi_install_irq(void)
0790 {
0791 rtems_status_code status;
0792
0793 status = rtems_interrupt_handler_install(
0794 16,
0795 "smp-imps",
0796 RTEMS_INTERRUPT_UNIQUE,
0797 bsp_inter_processor_interrupt,
0798 NULL
0799 );
0800 assert(status == RTEMS_SUCCESSFUL);
0801 }
0802
0803 #ifdef __SSE__
0804 extern void enable_sse(void);
0805 #endif
0806
0807
0808 static void secondary_cpu_initialize(void)
0809 {
0810 int apicid;
0811
0812 asm volatile( "lidt IDT_Descriptor" );
0813
0814 apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
0815 IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
0816
0817 #ifdef __SSE__
0818 enable_sse();
0819 #endif
0820
0821 _SMP_Start_multitasking_on_secondary_processor( _Per_CPU_Get() );
0822 }