Changeset fe32163 in mainline for kernel/genarch/src/acpi/madt.c


Ignore:
Timestamp:
2010-06-29T00:08:48Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c19aa612
Parents:
9a21f9d
Message:

improve support for inactive CPUs
major revision of MADT and MPS parsing code
limit the number of active CPUs on ia32 and amd64 to 8 (actually the APIC ID of all active CPUs must be in the range 0 .. 7 to avoid tripping on an assertion in APIC code)
fix off-by-one bug in MADT parsing code (missing the last entry)

File:
1 edited

Legend:

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

    r9a21f9d rfe32163  
    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 /** Standard ISA IRQ map; can be overriden by Interrupt Source Override entries of MADT. */
    55 int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    56 
    57 static void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index);
    58 static void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index);
    59 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index);
    60 static int madt_cmp(void * a, void * b);
     54/**
     55 * Standard ISA IRQ map; can be overriden by
     56 * Interrupt Source Override entries of MADT.
     57 */
     58static int isa_irq_map[] =
     59    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    6160
    6261struct madt_l_apic *madt_l_apic_entries = NULL;
    6362struct madt_io_apic *madt_io_apic_entries = NULL;
    6463
    65 size_t madt_l_apic_entry_index = 0;
    66 size_t madt_io_apic_entry_index = 0;
    67 size_t madt_l_apic_entry_cnt = 0;
    68 size_t madt_io_apic_entry_cnt = 0;
    69 size_t cpu_count = 0;
    70 
    71 struct madt_apic_header * * madt_entries_index = NULL;
    72 unsigned int madt_entries_index_cnt = 0;
     64static size_t madt_l_apic_entry_index = 0;
     65static size_t madt_io_apic_entry_index = 0;
     66static size_t madt_l_apic_entry_cnt = 0;
     67static size_t madt_io_apic_entry_cnt = 0;
     68
     69static struct madt_apic_header **madt_entries_index = NULL;
    7370
    7471const char *entry[] = {
     
    8481};
    8582
    86 /*
    87  * ACPI MADT Implementation of SMP configuration interface.
    88  */
    89 static size_t madt_cpu_count(void);
    90 static bool madt_cpu_enabled(size_t i);
    91 static bool madt_cpu_bootstrap(size_t i);
    92 static uint8_t madt_cpu_apic_id(size_t i);
    93 static int madt_irq_to_pin(unsigned int irq);
    94 
     83static 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
     91static 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
     107static 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
     116static 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 */
    95126struct smp_config_operations madt_config_operations = {
    96         .cpu_count = madt_cpu_count,
    97127        .cpu_enabled = madt_cpu_enabled,
    98128        .cpu_bootstrap = madt_cpu_bootstrap,
     
    101131};
    102132
    103 size_t madt_cpu_count(void)
    104 {
    105         return madt_l_apic_entry_cnt;
    106 }
    107 
    108 bool 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 
    115 bool 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 
    121 uint8_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 
    127 int 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 
    133 int 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        
    141 void 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 
    207 void 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                
     133static 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
     147static 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       
    213152        if (!(la->flags & 0x1)) {
    214153                /* Processor is unusable, skip it. */
     
    216155        }
    217156       
    218         cpu_count++;   
    219         apic_id_mask |= 1<<la->apic_id;
    220 }
    221 
    222 void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index)
     157        apic_id_mask |= 1 << la->apic_id;
     158}
     159
     160static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
    223161{
    224162        if (!madt_io_apic_entry_cnt++) {
    225                 /* remember index of the first io apic entry */
    226                 madt_io_apic_entry_index = index;
     163                /* Remember index of the first io apic entry */
     164                madt_io_apic_entry_index = i;
    227165                io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
    228166        } else {
    229                 /* currently not supported */
    230                 return;
     167                /* Currently not supported */
    231168        }
    232169}
    233170
    234 void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
     171static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
     172    size_t i)
    235173{
    236174        ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
    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);
     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
     182void 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;
    240252}
    241253
Note: See TracChangeset for help on using the changeset viewer.