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.
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>
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>
30 #include <linux/apm_bios.h>
32 #ifdef CONFIG_BLK_DEV_RAM
33 #include <linux/blk.h>
35 #include <asm/processor.h>
36 #include <linux/console.h>
37 #include <asm/uaccess.h>
38 #include <asm/system.h>
41 #include <asm/cobalt.h>
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 };
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;
64 struct drive_info_struct
{ char dummy
[32]; } drive_info
;
65 struct screen_info screen_info
;
67 struct apm_bios_info apm_bios_info
;
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 */
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
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
158 visws_get_board_type_and_rev(void)
162 visws_board_type
= (char)(inb_p(PIIX_GPI_BD_REG
) & PIIX_GPI_BD_REG
)
163 >> PIIX_GPI_BD_SHIFT
;
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
) {
217 } else if (raw
< 0xc) {
223 } else if (visws_board_type
== VISWS_540
) {
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" :
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
;
247 static unsigned char smptrap
=0;
254 visws_get_board_type_and_rev();
257 ROOT_DEV
= to_kdev_t(ORIG_ROOT_DEV
);
258 drive_info
= DRIVE_INFO
;
259 screen_info
= SCREEN_INFO
;
261 apm_bios_info
= APM_BIOS_INFO
;
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
;
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);
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';
300 * "mem=nopentium" disables the 4MB page tables.
301 * "mem=XXX[kKmM]" overrides the BIOS-reported
304 if (c
== ' ' && *(const unsigned long *)from
== *(const unsigned long *)"mem=") {
305 if (to
!= command_line
) to
--;
306 if (!memcmp(from
+4, "nopentium", 9)) {
308 boot_cpu_data
.x86_capability
&= ~X86_FEATURE_PSE
;
310 memory_end
= simple_strtoul(from
+4, &from
, 0);
311 if ( *from
== 'K' || *from
== 'k' ) {
312 memory_end
= memory_end
<< 10;
314 } else if ( *from
== 'M' || *from
== 'm' ) {
315 memory_end
= memory_end
<< 20;
323 if (COMMAND_LINE_SIZE
<= ++len
)
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
)
336 printk(KERN_WARNING
"Warning only %ldMB will be used.\n",
340 memory_end
+= PAGE_OFFSET
;
341 *memory_start_p
= memory_start
;
342 *memory_end_p
= memory_end
;
346 * Save possible boot-time SMP configuration:
351 #ifdef CONFIG_BLK_DEV_INITRD
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
);
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");
372 #if defined(CONFIG_VGA_CONSOLE)
373 conswitchp
= &vga_con
;
374 #elif defined(CONFIG_DUMMY_CONSOLE)
375 conswitchp
= &dummy_con
;
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
);
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;
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 */
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 */
424 else { /* Cx486S A step */
425 setCx86(CX86_CCR2
, ccr2
);
430 setCx86(CX86_CCR3
, ccr3
); /* restore CCR3 */
432 /* read DIR0 and DIR1 CPU registers */
433 *dir0
= getCx86(CX86_DIR0
);
434 *dir1
= getCx86(CX86_DIR1
);
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 ",
449 static char Cx486_name
[][5] __initdata
= {
450 "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
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.
487 case 0: /* Cx486SLC/DLC/SRx/DRx */
488 p
= Cx486_name
[dir0_lsn
& 7];
491 case 1: /* Cx486S/DX/DX2/DX4 */
492 p
= (dir0_lsn
& 8) ? Cx486D_name
[dir0_lsn
& 5]
493 : Cx486S_name
[dir0_lsn
& 3];
497 Cx86_cb
[2] = cyrix_model_mult1
[dir0_lsn
& 5];
501 case 3: /* 6x86/6x86L */
503 Cx86_cb
[2] = cyrix_model_mult1
[dir0_lsn
& 5];
504 if (dir1
> 0x21) { /* 686L */
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
;
525 Cx86_cb
[2] = (dir0_lsn
& 1) ? '3' : '4';
527 c
->x86_model
= (dir1
& 0x20) ? 1 : 2;
528 c
->x86_capability
&=~X86_FEATURE_TSC
;
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];
537 if (((dir1
& 0x0f) > 4) || ((dir1
& 0xf0) == 0x20))
541 case 0xf: /* Cyrix 486 without DEVID registers */
543 case 0xd: /* either a 486SLC or DLC w/o DEVID */
545 p
= Cx486_name
[(c
->hard_math
) ? 1 : 0];
548 case 0xe: /* a 486S A step */
555 default: /* unknown (shouldn't happen, we know everyone ;-) */
559 strcpy(buf
, Cx86_model
[dir0_msn
& 7]);
560 if (p
) strcat(buf
, p
);
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
;
581 c
->x86_vendor
= X86_VENDOR_UNKNOWN
;
584 struct cpu_model_info
{
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
}},
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",
610 "K5", "K5", NULL
, NULL
,
612 "K6-3", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}},
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
))
629 c
->loops_per_sec
= loops_per_sec
;
630 c
->x86_cache_size
= -1;
634 if (c
->x86_vendor
== X86_VENDOR_UNKNOWN
&&
638 if (c
->x86_vendor
== X86_VENDOR_CYRIX
) {
643 if (c
->x86_vendor
== X86_VENDOR_AMD
&& amd_model(c
))
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 */
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)";
706 strcpy(c
->x86_model_id
, p
);
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
)
725 cyrix_model(&boot_cpu_data
);
729 #define rdmsr(msr,val1,val2) \
730 __asm__ __volatile__("rdmsr" \
731 : "=a" (val1), "=d" (val2) \
734 #define wrmsr(msr,val1,val2) \
735 __asm__ __volatile__("wrmsr" \
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
))
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
;
753 printk("%s ", vendor
);
755 if (!c
->x86_model_id
[0])
756 printk("%d86", c
->x86
);
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
)
766 rdmsr(0x107, lv
, hv
);
767 printk("\nCentaur FSR was 0x%X ",lv
);
770 /* lv|=(1<<6); - may help too if the board can cope */
771 printk("now 0x%X", lv
);
772 wrmsr(0x107, lv
, hv
);
778 * Get CPU information for use by the procfs.
781 int get_cpuinfo(char * buffer
)
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
;
794 for(n
=0; n
<NR_CPUS
; n
++, c
++) {
796 if (!(cpu_online_map
& (1<<n
)))
799 p
+= sprintf(p
,"processor\t: %d\n"
803 "model name\t: %s\n",
805 c
->x86_vendor_id
[0] ? c
->x86_vendor_id
: "unknown",
808 c
->x86_model_id
[0] ? c
->x86_model_id
: "unknown");
811 p
+= sprintf(p
, "stepping\t: %d\n", c
->x86_mask
);
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));
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
&&
844 c
->cpuid_level
>= 0 &&
845 (c
->x86_capability
& X86_FEATURE_SEP
) &&
849 p
+= sprintf(p
, "fdiv_bug\t: %s\n"
854 "fpu_exception\t: %s\n"
855 "cpuid level\t: %d\n"
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",
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);