00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
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
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
00166 qsort(madt_entries_index, madt_entries_index_cnt, sizeof(__address), &madt_cmp);
00167
00168
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
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
00228 madt_io_apic_entry_index = index;
00229 io_apic = (__u32 *) (__native) ioa->io_apic_address;
00230 } else {
00231
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
00245