Changeset fe32163 in mainline for kernel/genarch/src/acpi/madt.c
- Timestamp:
- 2010-06-29T00:08:48Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c19aa612
- Parents:
- 9a21f9d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/acpi/madt.c
r9a21f9d rfe32163 27 27 */ 28 28 29 /** @addtogroup genarch 29 /** @addtogroup genarch 30 30 * @{ 31 31 */ 32 32 /** 33 33 * @file 34 * @brief 34 * @brief Multiple APIC Description Table (MADT) parsing. 35 35 */ 36 36 … … 52 52 #ifdef CONFIG_SMP 53 53 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 */ 58 static int isa_irq_map[] = 59 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 61 60 62 61 struct madt_l_apic *madt_l_apic_entries = NULL; 63 62 struct madt_io_apic *madt_io_apic_entries = NULL; 64 63 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; 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; 73 70 74 71 const char *entry[] = { … … 84 81 }; 85 82 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 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 * 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 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 l_apic_id(); 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 */ 95 126 struct smp_config_operations madt_config_operations = { 96 .cpu_count = madt_cpu_count,97 127 .cpu_enabled = madt_cpu_enabled, 98 128 .cpu_bootstrap = madt_cpu_bootstrap, … … 101 131 }; 102 132 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 133 static 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 147 static 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 213 152 if (!(la->flags & 0x1)) { 214 153 /* Processor is unusable, skip it. */ … … 216 155 } 217 156 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 160 static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i) 223 161 { 224 162 if (!madt_io_apic_entry_cnt++) { 225 /* remember index of the first io apic entry */226 madt_io_apic_entry_index = i ndex;163 /* Remember index of the first io apic entry */ 164 madt_io_apic_entry_index = i; 227 165 io_apic = (uint32_t *) (unative_t) ioa->io_apic_address; 228 166 } else { 229 /* currently not supported */ 230 return; 167 /* Currently not supported */ 231 168 } 232 169 } 233 170 234 void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index) 171 static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, 172 size_t i) 235 173 { 236 174 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 182 void 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; 240 252 } 241 253
Note:
See TracChangeset
for help on using the changeset viewer.