lkml.org 
[lkml]   [1997]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subjectx86-a-like processor support (patch against 2.1.35)
    WARNING: This is semi-*ALPHA*

    Attached is the latest version of my old definitive cyrix patch
    against the 2.1.35 kernel. All known bugs have been fixed, the
    (mis?)"features" are config options (read Documentation/Cyrix
    and the config help!) and the config questions have been slightly
    reordered to be more sensible (IMHO).

    The alpha bit is related to the new support for Cyrix M2 and
    AMD K5/6 recognition. M2 support should be perfectly safe even
    if wrong - it will be tested as soon as someone sends me an
    M2 machine (yeah right...). AMD K5/K6 support uses the extended
    AMD cpuid ops. If this is wrong it will _only_ be a problem
    when reading /proc/cpuinfo so boot single user, cat /proc/cpuinfo
    and see what happens...

    If you have an M2, K5 or K6 please let me know if it works!

    Oh yeah, the Cx486 recognition should get closer to reality
    and the Cyrix Gx86 (aka MediaGX) should be recognised as such.

    Oh yeah (2), there is a new config option that removes the
    Cyrix processor induced delays on I/O instructions. We _shouldn't_
    need them because we use dummy I/O to get delays where necessary.
    Let someone know if drivers start to fail with this option enabled.

    Oh yeah (3), I changed some fields in /proc/cpuinfo. "cpu" becomes
    "cpu family" and the value is a single digit without the trailing
    "86" added. This agrees with how the CPU vendors refer to the
    family data these days. "cpuid" becomes "cpuid level" and the value
    gives the highest cpuid code supported (excluding such things as
    AMD extensions) or -1 if cpuid is not supported. These changes
    may break things that parse /proc/cpuinfo but I don't know of
    anything that does at the moment. Touch wood...

    Mike

    --
    .----------------------------------------------------------------------.
    | Mike Jagdis | Internet: mailto:mike@roan.co.uk |
    | Roan Technology Ltd. | |
    | 54A Peach Street, Wokingham | Telephone: +44 118 989 0403 |
    | RG40 1XG, ENGLAND | Fax: +44 118 989 1195 |
    `----------------------------------------------------------------------'
    Index: Documentation/Configure.help
    ===================================================================
    RCS file: /usr/CVS/linux/Documentation/Configure.help,v
    retrieving revision 1.1.2.30
    diff -u -u -r1.1.2.30 Configure.help
    --- Configure.help 1997/04/16 20:52:10 1.1.2.30
    +++ Configure.help 1997/04/18 22:48:10
    @@ -794,11 +794,11 @@
    will be called binfmt_java.o. If you don't know what to answer at
    this point then answer Y.

    -Processor type
    +Processor family
    CONFIG_M386
    This is the processor type of your CPU. This information is used for
    optimizing purposes. In order to compile a kernel that can run on
    - all Intel CPU types (albeit not optimally fast), you can specify
    + all x86 CPU types (albeit not optimally fast), you can specify
    "386" here. If you specify one of "486" or "Pentium" or "PPro",
    then the kernel will run on all of these CPUs: 486 and Pentium
    (=586) and Pentium Pro (=686). In rare cases, it can make sense to
    @@ -4820,6 +4820,81 @@
    called AP1000+. For details on our efforts to port Linux to this
    machine see http://cap.anu.edu.au/cap/projects/linux or mail to
    hackers@cafe.anu.edu.au
    +
    +Support for Cyrix processors
    +CONFIG_CYRIX
    + This enables recognition of Cyrix processors. Without it
    + /proc/cpuinfo will list your processor as an unknown model
    + of Cyrix. With it it will list the correct details. It should
    + be safe to say Y here regardless of what processor you are
    + actually using. If this option is not enabled none of the
    + Cyrix feature options are available.
    +
    +Enable suspend on halt power saving feature
    +CONFIG_CYRIX_SUSP_HLT
    + Suspend on halt causes the processor to enter a low power state
    + when the "hlt" instruction is executed. This is disabled at
    + power up and many BIOSs leave it that way. You probably want it
    + enabled since it dramatically reduces the operating temperature
    + of the processor. In a few rare cases there may be problems
    + with some bus master DMA cards if this is enabled.
    +
    +No I/O recovery delays
    +CONFIG_CYRIX_FAST_IO
    + Historically programmers used "jmp $+2" instructions to create
    + delays between I/O instructions. The branch prediction of 5x86
    + and higher processors renders this ineffective and so a selectable
    + delay is implemented for I/O instructions in the processor. Linux
    + uses dummy I/O instructions where necessary rather than jumps
    + and so the extra processor imposed delay should not be necessary.
    + Enabling this option removes this delay.
    +
    +5x86 performance features
    +CONFIG_CYRIX_5X86
    + The Cyrix 5x86 has several performance feature which are enabled
    + using on-chip registers. This code attempts to ensure that the
    + useful features are set to suit Linux. Read Documentation/Cyrix
    + before enabling this.
    +
    +6x86 performance features
    +CONFIG_CYRIX_6X86
    + The Cyrix 6x86 has several performance feature which are enabled
    + using on-chip registers. Most are normally enabled by the BIOS
    + however this code ensures that all the useful ones are set to
    + suit Linux. Read Documentation/Cyrix before enabling this.
    +
    +Avoid unnecessary locked cycles
    +CONFIG_CYRIX_6X86_NOLOCK
    + Enabling this option causes the 6x86 not to use locked bus cycles
    + except for page table access and interrupt acknowledge cycles.
    + This allows the data used by descriptor tables, xchg instructions
    + and instructions preceeded by the LOCK prefix to be cached leading
    + to improved performance. Enabling this option has no effect if
    + an SMP kernel is being built - SMP requires locked cycles to
    + guarantee processor synchronization.
    +
    +Allocate L1 cache lines on write misses
    +CONFIG_CYRIX_6X86_WTALLOC
    + If this is enabled L1 cache write misses will cause a cache line
    + to be allocated. This may result in increased performance. On the
    + other hand it may cause excessive trashing of the L1 cache when
    + copying or zeroing pages.
    +
    +Branch Target Buffer features
    +CONFIG_CYRIX_6X86_BTB
    + The Cyrix 6x86 has branch prediction logic which is normally
    + only set to handle short branches (as in small loops and ifs).
    + This code attempts on configure the branch prediction logic
    + approriately. Read Documentation/Cyrix before enabling this.
    +
    +Variable sized paging mechanism (VSPM)
    +CONFIG_CYRIX_6X86_VSPM
    + Variable sized paging mechanism (VSPM) is a feature of the Cyrix
    + 6x86 family of processors that allows large regions of memory
    + to be mapped in one go, significantly reducing the amount of work
    + the MMU has to do compared with traditional paging. However VSPM
    + is known to be buggy in many 6x86 chip revisions. Please read
    + Documentation/Cyrix before enabling this.

    Sparc ESP SCSI support
    CONFIG_SCSI_SUNESP
    Index: Documentation/Cyrix
    ===================================================================
    RCS file: Cyrix
    diff -N Cyrix
    --- /dev/null Sat Dec 21 17:56:06 1996
    +++ Cyrix Tue Apr 22 23:55:58 1997
    @@ -0,0 +1,153 @@
    + Cyrix Processor Support
    + -----------------------
    +
    +Processor Recognition
    +---------------------
    +
    +Cyrix processors prior to the M2 power up in a default mode which
    +is designed to avoid compatibility problems with software that
    +makes assumptions about processor capabilities based solely on
    +the apparent family of processor. Unless special handling is
    +provided Cyrix chips will be identified as some unknown model
    +of 486.
    +
    + The Cyrix processor recognition kernel build option compiles
    +in code that enables the CPUID instruction on Cyrix processors
    +and that uses the Cyrix specific DEVID feature to identify the
    +particular type of Cyrix chip present.
    +
    + The M2 and later processors have CPUID enabled by default
    +however special handling is still required to read the specific
    +processor type using DEVID since the CPUID information gives
    +family 6, model 0 - i.e. an A step PPro.
    +
    + The combination of CPUID and DEVID allows all current Cyrix
    +processors to be recognised and listed correctly in /proc/cpuinfo.
    +This includes Cx486, 5x86, 6x86, Gx86 (aka MediaGx) and M2.
    +
    + Processor recognition is required for all other Cyrix specific
    +options.
    +
    +
    +Suspend on Halt Power Saving
    +----------------------------
    +
    +The suspend on halt power saving feature allows the processor to
    +enter a low power mode when the "hlt" instruction is executed. This
    +results in dramatically reduced operating temperatures if you do
    +not spend long periods of time running processor intensive tasks.
    +Cyrix processors allow this feature to be enabled an disabled
    +through their configuration registers. The default state on reset
    +is disabled and many (most?) BIOSs leave it disabled hence a
    +kernel configuration option is provided that adds code to explicitly
    +enabled suspend on halt when Linux boots.
    +
    + However there appear to be a few rare cases in which the
    +combination of suspend on halt and some bus master DMA cards can
    +cause the system to lock up. If this appears to happen you may
    +need to leave suspend on halt in its default state. (Note that
    +an option to _disable_ suspend on halt is not provided. If your
    +BIOS enables it you have to live with it)
    +
    +
    +5x86 Performance Features
    +-------------------------
    +
    +The 5x86 contains a performance control register that allows
    +several performance enhancing features to be turned on. Unfortunately
    +many of these features do not appear to work correctly. The 5x86
    +performance features kernel build option will attempt to set
    +the performance control register appropriately but it is
    +impossible to guarantee that even these conservative settings
    +will work on all chips.
    +
    + WARNING: If this is enabled you may find that the only way to
    +reboot is to power cycle the machine. Even a hard reboot seems
    +to fail on some systems.
    +
    +
    +6x86 Performance Features
    +-------------------------
    +
    +Like the 5x86 the 6x86 has several Cyrix specific performance
    +features. Normally a 6x86 aware BIOS will set these to reasonable,
    +if not fully optimal, settings. The 6x86 performance features
    +kernel build option mostly fine tunes them, however it also
    +enables the SUSP_HLT feature that causes the 6x86 to enter a low
    +power mode whenever the hlt instruction is executed causing the
    +CPU to wait for an external event such as an interrupt. This
    +dramatically reduces the working temperature of the chip but
    +is one feature that many BIOS leave disabled.
    +
    +
    +6x86 Branch Prediction
    +----------------------
    +
    +The 6x86 uses speculative execution coupled with several levels
    +of branch prediction to maximise processing speed. While the
    +default power up state is reasonable the branch prediction logic
    +is configurable and there may be some benefit in fine tuning it.
    +
    + Unfortunately Cyrix offer no documentation on how to configure
    +branch prediction and IBM have only partial documentation available.
    +Further detail and speculation is available from the 6x86opt package
    +by Mikael Johansson <Mikael.Johansson@helsinki.fi>.
    +
    + The initial power up state of the 6x86 configures the branch
    +prediction logic to handle short branches. The 6x86 branch target
    +buffer features kernel build option enables code that enables
    +handling of long branches as well. It is not clear if this will
    +benefit in your particular case or not.
    +
    +
    +6x86 Variable Sized Paging Mechanism
    +------------------------------------
    +
    +The variable sized paging mechanism (VSPM) is a feature of the Cyrix
    +6x86 family of processors that allows large regions of memory
    +to be mapped using a single MMU entry rather than many individual
    +page sized entries. This significantly reduces the overhead in
    +accessing such regions. It is also ideally suited to use for the
    +linear mapping of physical memory to kernel memory used by Linux.
    +
    + The Cyrix documenation offers only a brief paragraph of explanation.
    +Unfortunately the observed behaviour of VSPM suggests that even
    +this little information is not entirely correct. Worse still, no one
    +at Cyrix is able to answer questions concerning VSPM. Given that
    +every revision of 6x86 has *different* VSPM bugs this is not entirely
    +surprising! Work arounds are in place for the known bugs in step 1,
    +revisions 4, 5 and 6 chips. Revision 7 is also believed to work.
    +
    + WARNING: There appears to be no way to disable a VSPM entry once
    +it has been created short of a hard reset (which may mean a power
    +cycle). Failure to clear the VSPM entries means that programs that
    +use virtual memory layouts different from Linux will crash unexpectedly
    +after Linux has been running. This includes Windows NT/95, programs
    +that use DOS extenders etc.
    +
    + By experiment:
    +
    + * VSPM pages must be power of two sizes. A single 24MB page fails.
    + This is not entirely surprising but the documentation could give
    + the impression that VSPM supports arbitrary sizes.
    +
    + * Documentation suggests there are 8 VSPM slots (3 bit index) but
    + tests show the upper four slots mirror the lower four.
    +
    + * With a 16MB page followed by an 8MB page I always get a write
    + fault on the last 4k of the 8MB page. With 8MB plus 4MB I can't
    + even boot.
    + If we have such a memory size we map the first power of two
    + with a VSPM entry and use traditional paging for the rest.
    +
    + * VSPM entries appear to override traditional page table entries
    + so we must not overlap the start of the vmalloc region.
    +
    + * Do not try and create a mapping with dirty and accessed flags
    + clear - a step 1 rev 5 chip will crash.
    +
    + * The valid bit in a VSPM entry is non-functional. There is no way
    + to invalidate a VSPM entry once it has been written.
    +
    + * Attempting to replace a VSPM entry with one that maps a zero
    + sized region from 0 to 0 crashes the CPU.
    Index: arch/i386/config.in
    ===================================================================
    RCS file: /usr/CVS/linux/arch/i386/config.in,v
    retrieving revision 1.1.2.6
    diff -u -u -r1.1.2.6 config.in
    --- config.in 1997/04/11 22:10:18 1.1.2.6
    +++ config.in 1997/04/18 22:41:04
    @@ -9,6 +9,30 @@
    bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
    endmenu

    +choice 'Processor family' \
    + "386 CONFIG_M386 \
    + 486 CONFIG_M486 \
    + Pentium CONFIG_M586 \
    + PPro CONFIG_M686" Pentium
    +
    +mainmenu_option next_comment
    +comment 'Processor features'
    +
    +bool 'Cyrix processor recognition' CONFIG_CYRIX
    +if [ "$CONFIG_CYRIX" = "y" ]; then
    + bool 'Enable suspend on halt power saving' CONFIG_CYRIX_SUSP_HLT
    + bool 'No I/O recovery delays' CONFIG_CYRIX_FAST_IO
    + bool '5x86 performance features' CONFIG_CYRIX_5X86
    + bool '6x86 performance features' CONFIG_CYRIX_6X86
    + if [ "$CONFIG_CYRIX_6X86" = "y" ]; then
    + bool ' Avoid unnecessary locked cycles' CONFIG_CYRIX_6X86_NOLOCK
    + bool ' Allocate L1 cache lines on write misses' CONFIG_CYRIX_6X86_WTALLOC
    + bool ' Branch Target Buffer features' CONFIG_CYRIX_6X86_BTB
    + bool ' Variable sized paging mechanism (VSPM)' CONFIG_CYRIX_6X86_VSPM
    + fi
    +fi
    +endmenu
    +
    mainmenu_option next_comment
    comment 'Loadable module support'
    bool 'Enable loadable module support' CONFIG_MODULES
    @@ -38,11 +62,6 @@
    tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
    fi

    -choice 'Processor type' \
    - "386 CONFIG_M386 \
    - 486 CONFIG_M486 \
    - Pentium CONFIG_M586 \
    - PPro CONFIG_M686" Pentium
    bool 'Video mode selection support' CONFIG_VIDEO_SELECT

    tristate 'Parallel port support' CONFIG_PNP_PARPORT
    Index: arch/i386/defconfig
    ===================================================================
    RCS file: /usr/CVS/linux/arch/i386/defconfig,v
    retrieving revision 1.1.2.19
    diff -u -u -r1.1.2.19 defconfig
    --- defconfig 1997/04/16 20:06:30 1.1.2.19
    +++ defconfig 1997/04/18 21:58:32
    @@ -8,6 +8,23 @@
    # CONFIG_EXPERIMENTAL is not set

    #
    +# Processor options
    +#
    +# CONFIG_M386 is not set
    +# CONFIG_M486 is not set
    +# CONFIG_M586 is not set
    +CONFIG_M686=y
    +CONFIG_CYRIX=y
    +CONFIG_CYRIX_SUSP_HLT=y
    +# CONFIG_CYRIX_FAST_IO is not set
    +# CONFIG_CYRIX_5X86 is not set
    +# CONFIG_CYRIX_6X86 is not set
    +# CONFIG_CYRIX_6X86_NOLOCK is not set
    +# CONFIG_CYRIX_6X86_WTALLOC is not set
    +# CONFIG_CYRIX_6X86_BTB is not set
    +# CONFIG_CYRIX_6X86_VSPM is not set
    +
    +#
    # Loadable module support
    #
    CONFIG_MODULES=y
    @@ -29,6 +46,12 @@
    # CONFIG_M486 is not set
    # CONFIG_M586 is not set
    CONFIG_M686=y
    +CONFIG_CYRIX=y
    +CONFIG_CYRIX_SUSP_HLT=y
    +# CONFIG_CYRIX_5X86 is not set
    +# CONFIG_CYRIX_6X86 is not set
    +# CONFIG_CYRIX_6X86_BTB is not set
    +# CONFIG_CYRIX_6X86_VSPM is not set
    # CONFIG_VIDEO_SELECT is not set
    # CONFIG_PNP_PARPORT is not set

    Index: arch/i386/kernel/head.S
    ===================================================================
    RCS file: /usr/CVS/linux/arch/i386/kernel/head.S,v
    retrieving revision 1.1.2.3
    diff -u -u -r1.1.2.3 head.S
    --- head.S 1997/04/16 20:52:27 1.1.2.3
    +++ head.S 1997/04/18 22:36:09
    @@ -140,13 +140,80 @@
    checkCPUtype:
    #endif

    + movl $-1,SYMBOL_NAME(have_cpuid) # -1 for no CPUID initially
    +
    /* check if it is 486 or 386. */
    /*
    * XXX - this does a lot of unnecessary setup. Alignment checks don't
    * apply at our cpl of 0 and the stack ought to be aligned already, and
    * we don't need to preserve eflags.
    */
    - movl $3, SYMBOL_NAME(x86)
    + /*
    + * A Cyrix preserves flags in cases where other CPUs change
    + * them in undefined ways. We need to know this since we may
    + * need to enable the CPUID instruction at least. (Cyrix chips
    + * prior to M2 have CPUID disabled by default, the Cx486s
    + * didn't have it at all.)
    + */
    + xor %ax,%ax
    + sahf
    + movb $5,%ax
    + movb $2,%bx
    + div %bl
    + lahf
    + cmpb $2,%ah
    + jne ncyrix
    +
    + /*
    + * It behaves like a Cyrix so put "Cyrix" in the vendor id
    + * field. It may be overwritten later with the real thing
    + * if CPUID works.
    + */
    + movl $0x69727943,SYMBOL_NAME(x86_vendor_id) # low 4 chars
    + movl $0x00000078,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars
    +
    +#ifdef CONFIG_CYRIX
    + /*
    + * N.B. The pattern of accesses to 0x22 and 0x23 is *important*
    + * so do not try and "optimise" it! For the same reason we
    + * do all this with interrupts off just to be sure.
    + */
    +#define setCx86(reg, val) \
    + movb reg,%ax; \
    + outb %ax,$0x22; \
    + movb val,%ax; \
    + outb %ax,$0x23
    +
    +#define getCx86(reg) \
    + movb reg,%ax; \
    + outb %ax,$0x22; \
    + inb $0x23,%ax
    +
    + cli
    + getCx86($0xc3) # get CCR3
    + movb %ax,%cx # Save old value
    + movb %ax,%bx
    + andb $0x0f,%bx # Enable all config registers (for CCR4 access)
    + orb $0x10,%bx
    + setCx86($0xc3,%bx)
    +
    +#ifdef CONFIG_CYRIX_SUSP_HLT
    + getCx86($0xc2) # CCR2 |= SUSP_HLT
    + orb $8,%ax
    + movb %ax,%bx
    + setCx86($0xc2,%bx)
    +#endif
    +
    + getCx86($0xe8) # CCR4 |= CPUID | DTE_EN
    + orb $0x90,%ax
    + movb %ax,%bx
    + setCx86($0xe8,%bx)
    +
    + setCx86($0xc3,%cx) # Restore old CCR3
    + sti
    +#endif /* CONFIG_CYRIX */
    +
    +ncyrix: movl $3, SYMBOL_NAME(x86)# at least 386
    pushfl # push EFLAGS
    popl %eax # get EFLAGS
    movl %eax,%ecx # save original EFLAGS
    @@ -158,7 +225,8 @@
    xorl %ecx,%eax # change in flags
    andl $0x40000,%eax # check if AC bit changed
    je is386
    - movl $4,SYMBOL_NAME(x86)
    +
    + movl $4,SYMBOL_NAME(x86)# at least 486
    movl %ecx,%eax
    xorl $0x200000,%eax # check ID flag
    pushl %eax
    @@ -166,14 +234,23 @@
    pushfl # 487SX we can't change it
    popl %eax
    xorl %ecx,%eax
    - andl $0x200000,%eax
    - je is486
    -isnew: pushl %ecx # restore original EFLAGS
    + pushl %ecx # restore original EFLAGS
    popfl
    - incl SYMBOL_NAME(have_cpuid) # we have CPUID
    + andl $0x200000,%eax
    + je nocpuid
    +
    + /* get vendor info */
    + xorl %eax, %eax # call CPUID with 0 -> return vendor ID
    + .byte 0x0f, 0xa2 # CPUID
    + movl %eax,SYMBOL_NAME(have_cpuid) # save CPUID level
    + movl %ebx,SYMBOL_NAME(x86_vendor_id) # lo 4 chars
    + movl %edx,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars
    + movl %ecx,SYMBOL_NAME(x86_vendor_id)+8 # last 4 chars
    +
    + cmpl $0,%eax # do we have processor info as well?
    + je nocpuid
    +
    /* get processor type */
    - # LINUS WE HAVE A BUG HERE - MUST CHECK WITH
    - # CPUID#0 THAT CPUID#1 IS SUPPORTED...
    movl $1, %eax # Use the CPUID instruction to
    .byte 0x0f, 0xa2 # check the processor type
    movb %al, %cl # save reg for future use
    @@ -185,23 +262,154 @@
    andb $0x0f, %cl # mask mask revision
    movb %cl,SYMBOL_NAME(x86_mask)
    movl %edx,SYMBOL_NAME(x86_capability)
    - /* get vendor info */
    - xorl %eax, %eax # call CPUID with 0 -> return vendor ID
    - .byte 0x0f, 0xa2 # CPUID
    - movl %ebx,SYMBOL_NAME(x86_vendor_id) # lo 4 chars
    - movl %edx,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars
    - movl %ecx,SYMBOL_NAME(x86_vendor_id)+8 # last 4 chars

    - movl %cr0,%eax # 486+
    - andl $0x80000011,%eax # Save PG,PE,ET
    - orl $0x50022,%eax # set AM, WP, NE and MP
    - jmp 2f
    -is486: pushl %ecx # restore original EFLAGS
    - popfl
    - movl %cr0,%eax # 486
    +nocpuid:
    + /*
    + * Even if we had CPUID Cyrix tries to look compatible with
    + * Intel so we have to go elsewhere for the nitty gritty.
    + */
    + cmpl $0x69727943,SYMBOL_NAME(x86_vendor_id) # "Cyri[x.*]"?
    + je chkdevid # maybe ...
    + cmpl $0x444d4163,SYMBOL_NAME(x86_vendor_id)+8 # "[Authenti]cAMD"?
    + jne is486
    + orb $0x20,SYMBOL_NAME(x86) # Flag as AMD
    + jmp is486
    +
    +chkdevid:
    + orb $0x10,SYMBOL_NAME(x86) # Flag as Cyrix
    + movb $0xfe,SYMBOL_NAME(x86_model) # Generic Cx486?
    + movb $0,SYMBOL_NAME(x86_mask)
    +
    +#ifdef CONFIG_CYRIX
    + cli # Test for DEVID
    + getCx86($0xc3) # by writing CCR3
    + movb %ax,%cx
    + movb %ax,%bx
    + orb $0x80,%bx
    + setCx86($0xc3,%bx)
    + getCx86($0xc0) # dummy to change bus
    + getCx86($0xc3)
    + sti
    + cmp %ax,%cx
    + je is486 # not writable == no DEVID
    +
    + cli
    + setCx86($0xc3,%cx) # restore CCR3
    +
    + getCx86($0xff) # get DEVID in preference to any CPUID
    + movb %al,SYMBOL_NAME(x86_mask)
    + getCx86($0xfe)
    + movb %al,SYMBOL_NAME(x86_model)
    + sti
    +
    +#if defined(CONFIG_CYRIX_5X86) || defined(CONFIG_CYRIX_6X86)
    + andb $0xf0,%al
    +# ifdef CONFIG_CYRIX_6X86
    + cmpb $0x30,%al
    + je is6x86
    +# endif
    +# ifdef CONFIG_CYRIX_5X86
    + cmpb $0x20,%al
    + je is5x86
    +# endif
    + /* Cx486 or something beyond a 6x86 (M2 or better). Note that
    + * the Cx486 also have performance features we could tweak
    + * but given the problems with [56]x86, the number of Cx486
    + * variants, the fact that the Cx486 is pretty well dead
    + * now and the fact that I have no Cx486 myself I haven't
    + * risked it. Nor have I looked at the M2 in any detail yet.
    + */
    + jmp is486
    +#endif
    +
    +#if defined(CONFIG_CYRIX_5X86) || defined(CONFIG_CYRIX_FAST_IO)
    + /* Special set up for 5x86 */
    +is5x86:
    + cli
    + movb %cx,%bx
    + andb $0x0f,%bx # Enable all config registers
    + orb $0x10,%bx
    + setCx86($0xc3,%bx)
    +
    + getCx86($0x20) # PCR0 |= LSSER | BTB_EN
    + orb $0x82,%ax # LOOP_EN is broken, RSTK_EN shows no benefit
    + movb %ax,%bx # and LSSER=0 could break memory mapped
    + setCx86($0x20,%bx) # devices - we have no way of knowing)
    +
    +#ifdef CONFIG_CYRIX_FAST_IO
    + getCx86($0xe8) # CCR4: IORT=0 (nodelay)
    + andb $0xf1,%ax
    + movb %ax,%bx
    + setCx86($0xe8,%bx)
    +#endif
    +
    + setCx86($0xc3,%cx) # restore CCR3
    + sti
    + jmp is486
    +#endif
    +
    +#if defined(CONFIG_CYRIX_6X86) || defined(CONFIG_CYRIX_FAST_IO)
    + /* Special set up for 6x86 */
    +is6x86:
    + cli
    + movb %cx,%bx
    + andb $0x0f,%bx # Enable all config registers
    + orb $0x10,%bx
    + setCx86($0xc3,%bx)
    +
    +#if !defined(__SMP__) && defined(CONFIG_CYRIX_6X86_NOLOCK)
    + getCx86($0xc1) # CCR1 |= NO_LOCK
    + orb $0x10,%ax
    + movb %ax,%bx
    + setCx86($0xe8,%bx)
    +#endif
    +
    +#ifdef CONFIG_CYRIX_FAST_IO
    + getCx86($0xe8) # CCR4: IORT=7 (nodelay)
    + orb $0x97,%ax
    + movb %ax,%bx
    + setCx86($0xe8,%bx)
    +#endif
    +
    + getCx86($0xe9) # CCR5 &= ~SLOP
    + andb $0xfd,%ax
    +#ifdef CONFIG_CYRIX_6X86_WTALLOC
    + orb $0x01,%ax # CCR5 |= WT_ALLOC
    +#endif
    + movb %ax,%bx
    + setCx86($0xe9,%bx)
    +
    +#ifdef CONFIG_CYRIX_6X86_BTB # IBM documentation, no Cyrix docs
    + getCx86($0x30) # Enable test register opcodes
    + movb %ax,%dx
    + orb $0x40,%ax
    + movb %ax,%bx
    + setCx86($0x30,%bx)
    +
    + mov $0x28,%ebx # Enable FAR COFs in BTB
    + .byte 0x0f,0x26,0xcb # mov %ebx,%tr1
    + .byte 0x0f,0x24,0xd0 # mov %tr2,%eax
    +#if 0
    + and $0xfffffffd,%eax # according to Cyrix/IBM documentation
    +#else
    + and $0xfffffff8,%eax # according to 6x86opt
    + or $0x00000070,%eax
    +#endif
    + .byte 0x0f,0x26,0xd0 # mov %eax,%tr2
    +
    + setCx86($0x30,%dx) # Disable test register opcodes
    +#endif /* CONFIG_CYRIX_6X86_BTB */
    +
    + setCx86($0xc3,%cx) # restore CCR3
    + sti
    +#endif /* CONFIG_CYRIX_6X86 or CONFIG_CYRIX_FAST_IO */
    +#endif /* CONFIG_CYRIX */
    +
    +is486: movl %cr0,%eax # 486 or better
    andl $0x80000011,%eax # Save PG,PE,ET
    orl $0x50022,%eax # set AM, WP, NE and MP
    jmp 2f
    +
    is386: pushl %ecx # restore original EFLAGS
    popfl
    movl %cr0,%eax # 386
    Index: arch/i386/kernel/setup.c
    ===================================================================
    RCS file: /usr/CVS/linux/arch/i386/kernel/setup.c,v
    retrieving revision 1.1.2.7
    diff -u -u -r1.1.2.7 setup.c
    --- setup.c 1997/04/16 20:52:30 1.1.2.7
    +++ setup.c 1997/04/22 22:26:51
    @@ -42,7 +42,7 @@
    char x86_mask = 0; /* set by kernel/head.S */
    int x86_capability = 0; /* set by kernel/head.S */
    int fdiv_bug = 0; /* set if Pentium(TM) with FP bug */
    -int have_cpuid = 0; /* set if CPUID instruction works */
    +int have_cpuid = -1; /* CPUID level (-1 if no CPUID) */

    char x86_vendor_id[13] = "unknown";

    @@ -254,11 +254,83 @@
    return NULL;
    }

    -static const char * getmodel(int x86, int model)
    +static const char * cyrixmodel(unsigned int nr)
    +{
    + static char nbuf[32];
    +
    + /* Note that some of the possibilities this decoding allows
    + * have never actually been manufactured - but those that
    + * do actually exist are correctly decoded.
    + */
    + if (nr < 0x20) {
    + strcpy(nbuf, "Cx486");
    + if (!(nr & 0x10)) {
    + sprintf(nbuf+5, "%c%s%c",
    + (nr & 0x01) ? 'D' : 'S',
    + (nr & 0x04) ? "Rx" : "LC",
    + (nr & 0x02) ? '2' : '\000');
    + } else if (!(nr & 0x08)) {
    + sprintf(nbuf+5, "S%s%c",
    + (nr & 0x01) ? "2" : "",
    + (nr & 0x02) ? 'e' : '\000');
    + } else {
    + sprintf(nbuf+5, "DX%c",
    + nr == 0x1b ? '2'
    + : (nr == 0x1f ? '4' : '\000'));
    + }
    + return nbuf;
    + } else if (nr >= 0x20 && nr <= 0x4f) { /* 5x86, 6x86 or Gx86 */
    + sprintf(nbuf, "%cx86 %cx Core/Bus Clock",
    + "??56G"[nr>>4],
    + "12??43"[nr & 0x05]);
    + return nbuf;
    + } else if (nr >= 0x50 && nr <= 0x5f) { /* Cyrix M2 */
    + sprintf(nbuf, "M2 %c%sx Core/Bus Clock",
    + "12233445"[nr & 0x07],
    + (nr && !(nr&1)) ? ".5" : "");
    + return nbuf;
    + }
    +
    + /* Probably 0xfd (Cx486[SD]LC with no ID register)
    + * or 0xfe (Cx486 A step with no ID register).
    + */
    + return "Cx486";
    +}
    +
    +static const char * getmodel(int x86, int model, int have_cpuid)
    {
    const char *p = NULL;
    - static char nbuf[12];
    - switch (x86) {
    + static char nbuf[49];
    +
    + if ((x86 & 0xf0) == 0x10) { /* Cyrix */
    + p = cyrixmodel(model);
    + } else if ((x86 & 0xf0) == 0x20) { /* AMD */
    + /* Actually we must have cpuid or we could never have
    + * figured out that this was AMD from the vendor info :-).
    + */
    + if (have_cpuid < 0)
    + p = "Am486";
    + else {
    + int n, dummy;
    + cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
    + if (!n) {
    + if (x86 == 4)
    + p = i486model(model);
    + else if (x86 == 5)
    + p = "AMD-K5 (Model 0)";
    + } else {
    + int *v = (int *)nbuf;
    + cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
    + cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
    + cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
    + nbuf[48] = '\0';
    + p = nbuf;
    + }
    + }
    + } else switch (x86) { /* Intel */
    + case 0:
    + p = "unknown";
    + break;
    case 4:
    p = i486model(model);
    break;
    @@ -304,21 +376,25 @@
    #endif

    len += sprintf(buffer+len,"processor\t: %d\n"
    - "cpu\t\t: %c86\n"
    + "cpu family\t: %c\n"
    "model\t\t: %s\n"
    "vendor_id\t: %s\n",
    CPUN,
    - CD(x86)+'0',
    - CD(have_cpuid) ?
    - getmodel(CD(x86), CD(x86_model)) :
    - "unknown",
    + (CD(x86) & 0x0f)+'0',
    + getmodel(CD(x86), CD(x86_model), CD(have_cpuid)),
    CD(x86_vendor_id));

    - if (CD(x86_mask))
    - len += sprintf(buffer+len,
    - "stepping\t: %d\n",
    - CD(x86_mask));
    - else
    + if (CD(x86_mask)) {
    + if ((CD(x86) & 0xf0) == 0x10)
    + len += sprintf(buffer+len,
    + "stepping\t: %d rev %d\n",
    + CD(x86_mask) >> 4,
    + CD(x86_mask) & 0x0f);
    + else
    + len += sprintf(buffer+len,
    + "stepping\t: %d\n",
    + CD(x86_mask));
    + } else
    len += sprintf(buffer+len,
    "stepping\t: unknown\n");

    @@ -327,7 +403,7 @@
    "hlt_bug\t\t: %s\n"
    "fpu\t\t: %s\n"
    "fpu_exception\t: %s\n"
    - "cpuid\t\t: %s\n"
    + "cpuid level\t: %d\n"
    "wp\t\t: %s\n"
    "flags\t\t:",
    CD(fdiv_bug) ? "yes" : "no",
    @@ -335,7 +411,7 @@
    CD(hard_math) ? "yes" : "no",
    (CD(hard_math) && ignore_irq13)
    ? "yes" : "no",
    - CD(have_cpuid) ? "yes" : "no",
    + CD(have_cpuid),
    CD(wp_works_ok) ? "yes" : "no");

    for ( i = 0 ; i < 32 ; i++ ) {
    Index: arch/i386/mm/init.c
    ===================================================================
    RCS file: /usr/CVS/linux/arch/i386/mm/init.c,v
    retrieving revision 1.1.2.10
    diff -u -u -r1.1.2.10 init.c
    --- init.c 1997/04/16 20:52:32 1.1.2.10
    +++ init.c 1997/04/16 21:49:19
    @@ -116,6 +116,67 @@
    unsigned long tmp;
    unsigned long address;

    +#if defined(CONFIG_CYRIX) && defined(CONFIG_CYRIX_6X86_VSPM) && !defined(__SMP__)
    + unsigned long vspm_max = __va(0);
    +
    + /* If this is a Cyrix 6x86 we use the variable size paging
    + * mechanism (VSPM) to map physical memory at 0xc0000000.
    + * Note that VSPM pages are stored on the CPU only so this
    + * needs to be done for each processor in a multi-processor
    + * system. If we have a mixture of processors we would also
    + * need to set up the traditional page tables for them.
    + * Note also that VSPM pages will be global to all memory
    + * spaces since they are not stored in the normal page
    + * directories.
    + */
    + if ((x86 & 0xf0) == 0x10 || (x86_model & 0xf0) == 0x30) {
    + int vspm_index = 0;
    +
    + do {
    + unsigned long mem_size;
    +
    + mem_size = 4096;
    + while (vspm_max+mem_size < end_mem)
    + mem_size <<= 1;
    + if (vspm_max+mem_size > end_mem)
    + if ((mem_size >>= 1) < 4096)
    + break;
    +
    + asm( "movl %0,%%eax\n"
    + "movl %%eax,%%tr7\n"
    + "movl $0x00000004,%%eax\n"
    + "movl %%eax,%%tr6\n"
    + "movl %1,%%eax\n"
    + "movl %%eax,%%tr7\n"
    + "movl %2,%%eax\n"
    + "movl %%eax,%%tr6\n"
    + : /* no outputs */
    + : "g" ((((mem_size-1) & 0xfffff000)) | (vspm_index<<7)),
    + "g" ((__pa(vspm_max) & 0xfffff000) | (vspm_index<<7)),
    + "g" ((vspm_max & 0xfffff000) | 0x00000cd6)
    + : "eax", "cc"
    + );
    +
    + vspm_max += mem_size;
    +
    +#if 1
    + /* Just use one VSPM page for now, anything
    + * over will be traditionally paged.
    + * (See Documentation/Cyrix.)
    + */
    + break;
    +#endif
    + } while (vspm_max < end_mem && vspm_index++ < 4);
    +
    + /* Write protect does work correctly but the test
    + * will fail because we can't map just page 0 read
    + * only from under the VSPM big page. If we didn't
    + * know before we do now.
    + */
    + wp_works_ok = 1;
    + }
    +#endif
    +
    /*
    * Physical page 0 is special; it's not touched by Linux since BIOS
    * and SMM (for laptops with [34]86/SL chips) may need it. It is read
    @@ -182,6 +243,17 @@
    address += 4*1024*1024;
    continue;
    }
    +
    +#if defined(CONFIG_CYRIX) && defined(CONFIG_CYRIX_6X86_VSPM) && !defined(__SMP__)
    + if ((x86 & 0xf0) == 0x10 /* Cyrix */
    + && (x86_model & 0xf0) == 0x30 /* 6x86 */
    + && (address + PAGE_SIZE*PTRS_PER_PTE) < vspm_max) { /* within VSPM mappings */
    + pg_dir++;
    + address += PAGE_SIZE * PTRS_PER_PTE;
    + continue;
    + }
    +#endif
    +
    /*
    * We're on a [34]86, use normal page tables.
    * pg_table is physical at this point
    @@ -194,12 +266,18 @@

    pgd_val(pg_dir[768]) = _PAGE_TABLE | (unsigned long) pg_table;
    pg_dir++;
    +
    /* now change pg_table to kernel virtual addresses */
    pg_table = (pte_t *) __va(pg_table);
    for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
    pte_t pte = mk_pte(address, PAGE_KERNEL);
    +#if defined(CONFIG_CYRIX) && defined(CONFIG_CYRIX_6X86_VSPM) && !defined(__SMP__)
    + if (address < vspm_max || address >= end_mem)
    + pte_val(pte) = 0;
    +#else
    if (address >= end_mem)
    pte_val(pte) = 0;
    +#endif
    set_pte(pg_table, pte);
    address += PAGE_SIZE;
    }
    Index: include/asm-i386/bugs.h
    ===================================================================
    RCS file: /usr/CVS/linux/include/asm-i386/bugs.h,v
    retrieving revision 1.1.2.2
    diff -u -u -r1.1.2.2 bugs.h
    --- bugs.h 1996/10/09 20:59:53 1.1.2.2
    +++ bugs.h 1997/04/19 12:16:35
    @@ -130,5 +130,5 @@
    check_tlb();
    check_fpu();
    check_hlt();
    - system_utsname.machine[1] = '0' + x86;
    + system_utsname.machine[1] = '0' + (x86 & 0x0f);
    }
    Index: include/asm-i386/processor.h
    ===================================================================
    RCS file: /usr/CVS/linux/include/asm-i386/processor.h,v
    retrieving revision 1.1.2.8
    diff -u -u -r1.1.2.8 processor.h
    --- processor.h 1997/01/27 20:26:27 1.1.2.8
    +++ processor.h 1997/04/11 22:42:49
    @@ -16,7 +16,7 @@
    */

    extern char hard_math;
    -extern char x86; /* lower 4 bits */
    +extern char x86; /* upper 4 bits=vendor, lower 4 bits=family */
    extern char x86_vendor_id[13];
    extern char x86_model; /* lower 4 bits */
    extern char x86_mask; /* lower 4 bits */
    @@ -168,5 +168,21 @@
    #define alloc_kernel_stack(p) __get_free_page(GFP_KERNEL)
    #define free_task_struct(p) kfree(p)
    #define free_kernel_stack(page) free_page((page))
    +
    +extern inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
    +{
    + __asm__("movl %4,%%eax\n\t"
    + ".byte 0x0f, 0xa2\n\t"
    + "movl %%eax,%0\n\t"
    + "movl %%ebx,%1\n\t"
    + "movl %%ecx,%2\n\t"
    + "movl %%edx,%3\n\t"
    + : "=m" (*eax),
    + "=m" (*ebx),
    + "=m" (*ecx),
    + "=m" (*edx)
    + : "g" (op)
    + : "eax", "ebx", "ecx", "edx", "cc");
    +}

    #endif /* __ASM_I386_PROCESSOR_H */
    \
     
     \ /
      Last update: 2005-03-22 13:39    [W:4.370 / U:1.076 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site