Linux 2.2.0
[davej-history.git] / arch / i386 / kernel / setup.c
blobc3f34270a1bd85a567f114590ac04b4876e3fb71
1 /*
2 * linux/arch/i386/kernel/setup.c
4 * Copyright (C) 1995 Linus Torvalds
6 * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean
7 * and Martin Mares, November 1997.
8 */
11 * This file handles the architecture-dependent parts of initialization
14 #include <linux/errno.h>
15 #include <linux/sched.h>
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/stddef.h>
19 #include <linux/unistd.h>
20 #include <linux/ptrace.h>
21 #include <linux/malloc.h>
22 #include <linux/user.h>
23 #include <linux/a.out.h>
24 #include <linux/tty.h>
25 #include <linux/ioport.h>
26 #include <linux/delay.h>
27 #include <linux/config.h>
28 #include <linux/init.h>
29 #ifdef CONFIG_APM
30 #include <linux/apm_bios.h>
31 #endif
32 #ifdef CONFIG_BLK_DEV_RAM
33 #include <linux/blk.h>
34 #endif
35 #include <asm/processor.h>
36 #include <linux/console.h>
37 #include <asm/uaccess.h>
38 #include <asm/system.h>
39 #include <asm/io.h>
40 #include <asm/smp.h>
41 #include <asm/cobalt.h>
44 * Machine setup..
47 char ignore_irq13 = 0; /* set if exception 16 works */
48 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
51 * Bus types ..
53 int EISA_bus = 0;
54 int MCA_bus = 0;
56 /* for MCA, but anyone else can use it if they want */
57 unsigned int machine_id = 0;
58 unsigned int machine_submodel_id = 0;
59 unsigned int BIOS_revision = 0;
62 * Setup options
64 struct drive_info_struct { char dummy[32]; } drive_info;
65 struct screen_info screen_info;
66 #ifdef CONFIG_APM
67 struct apm_bios_info apm_bios_info;
68 #endif
69 struct sys_desc_table_struct {
70 unsigned short length;
71 unsigned char table[0];
74 unsigned char aux_device_present;
76 #ifdef CONFIG_BLK_DEV_RAM
77 extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
78 extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
79 extern int rd_image_start; /* starting block # of image */
80 #endif
82 extern int root_mountflags;
83 extern int _etext, _edata, _end;
84 extern unsigned long cpu_hz;
87 * This is set up by the setup-routine at boot-time
89 #define PARAM ((unsigned char *)empty_zero_page)
90 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
91 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
92 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
93 #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
94 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
95 #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
96 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
97 #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
98 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
99 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
100 #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
101 #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
102 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
103 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
104 #define COMMAND_LINE ((char *) (PARAM+2048))
105 #define COMMAND_LINE_SIZE 256
107 #define RAMDISK_IMAGE_START_MASK 0x07FF
108 #define RAMDISK_PROMPT_FLAG 0x8000
109 #define RAMDISK_LOAD_FLAG 0x4000
111 #ifdef CONFIG_VISWS
112 char visws_board_type = -1;
113 char visws_board_rev = -1;
115 #define PIIX_PM_START 0x0F80
117 #define SIO_GPIO_START 0x0FC0
119 #define SIO_PM_START 0x0FC8
121 #define PMBASE PIIX_PM_START
122 #define GPIREG0 (PMBASE+0x30)
123 #define GPIREG(x) (GPIREG0+((x)/8))
124 #define PIIX_GPI_BD_ID1 18
125 #define PIIX_GPI_BD_REG GPIREG(PIIX_GPI_BD_ID1)
127 #define PIIX_GPI_BD_SHIFT (PIIX_GPI_BD_ID1 % 8)
129 #define SIO_INDEX 0x2e
130 #define SIO_DATA 0x2f
132 #define SIO_DEV_SEL 0x7
133 #define SIO_DEV_ENB 0x30
134 #define SIO_DEV_MSB 0x60
135 #define SIO_DEV_LSB 0x61
137 #define SIO_GP_DEV 0x7
139 #define SIO_GP_BASE SIO_GPIO_START
140 #define SIO_GP_MSB (SIO_GP_BASE>>8)
141 #define SIO_GP_LSB (SIO_GP_BASE&0xff)
143 #define SIO_GP_DATA1 (SIO_GP_BASE+0)
145 #define SIO_PM_DEV 0x8
147 #define SIO_PM_BASE SIO_PM_START
148 #define SIO_PM_MSB (SIO_PM_BASE>>8)
149 #define SIO_PM_LSB (SIO_PM_BASE&0xff)
150 #define SIO_PM_INDEX (SIO_PM_BASE+0)
151 #define SIO_PM_DATA (SIO_PM_BASE+1)
153 #define SIO_PM_FER2 0x1
155 #define SIO_PM_GP_EN 0x80
157 static void
158 visws_get_board_type_and_rev(void)
160 int raw;
162 visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
163 >> PIIX_GPI_BD_SHIFT;
165 * Get Board rev.
166 * First, we have to initialize the 307 part to allow us access
167 * to the GPIO registers. Let's map them at 0x0fc0 which is right
168 * after the PIIX4 PM section.
170 outb_p(SIO_DEV_SEL, SIO_INDEX);
171 outb_p(SIO_GP_DEV, SIO_DATA); /* Talk to GPIO regs. */
173 outb_p(SIO_DEV_MSB, SIO_INDEX);
174 outb_p(SIO_GP_MSB, SIO_DATA); /* MSB of GPIO base address */
176 outb_p(SIO_DEV_LSB, SIO_INDEX);
177 outb_p(SIO_GP_LSB, SIO_DATA); /* LSB of GPIO base address */
179 outb_p(SIO_DEV_ENB, SIO_INDEX);
180 outb_p(1, SIO_DATA); /* Enable GPIO registers. */
183 * Now, we have to map the power management section to write
184 * a bit which enables access to the GPIO registers.
185 * What lunatic came up with this shit?
187 outb_p(SIO_DEV_SEL, SIO_INDEX);
188 outb_p(SIO_PM_DEV, SIO_DATA); /* Talk to GPIO regs. */
190 outb_p(SIO_DEV_MSB, SIO_INDEX);
191 outb_p(SIO_PM_MSB, SIO_DATA); /* MSB of PM base address */
193 outb_p(SIO_DEV_LSB, SIO_INDEX);
194 outb_p(SIO_PM_LSB, SIO_DATA); /* LSB of PM base address */
196 outb_p(SIO_DEV_ENB, SIO_INDEX);
197 outb_p(1, SIO_DATA); /* Enable PM registers. */
200 * Now, write the PM register which enables the GPIO registers.
202 outb_p(SIO_PM_FER2, SIO_PM_INDEX);
203 outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
206 * Now, initialize the GPIO registers.
207 * We want them all to be inputs which is the
208 * power on default, so let's leave them alone.
209 * So, let's just read the board rev!
211 raw = inb_p(SIO_GP_DATA1);
212 raw &= 0x7f; /* 7 bits of valid board revision ID. */
214 if (visws_board_type == VISWS_320) {
215 if (raw < 0x6) {
216 visws_board_rev = 4;
217 } else if (raw < 0xc) {
218 visws_board_rev = 5;
219 } else {
220 visws_board_rev = 6;
223 } else if (visws_board_type == VISWS_540) {
224 visws_board_rev = 2;
225 } else {
226 visws_board_rev = raw;
229 printk("Silicon Graphics %s (rev %d)\n",
230 visws_board_type == VISWS_320 ? "320" :
231 (visws_board_type == VISWS_540 ? "540" :
232 "unknown"),
233 visws_board_rev);
235 #endif
238 static char command_line[COMMAND_LINE_SIZE] = { 0, };
239 char saved_command_line[COMMAND_LINE_SIZE];
241 __initfunc(void setup_arch(char **cmdline_p,
242 unsigned long * memory_start_p, unsigned long * memory_end_p))
244 unsigned long memory_start, memory_end;
245 char c = ' ', *to = command_line, *from = COMMAND_LINE;
246 int len = 0;
247 static unsigned char smptrap=0;
249 if (smptrap)
250 return;
251 smptrap=1;
253 #ifdef CONFIG_VISWS
254 visws_get_board_type_and_rev();
255 #endif
257 ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
258 drive_info = DRIVE_INFO;
259 screen_info = SCREEN_INFO;
260 #ifdef CONFIG_APM
261 apm_bios_info = APM_BIOS_INFO;
262 #endif
263 if( SYS_DESC_TABLE.length != 0 ) {
264 MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
265 machine_id = SYS_DESC_TABLE.table[0];
266 machine_submodel_id = SYS_DESC_TABLE.table[1];
267 BIOS_revision = SYS_DESC_TABLE.table[2];
269 aux_device_present = AUX_DEVICE_INFO;
270 memory_end = (1<<20) + (EXT_MEM_K<<10);
271 #ifndef STANDARD_MEMORY_BIOS_CALL
273 unsigned long memory_alt_end = (1<<20) + (ALT_MEM_K<<10);
274 /* printk(KERN_DEBUG "Memory sizing: %08x %08x\n", memory_end, memory_alt_end); */
275 if (memory_alt_end > memory_end)
276 memory_end = memory_alt_end;
278 #endif
280 memory_end &= PAGE_MASK;
281 #ifdef CONFIG_BLK_DEV_RAM
282 rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
283 rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
284 rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
285 #endif
286 if (!MOUNT_ROOT_RDONLY)
287 root_mountflags &= ~MS_RDONLY;
288 memory_start = (unsigned long) &_end;
289 init_task.mm->start_code = PAGE_OFFSET;
290 init_task.mm->end_code = (unsigned long) &_etext;
291 init_task.mm->end_data = (unsigned long) &_edata;
292 init_task.mm->brk = (unsigned long) &_end;
294 /* Save unparsed command line copy for /proc/cmdline */
295 memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
296 saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
298 for (;;) {
300 * "mem=nopentium" disables the 4MB page tables.
301 * "mem=XXX[kKmM]" overrides the BIOS-reported
302 * memory size
304 if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
305 if (to != command_line) to--;
306 if (!memcmp(from+4, "nopentium", 9)) {
307 from += 9+4;
308 boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
309 } else {
310 memory_end = simple_strtoul(from+4, &from, 0);
311 if ( *from == 'K' || *from == 'k' ) {
312 memory_end = memory_end << 10;
313 from++;
314 } else if ( *from == 'M' || *from == 'm' ) {
315 memory_end = memory_end << 20;
316 from++;
320 c = *(from++);
321 if (!c)
322 break;
323 if (COMMAND_LINE_SIZE <= ++len)
324 break;
325 *(to++) = c;
327 *to = '\0';
328 *cmdline_p = command_line;
330 #define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */
331 #define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
333 if (memory_end > MAXMEM)
335 memory_end = MAXMEM;
336 printk(KERN_WARNING "Warning only %ldMB will be used.\n",
337 MAXMEM>>20);
340 memory_end += PAGE_OFFSET;
341 *memory_start_p = memory_start;
342 *memory_end_p = memory_end;
344 #ifdef __SMP__
346 * Save possible boot-time SMP configuration:
348 init_smp_config();
349 #endif
351 #ifdef CONFIG_BLK_DEV_INITRD
352 if (LOADER_TYPE) {
353 initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
354 initrd_end = initrd_start+INITRD_SIZE;
355 if (initrd_end > memory_end) {
356 printk("initrd extends beyond end of memory "
357 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
358 initrd_end,memory_end);
359 initrd_start = 0;
362 #endif
364 /* request I/O space for devices used on all i[345]86 PCs */
365 request_region(0x00,0x20,"dma1");
366 request_region(0x40,0x20,"timer");
367 request_region(0x80,0x10,"dma page reg");
368 request_region(0xc0,0x20,"dma2");
369 request_region(0xf0,0x10,"fpu");
371 #ifdef CONFIG_VT
372 #if defined(CONFIG_VGA_CONSOLE)
373 conswitchp = &vga_con;
374 #elif defined(CONFIG_DUMMY_CONSOLE)
375 conswitchp = &dummy_con;
376 #endif
377 #endif
379 * Check the bugs that will bite us before we get booting
384 __initfunc(static int amd_model(struct cpuinfo_x86 *c))
386 unsigned int n, dummy, *v;
388 /* Actually we must have cpuid or we could never have
389 * figured out that this was AMD from the vendor info :-).
392 cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
393 if (n < 4)
394 return 0;
395 cpuid(0x80000001, &dummy, &dummy, &dummy, &(c->x86_capability));
396 v = (unsigned int *) c->x86_model_id;
397 cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
398 cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
399 cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
400 c->x86_model_id[48] = 0;
401 return 1;
405 * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
407 static inline void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
409 unsigned char ccr2, ccr3;
411 /* we test for DEVID by checking whether CCR3 is writable */
412 cli();
413 ccr3 = getCx86(CX86_CCR3);
414 setCx86(CX86_CCR3, ccr3 ^ 0x80);
415 getCx86(0xc0); /* dummy to change bus */
417 if (getCx86(CX86_CCR3) == ccr3) { /* no DEVID regs. */
418 ccr2 = getCx86(CX86_CCR2);
419 setCx86(CX86_CCR2, ccr2 ^ 0x04);
420 getCx86(0xc0); /* dummy */
422 if (getCx86(CX86_CCR2) == ccr2) /* old Cx486SLC/DLC */
423 *dir0 = 0xfd;
424 else { /* Cx486S A step */
425 setCx86(CX86_CCR2, ccr2);
426 *dir0 = 0xfe;
429 else {
430 setCx86(CX86_CCR3, ccr3); /* restore CCR3 */
432 /* read DIR0 and DIR1 CPU registers */
433 *dir0 = getCx86(CX86_DIR0);
434 *dir1 = getCx86(CX86_DIR1);
436 sti();
440 * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
441 * order to identify the Cyrix CPU model after we're out of setup.c
443 unsigned char Cx86_dir0_msb __initdata = 0;
445 static char Cx86_model[][9] __initdata = {
446 "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
447 "M II ", "Unknown"
449 static char Cx486_name[][5] __initdata = {
450 "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
451 "SRx2", "DRx2"
453 static char Cx486S_name[][4] __initdata = {
454 "S", "S2", "Se", "S2e"
456 static char Cx486D_name[][4] __initdata = {
457 "DX", "DX2", "?", "?", "?", "DX4"
459 static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
460 static char cyrix_model_mult1[] __initdata = "12??43";
461 static char cyrix_model_mult2[] __initdata = "12233445";
463 __initfunc(static void cyrix_model(struct cpuinfo_x86 *c))
465 unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
466 char *buf = c->x86_model_id;
467 const char *p = NULL;
469 do_cyrix_devid(&dir0, &dir1);
471 Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */
472 dir0_lsn = dir0 & 0xf; /* model or clock multiplier */
474 /* common case step number/rev -- exceptions handled below */
475 c->x86_model = (dir1 >> 4) + 1;
476 c->x86_mask = dir1 & 0xf;
478 /* Now cook; the original recipe is by Channing Corn, from Cyrix.
479 * We do the same thing for each generation: we work out
480 * the model, multiplier and stepping. Black magic included,
481 * to make the silicon step/rev numbers match the printed ones.
484 switch (dir0_msn) {
485 unsigned char tmp;
487 case 0: /* Cx486SLC/DLC/SRx/DRx */
488 p = Cx486_name[dir0_lsn & 7];
489 break;
491 case 1: /* Cx486S/DX/DX2/DX4 */
492 p = (dir0_lsn & 8) ? Cx486D_name[dir0_lsn & 5]
493 : Cx486S_name[dir0_lsn & 3];
494 break;
496 case 2: /* 5x86 */
497 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
498 p = Cx86_cb+2;
499 break;
501 case 3: /* 6x86/6x86L */
502 Cx86_cb[1] = ' ';
503 Cx86_cb[2] = cyrix_model_mult1[dir0_lsn & 5];
504 if (dir1 > 0x21) { /* 686L */
505 Cx86_cb[0] = 'L';
506 p = Cx86_cb;
507 (c->x86_model)++;
508 } else /* 686 */
509 p = Cx86_cb+1;
510 break;
512 case 4: /* MediaGX/GXm */
514 * Life sometimes gets weiiiiiiiird if we use this
515 * on the MediaGX. So we turn it off for now.
518 /* GXm supports extended cpuid levels 'ala' AMD */
519 if (c->cpuid_level == 2) {
520 amd_model(c); /* get CPU marketing name */
521 c->x86_capability&=~X86_FEATURE_TSC;
522 return;
524 else { /* MediaGX */
525 Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4';
526 p = Cx86_cb+2;
527 c->x86_model = (dir1 & 0x20) ? 1 : 2;
528 c->x86_capability&=~X86_FEATURE_TSC;
530 break;
532 case 5: /* 6x86MX/M II */
533 if (dir1 > 7) dir0_msn++; /* M II */
534 tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
535 Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
536 p = Cx86_cb+tmp;
537 if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
538 (c->x86_model)++;
539 break;
541 case 0xf: /* Cyrix 486 without DEVID registers */
542 switch (dir0_lsn) {
543 case 0xd: /* either a 486SLC or DLC w/o DEVID */
544 dir0_msn = 0;
545 p = Cx486_name[(c->hard_math) ? 1 : 0];
546 break;
548 case 0xe: /* a 486S A step */
549 dir0_msn = 0;
550 p = Cx486S_name[0];
551 break;
552 break;
555 default: /* unknown (shouldn't happen, we know everyone ;-) */
556 dir0_msn = 7;
557 break;
559 strcpy(buf, Cx86_model[dir0_msn & 7]);
560 if (p) strcat(buf, p);
561 return;
564 __initfunc(void get_cpu_vendor(struct cpuinfo_x86 *c))
566 char *v = c->x86_vendor_id;
568 if (!strcmp(v, "GenuineIntel"))
569 c->x86_vendor = X86_VENDOR_INTEL;
570 else if (!strcmp(v, "AuthenticAMD"))
571 c->x86_vendor = X86_VENDOR_AMD;
572 else if (!strcmp(v, "CyrixInstead"))
573 c->x86_vendor = X86_VENDOR_CYRIX;
574 else if (!strcmp(v, "UMC UMC UMC "))
575 c->x86_vendor = X86_VENDOR_UMC;
576 else if (!strcmp(v, "CentaurHauls"))
577 c->x86_vendor = X86_VENDOR_CENTAUR;
578 else if (!strcmp(v, "NexGenDriven"))
579 c->x86_vendor = X86_VENDOR_NEXGEN;
580 else
581 c->x86_vendor = X86_VENDOR_UNKNOWN;
584 struct cpu_model_info {
585 int vendor;
586 int x86;
587 char *model_names[16];
590 static struct cpu_model_info cpu_models[] __initdata = {
591 { X86_VENDOR_INTEL, 4,
592 { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL",
593 "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL,
594 NULL, NULL, NULL, NULL, NULL }},
595 { X86_VENDOR_INTEL, 5,
596 { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75 - 200",
597 "OverDrive PODP5V83", "Pentium MMX", NULL, NULL,
598 "Mobile Pentium 75 - 200", "Mobile Pentium MMX", NULL, NULL, NULL,
599 NULL, NULL, NULL, NULL }},
600 { X86_VENDOR_INTEL, 6,
601 { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)",
602 NULL, "Pentium II (Deschutes)", "Celeron (Mendocino)", NULL,
603 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
604 { X86_VENDOR_AMD, 4,
605 { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
606 "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT",
607 "Am5x86-WB" }},
608 { X86_VENDOR_AMD, 5,
609 { "K5/SSA5", "K5",
610 "K5", "K5", NULL, NULL,
611 "K6", "K6", "K6-2",
612 "K6-3", NULL, NULL, NULL, NULL, NULL, NULL }},
613 { X86_VENDOR_UMC, 4,
614 { NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
615 NULL, NULL, NULL, NULL, NULL, NULL }},
616 { X86_VENDOR_CENTAUR, 5,
617 { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL,
618 NULL, NULL, NULL, NULL, NULL }},
619 { X86_VENDOR_NEXGEN, 5,
620 { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
621 NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
624 __initfunc(void identify_cpu(struct cpuinfo_x86 *c))
626 int i;
627 char *p = NULL;
629 c->loops_per_sec = loops_per_sec;
630 c->x86_cache_size = -1;
632 get_cpu_vendor(c);
634 if (c->x86_vendor == X86_VENDOR_UNKNOWN &&
635 c->cpuid_level < 0)
636 return;
638 if (c->x86_vendor == X86_VENDOR_CYRIX) {
639 cyrix_model(c);
640 return;
643 if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
644 return;
646 for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) {
647 if (c->cpuid_level > 1) {
648 /* supports eax=2 call */
649 int edx, cache_size, dummy;
651 cpuid(2, &dummy, &dummy, &dummy, &edx);
653 /* We need only the LSB */
654 edx &= 0xff;
656 switch (edx) {
657 case 0x40:
658 cache_size = 0;
659 break;
661 case 0x41:
662 cache_size = 128;
663 break;
665 case 0x42:
666 cache_size = 256;
667 break;
669 case 0x43:
670 cache_size = 512;
671 break;
673 case 0x44:
674 cache_size = 1024;
675 break;
677 case 0x45:
678 cache_size = 2048;
679 break;
681 default:
682 cache_size = 0;
683 break;
686 c->x86_cache_size = cache_size;
689 if (cpu_models[i].vendor == c->x86_vendor &&
690 cpu_models[i].x86 == c->x86) {
691 if (c->x86_model <= 16)
692 p = cpu_models[i].model_names[c->x86_model];
694 /* Names for the Pentium II processors */
695 if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
696 && (cpu_models[i].x86 == 6)
697 && (c->x86_model == 5)
698 && (c->x86_cache_size == 0)) {
699 p = "Celeron (Covington)";
705 if (p) {
706 strcpy(c->x86_model_id, p);
707 return;
710 sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model);
714 * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
717 __initfunc(void dodgy_tsc(void))
719 get_cpu_vendor(&boot_cpu_data);
721 if(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)
723 return;
725 cyrix_model(&boot_cpu_data);
729 #define rdmsr(msr,val1,val2) \
730 __asm__ __volatile__("rdmsr" \
731 : "=a" (val1), "=d" (val2) \
732 : "c" (msr))
734 #define wrmsr(msr,val1,val2) \
735 __asm__ __volatile__("wrmsr" \
736 : /* no outputs */ \
737 : "c" (msr), "a" (val1), "d" (val2))
739 static char *cpu_vendor_names[] __initdata = {
740 "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
743 __initfunc(void print_cpu_info(struct cpuinfo_x86 *c))
745 char *vendor = NULL;
747 if (c->x86_vendor < sizeof(cpu_vendor_names)/sizeof(char *))
748 vendor = cpu_vendor_names[c->x86_vendor];
749 else if (c->cpuid_level >= 0)
750 vendor = c->x86_vendor_id;
752 if (vendor)
753 printk("%s ", vendor);
755 if (!c->x86_model_id[0])
756 printk("%d86", c->x86);
757 else
758 printk("%s", c->x86_model_id);
760 if (c->x86_mask || c->cpuid_level>=0)
761 printk(" stepping %02x", c->x86_mask);
763 if(c->x86_vendor == X86_VENDOR_CENTAUR)
765 u32 hv,lv;
766 rdmsr(0x107, lv, hv);
767 printk("\nCentaur FSR was 0x%X ",lv);
768 lv|=(1<<8);
769 lv|=(1<<7);
770 /* lv|=(1<<6); - may help too if the board can cope */
771 printk("now 0x%X", lv);
772 wrmsr(0x107, lv, hv);
774 printk("\n");
778 * Get CPU information for use by the procfs.
781 int get_cpuinfo(char * buffer)
783 char *p = buffer;
784 int sep_bug;
785 static char *x86_cap_flags[] = {
786 "fpu", "vme", "de", "pse", "tsc", "msr", "6", "mce",
787 "cx8", "9", "10", "sep", "12", "pge", "14", "cmov",
788 "16", "17", "18", "19", "20", "21", "22", "mmx",
789 "24", "25", "26", "27", "28", "29", "30", "31"
791 struct cpuinfo_x86 *c = cpu_data;
792 int i, n;
794 for(n=0; n<NR_CPUS; n++, c++) {
795 #ifdef __SMP__
796 if (!(cpu_online_map & (1<<n)))
797 continue;
798 #endif
799 p += sprintf(p,"processor\t: %d\n"
800 "vendor_id\t: %s\n"
801 "cpu family\t: %c\n"
802 "model\t\t: %d\n"
803 "model name\t: %s\n",
805 c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
806 c->x86 + '0',
807 c->x86_model,
808 c->x86_model_id[0] ? c->x86_model_id : "unknown");
810 if (c->x86_mask)
811 p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
812 else
813 p += sprintf(p, "stepping\t: unknown\n");
815 if (c->x86_capability & X86_FEATURE_TSC) {
816 p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n",
817 cpu_hz / 1000000, (cpu_hz % 1000000));
820 /* Cache size */
821 if (c->x86_cache_size >= 0)
822 p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size);
824 /* Modify the capabilities according to chip type */
825 if (c->x86_vendor == X86_VENDOR_CYRIX) {
826 x86_cap_flags[24] = "cxmmx";
827 } else if (c->x86_vendor == X86_VENDOR_AMD) {
828 x86_cap_flags[16] = "fcmov";
829 x86_cap_flags[31] = "3dnow";
830 if (c->x86 == 5 && c->x86_model == 6)
831 x86_cap_flags[10] = "sep";
832 } else if (c->x86_vendor == X86_VENDOR_INTEL) {
833 x86_cap_flags[6] = "pae";
834 x86_cap_flags[9] = "apic";
835 x86_cap_flags[12] = "mtrr";
836 x86_cap_flags[14] = "mca";
837 x86_cap_flags[16] = "pat";
838 x86_cap_flags[17] = "pse36";
839 x86_cap_flags[24] = "osfxsr";
842 sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
843 c->x86 == 0x06 &&
844 c->cpuid_level >= 0 &&
845 (c->x86_capability & X86_FEATURE_SEP) &&
846 c->x86_model < 3 &&
847 c->x86_mask < 3;
849 p += sprintf(p, "fdiv_bug\t: %s\n"
850 "hlt_bug\t\t: %s\n"
851 "sep_bug\t\t: %s\n"
852 "f00f_bug\t: %s\n"
853 "fpu\t\t: %s\n"
854 "fpu_exception\t: %s\n"
855 "cpuid level\t: %d\n"
856 "wp\t\t: %s\n"
857 "flags\t\t:",
858 c->fdiv_bug ? "yes" : "no",
859 c->hlt_works_ok ? "no" : "yes",
860 sep_bug ? "yes" : "no",
861 c->f00f_bug ? "yes" : "no",
862 c->hard_math ? "yes" : "no",
863 (c->hard_math && ignore_irq13) ? "yes" : "no",
864 c->cpuid_level,
865 c->wp_works_ok ? "yes" : "no");
867 for ( i = 0 ; i < 32 ; i++ )
868 if ( c->x86_capability & (1 << i) )
869 p += sprintf(p, " %s", x86_cap_flags[i]);
870 p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n",
871 (c->loops_per_sec+2500)/500000,
872 ((c->loops_per_sec+2500)/5000) % 100);
874 return p - buffer;