source: mainline/kernel/arch/ia32/src/smp/smp.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@…>, 8 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: 5.4 KB
Line 
1/*
2 * Copyright (c) 2008 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 ia32
30 * @{
31 */
32/** @file
33 */
34
35#include <smp/smp.h>
36#include <arch/smp/smp.h>
37#include <arch/smp/mps.h>
38#include <arch/smp/ap.h>
39#include <arch/boot/boot.h>
40#include <assert.h>
41#include <errno.h>
42#include <genarch/acpi/acpi.h>
43#include <genarch/acpi/madt.h>
44#include <config.h>
45#include <synch/waitq.h>
46#include <arch/pm.h>
47#include <halt.h>
48#include <panic.h>
49#include <arch/asm.h>
50#include <mm/page.h>
51#include <mm/frame.h>
52#include <mm/km.h>
53#include <mm/slab.h>
54#include <mm/as.h>
55#include <log.h>
56#include <mem.h>
57#include <arch/drivers/i8259.h>
58#include <cpu.h>
59
60#ifdef CONFIG_SMP
61
62static struct smp_config_operations *ops = NULL;
63
64void smp_init(void)
65{
66 if (acpi_madt) {
67 acpi_madt_parse();
68 ops = &madt_config_operations;
69 }
70
71 if (config.cpu_count == 1) {
72 mps_init();
73 ops = &mps_config_operations;
74 }
75
76 if (config.cpu_count > 1) {
77 l_apic = (uint32_t *) km_map((uintptr_t) l_apic, PAGE_SIZE,
78 PAGE_WRITE | PAGE_NOT_CACHEABLE);
79 io_apic = (uint32_t *) km_map((uintptr_t) io_apic, PAGE_SIZE,
80 PAGE_WRITE | PAGE_NOT_CACHEABLE);
81 }
82}
83
84static void cpu_arch_id_init(void)
85{
86 assert(ops != NULL);
87 assert(cpus != NULL);
88
89 for (unsigned int i = 0; i < config.cpu_count; ++i) {
90 cpus[i].arch.id = ops->cpu_apic_id(i);
91 }
92}
93
94/*
95 * Kernel thread for bringing up application processors. It becomes clear
96 * that we need an arrangement like this (AP's being initialized by a kernel
97 * thread), for a thread has its dedicated stack. (The stack used during the
98 * BSP initialization (prior the very first call to scheduler()) will be used
99 * as an initialization stack for each AP.)
100 */
101void kmp(void *arg __attribute__((unused)))
102{
103 unsigned int i;
104
105 assert(ops != NULL);
106
107 /*
108 * SMP initialized, cpus array allocated. Assign each CPU its
109 * physical APIC ID.
110 */
111 cpu_arch_id_init();
112
113 /*
114 * We need to access data in frame 0.
115 * We boldly make use of kernel address space mapping.
116 */
117
118 /*
119 * Set the warm-reset vector to the real-mode address of 4K-aligned ap_boot()
120 */
121 *((uint16_t *) (PA2KA(0x467 + 0))) =
122 (uint16_t) (((uintptr_t) ap_boot) >> 4); /* segment */
123 *((uint16_t *) (PA2KA(0x467 + 2))) = 0; /* offset */
124
125 /*
126 * Save 0xa to address 0xf of the CMOS RAM.
127 * BIOS will not do the POST after the INIT signal.
128 */
129 pio_write_8((ioport8_t *) 0x70, 0xf);
130 pio_write_8((ioport8_t *) 0x71, 0xa);
131
132 pic_disable_irqs(0xffff);
133 apic_init();
134
135 for (i = 0; i < config.cpu_count; i++) {
136 /*
137 * Skip processors marked unusable.
138 */
139 if (!ops->cpu_enabled(i))
140 continue;
141
142 /*
143 * The bootstrap processor is already up.
144 */
145 if (ops->cpu_bootstrap(i))
146 continue;
147
148 if (ops->cpu_apic_id(i) == bsp_l_apic) {
149 log(LF_ARCH, LVL_ERROR, "kmp: bad processor entry #%u, "
150 "will not send IPI to myself", i);
151 continue;
152 }
153
154 /*
155 * Prepare new GDT for CPU in question.
156 */
157
158 /* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
159 * it needs to be replaced by a generic fuctionality of
160 * the memory subsystem
161 */
162 descriptor_t *gdt_new =
163 (descriptor_t *) malloc(GDT_ITEMS * sizeof(descriptor_t),
164 FRAME_ATOMIC);
165 if (!gdt_new)
166 panic("Cannot allocate memory for GDT.");
167
168 memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(descriptor_t));
169 memsetb(&gdt_new[TSS_DES], sizeof(descriptor_t), 0);
170 protected_ap_gdtr.limit = GDT_ITEMS * sizeof(descriptor_t);
171 protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new);
172 gdtr.base = (uintptr_t) gdt_new;
173
174 if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) {
175 /*
176 * There may be just one AP being initialized at
177 * the time. After it comes completely up, it is
178 * supposed to wake us up.
179 */
180 if (waitq_sleep_timeout(&ap_completion_wq, 1000000,
181 SYNCH_FLAGS_NONE, NULL) == ETIMEOUT) {
182 log(LF_ARCH, LVL_NOTE, "%s: waiting for cpu%u "
183 "(APIC ID = %d) timed out", __FUNCTION__,
184 i, ops->cpu_apic_id(i));
185 }
186 } else
187 log(LF_ARCH, LVL_ERROR, "INIT IPI for l_apic%d failed",
188 ops->cpu_apic_id(i));
189 }
190}
191
192int smp_irq_to_pin(unsigned int irq)
193{
194 assert(ops != NULL);
195 return ops->irq_to_pin(irq);
196}
197
198#endif /* CONFIG_SMP */
199
200/** @}
201 */
Note: See TracBrowser for help on using the repository browser.