Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/acpi/madt.c

    rfe32163 rd99c1d2  
    2727 */
    2828
    29 /** @addtogroup genarch
     29/** @addtogroup genarch 
    3030 * @{
    3131 */
    3232/**
    3333 * @file
    34  * @brief Multiple APIC Description Table (MADT) parsing.
     34 * @brief       Multiple APIC Description Table (MADT) parsing.
    3535 */
    3636
     
    5252#ifdef CONFIG_SMP
    5353
    54 /**
    55  * Standard ISA IRQ map; can be overriden by
    56  * Interrupt Source Override entries of MADT.
    57  */
    58 static int isa_irq_map[] =
    59     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
     54/** Standard ISA IRQ map; can be overriden by Interrupt Source Override entries of MADT. */
     55int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
     56
     57static void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index);
     58static void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index);
     59static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index);
     60static int madt_cmp(void * a, void * b);
    6061
    6162struct madt_l_apic *madt_l_apic_entries = NULL;
    6263struct madt_io_apic *madt_io_apic_entries = NULL;
    6364
    64 static size_t madt_l_apic_entry_index = 0;
    65 static size_t madt_io_apic_entry_index = 0;
    66 static size_t madt_l_apic_entry_cnt = 0;
    67 static size_t madt_io_apic_entry_cnt = 0;
    68 
    69 static struct madt_apic_header **madt_entries_index = NULL;
     65size_t madt_l_apic_entry_index = 0;
     66size_t madt_io_apic_entry_index = 0;
     67size_t madt_l_apic_entry_cnt = 0;
     68size_t madt_io_apic_entry_cnt = 0;
     69size_t cpu_count = 0;
     70
     71struct madt_apic_header * * madt_entries_index = NULL;
     72unsigned int madt_entries_index_cnt = 0;
    7073
    7174const char *entry[] = {
     
    8184};
    8285
    83 static uint8_t madt_cpu_apic_id(size_t i)
    84 {
    85         ASSERT(i < madt_l_apic_entry_cnt);
    86        
    87         return ((struct madt_l_apic *)
    88             madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
    89 }
    90 
    91 static bool madt_cpu_enabled(size_t i)
    92 {
    93         ASSERT(i < madt_l_apic_entry_cnt);
    94        
    95         /*
    96          * FIXME: The current local APIC driver limits usable
    97          * APIC IDs to 8.
    98          *
    99          */
    100         if (madt_cpu_apic_id(i) > 7)
    101                 return false;
    102        
    103         return ((struct madt_l_apic *)
    104             madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
    105 }
    106 
    107 static bool madt_cpu_bootstrap(size_t i)
    108 {
    109         ASSERT(i < madt_l_apic_entry_cnt);
    110        
    111         return ((struct madt_l_apic *)
    112             madt_entries_index[madt_l_apic_entry_index + i])->apic_id ==
    113             l_apic_id();
    114 }
    115 
    116 static int madt_irq_to_pin(unsigned int irq)
    117 {
    118         ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
    119        
    120         return isa_irq_map[irq];
    121 }
    122 
    123 /** ACPI MADT Implementation of SMP configuration interface.
    124  *
    125  */
     86/*
     87 * ACPI MADT Implementation of SMP configuration interface.
     88 */
     89static size_t madt_cpu_count(void);
     90static bool madt_cpu_enabled(size_t i);
     91static bool madt_cpu_bootstrap(size_t i);
     92static uint8_t madt_cpu_apic_id(size_t i);
     93static int madt_irq_to_pin(unsigned int irq);
     94
    12695struct smp_config_operations madt_config_operations = {
     96        .cpu_count = madt_cpu_count,
    12797        .cpu_enabled = madt_cpu_enabled,
    12898        .cpu_bootstrap = madt_cpu_bootstrap,
     
    131101};
    132102
    133 static int madt_cmp(void *a, void *b)
    134 {
    135         uint8_t typea = ((struct madt_apic_header *) a)->type;
    136         uint8_t typeb = ((struct madt_apic_header *) b)->type;
    137        
    138         if (typea > typeb)
    139                 return 1;
    140        
    141         if (typea < typeb)
    142                 return -1;
    143        
    144         return 0;
    145 }
    146 
    147 static void madt_l_apic_entry(struct madt_l_apic *la, size_t i)
    148 {
    149         if (!madt_l_apic_entry_cnt++)
    150                 madt_l_apic_entry_index = i;
    151        
     103size_t madt_cpu_count(void)
     104{
     105        return madt_l_apic_entry_cnt;
     106}
     107
     108bool madt_cpu_enabled(size_t i)
     109{
     110        ASSERT(i < madt_l_apic_entry_cnt);
     111        return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
     112
     113}
     114
     115bool madt_cpu_bootstrap(size_t i)
     116{
     117        ASSERT(i < madt_l_apic_entry_cnt);
     118        return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
     119}
     120
     121uint8_t madt_cpu_apic_id(size_t i)
     122{
     123        ASSERT(i < madt_l_apic_entry_cnt);
     124        return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
     125}
     126
     127int madt_irq_to_pin(unsigned int irq)
     128{
     129        ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
     130        return isa_irq_map[irq];
     131}
     132
     133int madt_cmp(void * a, void * b)
     134{
     135        return
     136                (((struct madt_apic_header *) a)->type > ((struct madt_apic_header *) b)->type) ?
     137                1 :
     138                ((((struct madt_apic_header *) a)->type < ((struct madt_apic_header *) b)->type) ? -1 : 0);
     139}
     140       
     141void acpi_madt_parse(void)
     142{
     143        struct madt_apic_header *end = (struct madt_apic_header *) (((uint8_t *) acpi_madt) + acpi_madt->header.length);
     144        struct madt_apic_header *h;
     145       
     146        l_apic = (uint32_t *) (unative_t) acpi_madt->l_apic_address;
     147
     148        /* calculate madt entries */
     149        for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
     150                madt_entries_index_cnt++;
     151        }
     152
     153        /* create madt apic entries index array */
     154        madt_entries_index = (struct madt_apic_header * *) malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *), FRAME_ATOMIC);
     155        if (!madt_entries_index)
     156                panic("Memory allocation error.");
     157
     158        uint32_t index = 0;
     159
     160        for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
     161                madt_entries_index[index++] = h;
     162        }
     163
     164        /* Quicksort MADT index structure */
     165        qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t), &madt_cmp);
     166
     167        /* Parse MADT entries */
     168        if (madt_entries_index_cnt > 0) {       
     169                for (index = 0; index < madt_entries_index_cnt - 1; index++) {
     170                        h = madt_entries_index[index];
     171                        switch (h->type) {
     172                                case MADT_L_APIC:
     173                                        madt_l_apic_entry((struct madt_l_apic *) h, index);
     174                                        break;
     175                                case MADT_IO_APIC:
     176                                        madt_io_apic_entry((struct madt_io_apic *) h, index);
     177                                        break;
     178                                case MADT_INTR_SRC_OVRD:
     179                                        madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) h, index);
     180                                        break;
     181                                case MADT_NMI_SRC:
     182                                case MADT_L_APIC_NMI:
     183                                case MADT_L_APIC_ADDR_OVRD:
     184                                case MADT_IO_SAPIC:
     185                                case MADT_L_SAPIC:
     186                                case MADT_PLATFORM_INTR_SRC:
     187                                        printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type);
     188                                        break;
     189       
     190                                default:
     191                                        if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
     192                                                printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type);
     193                                        }
     194                                        if (h->type >= MADT_RESERVED_OEM_BEGIN) {
     195                                                printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type);
     196                                        }
     197                                        break;
     198                        }
     199                }
     200        }
     201
     202        if (cpu_count)
     203                config.cpu_count = cpu_count;
     204}
     205 
     206
     207void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index)
     208{
     209        if (!madt_l_apic_entry_cnt++) {
     210                madt_l_apic_entry_index = index;
     211        }
     212               
    152213        if (!(la->flags & 0x1)) {
    153214                /* Processor is unusable, skip it. */
     
    155216        }
    156217       
    157         apic_id_mask |= 1 << la->apic_id;
    158 }
    159 
    160 static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
     218        cpu_count++;   
     219        apic_id_mask |= 1<<la->apic_id;
     220}
     221
     222void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index)
    161223{
    162224        if (!madt_io_apic_entry_cnt++) {
    163                 /* Remember index of the first io apic entry */
    164                 madt_io_apic_entry_index = i;
     225                /* remember index of the first io apic entry */
     226                madt_io_apic_entry_index = index;
    165227                io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
    166228        } else {
    167                 /* Currently not supported */
    168         }
    169 }
    170 
    171 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
    172     size_t i)
     229                /* currently not supported */
     230                return;
     231        }
     232}
     233
     234void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
    173235{
    174236        ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
    175        
    176         printf("MADT: Ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8
    177             ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
    178             entry[override->header.type], override->bus, override->source,
    179             override->global_int, override->flags);
    180 }
    181 
    182 void acpi_madt_parse(void)
    183 {
    184         struct madt_apic_header *end = (struct madt_apic_header *)
    185             (((uint8_t *) acpi_madt) + acpi_madt->header.length);
    186         struct madt_apic_header *hdr;
    187        
    188         l_apic = (uint32_t *) (unative_t) acpi_madt->l_apic_address;
    189        
    190         /* Count MADT entries */
    191         unsigned int madt_entries_index_cnt = 0;
    192         for (hdr = &acpi_madt->apic_header[0]; hdr < end;
    193             hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
    194                 madt_entries_index_cnt++;
    195        
    196         /* Create MADT APIC entries index array */
    197         madt_entries_index = (struct madt_apic_header **)
    198             malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header **),
    199             FRAME_ATOMIC);
    200         if (!madt_entries_index)
    201                 panic("Memory allocation error.");
    202        
    203         size_t i = 0;
    204        
    205         for (hdr = &acpi_madt->apic_header[0]; hdr < end;
    206             hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
    207                 madt_entries_index[i++] = hdr;
    208        
    209         /* Sort MADT index structure */
    210         qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t),
    211             &madt_cmp);
    212        
    213         /* Parse MADT entries */
    214         for (i = 0; i < madt_entries_index_cnt; i++) {
    215                 hdr = madt_entries_index[i];
    216                
    217                 switch (hdr->type) {
    218                 case MADT_L_APIC:
    219                         madt_l_apic_entry((struct madt_l_apic *) hdr, i);
    220                         break;
    221                 case MADT_IO_APIC:
    222                         madt_io_apic_entry((struct madt_io_apic *) hdr, i);
    223                 break;
    224                 case MADT_INTR_SRC_OVRD:
    225                         madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) hdr, i);
    226                         break;
    227                 case MADT_NMI_SRC:
    228                 case MADT_L_APIC_NMI:
    229                 case MADT_L_APIC_ADDR_OVRD:
    230                 case MADT_IO_SAPIC:
    231                 case MADT_L_SAPIC:
    232                 case MADT_PLATFORM_INTR_SRC:
    233                         printf("MADT: Skipping %s entry (type=%" PRIu8 ")\n",
    234                             entry[hdr->type], hdr->type);
    235                         break;
    236                 default:
    237                         if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN)
    238                             && (hdr->type <= MADT_RESERVED_SKIP_END))
    239                                 printf("MADT: Skipping reserved entry (type=%" PRIu8 ")\n",
    240                                     hdr->type);
    241                                
    242                         if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
    243                                 printf("MADT: Skipping OEM entry (type=%" PRIu8 ")\n",
    244                                     hdr->type);
    245                        
    246                         break;
    247                 }
    248         }
    249        
    250         if (madt_l_apic_entry_cnt > 0)
    251                 config.cpu_count = madt_l_apic_entry_cnt;
     237        printf("MADT: ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8 ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
     238                entry[override->header.type], override->bus, override->source,
     239                override->global_int, override->flags);
    252240}
    253241
Note: See TracChangeset for help on using the changeset viewer.