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


Ignore:
Timestamp:
2010-07-12T10:53:30Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bd11d3e
Parents:
c40e6ef (diff), bee2d4c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rc40e6ef rbd48f4c  
    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         * 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
     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            bsp_l_apic;
     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, 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
     147static 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       
    213154        if (!(la->flags & 0x1)) {
    214155                /* Processor is unusable, skip it. */
     
    216157        }
    217158       
    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)
    223 {
    224         if (!madt_io_apic_entry_cnt++) {
    225                 /* remember index of the first io apic entry */
    226                 madt_io_apic_entry_index = index;
     159        apic_id_mask |= 1 << la->apic_id;
     160}
     161
     162static 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;
    227167                io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
    228168        } else {
    229                 /* currently not supported */
    230                 return;
    231         }
    232 }
    233 
    234 void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
     169                /* Currently not supported */
     170        }
     171       
     172        madt_io_apic_entry_cnt++;
     173}
     174
     175static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
     176    size_t i)
    235177{
    236178        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);
     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
     186void 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 *) (unative_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;
    240259}
    241260
Note: See TracChangeset for help on using the changeset viewer.