Changeset 01f2692e in rtems


Ignore:
Timestamp:
Aug 1, 2011, 1:41:50 PM (9 years ago)
Author:
Jennifer Averett <Jennifer.Averett@…>
Branches:
4.11, 5, master
Children:
dce1032b
Parents:
8a7ed82
Message:

2011-08-01 Jennifer Averett <Jennifer.Averett@…>

PR 1802

  • shared/irq/irq_asm.S, shared/irq/irq_init.c, shared/smp/smp-imps.c, shared/smp/smp-imps.h: Add SMP support for i386.
  • shared/smp/getcpuid.c: New file.
Location:
c/src/lib/libbsp/i386
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/ChangeLog

    r8a7ed82 r01f2692e  
     12011-08-01      Jennifer Averett <Jennifer.Averett@OARcorp.com>
     2
     3        PR 1802
     4        * shared/irq/irq_asm.S, shared/irq/irq_init.c, shared/smp/smp-imps.c,
     5        shared/smp/smp-imps.h: Add SMP support for i386.
     6        * shared/smp/getcpuid.c: New file.
     7
    182011-07-18      Joel Sherrill <joel.sherrill@oarcorp.com>
    29
  • c/src/lib/libbsp/i386/shared/irq/irq_asm.S

    r8a7ed82 r01f2692e  
    3333#define ESP_OFF 16       /* esp being on top of ebp!         */
    3434#ifdef __SSE__
    35 /* need to be on 16 byte boundary for SSE */
     35/* need to be on 16 byte boundary for SSE, add 12 to do that */
    3636#define FRM_SIZ (20+12+512)
    3737#define SSE_OFF 32
     
    4747         *  entry point did the following:
    4848         *
    49          *     1. saved scratch registers registers eax edx ecx"
     49         *     1. saved scratch registers registers eax edx ecx
    5050         *     2. put the vector number in ecx.
    51          *
    52          * BEGINNING OF ESTABLISH SEGMENTS
    53          *
    54          *  WARNING: If an interrupt can occur when the segments are
    55          *           not correct, then this is where we should establish
    56          *           the segments.  In addition to establishing the
    57          *           segments, it may be necessary to establish a stack
    58          *           in the current data area on the outermost interrupt.
    5951         *
    6052         *  NOTE:  If the previous values of the segment registers are
     
    10597#endif
    10698
     99.check_stack_switch:
     100        movl      esp, ebp                  /* ebp = previous stack pointer */
     101#if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
     102        movl     $SYM(_Per_CPU_Information_p), ebx
     103        call     SYM(bsp_smp_processor_id)
     104        mov      (ebx,eax,4), ebx
     105        pushl    ecx
     106        call     SYM(_ISR_SMP_Enter)
     107        popl     ecx
     108        cmpl     $0, eax
     109        jne      .i8259
     110        movl     PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
     111       
     112#else
     113        movl     $SYM(_Per_CPU_Information), ebx
     114
     115        /*
     116         *  Is this the outermost interrupt?
     117         *  Switch stacks if necessary
     118         */
     119        cmpl      $0, PER_CPU_ISR_NEST_LEVEL(ebx)
     120        jne       nested                    /* No, then continue */
     121        movl      PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
     122
     123        /*
     124         *  We want to insure that the old stack pointer is in ebp
     125         *  By saving it on every interrupt, all we have to do is
     126         *  movl ebp->esp near the end of every interrupt.
     127         */
     128
     129nested:
     130        incl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one nest level deeper */
     131        incl      SYM (_Thread_Dispatch_disable_level) /* disable multitasking */
     132#endif
     133        /*
     134         *  i8259 Management
     135         */
     136
     137.i8259:
    107138        /* Do not disable any 8259 interrupts if this isn't from one */
    108139        cmp       ecx, 16               /* is this a PIC IRQ? */
    109         jge       .check_stack_switch
     140        jge       .end_of_i8259
    110141
    111142        /*
     
    137168.master:
    138169        outb      $PIC_MASTER_COMMAND_IO_PORT
    139 
    140         /*
    141          *  Now switch stacks if necessary
    142          */
    143 
    144 PUBLIC (ISR_STOP)
    145 ISR_STOP:
    146 .check_stack_switch:
    147         movl      esp, ebp                  /* ebp = previous stack pointer */
    148 #if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
    149         movl     $SYM(_Per_CPU_Information_p), ebx
    150         call     SYM(bsp_smp_processor_id)
    151         mov      (ebx,eax,4), ebx
    152 #else
    153         movl     $SYM(_Per_CPU_Information), ebx
    154 #endif
    155 
    156         /* is this the outermost interrupt? */
    157         cmpl      $0, PER_CPU_ISR_NEST_LEVEL(ebx)
    158         jne       nested                    /* No, then continue */
    159         movl      PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
    160 
    161         /*
    162          *  We want to insure that the old stack pointer is in ebp
    163          *  By saving it on every interrupt, all we have to do is
    164          *  movl ebp->esp near the end of every interrupt.
    165          */
    166 
    167 nested:
    168         incl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one nest level deeper */
    169         incl      SYM (_Thread_Dispatch_disable_level) /* disable multitasking */
    170 
    171         /*
    172          * GCC versions starting with 4.3 no longer place the cld
    173          * instruction before string operations.  We  need to ensure
    174          * it is set correctly for ISR handlers.
    175          */
    176         cld
     170.end_of_i8259:
    177171
    178172        /*
     
    217211        movb      ah, al
    218212        outb      $PIC_SLAVE_IMR_IO_PORT
    219 
    220213.dont_restore_i8259:
     214
     215
     216#if defined(RTEMS_SMP) && defined(BSP_HAS_SMP)
     217        call    SYM(_ISR_SMP_Exit)
     218        testl   eax, eax
     219        je      .exit
     220#else
    221221        decl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one less ISR nest level */
    222222                                            /* If interrupts are nested, */
     
    232232        jne       .schedule                 /* Yes, then call the scheduler */
    233233        jmp       .exit                     /* No, exit */
     234#endif
    234235
    235236.schedule:
  • c/src/lib/libbsp/i386/shared/irq/irq_init.c

    r8a7ed82 r01f2692e  
    66 *  Copyright (c) 2009 embedded brains GmbH
    77 *  CopyRight (C) 1998 valette@crf.canon.fr
     8 *
     9 *  COPYRIGHT (c) 2011.
     10 *  On-Line Applications Research Corporation (OAR).
    811 *
    912 *  The license and distribution terms for this file may be
  • c/src/lib/libbsp/i386/shared/smp/smp-imps.c

    r8a7ed82 r01f2692e  
    4848
    4949/*
     50 *  Includes here
     51 */
     52#if 0
     53#define IMPS_DEBUG
     54#endif
     55
     56#include <bsp/apic.h>
     57#include <bsp/smp-imps.h>
     58
     59/*
    5060 *  XXXXX  The following absolutely must be defined!!!
    5161 *
     
    6474#define TEST_BOOTED(x)        /* test bootaddr x to see if CPU started */
    6575#define READ_MSR_LO(x)        /* Read MSR low function */
     76#else
     77#include <string.h>
     78#include <unistd.h>
     79#include <rtems.h>
     80#include <rtems/bspsmp.h>
     81#include <rtems/bspIo.h>
     82#include <libcpu/cpu.h>
     83
     84extern void _pc386_delay(void);
     85
     86/* #define KERNEL_PRINT(_format)       printk(_format) */
     87
     88static void CMOS_WRITE_BYTE(
     89  unsigned int  offset,
     90  unsigned char value
     91)
     92{
     93  if ( offset < 128 ) {
     94    outport_byte( 0x70, offset );
     95    outport_byte( 0x71, value );
     96  } else {
     97    outport_byte( 0x72, offset );
     98    outport_byte( 0x73, value );
     99  }
     100}
     101
     102static unsigned char CMOS_READ_BYTE(
     103  unsigned int  offset
     104)
     105{
     106  unsigned char value;
     107  if ( offset < 128 ) {
     108    outport_byte( 0x70, offset );
     109    inport_byte( 0x71, value );
     110  } else {
     111    outport_byte( 0x72, offset );
     112    inport_byte( 0x73, value );
     113  }
     114  return value;
     115}
     116
     117#define PHYS_TO_VIRTUAL(_x)    _x
     118#define VIRTUAL_TO_PHYS(_x)    _x
     119static void UDELAY(int x)
     120{ int _i = x;
     121  while ( _i-- )
     122    _pc386_delay();
     123}
     124 
     125#define READ_MSR_LO(_x) \
     126  (unsigned int)(read_msr(_x) & 0xffffffff)
     127
     128#define TEST_BOOTED(_cpu) \
     129  (_Per_CPU_Information[_cpu].state == RTEMS_BSP_SMP_CPU_INITIALIZED)
     130
     131static inline unsigned long long read_msr(unsigned int msr)
     132{
     133  unsigned long long value;
     134 
     135  asm volatile("rdmsr" : "=A" (value) : "c" (msr));
     136  return value;
     137}
    66138#endif
    67 
    68 /*
    69  *  Includes here
    70  */
    71 
    72 #define IMPS_DEBUG
    73 
    74 #include "apic.h"
    75 #include "smp-imps.h"
    76 
    77139
    78140/*
     
    93155#define DEF_ENTRIES  23
    94156
    95 static int lapic_dummy = 0;
    96157static struct {
    97158  imps_processor proc[2];
     
    133194int imps_enabled = 0;
    134195int imps_num_cpus = 1;
    135 unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
    136196unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
    137197unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
     198
     199/* now defined in getcpuid.c */
     200extern unsigned imps_lapic_addr;
    138201
    139202/*
     
    181244 *  that is required.
    182245 */
    183 static int
     246int
    184247boot_cpu(imps_processor *proc)
    185248{
    186   int apicid = proc->apic_id, success = 1, to;
     249  int apicid = proc->apic_id, success = 1;
    187250  unsigned bootaddr, accept_status;
    188251  unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
     
    196259   */
    197260
    198   extern char patch_code_start[];
    199   extern char patch_code_end[];
     261  uint32_t *reset;
     262
    200263  bootaddr = (512-64)*1024;
    201   memcpy((char *)bootaddr, patch_code_start, patch_code_end - patch_code_start);
     264  reset= (uint32_t *)bootaddr;
     265
     266  memcpy(
     267    (char *) bootaddr,
     268    _binary_appstart_bin_start,
     269    (size_t)_binary_appstart_bin_size
     270  );
     271
     272  reset[1] = (uint32_t)rtems_smp_secondary_cpu_initialize;
     273  reset[2] = (uint32_t)_Per_CPU_Information[apicid].interrupt_stack_high;
    202274
    203275  /*
     
    215287  /* assert INIT IPI */
    216288  send_ipi(
    217     apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT);
    218 
     289    apicid,
     290    LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
     291  );
    219292  UDELAY(10000);
    220293
     
    239312   *  Check to see if other processor has started.
    240313   */
    241   to = 0;
    242   while (!TEST_BOOTED(bootaddr) && to++ < 100)
    243     UDELAY(10000);
    244   if (to >= 100) {
    245     KERNEL_PRINT(("CPU Not Responding, DISABLED"));
     314  bsp_smp_wait_for(
     315    (volatile unsigned int *)&_Per_CPU_Information[imps_num_cpus].state,
     316    RTEMS_BSP_SMP_CPU_INITIALIZED,
     317    1600
     318  );
     319  if ( _Per_CPU_Information[imps_num_cpus].state ==
     320        RTEMS_BSP_SMP_CPU_INITIALIZED )
     321    printk("#%d  Application Processor (AP)", imps_num_cpus);
     322  else {
     323    printk("CPU Not Responding, DISABLED");
    246324    success = 0;
    247   } else {
    248     KERNEL_PRINT(("#%d  Application Processor (AP)", imps_num_cpus));
    249325  }
    250326
     
    261337  *((volatile unsigned *) bios_reset_vector) = 0;
    262338
    263   KERNEL_PRINT(("\n"));
     339  printk("\n");
    264340
    265341  return success;
     
    274350  int apicid = proc->apic_id;
    275351
    276   KERNEL_PRINT(("  Processor [APIC id %d ver %d]:  ",
    277           apicid, proc->apic_ver));
     352  printk("  Processor [APIC id %d ver %d]: ", apicid, proc->apic_ver);
    278353  if (!(proc->flags & IMPS_FLAG_ENABLED)) {
    279     KERNEL_PRINT(("DISABLED\n"));
     354    printk("DISABLED\n");
    280355    return;
    281356  }
    282357  if (proc->flags & (IMPS_CPUFLAG_BOOT)) {
    283     KERNEL_PRINT(("#0  BootStrap Processor (BSP)\n"));
     358    printk("#0  BootStrap Processor (BSP)\n");
    284359    return;
    285360  }
     
    302377  memcpy(str, bus->bus_type, 6);
    303378  str[6] = 0;
    304   KERNEL_PRINT(("  Bus id %d is %s\n", bus->id, str));
     379  printk("  Bus id %d is %s\n", bus->id, str);
    305380
    306381  /*  XXXXX  add OS-specific code here */
     
    310385add_ioapic(imps_ioapic *ioapic)
    311386{
    312   KERNEL_PRINT(("  I/O APIC id %d ver %d, address: 0x%x  ",
    313           ioapic->id, ioapic->ver, ioapic->addr));
     387  printk("  I/O APIC id %d ver %d, address: 0x%x  ",
     388          ioapic->id, ioapic->ver, ioapic->addr);
    314389  if (!(ioapic->flags & IMPS_FLAG_ENABLED)) {
    315     KERNEL_PRINT(("DISABLED\n"));
     390    printk("DISABLED\n");
    316391    return;
    317392  }
    318   KERNEL_PRINT(("\n"));
     393  printk("\n");
    319394
    320395  /*  XXXXX  add OS-specific code here */
     
    327402    switch (*((unsigned char *)start)) {
    328403    case IMPS_BCT_PROCESSOR:
    329       add_processor((imps_processor *)start);
     404      if ( imps_num_cpus < rtems_configuration_smp_maximum_processors ) {
     405        add_processor((imps_processor *)start);
     406      } else
     407        imps_num_cpus++;
    330408      start += 12;  /* 20 total */
    331409      break;
     
    351429    start += 8;
    352430  }
     431  if ( imps_num_cpus > rtems_configuration_smp_maximum_processors ) {
     432    printk(
     433      "WARNING!! Found more CPUs (%d) than configured for (%d)!!\n",
     434      imps_num_cpus - 1,
     435      rtems_configuration_smp_maximum_processors
     436    );
     437    imps_num_cpus = rtems_configuration_smp_maximum_processors;
     438    return;
     439  }
    353440}
    354441
     
    361448
    362449  if (fps_ptr->feature_info[0] > IMPS_FPS_DEFAULT_MAX) {
    363     KERNEL_PRINT(("    Invalid MP System Configuration type %d\n",
    364             fps_ptr->feature_info[0]));
     450    printk("    Invalid MP System Configuration type %d\n",
     451            fps_ptr->feature_info[0]);
    365452    return 1;
    366453  }
     
    370457                                   local_cth_ptr->base_length);
    371458    if (local_cth_ptr->sig != IMPS_CTH_SIGNATURE || sum) {
    372       KERNEL_PRINT(
    373         ("    Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",
     459      printk(
     460        "    Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",
    374461        (unsigned)(fps_ptr->cth_ptr),
    375         sum)
     462        sum
    376463      );
    377464      return 1;
    378465    }
    379466    if (local_cth_ptr->spec_rev != fps_ptr->spec_rev) {
    380       KERNEL_PRINT(
    381         ("    Bad MP Config Table sub-revision # %d\n",
    382         local_cth_ptr->spec_rev)
     467      printk(
     468        "    Bad MP Config Table sub-revision # %d\n",
     469        local_cth_ptr->spec_rev
    383470      );
    384471      return 1;
     
    390477             + local_cth_ptr->extended_checksum) & 0xFF;
    391478      if (sum) {
    392         KERNEL_PRINT(("    Bad Extended MP Config Table checksum 0x%x\n", sum));
     479        printk("    Bad Extended MP Config Table checksum 0x%x\n", sum);
    393480        return 1;
    394481      }
    395482    }
    396483  } else if (!fps_ptr->feature_info[0]) {
    397     KERNEL_PRINT(("    Missing configuration information\n"));
     484    printk("    Missing configuration information\n");
    398485    return 1;
    399486  }
     
    411498  char *str_ptr;
    412499
    413   KERNEL_PRINT(("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
    414           fps_ptr->spec_rev));
     500  printk("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
     501          fps_ptr->spec_rev);
    415502
    416503  /*
     
    419506   */
    420507  if (imps_bad_bios(fps_ptr)) {
    421     KERNEL_PRINT(("    Disabling MPS support\n"));
     508    printk("    Disabling MPS support\n");
    422509    return;
    423510  }
     
    433520    imps_lapic_addr = LAPIC_ADDR_DEFAULT;
    434521  }
    435   KERNEL_PRINT(("    APIC config: \"%s mode\"    Local APIC address: 0x%x\n",
    436           str_ptr, imps_lapic_addr));
     522  printk("    APIC config: \"%s mode\"    Local APIC address: 0x%x\n",
     523          str_ptr, imps_lapic_addr);
    437524  if (imps_lapic_addr != (READ_MSR_LO(0x1b) & 0xFFFFF000)) {
    438     KERNEL_PRINT(("Inconsistent Local APIC address, Disabling SMP support\n"));
     525    printk("Inconsistent Local APIC address, Disabling SMP support\n");
    439526    return;
    440527  }
     
    456543    memcpy(str2, local_cth_ptr->prod_id, 12);
    457544    str2[12] = 0;
    458     KERNEL_PRINT(("  OEM id: %s  Product id: %s\n", str1, str2));
     545    printk("  OEM id: %s  Product id: %s\n", str1, str2);
    459546    cth_start = ((unsigned) local_cth_ptr) + sizeof(imps_cth);
    460547    cth_count = local_cth_ptr->entry_count;
     
    519606imps_scan(unsigned start, unsigned length)
    520607{
    521   IMPS_DEBUG_PRINT(("Scanning from 0x%x for %d bytes\n",
    522         start, length));
     608  printk("Scanning from 0x%x for %d bytes\n", start, length);
    523609
    524610  while (length > 0) {
     
    529615     && (fps_ptr->spec_rev == 1 || fps_ptr->spec_rev == 4)
    530616     && !get_checksum(start, 16)) {
    531       IMPS_DEBUG_PRINT(("Found MP Floating Structure Pointer at %x\n", start));
     617      printk("Found MP Floating Structure Pointer at %x\n", start);
    532618      imps_read_bios(fps_ptr);
    533619      return 1;
     
    541627}
    542628
     629#if !defined(__rtems__)
    543630/*
    544631 *  This is the primary function to "force" SMP support, with
     
    551638  imps_processor p;
    552639
    553   KERNEL_PRINT(("Intel MultiProcessor \"Force\" Support\n"));
     640  printk("Intel MultiProcessor \"Force\" Support\n");
    554641
    555642  imps_lapic_addr = (READ_MSR_LO(0x1b) & 0xFFFFF000);
     
    581668  return imps_num_cpus;
    582669}
     670#endif
    583671
    584672/*
     
    662750}
    663751
     752/*
     753 *  RTEMS SMP BSP Support
     754 */
     755void smp_apic_ack(void)
     756{
     757  (void) IMPS_LAPIC_READ(LAPIC_SPIV);  /* dummy read */
     758  IMPS_LAPIC_WRITE(LAPIC_EOI, 0 );     /* ACK the interrupt */
     759}
     760
     761rtems_isr ap_ipi_isr(
     762  rtems_vector_number vector
     763)
     764{
     765  smp_apic_ack();
     766
     767  rtems_smp_process_interrupt();
     768}
     769
     770#include <rtems/irq.h>
     771
     772static rtems_irq_connect_data apIPIIrqData = {
     773  16,
     774  (void *)ap_ipi_isr,
     775  0,
     776  NULL,            /* On */
     777  NULL,            /* Off */
     778  NULL,            /* IsOn */
     779};
     780
     781extern void bsp_reset(void);
     782void ipi_install_irq(void)
     783{
     784  if (!BSP_install_rtems_irq_handler (&apIPIIrqData)) {
     785    printk("Unable to initialize IPI\n");
     786    bsp_reset();
     787  }
     788}
     789
     790#ifdef __SSE__
     791extern void enable_sse(void);
     792#endif
     793
     794/* pc386 specific initialization */
     795void bsp_smp_secondary_cpu_initialize(int cpu)
     796{
     797  int apicid;
     798
     799  asm volatile( "lidt IDT_Descriptor" );
     800
     801  apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
     802  IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
     803
     804#ifdef __SSE__
     805  enable_sse();
     806#endif
     807}
     808
     809#include <rtems/bspsmp.h>
     810int bsp_smp_initialize(
     811  int maximum
     812)
     813{
     814  int cores;
     815  /* XXX need to deal with finding too many cores */
     816
     817  cores = imps_probe();
     818
     819  if ( cores > 1 )
     820    ipi_install_irq();
     821  return cores;
     822}
     823
     824void bsp_smp_interrupt_cpu(
     825  int cpu
     826)
     827{
     828  send_ipi( cpu, 0x30 );
     829}
     830
     831void bsp_smp_broadcast_interrupt(void)
     832{
     833  /* Single broadcast interrupt */
     834  send_ipi( 0, LAPIC_ICR_DS_ALLEX | 0x30 );
     835}
     836
     837void bsp_smp_wait_for(
     838  volatile unsigned int *address,
     839  unsigned int           desired,
     840  int                    maximum_usecs
     841)
     842{
     843  int iterations;
     844  volatile int i;
     845  volatile unsigned int *p = (volatile unsigned int *)address;
     846
     847  for (iterations=0 ;  iterations < maximum_usecs ; iterations++ ) {
     848    if ( *p == desired )
     849      break;
     850    #ifdef __SSE3__
     851      __builtin_ia32_monitor( (const void *)address, 0, 0 );
     852      if ( *p == desired )
     853        break;
     854      __builtin_ia32_mwait( 0, 0 );
     855    #endif
     856
     857    /*
     858     *  Until i386 ms delay does not depend upon the clock we
     859     *  will use this less sophisticated delay.
     860     */
     861    for(i=5000; i>0; i--)
     862      ;
     863  }
     864}
  • c/src/lib/libbsp/i386/shared/smp/smp-imps.h

    r8a7ed82 r01f2692e  
    3636 *  document, order number 242016-004, which can be ordered from the
    3737 *  Intel literature center.
     38 */
     39
     40/*
     41 *  This file is based upon code by Eric Boleyn as documented above. 
     42 *  RTEMS support was added and minimal other changes were made. 
     43 *  This should make it easier to compare this file with the original
     44 *  version.
     45 *
     46 *  COPYRIGHT (c) 2011.
     47 *  On-Line Applications Research Corporation (OAR).
     48 *
     49 *  The license and distribution terms for this file may be
     50 *  found in the file LICENSE in this distribution or at
     51 *  http://www.rtems.com/license/LICENSE.
     52 *
     53 *  $Id$
    3854 */
    3955
     
    195211
    196212/*
    197  *  "imps_enabled" is non-zero if the probe sequence found IMPS
    198  *  information and was successful.
    199  */
    200 extern int imps_enabled;
    201 
    202 /*
    203  *  This contains the local APIC hardware address.
    204  */
    205 extern unsigned imps_lapic_addr;
    206 
    207 /*
    208  *  This represents the number of CPUs found.
    209  */
    210 extern int imps_num_cpus;
    211 
    212 /*
    213213 *  These map from virtual cpu numbers to APIC id's and back.
    214214 */
     
    216216extern unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
    217217
    218 /*
    219  *  This is the primary function for probing for Intel MPS 1.1/1.4
    220  *  compatible hardware and BIOS information.  While probing the CPUs
    221  *  information returned from the BIOS, this also starts up each CPU
    222  *  and gets it ready for use.
    223  *
    224  *  Call this during the early stages of OS startup, before memory can
    225  *  be messed up.
    226  *
    227  *  Returns N if IMPS information was found (for number of CPUs started)
    228  *  and is valid, else 0.
    229  */
    230 int imps_probe(void);
    231 
    232 /*
    233  *  This one is used as a "force" function.  Give it the number of CPUs
    234  *  to start, and it will assume a certain number and try it.
    235  */
    236 int imps_force(int ncpus);
    237 
     218/* base address of application processor reset code at 0x70000 */
     219extern char _binary_appstart_bin_start[];
     220extern char _binary_appstart_bin_size[];
    238221
    239222/*
Note: See TracChangeset for help on using the changeset viewer.