madt.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00037 #include <arch/types.h>
00038 #include <typedefs.h>
00039 #include <genarch/acpi/acpi.h>
00040 #include <genarch/acpi/madt.h>
00041 #include <arch/smp/apic.h>
00042 #include <arch/smp/smp.h>
00043 #include <panic.h>
00044 #include <debug.h>
00045 #include <config.h>
00046 #include <print.h>
00047 #include <mm/slab.h>
00048 #include <memstr.h>
00049 #include <sort.h>
00050 
00051 struct acpi_madt *acpi_madt = NULL;
00052 
00053 #ifdef CONFIG_SMP
00054 
00056 int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
00057 
00058 static void madt_l_apic_entry(struct madt_l_apic *la, __u32 index);
00059 static void madt_io_apic_entry(struct madt_io_apic *ioa, __u32 index);
00060 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index);
00061 static int madt_cmp(void * a, void * b);
00062 
00063 struct madt_l_apic *madt_l_apic_entries = NULL;
00064 struct madt_io_apic *madt_io_apic_entries = NULL;
00065 
00066 index_t madt_l_apic_entry_index = 0;
00067 index_t madt_io_apic_entry_index = 0;
00068 count_t madt_l_apic_entry_cnt = 0;
00069 count_t madt_io_apic_entry_cnt = 0;
00070 count_t cpu_count = 0;
00071 
00072 struct madt_apic_header * * madt_entries_index = NULL;
00073 int madt_entries_index_cnt = 0;
00074 
00075 char *entry[] = {
00076         "L_APIC",
00077         "IO_APIC",
00078         "INTR_SRC_OVRD",
00079         "NMI_SRC",
00080         "L_APIC_NMI",
00081         "L_APIC_ADDR_OVRD",
00082         "IO_SAPIC",
00083         "L_SAPIC",
00084         "PLATFORM_INTR_SRC"
00085 };
00086 
00087 /*
00088  * ACPI MADT Implementation of SMP configuration interface.
00089  */
00090 static count_t madt_cpu_count(void);
00091 static bool madt_cpu_enabled(index_t i);
00092 static bool madt_cpu_bootstrap(index_t i);
00093 static __u8 madt_cpu_apic_id(index_t i);
00094 static int madt_irq_to_pin(int irq);
00095 
00096 struct smp_config_operations madt_config_operations = {
00097         .cpu_count = madt_cpu_count,
00098         .cpu_enabled = madt_cpu_enabled,
00099         .cpu_bootstrap = madt_cpu_bootstrap,
00100         .cpu_apic_id = madt_cpu_apic_id,
00101         .irq_to_pin = madt_irq_to_pin
00102 };
00103 
00104 count_t madt_cpu_count(void)
00105 {
00106         return madt_l_apic_entry_cnt;
00107 }
00108 
00109 bool madt_cpu_enabled(index_t i)
00110 {
00111         ASSERT(i < madt_l_apic_entry_cnt);
00112         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
00113 
00114 }
00115 
00116 bool madt_cpu_bootstrap(index_t i)
00117 {
00118         ASSERT(i < madt_l_apic_entry_cnt);
00119         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
00120 }
00121 
00122 __u8 madt_cpu_apic_id(index_t i)
00123 {
00124         ASSERT(i < madt_l_apic_entry_cnt);
00125         return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
00126 }
00127 
00128 int madt_irq_to_pin(int irq)
00129 {
00130         ASSERT(irq < sizeof(isa_irq_map)/sizeof(int));
00131         return isa_irq_map[irq];
00132 }
00133 
00134 int madt_cmp(void * a, void * b) 
00135 {
00136         return 
00137                 (((struct madt_apic_header *) a)->type > ((struct madt_apic_header *) b)->type) ?
00138                 1 : 
00139                 ((((struct madt_apic_header *) a)->type < ((struct madt_apic_header *) b)->type) ? -1 : 0);
00140 }
00141         
00142 void acpi_madt_parse(void)
00143 {
00144         struct madt_apic_header *end = (struct madt_apic_header *) (((__u8 *) acpi_madt) + acpi_madt->header.length);
00145         struct madt_apic_header *h;
00146         
00147         l_apic = (__u32 *) (__native) acpi_madt->l_apic_address;
00148 
00149         /* calculate madt entries */
00150         for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((__u8 *) h) + h->length)) {
00151                 madt_entries_index_cnt++;
00152         }
00153 
00154         /* create madt apic entries index array */
00155         madt_entries_index = (struct madt_apic_header * *) malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *), FRAME_ATOMIC);
00156         if (!madt_entries_index)
00157                 panic("Memory allocation error.");
00158 
00159         __u32 index = 0;
00160 
00161         for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((__u8 *) h) + h->length)) {
00162                 madt_entries_index[index++] = h;
00163         }
00164 
00165         /* Quicksort MADT index structure */
00166         qsort(madt_entries_index, madt_entries_index_cnt, sizeof(__address), &madt_cmp);
00167 
00168         /* Parse MADT entries */        
00169         for (index = 0; index < madt_entries_index_cnt - 1; index++) {
00170                 h = madt_entries_index[index];
00171                 switch (h->type) {
00172                         case MADT_L_APIC:
00173                                 madt_l_apic_entry((struct madt_l_apic *) h, index);
00174                                 break;
00175                         case MADT_IO_APIC:
00176                                 madt_io_apic_entry((struct madt_io_apic *) h, index);
00177                                 break;
00178                         case MADT_INTR_SRC_OVRD:
00179                                 madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) h, index);
00180                                 break;
00181                         case MADT_NMI_SRC:
00182                         case MADT_L_APIC_NMI:
00183                         case MADT_L_APIC_ADDR_OVRD:
00184                         case MADT_IO_SAPIC:
00185                         case MADT_L_SAPIC:
00186                         case MADT_PLATFORM_INTR_SRC:
00187                                 printf("MADT: skipping %s entry (type=%zd)\n", entry[h->type], h->type);
00188                                 break;
00189 
00190                         default:
00191                                 if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
00192                                         printf("MADT: skipping reserved entry (type=%zd)\n", h->type);
00193                                 }
00194                                 if (h->type >= MADT_RESERVED_OEM_BEGIN) {
00195                                         printf("MADT: skipping OEM entry (type=%zd)\n", h->type);
00196                                 }
00197                                 break;
00198                 }
00199         
00200         
00201         }
00202         
00203 
00204         if (cpu_count)
00205                 config.cpu_count = cpu_count;
00206 }
00207  
00208 
00209 void madt_l_apic_entry(struct madt_l_apic *la, __u32 index)
00210 {
00211         if (!madt_l_apic_entry_cnt++) {
00212                 madt_l_apic_entry_index = index;
00213         }
00214                 
00215         if (!(la->flags & 0x1)) {
00216                 /* Processor is unusable, skip it. */
00217                 return;
00218         }
00219         
00220         cpu_count++;    
00221         apic_id_mask |= 1<<la->apic_id;
00222 }
00223 
00224 void madt_io_apic_entry(struct madt_io_apic *ioa, __u32 index)
00225 {
00226         if (!madt_io_apic_entry_cnt++) {
00227                 /* remember index of the first io apic entry */
00228                 madt_io_apic_entry_index = index;
00229                 io_apic = (__u32 *) (__native) ioa->io_apic_address;
00230         } else {
00231                 /* currently not supported */
00232                 return;
00233         }
00234 }
00235 
00236 void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index)
00237 {
00238         ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int));
00239         printf("MADT: ignoring %s entry: bus=%zd, source=%zd, global_int=%zd, flags=%#hx\n",
00240                 entry[override->header.type], override->bus, override->source,
00241                 override->global_int, override->flags);
00242 }
00243 
00244 #endif /* CONFIG_SMP */
00245 

Generated on Sun Jun 18 16:38:50 2006 for HelenOS Kernel (ia32) by  doxygen 1.4.6