source: mainline/genarch/src/acpi/madt.c@ d9cf9d5f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d9cf9d5f was 0f27b4c, checked in by Jakub Jermar <jakub@…>, 20 years ago

Rename acpi/matd.c to madt.c (Multiple APIC Description Table).
Improve Doxygen comments in genarch/.

  • Property mode set to 100644
File size: 7.0 KB
RevLine 
[10a2e22]1/*
2 * Copyright (C) 2005 Jakub Jermar
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
[0f27b4c]29/**
30 * @file madt.c
31 * @brief Multiple APIC Description Table (MADT) parsing.
32 */
33
[ed0dd65]34#include <arch/types.h>
[232e3ec7]35#include <typedefs.h>
[e16e036a]36#include <genarch/acpi/acpi.h>
37#include <genarch/acpi/madt.h>
[ed0dd65]38#include <arch/smp/apic.h>
[232e3ec7]39#include <arch/smp/smp.h>
[6b7c36f]40#include <panic.h>
[232e3ec7]41#include <debug.h>
42#include <config.h>
[9c0a9b3]43#include <print.h>
[085d973]44#include <mm/slab.h>
[50a4e25]45#include <memstr.h>
[8491c48]46#include <sort.h>
[10a2e22]47
48struct acpi_madt *acpi_madt = NULL;
[ed0dd65]49
[5f85c91]50#ifdef CONFIG_SMP
[ed0dd65]51
[a83a802]52/** Standard ISA IRQ map; can be overriden by Interrupt Source Override entries of MADT. */
53int isa_irq_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
54
[50a4e25]55static void madt_l_apic_entry(struct madt_l_apic *la, __u32 index);
56static void madt_io_apic_entry(struct madt_io_apic *ioa, __u32 index);
[a83a802]57static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index);
[8491c48]58static int madt_cmp(void * a, void * b);
[6b7c36f]59
60struct madt_l_apic *madt_l_apic_entries = NULL;
61struct madt_io_apic *madt_io_apic_entries = NULL;
62
[74b2f5bf]63index_t madt_l_apic_entry_index = 0;
64index_t madt_io_apic_entry_index = 0;
65count_t madt_l_apic_entry_cnt = 0;
66count_t madt_io_apic_entry_cnt = 0;
67count_t cpu_count = 0;
[6b7c36f]68
[50a4e25]69struct madt_apic_header * * madt_entries_index = NULL;
70int madt_entries_index_cnt = 0;
71
[ed0dd65]72char *entry[] = {
73 "L_APIC",
74 "IO_APIC",
75 "INTR_SRC_OVRD",
76 "NMI_SRC",
77 "L_APIC_NMI",
78 "L_APIC_ADDR_OVRD",
79 "IO_SAPIC",
80 "L_SAPIC",
81 "PLATFORM_INTR_SRC"
82};
83
[232e3ec7]84/*
85 * ACPI MADT Implementation of SMP configuration interface.
86 */
87static count_t madt_cpu_count(void);
88static bool madt_cpu_enabled(index_t i);
89static bool madt_cpu_bootstrap(index_t i);
90static __u8 madt_cpu_apic_id(index_t i);
[a83a802]91static int madt_irq_to_pin(int irq);
[232e3ec7]92
93struct smp_config_operations madt_config_operations = {
94 .cpu_count = madt_cpu_count,
95 .cpu_enabled = madt_cpu_enabled,
96 .cpu_bootstrap = madt_cpu_bootstrap,
[a83a802]97 .cpu_apic_id = madt_cpu_apic_id,
98 .irq_to_pin = madt_irq_to_pin
[232e3ec7]99};
100
[a83a802]101count_t madt_cpu_count(void)
[232e3ec7]102{
103 return madt_l_apic_entry_cnt;
104}
105
[a83a802]106bool madt_cpu_enabled(index_t i)
[232e3ec7]107{
108 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]109 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
110
[232e3ec7]111}
112
[a83a802]113bool madt_cpu_bootstrap(index_t i)
[232e3ec7]114{
115 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]116 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id == l_apic_id();
[232e3ec7]117}
118
[a83a802]119__u8 madt_cpu_apic_id(index_t i)
[232e3ec7]120{
121 ASSERT(i < madt_l_apic_entry_cnt);
[50a4e25]122 return ((struct madt_l_apic *) madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
[232e3ec7]123}
124
[a83a802]125int madt_irq_to_pin(int irq)
126{
127 ASSERT(irq < sizeof(isa_irq_map)/sizeof(int));
128 return isa_irq_map[irq];
129}
130
[8491c48]131int madt_cmp(void * a, void * b)
132{
[01e48c1]133 return
134 (((struct madt_apic_header *) a)->type > ((struct madt_apic_header *) b)->type) ?
135 1 :
136 ((((struct madt_apic_header *) a)->type < ((struct madt_apic_header *) b)->type) ? -1 : 0);
[8491c48]137}
138
[ed0dd65]139void acpi_madt_parse(void)
140{
141 struct madt_apic_header *end = (struct madt_apic_header *) (((__u8 *) acpi_madt) + acpi_madt->header.length);
[50a4e25]142 struct madt_apic_header *h;
[2cd073bd]143
144 l_apic = (__u32 *) (__native) acpi_madt->l_apic_address;
[50a4e25]145
146 /* calculate madt entries */
147 for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((__u8 *) h) + h->length)) {
148 madt_entries_index_cnt++;
149 }
150
151 /* create madt apic entries index array */
[bb68433]152 madt_entries_index = (struct madt_apic_header * *) malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * *), FRAME_ATOMIC);
153 if (!madt_entries_index)
154 panic("Memory allocation error.");
[50a4e25]155
156 __u32 index = 0;
[6b7c36f]157
[50a4e25]158 for (h = &acpi_madt->apic_header[0]; h < end; h = (struct madt_apic_header *) (((__u8 *) h) + h->length)) {
159 madt_entries_index[index++] = h;
160 }
[ed0dd65]161
[8491c48]162 /* Quicksort MADT index structure */
163 qsort(madt_entries_index, madt_entries_index_cnt, sizeof(__address), &madt_cmp);
[50a4e25]164
165 /* Parse MADT entries */
166 for (index = 0; index < madt_entries_index_cnt - 1; index++) {
167 h = madt_entries_index[index];
[ed0dd65]168 switch (h->type) {
169 case MADT_L_APIC:
[50a4e25]170 madt_l_apic_entry((struct madt_l_apic *) h, index);
[6b7c36f]171 break;
[ed0dd65]172 case MADT_IO_APIC:
[50a4e25]173 madt_io_apic_entry((struct madt_io_apic *) h, index);
[6b7c36f]174 break;
[ed0dd65]175 case MADT_INTR_SRC_OVRD:
[a83a802]176 madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) h, index);
177 break;
[ed0dd65]178 case MADT_NMI_SRC:
179 case MADT_L_APIC_NMI:
180 case MADT_L_APIC_ADDR_OVRD:
181 case MADT_IO_SAPIC:
182 case MADT_L_SAPIC:
183 case MADT_PLATFORM_INTR_SRC:
[280a27e]184 printf("MADT: skipping %s entry (type=%zd)\n", entry[h->type], h->type);
[ed0dd65]185 break;
186
187 default:
188 if (h->type >= MADT_RESERVED_SKIP_BEGIN && h->type <= MADT_RESERVED_SKIP_END) {
[280a27e]189 printf("MADT: skipping reserved entry (type=%zd)\n", h->type);
[ed0dd65]190 }
191 if (h->type >= MADT_RESERVED_OEM_BEGIN) {
[280a27e]192 printf("MADT: skipping OEM entry (type=%zd)\n", h->type);
[ed0dd65]193 }
194 break;
195 }
[50a4e25]196
197
[ed0dd65]198 }
[50a4e25]199
[ed0dd65]200
[74b2f5bf]201 if (cpu_count)
202 config.cpu_count = cpu_count;
[ed0dd65]203}
[6b7c36f]204
205
[50a4e25]206void madt_l_apic_entry(struct madt_l_apic *la, __u32 index)
207{
208 if (!madt_l_apic_entry_cnt++) {
209 madt_l_apic_entry_index = index;
210 }
[6b7c36f]211
212 if (!(la->flags & 0x1)) {
213 /* Processor is unusable, skip it. */
214 return;
215 }
[74b2f5bf]216
217 cpu_count++;
[6b7c36f]218 apic_id_mask |= 1<<la->apic_id;
219}
220
[50a4e25]221void madt_io_apic_entry(struct madt_io_apic *ioa, __u32 index)
[6b7c36f]222{
223 if (!madt_io_apic_entry_cnt++) {
[50a4e25]224 /* remember index of the first io apic entry */
225 madt_io_apic_entry_index = index;
[ab08b42]226 io_apic = (__u32 *) (__native) ioa->io_apic_address;
[50a4e25]227 } else {
[6b7c36f]228 /* currently not supported */
229 return;
230 }
231}
232
[a83a802]233void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override, __u32 index)
234{
235 ASSERT(override->source < sizeof(isa_irq_map)/sizeof(int));
[280a27e]236 printf("MADT: ignoring %s entry: bus=%zd, source=%zd, global_int=%zd, flags=%#hX\n",
[9149135]237 entry[override->header.type], override->bus, override->source,
238 override->global_int, override->flags);
[a83a802]239}
[ed0dd65]240
[5f85c91]241#endif /* CONFIG_SMP */
Note: See TracBrowser for help on using the repository browser.