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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 6.8 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
[fe32163]29/** @addtogroup genarch
[b45c443]30 * @{
31 */
[0f27b4c]32/**
[7257021e]33 * @file
[fe32163]34 * @brief Multiple APIC Description Table (MADT) parsing.
[0f27b4c]35 */
36
[63e27ef]37#include <assert.h>
[d99c1d2]38#include <typedefs.h>
[e16e036a]39#include <genarch/acpi/acpi.h>
40#include <genarch/acpi/madt.h>
[ed0dd65]41#include <arch/smp/apic.h>
[232e3ec7]42#include <arch/smp/smp.h>
[6b7c36f]43#include <panic.h>
[232e3ec7]44#include <config.h>
[b2fa1204]45#include <log.h>
[085d973]46#include <mm/slab.h>
[f2460a50]47#include <gsort.h>
[10a2e22]48
49struct acpi_madt *acpi_madt = NULL;
[ed0dd65]50
[5f85c91]51#ifdef CONFIG_SMP
[ed0dd65]52
[fe32163]53/**
54 * Standard ISA IRQ map; can be overriden by
55 * Interrupt Source Override entries of MADT.
56 */
57static int isa_irq_map[] =
58 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
[6b7c36f]59
60struct madt_l_apic *madt_l_apic_entries = NULL;
61struct madt_io_apic *madt_io_apic_entries = NULL;
62
[fe32163]63static size_t madt_l_apic_entry_index = 0;
64static size_t madt_io_apic_entry_index = 0;
65static size_t madt_l_apic_entry_cnt = 0;
66static size_t madt_io_apic_entry_cnt = 0;
[6b7c36f]67
[fe32163]68static struct madt_apic_header **madt_entries_index = NULL;
[50a4e25]69
[a000878c]70const char *entry[] = {
[ed0dd65]71 "L_APIC",
72 "IO_APIC",
73 "INTR_SRC_OVRD",
74 "NMI_SRC",
75 "L_APIC_NMI",
76 "L_APIC_ADDR_OVRD",
77 "IO_SAPIC",
78 "L_SAPIC",
79 "PLATFORM_INTR_SRC"
80};
81
[fe32163]82static uint8_t madt_cpu_apic_id(size_t i)
[232e3ec7]83{
[63e27ef]84 assert(i < madt_l_apic_entry_cnt);
[a35b458]85
[fe32163]86 return ((struct madt_l_apic *)
87 madt_entries_index[madt_l_apic_entry_index + i])->apic_id;
[232e3ec7]88}
89
[fe32163]90static bool madt_cpu_enabled(size_t i)
[232e3ec7]91{
[63e27ef]92 assert(i < madt_l_apic_entry_cnt);
[a35b458]93
[fe32163]94 /*
95 * FIXME: The current local APIC driver limits usable
[4edd57fd]96 * CPU IDs to 8.
[fe32163]97 *
98 */
[4edd57fd]99 if (i > 7)
[fe32163]100 return false;
[a35b458]101
[fe32163]102 return ((struct madt_l_apic *)
103 madt_entries_index[madt_l_apic_entry_index + i])->flags & 0x1;
[232e3ec7]104}
105
[fe32163]106static bool madt_cpu_bootstrap(size_t i)
[232e3ec7]107{
[63e27ef]108 assert(i < madt_l_apic_entry_cnt);
[a35b458]109
[fe32163]110 return ((struct madt_l_apic *)
111 madt_entries_index[madt_l_apic_entry_index + i])->apic_id ==
[99718a2e]112 bsp_l_apic;
[232e3ec7]113}
114
[fe32163]115static int madt_irq_to_pin(unsigned int irq)
[a83a802]116{
[e2793a4]117 if (irq >= sizeof(isa_irq_map) / sizeof(int))
118 return (int) irq;
[a35b458]119
[fe32163]120 return isa_irq_map[irq];
[a83a802]121}
122
[fe32163]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
[e9f4b59]133static int madt_cmp(void *a, void *b, void *arg)
[8491c48]134{
[e9f4b59]135 uint8_t typea = (*((struct madt_apic_header **) a))->type;
136 uint8_t typeb = (*((struct madt_apic_header **) b))->type;
[a35b458]137
[fe32163]138 if (typea > typeb)
139 return 1;
[a35b458]140
[fe32163]141 if (typea < typeb)
142 return -1;
[a35b458]143
[fe32163]144 return 0;
[ed0dd65]145}
[6b7c36f]146
[fe32163]147static void madt_l_apic_entry(struct madt_l_apic *la, size_t i)
[50a4e25]148{
[99718a2e]149 if (madt_l_apic_entry_cnt == 0)
[fe32163]150 madt_l_apic_entry_index = i;
[a35b458]151
[99718a2e]152 madt_l_apic_entry_cnt++;
[a35b458]153
[6b7c36f]154 if (!(la->flags & 0x1)) {
155 /* Processor is unusable, skip it. */
156 return;
157 }
[a35b458]158
[fe32163]159 apic_id_mask |= 1 << la->apic_id;
[6b7c36f]160}
161
[fe32163]162static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i)
[6b7c36f]163{
[99718a2e]164 if (madt_io_apic_entry_cnt == 0) {
[fe32163]165 /* Remember index of the first io apic entry */
166 madt_io_apic_entry_index = i;
[96b02eb9]167 io_apic = (uint32_t *) (sysarg_t) ioa->io_apic_address;
[50a4e25]168 } else {
[fe32163]169 /* Currently not supported */
[6b7c36f]170 }
[a35b458]171
[99718a2e]172 madt_io_apic_entry_cnt++;
[6b7c36f]173}
174
[fe32163]175static void madt_intr_src_ovrd_entry(struct madt_intr_src_ovrd *override,
176 size_t i)
[a83a802]177{
[63e27ef]178 assert(override->source < sizeof(isa_irq_map) / sizeof(int));
[a35b458]179
[e2793a4]180 isa_irq_map[override->source] = override->global_int;
[fe32163]181}
182
183void acpi_madt_parse(void)
184{
185 struct madt_apic_header *end = (struct madt_apic_header *)
186 (((uint8_t *) acpi_madt) + acpi_madt->header.length);
187 struct madt_apic_header *hdr;
[a35b458]188
[96b02eb9]189 l_apic = (uint32_t *) (sysarg_t) acpi_madt->l_apic_address;
[a35b458]190
[fe32163]191 /* Count MADT entries */
192 unsigned int madt_entries_index_cnt = 0;
[99718a2e]193 for (hdr = acpi_madt->apic_header; hdr < end;
[fe32163]194 hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length))
195 madt_entries_index_cnt++;
[a35b458]196
[fe32163]197 /* Create MADT APIC entries index array */
198 madt_entries_index = (struct madt_apic_header **)
[99718a2e]199 malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header *),
[fe32163]200 FRAME_ATOMIC);
201 if (!madt_entries_index)
202 panic("Memory allocation error.");
[a35b458]203
[fe32163]204 size_t i = 0;
[a35b458]205
[99718a2e]206 for (hdr = acpi_madt->apic_header; hdr < end;
207 hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) {
208 madt_entries_index[i] = hdr;
209 i++;
210 }
[a35b458]211
[fe32163]212 /* Sort MADT index structure */
[e9f4b59]213 if (!gsort(madt_entries_index, madt_entries_index_cnt,
214 sizeof(struct madt_apic_header *), madt_cmp, NULL))
215 panic("Sorting error.");
[a35b458]216
[fe32163]217 /* Parse MADT entries */
218 for (i = 0; i < madt_entries_index_cnt; i++) {
219 hdr = madt_entries_index[i];
[a35b458]220
[fe32163]221 switch (hdr->type) {
222 case MADT_L_APIC:
223 madt_l_apic_entry((struct madt_l_apic *) hdr, i);
224 break;
225 case MADT_IO_APIC:
226 madt_io_apic_entry((struct madt_io_apic *) hdr, i);
227 break;
228 case MADT_INTR_SRC_OVRD:
229 madt_intr_src_ovrd_entry((struct madt_intr_src_ovrd *) hdr, i);
230 break;
231 case MADT_NMI_SRC:
232 case MADT_L_APIC_NMI:
233 case MADT_L_APIC_ADDR_OVRD:
234 case MADT_IO_SAPIC:
235 case MADT_L_SAPIC:
236 case MADT_PLATFORM_INTR_SRC:
[b2fa1204]237 log(LF_ARCH, LVL_WARN,
238 "MADT: Skipping %s entry (type=%" PRIu8 ")",
[fe32163]239 entry[hdr->type], hdr->type);
240 break;
241 default:
242 if ((hdr->type >= MADT_RESERVED_SKIP_BEGIN)
243 && (hdr->type <= MADT_RESERVED_SKIP_END))
[b2fa1204]244 log(LF_ARCH, LVL_NOTE,
245 "MADT: Skipping reserved entry (type=%" PRIu8 ")",
[fe32163]246 hdr->type);
[a35b458]247
[fe32163]248 if (hdr->type >= MADT_RESERVED_OEM_BEGIN)
[b2fa1204]249 log(LF_ARCH, LVL_NOTE,
250 "MADT: Skipping OEM entry (type=%" PRIu8 ")",
[fe32163]251 hdr->type);
[a35b458]252
[fe32163]253 break;
254 }
255 }
[a35b458]256
[fe32163]257 if (madt_l_apic_entry_cnt > 0)
258 config.cpu_count = madt_l_apic_entry_cnt;
[a83a802]259}
[ed0dd65]260
[5f85c91]261#endif /* CONFIG_SMP */
[b45c443]262
[06e1e95]263/** @}
[b45c443]264 */
Note: See TracBrowser for help on using the repository browser.