source: mainline/kernel/genarch/src/acpi/madt.c@ 4edd57fd

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

the limit in the APIC driver is on CPU ids, not APIC ids
(however, I believe that there is still some unfortunate change of even a deeper confusion somewhere ..)

  • Property mode set to 100644
File size: 6.8 KB
Line 
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
29/** @addtogroup genarch
30 * @{
31 */
32/**
33 * @file
34 * @brief Multiple APIC Description Table (MADT) parsing.
35 */
36
37#include <typedefs.h>
38#include <genarch/acpi/acpi.h>
39#include <genarch/acpi/madt.h>
40#include <arch/smp/apic.h>
41#include <arch/smp/smp.h>
42#include <panic.h>
43#include <debug.h>
44#include <config.h>
45#include <print.h>
46#include <mm/slab.h>
47#include <memstr.h>
48#include <sort.h>
49
50struct acpi_madt *acpi_madt = NULL;
51
52#ifdef CONFIG_SMP
53
54/**
55 * Standard ISA IRQ map; can be overriden by
56 * Interrupt Source Override entries of MADT.
57 */
58static int isa_irq_map[] =
59 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
60
61struct madt_l_apic *madt_l_apic_entries = NULL;
62struct madt_io_apic *madt_io_apic_entries = NULL;
63
64static size_t madt_l_apic_entry_index = 0;
65static size_t madt_io_apic_entry_index = 0;
66static size_t madt_l_apic_entry_cnt = 0;
67static size_t madt_io_apic_entry_cnt = 0;
68
69static struct madt_apic_header **madt_entries_index = NULL;
70
71const char *entry[] = {
72 "L_APIC",
73 "IO_APIC",
74 "INTR_SRC_OVRD",
75 "NMI_SRC",
76 "L_APIC_NMI",
77 "L_APIC_ADDR_OVRD",
78 "IO_SAPIC",
79 "L_SAPIC",
80 "PLATFORM_INTR_SRC"
81};
82
83static 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
91static 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 * CPU IDs to 8.
98 *
99 */
100 if (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
107static 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
116static 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 */
126struct smp_config_operations madt_config_operations = {
127 .cpu_enabled = madt_cpu_enabled,
128 .cpu_bootstrap = madt_cpu_bootstrap,
129 .cpu_apic_id = madt_cpu_apic_id,
130 .irq_to_pin = madt_irq_to_pin
131};
132
133static 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
147static 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
152 if (!(la->flags & 0x1)) {
153 /* Processor is unusable, skip it. */
154 return;
155 }
156
157 apic_id_mask |= 1 << la->apic_id;
158}
159
160static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
161{
162 if (!madt_io_apic_entry_cnt++) {
163 /* Remember index of the first io apic entry */
164 madt_io_apic_entry_index = i;
165 io_apic = (uint32_t *) (unative_t) ioa->io_apic_address;
166 } else {
167 /* Currently not supported */
168 }
169}
170
171static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
172 size_t i)
173{
174 ASSERT(override->source < sizeof(isa_irq_map) / sizeof(int));
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
182void 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;
252}
253
254#endif /* CONFIG_SMP */
255
256/** @}
257 */
Note: See TracBrowser for help on using the repository browser.