From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S264329AbUEDMgw (ORCPT ); Tue, 4 May 2004 08:36:52 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S264330AbUEDMgw (ORCPT ); Tue, 4 May 2004 08:36:52 -0400 Received: from ylug.da-cha.jp ([61.211.239.235]:6828 "EHLO maison.kyo-ko.org") by vger.kernel.org with ESMTP id S264329AbUEDMgm (ORCPT ); Tue, 4 May 2004 08:36:42 -0400 Date: Tue, 04 May 2004 21:33:56 +0900 Message-ID: <87isfcl6bv.wl%miura@da-cha.org> From: Hiroshi Miura To: davej@codemonkey.org.uk Cc: linux-kernel@vger.kernel.org Subject: [PATCH] old 486 grade cpu detection(cyrix/nexgen) User-Agent: Wanderlust/2.11.24 (Wonderwall) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/21.3 (i386-pc-linux-gnu) MULE/5.0 (=?ISO-2022-JP?B?GyRCOC1MWhsoQg==?=) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Hi Dave, An old Cyrix and Nexgen 486 base CPU are not identified on 2.6 series kernel. These CPUs needs to probe a vendor id very-early and magically. I splited these very-early detection codes from nexgen.c and cyrix.c, and create new oldcpuident.c as old historical cpu ident. If setup code(common.c) cannot detect any vendor id on 486 grade cpu, then it try to do a cyrix and nexgen magical vendor id enabler. After that, if it detects cx486 or nexgen486 cpu, normal initialization on cyrix.c or nexgen.c is called by normal scheme. If it cannot detect these, kernel think it is 'UNKNOWN 486'. I need to detect cyrix 486 cpu as Cyrix because I try to write a CPUFreq driver for ZFx86 that is based on Cx486dx2/4 cpu. # This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1670.1.2 -> 1.1670.1.3 # arch/i386/kernel/cpu/common.c 1.26 -> 1.27 # arch/i386/kernel/cpu/nexgen.c 1.3 -> 1.4 # arch/i386/kernel/cpu/cyrix.c 1.11 -> 1.11.1.1 # arch/i386/kernel/cpu/Makefile 1.6 -> 1.7 # (new) -> 1.1 arch/i386/kernel/cpu/oldcpuident.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 04/04/14 torvalds@ppc970.osdl.org 1.1801 # Linux 2.6.6-rc1 # -------------------------------------------- # 04/04/15 miura@da-cha.org 1.1670.1.3 # enable old Cyrix/Nexgen vendor id detection hacks on 486 cpu which have not devid in normal way. # -------------------------------------------- # diff -Nru a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile --- a/arch/i386/kernel/cpu/Makefile Tue May 4 21:11:40 2004 +++ b/arch/i386/kernel/cpu/Makefile Tue May 4 21:11:40 2004 @@ -12,6 +12,7 @@ obj-y += rise.o obj-y += nexgen.o obj-y += umc.o +obj-y += oldcpuident.o obj-$(CONFIG_X86_MCE) += mcheck/ diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c --- a/arch/i386/kernel/cpu/common.c Tue May 4 21:11:40 2004 +++ b/arch/i386/kernel/cpu/common.c Tue May 4 21:11:40 2004 @@ -17,6 +17,7 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; extern void mcheck_init(struct cpuinfo_x86 *c); +extern int try_enable_cpuid(struct cpuinfo_x86 *c); extern int disable_pse; @@ -164,7 +165,6 @@ } __setup("nofxsr", x86_fxsr_setup); - /* Standard macro to see if a specific flag is changeable */ static inline int flag_is_changeable_p(u32 flag) { @@ -235,6 +235,9 @@ if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } + } else { /* no cpuid */ + try_enable_cpuid(c); + get_cpu_vendor(c); } } diff -Nru a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c --- a/arch/i386/kernel/cpu/cyrix.c Tue May 4 21:11:40 2004 +++ b/arch/i386/kernel/cpu/cyrix.c Tue May 4 21:11:40 2004 @@ -336,51 +336,18 @@ return; } -/* - * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected - * by the fact that they preserve the flags across the division of 5/2. - * PII and PPro exhibit this behavior too, but they have cpuid available. - */ - -/* - * Perform the Cyrix 5/2 test. A Cyrix won't change - * the flags, while other 486 chips will. - */ -static inline int test_cyrix_52div(void) -{ - unsigned int test; - - __asm__ __volatile__( - "sahf\n\t" /* clear flags (%eax = 0x0005) */ - "div %b2\n\t" /* divide 5 by 2 */ - "lahf" /* store flags into %ah */ - : "=a" (test) - : "0" (5), "q" (2) - : "cc"); - - /* AH is 0x02 on Cyrix after the divide.. */ - return (unsigned char) (test >> 8) == 0x02; -} - static void cyrix_identify(struct cpuinfo_x86 * c) { - /* Detect Cyrix with disabled CPUID */ - if ( c->x86 == 4 && test_cyrix_52div() ) { + /* Actually enable cpuid on the older cyrix */ + if ( c->x86 == 4 ) { unsigned char dir0, dir1; - - strcpy(c->x86_vendor_id, "CyrixInstead"); - c->x86_vendor = X86_VENDOR_CYRIX; - - /* Actually enable cpuid on the older cyrix */ - + /* Retrieve CPU revisions */ - do_cyrix_devid(&dir0, &dir1); dir0>>=4; /* Check it is an affected model */ - if (dir0 == 5 || dir0 == 3) { unsigned char ccr3, ccr4; @@ -395,7 +362,7 @@ local_irq_restore(flags); } } - generic_identify(c); + } static struct cpu_dev cyrix_cpu_dev __initdata = { diff -Nru a/arch/i386/kernel/cpu/nexgen.c b/arch/i386/kernel/cpu/nexgen.c --- a/arch/i386/kernel/cpu/nexgen.c Tue May 4 21:11:40 2004 +++ b/arch/i386/kernel/cpu/nexgen.c Tue May 4 21:11:40 2004 @@ -5,42 +5,11 @@ #include "cpu.h" -/* - * Detect a NexGen CPU running without BIOS hypercode new enough - * to have CPUID. (Thanks to Herbert Oppmann) - */ - -static int __init deep_magic_nexgen_probe(void) -{ - int ret; - - __asm__ __volatile__ ( - " movw $0x5555, %%ax\n" - " xorw %%dx,%%dx\n" - " movw $2, %%cx\n" - " divw %%cx\n" - " movl $0, %%eax\n" - " jnz 1f\n" - " movl $1, %%eax\n" - "1:\n" - : "=a" (ret) : : "cx", "dx" ); - return ret; -} - static void __init init_nexgen(struct cpuinfo_x86 * c) { c->x86_cache_size = 256; /* A few had 1 MB... */ } -static void nexgen_identify(struct cpuinfo_x86 * c) -{ - /* Detect NexGen with old hypercode */ - if ( deep_magic_nexgen_probe() ) { - strcpy(c->x86_vendor_id, "NexGenDriven"); - } - generic_identify(c); -} - static struct cpu_dev nexgen_cpu_dev __initdata = { .c_vendor = "Nexgen", .c_ident = { "NexGenDriven" }, @@ -51,7 +20,7 @@ }, }, .c_init = init_nexgen, - .c_identify = nexgen_identify, + .c_identify = generic_identify, }; int __init nexgen_init_cpu(void) diff -Nru a/arch/i386/kernel/cpu/oldcpuident.c b/arch/i386/kernel/cpu/oldcpuident.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/cpu/oldcpuident.c Tue May 4 21:11:40 2004 @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#include "cpu.h" + +/* + * This is early identify routine for old (386, 486 level non-intel) CPUs + */ + + +/* + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected + * by the fact that they preserve the flags across the division of 5/2. + * PII and PPro exhibit this behavior too, but they have cpuid available. + */ + +/* + * Perform the Cyrix 5/2 test. A Cyrix won't change + * the flags, while other 486 chips will. + */ +static inline int test_cyrix_52div(void) +{ + unsigned int test; + + __asm__ __volatile__( + "sahf\n\t" /* clear flags (%eax = 0x0005) */ + "div %b2\n\t" /* divide 5 by 2 */ + "lahf" /* store flags into %ah */ + : "=a" (test) + : "0" (5), "q" (2) + : "cc"); + + /* AH is 0x02 on Cyrix after the divide.. */ + return (unsigned char) (test >> 8) == 0x02; +} + +/* + * Detect a NexGen CPU running without BIOS hypercode new enough + * to have CPUID. (Thanks to Herbert Oppmann) + */ + +static int __init deep_magic_nexgen_probe(void) +{ + int ret; + + __asm__ __volatile__ ( + " movw $0x5555, %%ax\n" + " xorw %%dx,%%dx\n" + " movw $2, %%cx\n" + " divw %%cx\n" + " movl $0, %%eax\n" + " jnz 1f\n" + " movl $1, %%eax\n" + "1:\n" + : "=a" (ret) : : "cx", "dx" ); + return ret; +} + + +/* try enabling cpuid for old cyrix and nexgen cpus. + * call from common.c if cpu do not have CPUID. + */ + +int __init try_enable_cpuid(struct cpuinfo_x86 * c) +{ + /* Detect Cyrix with disabled CPUID */ + if ( c->x86 == 4 && test_cyrix_52div() ) { + strcpy(c->x86_vendor_id, "CyrixInstead"); + c->x86_vendor = X86_VENDOR_CYRIX; + return 1; + } else { + /* Detect NexGen with old hypercode */ + if ( deep_magic_nexgen_probe() ) { + strcpy(c->x86_vendor_id, "NexGenDriven"); + return 1; + } + } + return 0; +}