source: mainline/arch/ia32/src/smp/mps.c@ 9c0a9b3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9c0a9b3 was 9c0a9b3, checked in by Jakub Vana <jakub.vana@…>, 20 years ago

1) memcopy and _memcopy functions rewriten to ANSI C norm.
2) Repaired ia32,ia64 and mips version of SPARTAN to work with this memcopy functions
3) Warning for non declared funcions added and repaired ia32,ia64 and mips versions to pass build process with this warning and Werror option

  • Property mode set to 100644
File size: 10.1 KB
Line 
1/*
2 * Copyright (C) 2001-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#ifdef __SMP__
30
31#include <config.h>
32#include <print.h>
33#include <debug.h>
34#include <arch/smp/mps.h>
35#include <arch/smp/apic.h>
36#include <arch/smp/smp.h>
37#include <func.h>
38#include <arch/types.h>
39#include <typedefs.h>
40#include <cpu.h>
41#include <arch/asm.h>
42#include <arch/bios/bios.h>
43#include <mm/frame.h>
44
45/*
46 * MultiProcessor Specification detection code.
47 */
48
49#define FS_SIGNATURE 0x5f504d5f
50#define CT_SIGNATURE 0x504d4350
51
52int mps_fs_check(__u8 *base);
53int mps_ct_check(void);
54
55int configure_via_ct(void);
56int configure_via_default(__u8 n);
57
58int ct_processor_entry(struct __processor_entry *pr);
59void ct_bus_entry(struct __bus_entry *bus);
60void ct_io_apic_entry(struct __io_apic_entry *ioa);
61void ct_io_intr_entry(struct __io_intr_entry *iointr);
62void ct_l_intr_entry(struct __l_intr_entry *lintr);
63
64void ct_extended_entries(void);
65
66static struct mps_fs *fs;
67static struct mps_ct *ct;
68
69struct __processor_entry *processor_entries = NULL;
70struct __bus_entry *bus_entries = NULL;
71struct __io_apic_entry *io_apic_entries = NULL;
72struct __io_intr_entry *io_intr_entries = NULL;
73struct __l_intr_entry *l_intr_entries = NULL;
74
75int processor_entry_cnt = 0;
76int bus_entry_cnt = 0;
77int io_apic_entry_cnt = 0;
78int io_intr_entry_cnt = 0;
79int l_intr_entry_cnt = 0;
80
81waitq_t ap_completion_wq;
82waitq_t kmp_completion_wq;
83
84
85/*
86 * Implementation of IA-32 SMP configuration interface.
87 */
88static count_t get_cpu_count(void);
89static bool is_cpu_enabled(index_t i);
90static bool is_bsp(index_t i);
91static __u8 get_cpu_apic_id(index_t i);
92
93struct smp_config_operations mps_config_operations = {
94 .cpu_count = get_cpu_count,
95 .cpu_enabled = is_cpu_enabled,
96 .cpu_bootstrap = is_bsp,
97 .cpu_apic_id = get_cpu_apic_id
98};
99
100count_t get_cpu_count(void)
101{
102 return processor_entry_cnt;
103}
104
105bool is_cpu_enabled(index_t i)
106{
107 ASSERT(i < processor_entry_cnt);
108 return processor_entries[i].cpu_flags & 0x1;
109}
110
111bool is_bsp(index_t i)
112{
113 ASSERT(i < processor_entry_cnt);
114 return processor_entries[i].cpu_flags & 0x2;
115}
116
117__u8 get_cpu_apic_id(index_t i)
118{
119 ASSERT(i < processor_entry_cnt);
120 return processor_entries[i].l_apic_id;
121}
122
123
124/*
125 * Used to check the integrity of the MP Floating Structure.
126 */
127int mps_fs_check(__u8 *base)
128{
129 int i;
130 __u8 sum;
131
132 for (i = 0, sum = 0; i < 16; i++)
133 sum += base[i];
134
135 return !sum;
136}
137
138/*
139 * Used to check the integrity of the MP Configuration Table.
140 */
141int mps_ct_check(void)
142{
143 __u8 *base = (__u8 *) ct;
144 __u8 *ext = base + ct->base_table_length;
145 __u8 sum;
146 int i;
147
148 /* count the checksum for the base table */
149 for (i=0,sum=0; i < ct->base_table_length; i++)
150 sum += base[i];
151
152 if (sum)
153 return 0;
154
155 /* count the checksum for the extended table */
156 for (i=0,sum=0; i < ct->ext_table_length; i++)
157 sum += ext[i];
158
159 return sum == ct->ext_table_checksum;
160}
161
162void mps_init(void)
163{
164 __u8 *addr[2] = { NULL, (__u8 *) 0xf0000 };
165 int i, j, length[2] = { 1024, 64*1024 };
166
167
168 /*
169 * Find MP Floating Pointer Structure
170 * 1a. search first 1K of EBDA
171 * 1b. if EBDA is undefined, search last 1K of base memory
172 * 2. search 64K starting at 0xf0000
173 */
174
175 addr[0] = (__u8 *) (ebda ? ebda : 639 * 1024);
176 for (i = 0; i < 2; i++) {
177 for (j = 0; j < length[i]; j += 16) {
178 if (*((__u32 *) &addr[i][j]) == FS_SIGNATURE && mps_fs_check(&addr[i][j])) {
179 fs = (struct mps_fs *) &addr[i][j];
180 goto fs_found;
181 }
182 }
183 }
184
185 return;
186
187fs_found:
188 printf("%L: MPS Floating Pointer Structure\n", fs);
189
190 frame_not_free((__address) fs);
191
192 if (fs->config_type == 0 && fs->configuration_table) {
193 if (fs->mpfib2 >> 7) {
194 printf("%s: PIC mode not supported\n", __FUNCTION__);
195 return;
196 }
197
198 ct = fs->configuration_table;
199 frame_not_free((__address) ct);
200 config.cpu_count = configure_via_ct();
201 }
202 else
203 config.cpu_count = configure_via_default(fs->config_type);
204
205 return;
206}
207
208int configure_via_ct(void)
209{
210 __u8 *cur;
211 int i, cnt;
212
213 if (ct->signature != CT_SIGNATURE) {
214 printf("%s: bad ct->signature\n", __FUNCTION__);
215 return 1;
216 }
217 if (!mps_ct_check()) {
218 printf("%s: bad ct checksum\n", __FUNCTION__);
219 return 1;
220 }
221 if (ct->oem_table) {
222 printf("%s: ct->oem_table not supported\n", __FUNCTION__);
223 return 1;
224 }
225
226 l_apic = ct->l_apic;
227
228 cnt = 0;
229 cur = &ct->base_table[0];
230 for (i=0; i < ct->entry_count; i++) {
231 switch (*cur) {
232 /* Processor entry */
233 case 0:
234 processor_entries = processor_entries ? processor_entries : (struct __processor_entry *) cur;
235 processor_entry_cnt++;
236 cnt += ct_processor_entry((struct __processor_entry *) cur);
237 cur += 20;
238 break;
239
240 /* Bus entry */
241 case 1:
242 bus_entries = bus_entries ? bus_entries : (struct __bus_entry *) cur;
243 bus_entry_cnt++;
244 ct_bus_entry((struct __bus_entry *) cur);
245 cur += 8;
246 break;
247
248 /* I/O Apic */
249 case 2:
250 io_apic_entries = io_apic_entries ? io_apic_entries : (struct __io_apic_entry *) cur;
251 io_apic_entry_cnt++;
252 ct_io_apic_entry((struct __io_apic_entry *) cur);
253 cur += 8;
254 break;
255
256 /* I/O Interrupt Assignment */
257 case 3:
258 io_intr_entries = io_intr_entries ? io_intr_entries : (struct __io_intr_entry *) cur;
259 io_intr_entry_cnt++;
260 ct_io_intr_entry((struct __io_intr_entry *) cur);
261 cur += 8;
262 break;
263
264 /* Local Interrupt Assignment */
265 case 4:
266 l_intr_entries = l_intr_entries ? l_intr_entries : (struct __l_intr_entry *) cur;
267 l_intr_entry_cnt++;
268 ct_l_intr_entry((struct __l_intr_entry *) cur);
269 cur += 8;
270 break;
271
272 default:
273 /*
274 * Something is wrong. Fallback to UP mode.
275 */
276
277 printf("%s: ct badness\n", __FUNCTION__);
278 return 1;
279 }
280 }
281
282 /*
283 * Process extended entries.
284 */
285 ct_extended_entries();
286 return cnt;
287}
288
289int configure_via_default(__u8 n)
290{
291 /*
292 * Not yet implemented.
293 */
294 printf("%s: not supported\n", __FUNCTION__);
295 return 1;
296}
297
298
299int ct_processor_entry(struct __processor_entry *pr)
300{
301 /*
302 * Ignore processors which are not marked enabled.
303 */
304 if ((pr->cpu_flags & (1<<0)) == 0)
305 return 0;
306
307 apic_id_mask |= (1<<pr->l_apic_id);
308 return 1;
309}
310
311void ct_bus_entry(struct __bus_entry *bus)
312{
313#ifdef MPSCT_VERBOSE
314 char buf[7];
315 memcopy((__address) bus->bus_type, (__address) buf, 6);
316 buf[6] = 0;
317 printf("bus%d: %s\n", bus->bus_id, buf);
318#endif
319}
320
321void ct_io_apic_entry(struct __io_apic_entry *ioa)
322{
323 static int io_apic_count = 0;
324
325 /* this ioapic is marked unusable */
326 if (ioa->io_apic_flags & 1 == 0)
327 return;
328
329 if (io_apic_count++ > 0) {
330 /*
331 * Multiple IO APIC's are currently not supported.
332 */
333 return;
334 }
335
336 io_apic = ioa->io_apic;
337}
338
339//#define MPSCT_VERBOSE
340void ct_io_intr_entry(struct __io_intr_entry *iointr)
341{
342#ifdef MPSCT_VERBOSE
343 switch (iointr->intr_type) {
344 case 0: printf("INT"); break;
345 case 1: printf("NMI"); break;
346 case 2: printf("SMI"); break;
347 case 3: printf("ExtINT"); break;
348 }
349 putchar(',');
350 switch (iointr->poel&3) {
351 case 0: printf("bus-like"); break;
352 case 1: printf("active high"); break;
353 case 2: printf("reserved"); break;
354 case 3: printf("active low"); break;
355 }
356 putchar(',');
357 switch ((iointr->poel>>2)&3) {
358 case 0: printf("bus-like"); break;
359 case 1: printf("edge-triggered"); break;
360 case 2: printf("reserved"); break;
361 case 3: printf("level-triggered"); break;
362 }
363 putchar(',');
364 printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
365 putchar(',');
366 printf("io_apic%d,pin%d", iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
367 putchar('\n');
368#endif
369}
370
371void ct_l_intr_entry(struct __l_intr_entry *lintr)
372{
373#ifdef MPSCT_VERBOSE
374 switch (lintr->intr_type) {
375 case 0: printf("INT"); break;
376 case 1: printf("NMI"); break;
377 case 2: printf("SMI"); break;
378 case 3: printf("ExtINT"); break;
379 }
380 putchar(',');
381 switch (lintr->poel&3) {
382 case 0: printf("bus-like"); break;
383 case 1: printf("active high"); break;
384 case 2: printf("reserved"); break;
385 case 3: printf("active low"); break;
386 }
387 putchar(',');
388 switch ((lintr->poel>>2)&3) {
389 case 0: printf("bus-like"); break;
390 case 1: printf("edge-triggered"); break;
391 case 2: printf("reserved"); break;
392 case 3: printf("level-triggered"); break;
393 }
394 putchar(',');
395 printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
396 putchar(',');
397 printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
398 putchar('\n');
399#endif
400}
401
402void ct_extended_entries(void)
403{
404 __u8 *ext = (__u8 *) ct + ct->base_table_length;
405 __u8 *cur;
406
407 for (cur = ext; cur < ext + ct->ext_table_length; cur += cur[CT_EXT_ENTRY_LEN]) {
408 switch (cur[CT_EXT_ENTRY_TYPE]) {
409 default:
410 printf("%L: skipping MP Configuration Table extended entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]);
411 break;
412 }
413 }
414}
415
416int mps_irq_to_pin(int irq)
417{
418 int i;
419
420 for(i=0;i<io_intr_entry_cnt;i++) {
421 if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0)
422 return io_intr_entries[i].dst_io_apic_pin;
423 }
424
425 return -1;
426}
427
428#endif /* __SMP__ */
Note: See TracBrowser for help on using the repository browser.