source: mainline/kernel/genarch/src/acpi/madt.c@ 08a19ba

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 08a19ba was f4c2b6a, checked in by Martin Decky <martin@…>, 17 years ago

reflect changes in generic code
proper formatting directives
coding style

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[10a2e22]1/*
[df4ed85]2 * Copyright (c) 2005 Jakub Jermar
[10a2e22]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[06e1e95]29/** @addtogroup genarch
[b45c443]30 * @{
31 */
[0f27b4c]32/**
[7257021e]33 * @file
[0f27b4c]34 * @brief Multiple APIC Description Table (MADT) parsing.
35 */
36
[ed0dd65]37#include <arch/types.h>
[e16e036a]38#include <genarch/acpi/acpi.h>
39#include <genarch/acpi/madt.h>
[ed0dd65]40#include <arch/smp/apic.h>
[232e3ec7]41#include <arch/smp/smp.h>
[6b7c36f]42#include <panic.h>
[232e3ec7]43#include <debug.h>
44#include <config.h>
[9c0a9b3]45#include <print.h>
[085d973]46#include <mm/slab.h>
[50a4e25]47#include <memstr.h>
[8491c48]48#include <sort.h>
[10a2e22]49
50struct acpi_madt *acpi_madt = NULL;
[ed0dd65]51
[5f85c91]52#ifdef CONFIG_SMP
[ed0dd65]53
[a83a802]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
[7f1c620]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);
[8491c48]60static int madt_cmp(void * a, void * b);
[6b7c36f]61
62struct madt_l_apic *madt_l_apic_entries = NULL;
63struct madt_io_apic *madt_io_apic_entries = NULL;
64
[74b2f5bf]65index_t madt_l_apic_entry_index = 0;
66index_t madt_io_apic_entry_index = 0;
67count_t madt_l_apic_entry_cnt = 0;
68count_t madt_io_apic_entry_cnt = 0;
69count_t cpu_count = 0;
[6b7c36f]70
[50a4e25]71struct madt_apic_header * * madt_entries_index = NULL;
[623b49f1]72unsigned int madt_entries_index_cnt = 0;
[50a4e25]73
[ed0dd65]74char *entry[] = {
75 "L_APIC",
76 "IO_APIC",
77 "INTR_SRC_OVRD",
78 "NMI_SRC",
79 "L_APIC_NMI",
80 "L_APIC_ADDR_OVRD",
81 "IO_SAPIC",
82 "L_SAPIC",
83 "PLATFORM_INTR_SRC"
84};
85
[232e3ec7]86/*
87 * ACPI MADT Implementation of SMP configuration interface.
88 */
89static count_t madt_cpu_count(void);
90static bool madt_cpu_enabled(index_t i);
91static bool madt_cpu_bootstrap(index_t i);
[7f1c620]92static uint8_t madt_cpu_apic_id(index_t i);
[623b49f1]93static int madt_irq_to_pin(unsigned int irq);
[232e3ec7]94
95struct smp_config_operations madt_config_operations = {
96 .cpu_count = madt_cpu_count,
97 .cpu_enabled = madt_cpu_enabled,
98 .cpu_bootstrap = madt_cpu_bootstrap,
[a83a802]99 .cpu_apic_id = madt_cpu_apic_id,
100 .irq_to_pin = madt_irq_to_pin
[232e3ec7]101};
102
[a83a802]103count_t madt_cpu_count(void)
[232e3ec7]104{
105 return madt_l_apic_entry_cnt;
106}
107
[a83a802]108bool madt_cpu_enabled(index_t i)
[232e3ec7]109{
110 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]111 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
112
[232e3ec7]113}
114
[a83a802]115bool madt_cpu_bootstrap(index_t i)
[232e3ec7]116{
117 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]118 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
[232e3ec7]119}
120
[7f1c620]121uint8_t madt_cpu_apic_id(index_t i)
[232e3ec7]122{
123 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]124 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
[232e3ec7]125}
126
[623b49f1]127int madt_irq_to_pin(unsigned int irq)
[a83a802]128{
[f4c2b6a]129 ASSERT(irq < sizeof(isa_irq_map) / sizeof(int));
[a83a802]130 return isa_irq_map[irq];
131}
132
[8491c48]133int madt_cmp(void * a, void * b)
134{
[01e48c1]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);
[8491c48]139}
140
[ed0dd65]141void acpi_madt_parse(void)
142{
[7f1c620]143 struct madt_apic_header *end = (struct madt_apic_header *) (((uint8_t *) acpi_madt) + acpi_madt->header.length);
[50a4e25]144 struct madt_apic_header *h;
[2cd073bd]145
[623b49f1]146 l_apic = (uint32_t *) (unative_t) acpi_madt->l_apic_address;
[50a4e25]147
148 /* calculate madt entries */
[7f1c620]149 for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
[50a4e25]150 madt_entries_index_cnt++;
151 }
152
153 /* create madt apic entries index array */
[bb68433]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.");
[50a4e25]157
[7f1c620]158 uint32_t index = 0;
[6b7c36f]159
[7f1c620]160 for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((uint8_t *) h) + h->length)) {
[50a4e25]161 madt_entries_index[index++] = h;
162 }
[ed0dd65]163
[8491c48]164 /* Quicksort MADT index structure */
[7f1c620]165 qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t), &madt_cmp);
[50a4e25]166
[623b49f1]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:
[f4c2b6a]187 printf("MADT: skipping %s entry (type=%" PRIu8 ")\n", entry[h->type], h->type);
[623b49f1]188 break;
[50a4e25]189
[623b49f1]190 default:
191 if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
[f4c2b6a]192 printf("MADT: skipping reserved entry (type=%" PRIu8 ")\n", h->type);
[623b49f1]193 }
194 if (h->type >= MADT_RESERVED_OEM_BEGIN) {
[f4c2b6a]195 printf("MADT: skipping OEM entry (type=%" PRIu8 ")\n", h->type);
[623b49f1]196 }
197 break;
198 }
199 }
[ed0dd65]200 }
201
[74b2f5bf]202 if (cpu_count)
203 config.cpu_count = cpu_count;
[ed0dd65]204}
[6b7c36f]205
206
[7f1c620]207void madt_l_apic_entry(struct madt_l_apic *la, uint32_t index)
[50a4e25]208{
209 if (!madt_l_apic_entry_cnt++) {
210 madt_l_apic_entry_index = index;
211 }
[6b7c36f]212
213 if (!(la->flags & 0x1)) {
214 /* Processor is unusable, skip it. */
215 return;
216 }
[74b2f5bf]217
218 cpu_count++;
[6b7c36f]219 apic_id_mask |= 1<<la->apic_id;
220}
221
[7f1c620]222void madt_io_apic_entry(struct madt_io_apic *ioa, uint32_t index)
[6b7c36f]223{
224 if (!madt_io_apic_entry_cnt++) {
[50a4e25]225 /* remember index of the first io apic entry */
226 madt_io_apic_entry_index = index;
[7f1c620]227 io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
[50a4e25]228 } else {
[6b7c36f]229 /* currently not supported */
230 return;
231 }
232}
233
[7f1c620]234void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, uint32_t index)
[a83a802]235{
[f4c2b6a]236 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",
[9149135]238 entry[override->header.type], override->bus, override->source,
239 override->global_int, override->flags);
[a83a802]240}
[ed0dd65]241
[5f85c91]242#endif /* CONFIG_SMP */
[b45c443]243
[06e1e95]244/** @}
[b45c443]245 */
Note: See TracBrowser for help on using the repository browser.