Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/smp/mps.c

    r0a79ad9 rd99c1d2  
    2727 */
    2828
    29 /** @addtogroup ia32
     29/** @addtogroup ia32   
    3030 * @{
    3131 */
     
    5252 */
    5353
    54 #define FS_SIGNATURE  0x5f504d5f
    55 #define CT_SIGNATURE  0x504d4350
     54#define FS_SIGNATURE    0x5f504d5f
     55#define CT_SIGNATURE    0x504d4350
     56
     57static int mps_fs_check(uint8_t *base);
     58static int mps_ct_check(void);
     59
     60static int configure_via_ct(void);
     61static int configure_via_default(uint8_t n);
     62
     63static int ct_processor_entry(struct __processor_entry *pr);
     64static void ct_bus_entry(struct __bus_entry *bus);
     65static void ct_io_apic_entry(struct __io_apic_entry *ioa);
     66static void ct_io_intr_entry(struct __io_intr_entry *iointr);
     67static void ct_l_intr_entry(struct __l_intr_entry *lintr);
     68
     69static void ct_extended_entries(void);
    5670
    5771static struct mps_fs *fs;
    5872static struct mps_ct *ct;
    5973
    60 static struct __processor_entry *processor_entries = NULL;
    61 static struct __bus_entry *bus_entries = NULL;
    62 static struct __io_apic_entry *io_apic_entries = NULL;
    63 static struct __io_intr_entry *io_intr_entries = NULL;
    64 static struct __l_intr_entry *l_intr_entries = NULL;
    65 
    66 static size_t io_apic_cnt = 0;
    67 
    68 static size_t processor_entry_cnt = 0;
    69 static size_t bus_entry_cnt = 0;
    70 static size_t io_apic_entry_cnt = 0;
    71 static size_t io_intr_entry_cnt = 0;
    72 static size_t l_intr_entry_cnt = 0;
    73 
    74 static uint8_t mps_cpu_apic_id(size_t i)
    75 {
    76         ASSERT(i < processor_entry_cnt);
    77        
    78         return processor_entries[i].l_apic_id;
    79 }
    80 
    81 static bool mps_cpu_enabled(size_t i)
    82 {
    83         ASSERT(i < processor_entry_cnt);
    84        
    85         /*
    86          * FIXME: The current local APIC driver limits usable
    87          * CPU IDs to 8.
    88          *
    89          */
    90         if (i > 7)
    91                 return false;
    92        
    93         return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
    94 }
    95 
    96 static bool mps_cpu_bootstrap(size_t i)
    97 {
    98         ASSERT(i < processor_entry_cnt);
    99        
    100         return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
    101 }
    102 
    103 static int mps_irq_to_pin(unsigned int irq)
    104 {
    105         size_t i;
    106        
    107         for (i = 0; i < io_intr_entry_cnt; i++) {
    108                 if (io_intr_entries[i].src_bus_irq == irq &&
    109                     io_intr_entries[i].intr_type == 0)
    110                         return io_intr_entries[i].dst_io_apic_pin;
    111         }
    112        
    113         return -1;
    114 }
    115 
    116 /** Implementation of IA-32 SMP configuration interface.
    117  *
    118  */
     74struct __processor_entry *processor_entries = NULL;
     75struct __bus_entry *bus_entries = NULL;
     76struct __io_apic_entry *io_apic_entries = NULL;
     77struct __io_intr_entry *io_intr_entries = NULL;
     78struct __l_intr_entry *l_intr_entries = NULL;
     79
     80unsigned int processor_entry_cnt = 0;
     81unsigned int bus_entry_cnt = 0;
     82unsigned int io_apic_entry_cnt = 0;
     83unsigned int io_intr_entry_cnt = 0;
     84unsigned int l_intr_entry_cnt = 0;
     85
     86/*
     87 * Implementation of IA-32 SMP configuration interface.
     88 */
     89static size_t get_cpu_count(void);
     90static bool is_cpu_enabled(size_t i);
     91static bool is_bsp(size_t i);
     92static uint8_t get_cpu_apic_id(size_t i);
     93static int mps_irq_to_pin(unsigned int irq);
     94
    11995struct smp_config_operations mps_config_operations = {
    120         .cpu_enabled = mps_cpu_enabled,
    121         .cpu_bootstrap = mps_cpu_bootstrap,
    122         .cpu_apic_id = mps_cpu_apic_id,
     96        .cpu_count = get_cpu_count,
     97        .cpu_enabled = is_cpu_enabled,
     98        .cpu_bootstrap = is_bsp,
     99        .cpu_apic_id = get_cpu_apic_id,
    123100        .irq_to_pin = mps_irq_to_pin
    124101};
    125102
    126 /** Check the integrity of the MP Floating Structure.
    127  *
    128  */
    129 static bool mps_fs_check(uint8_t *base)
     103size_t get_cpu_count(void)
     104{
     105        return processor_entry_cnt;
     106}
     107
     108bool is_cpu_enabled(size_t i)
     109{
     110        ASSERT(i < processor_entry_cnt);
     111        return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01);
     112}
     113
     114bool is_bsp(size_t i)
     115{
     116        ASSERT(i < processor_entry_cnt);
     117        return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02);
     118}
     119
     120uint8_t get_cpu_apic_id(size_t i)
     121{
     122        ASSERT(i < processor_entry_cnt);
     123        return processor_entries[i].l_apic_id;
     124}
     125
     126
     127/*
     128 * Used to check the integrity of the MP Floating Structure.
     129 */
     130int mps_fs_check(uint8_t *base)
    130131{
    131132        unsigned int i;
     
    135136                sum = (uint8_t) (sum + base[i]);
    136137       
    137         return (sum == 0);
    138 }
    139 
    140 /** Check the integrity of the MP Configuration Table.
    141  *
    142  */
    143 static bool mps_ct_check(void)
     138        return !sum;
     139}
     140
     141/*
     142 * Used to check the integrity of the MP Configuration Table.
     143 */
     144int mps_ct_check(void)
    144145{
    145146        uint8_t *base = (uint8_t *) ct;
    146147        uint8_t *ext = base + ct->base_table_length;
    147148        uint8_t sum;
    148         uint16_t i;
    149        
    150         /* Compute the checksum for the base table */
    151         for (i = 0, sum = 0; i < ct->base_table_length; i++)
     149        int i; 
     150       
     151        /* count the checksum for the base table */
     152        for (i = 0,sum = 0; i < ct->base_table_length; i++)
    152153                sum = (uint8_t) (sum + base[i]);
    153        
     154               
    154155        if (sum)
    155                 return false;
    156        
    157         /* Compute the checksum for the extended table */
     156                return 0;
     157               
     158        /* count the checksum for the extended table */
    158159        for (i = 0, sum = 0; i < ct->ext_table_length; i++)
    159160                sum = (uint8_t) (sum + ext[i]);
    160        
    161         return (sum == ct->ext_table_checksum);
    162 }
    163 
    164 static void ct_processor_entry(struct __processor_entry *pr)
    165 {
     161               
     162        return sum == ct->ext_table_checksum;
     163}
     164
     165void mps_init(void)
     166{
     167        uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) };
     168        unsigned int i, j, length[2] = { 1024, 64 * 1024 };
     169       
     170
    166171        /*
    167          * Ignore processors which are not marked enabled.
     172         * Find MP Floating Pointer Structure
     173         * 1a. search first 1K of EBDA
     174         * 1b. if EBDA is undefined, search last 1K of base memory
     175         *  2. search 64K starting at 0xf0000
    168176         */
    169         if ((pr->cpu_flags & (1 << 0)) == 0)
    170                 return;
    171        
    172         apic_id_mask |= (1 << pr->l_apic_id);
    173 }
    174 
    175 static void ct_bus_entry(struct __bus_entry *bus __attribute__((unused)))
    176 {
    177 #ifdef MPSCT_VERBOSE
    178         char buf[7];
    179        
    180         memcpy((void *) buf, (void *) bus->bus_type, 6);
    181         buf[6] = 0;
    182        
    183         printf("MPS: bus=%" PRIu8 " (%s)\n", bus->bus_id, buf);
    184 #endif
    185 }
    186 
    187 static void ct_io_apic_entry(struct __io_apic_entry *ioa)
    188 {
    189         /* This I/O APIC is marked unusable */
    190         if ((ioa->io_apic_flags & 1) == 0)
    191                 return;
    192        
    193         if (io_apic_cnt++ > 0) {
    194                 /*
    195                  * Multiple I/O APICs are currently not supported.
    196                  */
    197                 return;
    198         }
    199        
    200         io_apic = (uint32_t *) (uintptr_t) ioa->io_apic;
    201 }
    202 
    203 static void ct_io_intr_entry(struct __io_intr_entry *iointr
    204     __attribute__((unused)))
    205 {
    206 #ifdef MPSCT_VERBOSE
    207         printf("MPS: ");
    208        
    209         switch (iointr->intr_type) {
    210         case 0:
    211                 printf("INT");
    212                 break;
    213         case 1:
    214                 printf("NMI");
    215                 break;
    216         case 2:
    217                 printf("SMI");
    218                 break;
    219         case 3:
    220                 printf("ExtINT");
    221                 break;
    222         }
    223        
    224         printf(", ");
    225        
    226         switch (iointr->poel & 3) {
    227         case 0:
    228                 printf("bus-like");
    229                 break;
    230         case 1:
    231                 printf("active high");
    232                 break;
    233         case 2:
    234                 printf("reserved");
    235                 break;
    236         case 3:
    237                 printf("active low");
    238                 break;
    239         }
    240        
    241         printf(", ");
    242        
    243         switch ((iointr->poel >> 2) & 3) {
    244         case 0:
    245                 printf("bus-like");
    246                 break;
    247         case 1:
    248                 printf("edge-triggered");
    249                 break;
    250         case 2:
    251                 printf("reserved");
    252                 break;
    253         case 3:
    254                 printf("level-triggered");
    255                 break;
    256         }
    257        
    258         printf(", bus=%" PRIu8 " irq=%" PRIu8 " io_apic=%" PRIu8" pin=%"
    259             PRIu8 "\n", iointr->src_bus_id, iointr->src_bus_irq,
    260             iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
    261 #endif
    262 }
    263 
    264 static void ct_l_intr_entry(struct __l_intr_entry *lintr
    265     __attribute__((unused)))
    266 {
    267 #ifdef MPSCT_VERBOSE
    268         printf("MPS: ");
    269        
    270         switch (lintr->intr_type) {
    271         case 0:
    272                 printf("INT");
    273                 break;
    274         case 1:
    275                 printf("NMI");
    276                 break;
    277         case 2:
    278                 printf("SMI");
    279                 break;
    280         case 3:
    281                 printf("ExtINT");
    282                 break;
    283         }
    284        
    285         printf(", ");
    286        
    287         switch (lintr->poel & 3) {
    288         case 0:
    289                 printf("bus-like");
    290                 break;
    291         case 1:
    292                 printf("active high");
    293                 break;
    294         case 2:
    295                 printf("reserved");
    296                 break;
    297         case 3:
    298                 printf("active low");
    299                 break;
    300         }
    301        
    302         printf(", ");
    303        
    304         switch ((lintr->poel >> 2) & 3) {
    305         case 0:
    306                 printf("bus-like");
    307                 break;
    308         case 1:
    309                 printf("edge-triggered");
    310                 break;
    311         case 2:
    312                 printf("reserved");
    313                 break;
    314         case 3:
    315                 printf("level-triggered");
    316                 break;
    317         }
    318        
    319         printf(", bus=%" PRIu8 " irq=%" PRIu8 " l_apic=%" PRIu8" pin=%"
    320             PRIu8 "\n", lintr->src_bus_id, lintr->src_bus_irq,
    321             lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
    322 #endif
    323 }
    324 
    325 static void ct_extended_entries(void)
    326 {
    327         uint8_t *ext = (uint8_t *) ct + ct->base_table_length;
     177
     178        addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024);
     179        for (i = 0; i < 2; i++) {
     180                for (j = 0; j < length[i]; j += 16) {
     181                        if (*((uint32_t *) &addr[i][j]) ==
     182                            FS_SIGNATURE && mps_fs_check(&addr[i][j])) {
     183                                fs = (struct mps_fs *) &addr[i][j];
     184                                goto fs_found;
     185                        }
     186                }
     187        }
     188
     189        return;
     190       
     191fs_found:
     192        printf("%p: MPS Floating Pointer Structure\n", fs);
     193
     194        if (fs->config_type == 0 && fs->configuration_table) {
     195                if (fs->mpfib2 >> 7) {
     196                        printf("%s: PIC mode not supported\n", __func__);
     197                        return;
     198                }
     199
     200                ct = (struct mps_ct *)PA2KA((uintptr_t)fs->configuration_table);
     201                config.cpu_count = configure_via_ct();
     202        }
     203        else
     204                config.cpu_count = configure_via_default(fs->config_type);
     205
     206        return;
     207}
     208
     209int configure_via_ct(void)
     210{
    328211        uint8_t *cur;
    329        
    330         for (cur = ext; cur < ext + ct->ext_table_length;
    331             cur += cur[CT_EXT_ENTRY_LEN]) {
    332                 switch (cur[CT_EXT_ENTRY_TYPE]) {
    333                 default:
    334                         printf("MPS: Skipping MP Configuration Table extended "
    335                             "entry type %" PRIu8 "\n", cur[CT_EXT_ENTRY_TYPE]);
    336                 }
    337         }
    338 }
    339 
    340 static void configure_via_ct(void)
    341 {
     212        unsigned int i, cnt;
     213               
    342214        if (ct->signature != CT_SIGNATURE) {
    343                 printf("MPS: Wrong ct->signature\n");
    344                 return;
    345         }
    346        
     215                printf("%s: bad ct->signature\n", __func__);
     216                return 1;
     217        }
    347218        if (!mps_ct_check()) {
    348                 printf("MPS: Wrong ct checksum\n");
    349                 return;
    350         }
    351        
     219                printf("%s: bad ct checksum\n", __func__);
     220                return 1;
     221        }
    352222        if (ct->oem_table) {
    353                 printf("MPS: ct->oem_table not supported\n");
    354                 return;
    355         }
    356        
    357         l_apic = (uint32_t *) (uintptr_t) ct->l_apic;
    358        
    359         uint8_t *cur = &ct->base_table[0];
    360         uint16_t i;
    361        
     223                printf("%s: ct->oem_table not supported\n", __func__);
     224                return 1;
     225        }
     226       
     227        l_apic = (uint32_t *)(uintptr_t)ct->l_apic;
     228
     229        cnt = 0;
     230        cur = &ct->base_table[0];
    362231        for (i = 0; i < ct->entry_count; i++) {
    363232                switch (*cur) {
    364                 case 0:  /* Processor entry */
     233                /* Processor entry */
     234                case 0:
    365235                        processor_entries = processor_entries ?
    366236                            processor_entries :
    367237                            (struct __processor_entry *) cur;
    368238                        processor_entry_cnt++;
    369                         ct_processor_entry((struct __processor_entry *) cur);
     239                        cnt += ct_processor_entry((struct __processor_entry *)
     240                            cur);
    370241                        cur += 20;
    371242                        break;
    372                 case 1:  /* Bus entry */
     243
     244                /* Bus entry */
     245                case 1:
    373246                        bus_entries = bus_entries ?
    374247                            bus_entries : (struct __bus_entry *) cur;
     
    377250                        cur += 8;
    378251                        break;
    379                 case 2:  /* I/O APIC */
     252                               
     253                /* I/O Apic */
     254                case 2:
    380255                        io_apic_entries = io_apic_entries ?
    381256                            io_apic_entries : (struct __io_apic_entry *) cur;
    382                         io_apic_entry_cnt++;
     257                                io_apic_entry_cnt++;
    383258                        ct_io_apic_entry((struct __io_apic_entry *) cur);
    384259                        cur += 8;
    385260                        break;
    386                 case 3:  /* I/O Interrupt Assignment */
     261                               
     262                /* I/O Interrupt Assignment */
     263                case 3:
    387264                        io_intr_entries = io_intr_entries ?
    388265                            io_intr_entries : (struct __io_intr_entry *) cur;
     
    391268                        cur += 8;
    392269                        break;
    393                 case 4:  /* Local Interrupt Assignment */
     270
     271                /* Local Interrupt Assignment */
     272                case 4:
    394273                        l_intr_entries = l_intr_entries ?
    395274                            l_intr_entries : (struct __l_intr_entry *) cur;
     
    398277                        cur += 8;
    399278                        break;
     279
    400280                default:
    401281                        /*
    402282                         * Something is wrong. Fallback to UP mode.
    403283                         */
    404                         printf("MPS: ct badness %" PRIu8 "\n", *cur);
    405                         return;
     284
     285                        printf("%s: ct badness\n", __func__);
     286                        return 1;
    406287                }
    407288        }
     
    411292         */
    412293        ct_extended_entries();
    413 }
    414 
    415 static void configure_via_default(uint8_t n __attribute__((unused)))
     294        return cnt;
     295}
     296
     297int configure_via_default(uint8_t n __attribute__((unused)))
    416298{
    417299        /*
    418300         * Not yet implemented.
    419301         */
    420         printf("MPS: Default configuration not supported\n");
    421 }
    422 
    423 void mps_init(void)
    424 {
    425         uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) };
     302        printf("%s: not supported\n", __func__);
     303        return 1;
     304}
     305
     306
     307int ct_processor_entry(struct __processor_entry *pr __attribute__((unused)))
     308{
     309        /*
     310         * Ignore processors which are not marked enabled.
     311         */
     312        if ((pr->cpu_flags & (1 << 0)) == 0)
     313                return 0;
     314       
     315        apic_id_mask |= (1 << pr->l_apic_id);
     316        return 1;
     317}
     318
     319void ct_bus_entry(struct __bus_entry *bus __attribute__((unused)))
     320{
     321#ifdef MPSCT_VERBOSE
     322        char buf[7];
     323        memcpy((void *) buf, (void *) bus->bus_type, 6);
     324        buf[6] = 0;
     325        printf("bus%d: %s\n", bus->bus_id, buf);
     326#endif
     327}
     328
     329void ct_io_apic_entry(struct __io_apic_entry *ioa)
     330{
     331        static unsigned int io_apic_count = 0;
     332
     333        /* this ioapic is marked unusable */
     334        if ((ioa->io_apic_flags & 1) == 0)
     335                return;
     336       
     337        if (io_apic_count++ > 0) {
     338                /*
     339                 * Multiple IO APIC's are currently not supported.
     340                 */
     341                return;
     342        }
     343       
     344        io_apic = (uint32_t *)(uintptr_t)ioa->io_apic;
     345}
     346
     347//#define MPSCT_VERBOSE
     348void ct_io_intr_entry(struct __io_intr_entry *iointr __attribute__((unused)))
     349{
     350#ifdef MPSCT_VERBOSE
     351        switch (iointr->intr_type) {
     352        case 0:
     353                printf("INT");
     354                break;
     355        case 1:
     356                printf("NMI");
     357                break;
     358        case 2:
     359                printf("SMI");
     360                break;
     361        case 3:
     362                printf("ExtINT");
     363                break;
     364        }
     365        putchar(',');
     366        switch (iointr->poel & 3) {
     367        case 0:
     368                printf("bus-like");
     369                break;
     370        case 1:
     371                printf("active high");
     372                break;
     373        case 2:
     374                printf("reserved");
     375                break;
     376        case 3:
     377                printf("active low");
     378                break;
     379        }
     380        putchar(',');
     381        switch ((iointr->poel >> 2) & 3) {
     382        case 0:
     383                printf("bus-like");
     384                break;
     385        case 1:
     386                printf("edge-triggered");
     387                break;
     388        case 2:
     389                printf("reserved");
     390                break;
     391        case 3:
     392                printf("level-triggered");
     393                break;
     394        }
     395        putchar(',');
     396        printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
     397        putchar(',');
     398        printf("io_apic%d,pin%d", iointr->dst_io_apic_id,
     399            iointr->dst_io_apic_pin);
     400        putchar('\n'); 
     401#endif
     402}
     403
     404void ct_l_intr_entry(struct __l_intr_entry *lintr __attribute__((unused)))
     405{
     406#ifdef MPSCT_VERBOSE
     407        switch (lintr->intr_type) {
     408        case 0:
     409            printf("INT");
     410            break;
     411        case 1:
     412            printf("NMI");
     413            break;
     414        case 2:
     415            printf("SMI");
     416            break;
     417        case 3:
     418            printf("ExtINT");
     419            break;
     420        }
     421        putchar(',');
     422        switch (lintr->poel & 3) {
     423        case 0:
     424            printf("bus-like");
     425            break;
     426        case 1:
     427            printf("active high");
     428            break;
     429        case 2:
     430            printf("reserved");
     431            break;
     432        case 3:
     433            printf("active low");
     434            break;
     435        }
     436        putchar(',');
     437        switch ((lintr->poel >> 2) & 3) {
     438        case 0:
     439            printf("bus-like");
     440            break;
     441        case 1:
     442            printf("edge-triggered");
     443            break;
     444        case 2:
     445            printf("reserved");
     446            break;
     447        case 3:
     448            printf("level-triggered");
     449            break;
     450        }
     451        putchar(',');
     452        printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
     453        putchar(',');
     454        printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
     455        putchar('\n');
     456#endif
     457}
     458
     459void ct_extended_entries(void)
     460{
     461        uint8_t *ext = (uint8_t *) ct + ct->base_table_length;
     462        uint8_t *cur;
     463
     464        for (cur = ext; cur < ext + ct->ext_table_length;
     465            cur += cur[CT_EXT_ENTRY_LEN]) {
     466                switch (cur[CT_EXT_ENTRY_TYPE]) {
     467                default:
     468                        printf("%p: skipping MP Configuration Table extended "
     469                            "entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]);
     470                        break;
     471                }
     472        }
     473}
     474
     475int mps_irq_to_pin(unsigned int irq)
     476{
    426477        unsigned int i;
    427         unsigned int j;
    428         unsigned int length[2] = { 1024, 64 * 1024 };
    429        
    430         /*
    431          * Find MP Floating Pointer Structure
    432          *  1a. search first 1K of EBDA
    433          *  1b. if EBDA is undefined, search last 1K of base memory
    434          *  2.  search 64K starting at 0xf0000
    435          */
    436        
    437         addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024);
    438         for (i = 0; i < 2; i++) {
    439                 for (j = 0; j < length[i]; j += 16) {
    440                         if ((*((uint32_t *) &addr[i][j]) ==
    441                             FS_SIGNATURE) && (mps_fs_check(&addr[i][j]))) {
    442                                 fs = (struct mps_fs *) &addr[i][j];
    443                                 goto fs_found;
    444                         }
    445                 }
    446         }
    447        
    448         return;
    449        
    450 fs_found:
    451         printf("%p: MPS Floating Pointer Structure\n", fs);
    452        
    453         if ((fs->config_type == 0) && (fs->configuration_table)) {
    454                 if (fs->mpfib2 >> 7) {
    455                         printf("MPS: PIC mode not supported\n");
    456                         return;
    457                 }
    458                
    459                 ct = (struct mps_ct *) PA2KA((uintptr_t) fs->configuration_table);
    460                 configure_via_ct();
    461         } else
    462                 configure_via_default(fs->config_type);
    463        
    464         if (processor_entry_cnt > 0)
    465                 config.cpu_count = processor_entry_cnt;
     478       
     479        for (i = 0; i < io_intr_entry_cnt; i++) {
     480                if (io_intr_entries[i].src_bus_irq == irq &&
     481                    io_intr_entries[i].intr_type == 0)
     482                        return io_intr_entries[i].dst_io_apic_pin;
     483        }
     484       
     485        return -1;
    466486}
    467487
Note: See TracChangeset for help on using the changeset viewer.