Ignore:
File:
1 edited

Legend:

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

    r96b02eb9 r98000fb  
    2727 */
    2828
    29 /** @addtogroup genarch
     29/** @addtogroup genarch 
    3030 * @{
    3131 */
    3232/**
    3333 * @file
    34  * @brief Multiple APIC Description Table (MADT) parsing.
    35  */
    36 
    37 #include <typedefs.h>
     34 * @brief       Multiple APIC Description Table (MADT) parsing.
     35 */
     36
     37#include <arch/types.h>
    3838#include <genarch/acpi/acpi.h>
    3939#include <genarch/acpi/madt.h>
     
    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;
    70 
    71 const char *entry[] = {
     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;
     73
     74char *entry[] = {
    7275        "L_APIC",
    7376        "IO_APIC",
     
    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          * CPU IDs to 8.
    98          *
    99          */
    100         if (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             bsp_l_apic;
    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, void *arg)
    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 == 0)
    150                 madt_l_apic_entry_index = i;
    151        
    152         madt_l_apic_entry_cnt++;
    153        
     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               
    154213        if (!(la->flags & 0x1)) {
    155214                /* Processor is unusable, skip it. */
     
    157216        }
    158217       
    159         apic_id_mask |= 1 << la->apic_id;
    160 }
    161 
    162 static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
    163 {
    164         if (madt_io_apic_entry_cnt == 0) {
    165                 /* Remember index of the first io apic entry */
    166                 madt_io_apic_entry_index = i;
    167                 io_apic = (uint32_t *) (sysarg_t) ioa->io_apic_address;
     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)
     223{
     224        if (!madt_io_apic_entry_cnt++) {
     225                /* remember index of the first io apic entry */
     226                madt_io_apic_entry_index = index;
     227                io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
    168228        } else {
    169                 /* Currently not supported */
    170         }
    171        
    172         madt_io_apic_entry_cnt++;
    173 }
    174 
    175 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
    176     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)
    177235{
    178236        ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
    179        
    180         printf("MADT: Ignoring %s entry: bus=%" PRIu8 ", source=%" PRIu8
    181             ", global_int=%" PRIu32 ", flags=%#" PRIx16 "\n",
    182             entry[override->header.type], override->bus, override->source,
    183             override->global_int, override->flags);
    184 }
    185 
    186 void acpi_madt_parse(void)
    187 {
    188         struct madt_apic_header *end = (struct madt_apic_header *)
    189             (((uint8_t *) acpi_madt) + acpi_madt->header.length);
    190         struct madt_apic_header *hdr;
    191        
    192         l_apic = (uint32_t *) (sysarg_t) acpi_madt->l_apic_address;
    193        
    194         /* Count MADT entries */
    195         unsigned int madt_entries_index_cnt = 0;
    196         for (hdr = acpi_madt->apic_header; hdr < end;
    197             hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
    198                 madt_entries_index_cnt++;
    199        
    200         /* Create MADT APIC entries index array */
    201         madt_entries_index = (struct madt_apic_header **)
    202             malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header *),
    203             FRAME_ATOMIC);
    204         if (!madt_entries_index)
    205                 panic("Memory allocation error.");
    206        
    207         size_t i = 0;
    208        
    209         for (hdr = acpi_madt->apic_header; hdr < end;
    210             hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) {
    211                 madt_entries_index[i] = hdr;
    212                 i++;
    213         }
    214        
    215         /* Sort MADT index structure */
    216         if (!gsort(madt_entries_index, madt_entries_index_cnt,
    217             sizeof(struct madt_apic_header *), madt_cmp, NULL))
    218                 panic("Sorting error.");
    219        
    220         /* Parse MADT entries */
    221         for (i = 0; i < madt_entries_index_cnt; i++) {
    222                 hdr = madt_entries_index[i];
    223                
    224                 switch (hdr->type) {
    225                 case MADT_L_APIC:
    226                         madt_l_apic_entry((struct madt_l_apic *) hdr, i);
    227                         break;
    228                 case MADT_IO_APIC:
    229                         madt_io_apic_entry((struct madt_io_apic *) hdr, i);
    230                 break;
    231                 case MADT_INTR_SRC_OVRD:
    232                         madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) hdr, i);
    233                         break;
    234                 case MADT_NMI_SRC:
    235                 case MADT_L_APIC_NMI:
    236                 case MADT_L_APIC_ADDR_OVRD:
    237                 case MADT_IO_SAPIC:
    238                 case MADT_L_SAPIC:
    239                 case MADT_PLATFORM_INTR_SRC:
    240                         printf("MADT: Skipping %s entry (type=%" PRIu8 ")\n",
    241                             entry[hdr->type], hdr->type);
    242                         break;
    243                 default:
    244                         if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN)
    245                             && (hdr->type <= MADT_RESERVED_SKIP_END))
    246                                 printf("MADT: Skipping reserved entry (type=%" PRIu8 ")\n",
    247                                     hdr->type);
    248                                
    249                         if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
    250                                 printf("MADT: Skipping OEM entry (type=%" PRIu8 ")\n",
    251                                     hdr->type);
    252                        
    253                         break;
    254                 }
    255         }
    256        
    257         if (madt_l_apic_entry_cnt > 0)
    258                 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);
    259240}
    260241
Note: See TracChangeset for help on using the changeset viewer.