diff options
32 files changed, 1420 insertions, 1510 deletions
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index b4b8af8..e78382b 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -1,6 +1,7 @@ -/*- +/* * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. + * Copyright (c) 1997 KATO Takenori. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -35,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id$ + * $Id: identcpu.c,v 1.13 1997/02/22 09:32:19 peter Exp $ */ #include "opt_cpu.h" @@ -54,12 +55,18 @@ #include <machine/sysarch.h> #include <machine/md_var.h> +#include <i386/isa/isa_device.h> + /* XXX - should be in header file */ void i486_bzero __P((void *buf, size_t len)); -void identifycpu(void); /* XXX should be in different header file */ +void printcpuinfo(void); /* XXX should be in different header file */ +void finishidentcpu(void); void earlysetcpuclass(void); +void panicifcpuunsupported(void); +static void identifycyrix(void); +u_long cyrix_did; /* Device ID of Cyirx CPU */ int cpu_class = CPUCLASS_386; /* least common denominator */ char machine[] = "i386"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); @@ -74,13 +81,19 @@ static struct cpu_nameclass i386_cpus[] = { { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ { "i486DX", CPUCLASS_486 }, /* CPU_486 */ { "Pentium", CPUCLASS_586 }, /* CPU_586 */ - { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ + { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */ { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ + { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */ + { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */ + { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */ + { "Cyrix 6x86 MMX", CPUCLASS_586 }, /* CPU_M2 (XXX) */ + { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */ }; void -identifycpu(void) +printcpuinfo(void) { + cpu_class = i386_cpus[cpu].cpu_class; printf("CPU: "); strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); @@ -140,7 +153,6 @@ identifycpu(void) * Values taken from AMD Processor Recognition * http://www.amd.com/html/products/pcd/techdocs/appnotes/20734c.pdf */ - cpu_model[0] = '\0'; strcpy(cpu_model, "AMD "); switch (cpu_id & 0xFF0) { case 0x4E0: @@ -162,8 +174,119 @@ identifycpu(void) strcat(cpu_model, "Unknown"); break; } - } + } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { + strcpy(cpu_model, "Cyrix "); + switch (cyrix_did & 0xf0) { + case 0x00: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486SLC"); + break; + case 0x01: + strcat(cpu_model, "486DLC"); + break; + case 0x02: + strcat(cpu_model, "486SLC2"); + break; + case 0x03: + strcat(cpu_model, "486DLC2"); + break; + case 0x04: + strcat(cpu_model, "486SRx"); + break; + case 0x05: + strcat(cpu_model, "486DRx"); + break; + case 0x06: + strcat(cpu_model, "486SRx2"); + break; + case 0x07: + strcat(cpu_model, "486DRx2"); + break; + case 0x08: + strcat(cpu_model, "486SRu"); + break; + case 0x09: + strcat(cpu_model, "486DRu"); + break; + case 0x0a: + strcat(cpu_model, "486SRu2"); + break; + case 0x0b: + strcat(cpu_model, "486DRu2"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x10: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486S"); + break; + case 0x01: + strcat(cpu_model, "486S2"); + break; + case 0x02: + strcat(cpu_model, "486Se"); + break; + case 0x03: + strcat(cpu_model, "486S2e"); + break; + case 0x0a: + strcat(cpu_model, "486DX"); + break; + case 0x0b: + strcat(cpu_model, "486DX2"); + break; + case 0x0f: + strcat(cpu_model, "486DX4"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x20: + if ((cyrix_did & 0x0f) < 8) + strcat(cpu_model, "6x86"); /* Where did you get it? */ + else + strcat(cpu_model, "5x86"); + break; + case 0x30: + strcat(cpu_model, "6x86"); + break; + case 0x40: + /* XXX */ + strcat(cpu_model, "Gx86"); + break; + case 0x50: + strcat(cpu_model, "Enhanced 6x86 with MMX"); + break; + case 0xf0: + switch (cyrix_did & 0x0f) { + case 0x0d: + strcat(cpu_model, "Overdrive CPU"); + case 0x0e: + strcpy(cpu_model, "Texas Instruments 486SXL"); + break; + case 0x0f: + strcat(cpu_model, "486SLC/DLC"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + } else if (strcmp(cpu_vendor,"IBM") == 0) + strcpy(cpu_model, "Blue Lightning CPU"); #endif + printf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_286: @@ -238,6 +361,14 @@ identifycpu(void) "\020CMOV" ); } + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + printf(" Device ID = 0x%lx", cyrix_did); + printf(" Stepping=%ld", (cyrix_did & 0xf000) >> 12); + printf(" Revision=%ld", (cyrix_did & 0x0fff) >> 8); +#ifndef CYRIX_CACHE_REALLY_WORKS + if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700) + printf("\n CPU cache: write-through mode"); +#endif } /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) @@ -248,6 +379,11 @@ identifycpu(void) * XXX - Do PPro CPUID level=2 stuff here? */ #endif +} + +void +panicifcpuunsupported(void) +{ /* * Now that we have told the user what they have, @@ -276,6 +412,152 @@ identifycpu(void) } } + +static volatile u_int trap_by_wrmsr; + +/* + * Special exception 16 handler. + * The wrmsr instruction generates invalid opcodes fault on 486-class + * Cyrix CPU. Stacked eip register points the wrmsr instruction in the + * function identblue() when this handler is called. Stacked eip should + * be advanced. + */ +inthand_t bluetrap; +asm +(" + .text +_bluetrap: + ss + movl $0xa8c1d, _trap_by_wrmsr # Don't ask meaning of the number :-). + addl $2, (%esp) # I know wrmsr is a 2-bytes instruction. + iret +"); + +/* + * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not + * support cpuid instruction. This function should be called after + * loading interrupt descriptor table register. + * + * I don't like this method that handles fault, but I couldn't get + * information for any other methods. Does blue giant know? + */ +static int +identblue(void) +{ + + trap_by_wrmsr = 0; + /* + * Cyrix 486-class CPU does not support wrmsr instruction. + * The wrmsr instruction causes invalid opcode fault, and exception + * will be trapped by bluetrap() on Cyrix 486-class CPU. The bluetrap() + * set the magic number to tra_by_wrmsr. + */ + setidt(6, bluetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + wrmsr(0x1002, 0x03000000LL); /* Fault on Cyrix 486-class CPU. */ + + if (trap_by_wrmsr == 0xa8c1d) + return 0; /* Cyrix CPU sets the magic number. */ + + return 1; /* IBM Blue Lightnig CPU */ +} + + +/* + * identifycyrix() set lower 16 bits of cyrix_did as follows: + * + * F E D C B A 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+---------------+ + * | SID | RID | Device ID | + * | (DIR 1) | (DIR 0) | + * +-------+-------+---------------+ + */ +static void +identifycyrix(void) +{ + u_long eflags; + int ccr2_test = 0, dir_test = 0; + u_char ccr2, ccr3; + + eflags = read_eflags(); + disable_intr(); + + ccr2 = read_cyrix_reg(CCR2); + write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW); + read_cyrix_reg(CCR2); + if (read_cyrix_reg(CCR2) != ccr2) + ccr2_test = 1; + write_cyrix_reg(CCR2, ccr2); + + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3); + read_cyrix_reg(CCR3); + if (read_cyrix_reg(CCR3) != ccr3) + dir_test = 1; /* CPU supports DIRs. */ + write_cyrix_reg(CCR3, ccr3); + + if (dir_test) { + /* Device ID registers are available. */ + cyrix_did = read_cyrix_reg(DIR1) << 8; + cyrix_did += read_cyrix_reg(DIR0); + } else if (ccr2_test) + cyrix_did = 0x0010; /* 486S A-step */ + else + cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ + + write_eflags(eflags); +} + +/* + * Final stage of CPU identification. -- Should I check TI? + */ +void +finishidentcpu(void) +{ + + if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + if (cpu == CPU_486) { + /* + * These conditions are equivalent to: + * - CPU does not support cpuid instruction. + * - Cyrix/IBM CPU is detected. + */ + if (identblue()) { + strcpy(cpu_vendor, "IBM"); + cpu = CPU_BLUE; + return; + } + } + identifycyrix(); + /* + * This routine contains a trick. + * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now. + */ + switch (cyrix_did & 0x00f0) { + case 0x00: + case 0x10: + case 0xf0: + cpu = CPU_486DLC; + break; + case 0x20: + if ((cyrix_did & 0x00f0) < 8) + cpu = CPU_M1; + else + cpu = CPU_M1SC; + break; + case 0x30: + cpu = CPU_M1; + break; + case 0x40: + cpu = CPU_M1SC; + break; + default: + /* M2 and later CPUs are treated as M2. */ + cpu = CPU_M2; + break; + } + } +} + /* * This routine is called specifically to set up cpu_class before * startrtclock() uses it. Probably this should be rearranged so that @@ -287,5 +569,6 @@ identifycpu(void) void earlysetcpuclass(void) { + cpu_class = i386_cpus[cpu].cpu_class; } diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S index 95930fe..5efddc5 100644 --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id$ + * $Id: locore.s,v 1.81 1997/02/22 09:32:22 peter Exp $ * * originally from: locore.s, by William F. Jolitz * @@ -192,6 +192,21 @@ _bdb_exists: .long 0 */ NON_GPROF_ENTRY(btext) +#ifdef PC98 + jmp 1f + .globl _pc98_system_parameter + .org 0x400 +_pc98_system_parameter: + .space 0x240 /* BIOS parameter block */ +1: + /* save SYSTEM PARAMETER for resume (NS/T or other) */ + movl $0xa1000,%esi + movl $0x100000,%edi + movl $0x0630,%ecx + cld + rep + movsb +#else /* IBM-PC */ #ifdef BDE_DEBUGGER #ifdef BIOS_STEALS_3K cmpl $0x0375c339,0x95504 @@ -205,6 +220,7 @@ NON_GPROF_ENTRY(btext) /* Tell the bios to warmboot next time */ movw $0x1234,0x472 +#endif /* PC98 */ /* Set up a real frame in case the double return in newboot is executed. */ pushl %ebp @@ -232,6 +248,28 @@ NON_GPROF_ENTRY(btext) */ movl $R(tmpstk),%esp +#ifdef PC98 + testb $0x02,0x100620 /* pc98_machine_type & M_EPSON_PC98 */ + jz 3f + cmpb $0x0b,0x100624 /* epson_machine_id <= 0x0b */ + ja 3f + + /* count up memory */ + movl $0x100000,%eax /* next, talley remaining memory */ + movl $0xFFF-0x100,%ecx +1: movl 0(%eax),%ebx /* save location to check */ + movl $0xa55a5aa5,0(%eax) /* write test pattern */ + cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ + jne 2f + movl %ebx,0(%eax) /* restore memory */ + addl $PAGE_SIZE,%eax + loop 1b +2: subl $0x100000,%eax + shrl $17,%eax + movb %al,0x100401 +3: +#endif + call identify_cpu /* clear bss */ @@ -326,7 +364,7 @@ begin: addl $(13*4),%esp /* back to a frame we can return with */ /* - * now we've run main() and determined what cpu-type we are, we can + * Now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ @@ -524,7 +562,11 @@ olddiskboot: movl %eax,R(_bootdev) #if defined(USERCONFIG_BOOT) && defined(USERCONFIG) +#ifdef PC98 + movl $0x90200, %esi +#else movl $0x10200, %esi +#endif movl $R(_userconfig_from_boot),%edi movl $512,%ecx cld @@ -557,11 +599,29 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz try486 + + /* NexGen CPU does not have aligment check flag. */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jz trynexgen + popfl movl $CPU_386,R(_cpu) jmp 3f -1: /* Try to toggle identification flag; does not exist on early 486s. */ +trynexgen: + movl $CPU_NX586,R(_cpu) + movl $0x4778654e,R(_cpu_vendor) # store vendor string + movl $0x72446e65,R(_cpu_vendor+4) + movl $0x6e657669,R(_cpu_vendor+8) + movl $0,R(_cpu_vendor+12) + jmp 3f + +try486: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx @@ -576,89 +636,40 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz trycpuid movl $CPU_486,R(_cpu) - /* check for Cyrix 486DLC -- based on check routine */ - /* documented in "Cx486SLC/e SMM Programmer's Guide" */ - xorw %dx,%dx - cmpw %dx,%dx # set flags to known state - pushfw - popw %cx # store flags in ecx - movw $0xffff,%ax - movw $0x0004,%bx - divw %bx - pushfw - popw %ax - andw $0x08d5,%ax # mask off important bits - andw $0x08d5,%cx - cmpw %ax,%cx - - jnz 3f # if flags changed, Intel chip - - movl $CPU_486DLC,R(_cpu) # set CPU value for Cyrix + /* + * Check Cyrix CPU + * Cyrix CPUs do not change the undefined flags following + * execution of the divide instruction which divides 5 by 2. + * + * Note: CPUID is enabled on M2, so it passes another way. + */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jnc trycyrix + popfl + jmp 3f /* You may use Intel CPU. */ + +trycyrix: + popfl + /* + * IBM Bluelighting CPU also doesn't change the undefined flags. + * Because IBM doesn't disclose the information for Bluelighting + * CPU, we couldn't distinguish it from Cyrix's (including IBM + * brand of Cyrix CPUs). + */ movl $0x69727943,R(_cpu_vendor) # store vendor string - movw $0x0078,R(_cpu_vendor+4) - -#ifndef CYRIX_CACHE_WORKS - /* Disable caching of the ISA hole only. */ - invd - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - orb $(CCR0_NC1|CCR0_BARB),%al - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - invd -#else /* CYRIX_CACHE_WORKS */ - /* Set cache parameters */ - invd # Start with guaranteed clean cache - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - andb $~CCR0_NC0,%al -#ifndef CYRIX_CACHE_REALLY_WORKS - orb $(CCR0_NC1|CCR0_BARB),%al -#else /* CYRIX_CACHE_REALLY_WORKS */ - orb $CCR0_NC1,%al -#endif /* !CYRIX_CACHE_REALLY_WORKS */ - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - /* clear non-cacheable region 1 */ - movb $(NCR1+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 2 */ - movb $(NCR2+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 3 */ - movb $(NCR3+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 4 */ - movb $(NCR4+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* enable caching in CR0 */ - movl %cr0,%eax - andl $~(CR0_CD|CR0_NW),%eax - movl %eax,%cr0 - invd -#endif /* !CYRIX_CACHE_WORKS */ + movl $0x736e4978,R(_cpu_vendor+4) + movl $0x64616574,R(_cpu_vendor+8) jmp 3f -1: /* Use the `cpuid' instruction. */ +trycpuid: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,R(_cpu_high) # highest capability diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s index 95930fe..5efddc5 100644 --- a/sys/amd64/amd64/locore.s +++ b/sys/amd64/amd64/locore.s @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id$ + * $Id: locore.s,v 1.81 1997/02/22 09:32:22 peter Exp $ * * originally from: locore.s, by William F. Jolitz * @@ -192,6 +192,21 @@ _bdb_exists: .long 0 */ NON_GPROF_ENTRY(btext) +#ifdef PC98 + jmp 1f + .globl _pc98_system_parameter + .org 0x400 +_pc98_system_parameter: + .space 0x240 /* BIOS parameter block */ +1: + /* save SYSTEM PARAMETER for resume (NS/T or other) */ + movl $0xa1000,%esi + movl $0x100000,%edi + movl $0x0630,%ecx + cld + rep + movsb +#else /* IBM-PC */ #ifdef BDE_DEBUGGER #ifdef BIOS_STEALS_3K cmpl $0x0375c339,0x95504 @@ -205,6 +220,7 @@ NON_GPROF_ENTRY(btext) /* Tell the bios to warmboot next time */ movw $0x1234,0x472 +#endif /* PC98 */ /* Set up a real frame in case the double return in newboot is executed. */ pushl %ebp @@ -232,6 +248,28 @@ NON_GPROF_ENTRY(btext) */ movl $R(tmpstk),%esp +#ifdef PC98 + testb $0x02,0x100620 /* pc98_machine_type & M_EPSON_PC98 */ + jz 3f + cmpb $0x0b,0x100624 /* epson_machine_id <= 0x0b */ + ja 3f + + /* count up memory */ + movl $0x100000,%eax /* next, talley remaining memory */ + movl $0xFFF-0x100,%ecx +1: movl 0(%eax),%ebx /* save location to check */ + movl $0xa55a5aa5,0(%eax) /* write test pattern */ + cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ + jne 2f + movl %ebx,0(%eax) /* restore memory */ + addl $PAGE_SIZE,%eax + loop 1b +2: subl $0x100000,%eax + shrl $17,%eax + movb %al,0x100401 +3: +#endif + call identify_cpu /* clear bss */ @@ -326,7 +364,7 @@ begin: addl $(13*4),%esp /* back to a frame we can return with */ /* - * now we've run main() and determined what cpu-type we are, we can + * Now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ @@ -524,7 +562,11 @@ olddiskboot: movl %eax,R(_bootdev) #if defined(USERCONFIG_BOOT) && defined(USERCONFIG) +#ifdef PC98 + movl $0x90200, %esi +#else movl $0x10200, %esi +#endif movl $R(_userconfig_from_boot),%edi movl $512,%ecx cld @@ -557,11 +599,29 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz try486 + + /* NexGen CPU does not have aligment check flag. */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jz trynexgen + popfl movl $CPU_386,R(_cpu) jmp 3f -1: /* Try to toggle identification flag; does not exist on early 486s. */ +trynexgen: + movl $CPU_NX586,R(_cpu) + movl $0x4778654e,R(_cpu_vendor) # store vendor string + movl $0x72446e65,R(_cpu_vendor+4) + movl $0x6e657669,R(_cpu_vendor+8) + movl $0,R(_cpu_vendor+12) + jmp 3f + +try486: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx @@ -576,89 +636,40 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz trycpuid movl $CPU_486,R(_cpu) - /* check for Cyrix 486DLC -- based on check routine */ - /* documented in "Cx486SLC/e SMM Programmer's Guide" */ - xorw %dx,%dx - cmpw %dx,%dx # set flags to known state - pushfw - popw %cx # store flags in ecx - movw $0xffff,%ax - movw $0x0004,%bx - divw %bx - pushfw - popw %ax - andw $0x08d5,%ax # mask off important bits - andw $0x08d5,%cx - cmpw %ax,%cx - - jnz 3f # if flags changed, Intel chip - - movl $CPU_486DLC,R(_cpu) # set CPU value for Cyrix + /* + * Check Cyrix CPU + * Cyrix CPUs do not change the undefined flags following + * execution of the divide instruction which divides 5 by 2. + * + * Note: CPUID is enabled on M2, so it passes another way. + */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jnc trycyrix + popfl + jmp 3f /* You may use Intel CPU. */ + +trycyrix: + popfl + /* + * IBM Bluelighting CPU also doesn't change the undefined flags. + * Because IBM doesn't disclose the information for Bluelighting + * CPU, we couldn't distinguish it from Cyrix's (including IBM + * brand of Cyrix CPUs). + */ movl $0x69727943,R(_cpu_vendor) # store vendor string - movw $0x0078,R(_cpu_vendor+4) - -#ifndef CYRIX_CACHE_WORKS - /* Disable caching of the ISA hole only. */ - invd - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - orb $(CCR0_NC1|CCR0_BARB),%al - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - invd -#else /* CYRIX_CACHE_WORKS */ - /* Set cache parameters */ - invd # Start with guaranteed clean cache - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - andb $~CCR0_NC0,%al -#ifndef CYRIX_CACHE_REALLY_WORKS - orb $(CCR0_NC1|CCR0_BARB),%al -#else /* CYRIX_CACHE_REALLY_WORKS */ - orb $CCR0_NC1,%al -#endif /* !CYRIX_CACHE_REALLY_WORKS */ - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - /* clear non-cacheable region 1 */ - movb $(NCR1+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 2 */ - movb $(NCR2+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 3 */ - movb $(NCR3+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 4 */ - movb $(NCR4+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* enable caching in CR0 */ - movl %cr0,%eax - andl $~(CR0_CD|CR0_NW),%eax - movl %eax,%cr0 - invd -#endif /* !CYRIX_CACHE_WORKS */ + movl $0x736e4978,R(_cpu_vendor+4) + movl $0x64616574,R(_cpu_vendor+8) jmp 3f -1: /* Use the `cpuid' instruction. */ +trycpuid: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,R(_cpu_high) # highest capability diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index bf3eaa2..c1094ee 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.228 1997/02/22 09:32:26 peter Exp $ + * $Id: machdep.c,v 1.229 1997/02/24 00:37:43 alex Exp $ */ #include "npx.h" @@ -122,8 +122,11 @@ extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); -extern void identifycpu(void); /* XXX header file */ +extern void printcpuinfo(void); /* XXX header file */ extern void earlysetcpuclass(void); /* same header file */ +extern void finishidentcpu(void); +extern void panicifcpuunsupported(void); +extern void initializecpu(void); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) @@ -208,7 +211,8 @@ cpu_startup(dummy) printf(version); earlysetcpuclass(); startrtclock(); - identifycpu(); + printcpuinfo(); + panicifcpuunsupported(); #ifdef PERFMON perfmon_init(); #endif @@ -1059,6 +1063,10 @@ init386(first) Debugger("Boot flags requested debugger"); #endif + finishidentcpu(); /* Final stage of CPU initialization */ + setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + initializecpu(); /* Initialize CPU registers */ + /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. */ diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 5dd24b1..9cd0351 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: cpufunc.h,v 1.61 1997/02/22 09:34:08 peter Exp $ */ /* @@ -196,6 +196,12 @@ insl(u_int port, void *addr, size_t cnt) } static __inline void +invd(void) +{ + __asm __volatile("invd"); +} + +static __inline void invlpg(u_int addr) { __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory"); @@ -339,6 +345,12 @@ setbits(volatile unsigned *addr, u_int bits) } static __inline void +wbinvd(void) +{ + __asm __volatile("wbinvd"); +} + +static __inline void write_eflags(u_long ef) { __asm __volatile("pushl %0; popfl" : : "r" (ef)); @@ -360,6 +372,7 @@ u_long inl __P((u_int port)); void insb __P((u_int port, void *addr, size_t cnt)); void insl __P((u_int port, void *addr, size_t cnt)); void insw __P((u_int port, void *addr, size_t cnt)); +void invd __P((void)); void invlpg __P((u_int addr)); void invltlb __P((void)); u_short inw __P((u_int port)); @@ -376,6 +389,7 @@ quad_t rdpmc __P((u_int pmc)); quad_t rdtsc __P((void)); u_long read_eflags __P((void)); void setbits __P((volatile unsigned *addr, u_int bits)); +void wbinvd __P((void)); void write_eflags __P((u_long ef)); void wrmsr __P((u_int msr, quad_t newval)); diff --git a/sys/amd64/include/cputypes.h b/sys/amd64/include/cputypes.h index 4905900..695dafc 100644 --- a/sys/amd64/include/cputypes.h +++ b/sys/amd64/include/cputypes.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ + * $Id: cputypes.h,v 1.7 1997/02/22 09:34:14 peter Exp $ */ #ifndef _MACHINE_CPUTYPES_H_ @@ -52,5 +52,9 @@ #define CPU_586 5 /* Intel P.....m (I hate lawyers; it's TM) */ #define CPU_486DLC 6 /* Cyrix 486DLC */ #define CPU_686 7 /* Pentium Pro */ - +#define CPU_M1SC 8 /* Cyrix M1sc (aka 5x86) */ +#define CPU_M1 9 /* Cyrix M1 (aka 6x86) */ +#define CPU_BLUE 10 /* IBM BlueLighting CPU */ +#define CPU_M2 11 /* Cyrix M2 (aka enhanced 6x86 with MMX */ +#define CPU_NX586 12 /* NexGen (now AMD) 586 */ #endif /* _MACHINE_CPUTYPES_H_ */ diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index c74313f..307257c 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: md_var.h,v 1.12 1997/02/22 09:34:49 peter Exp $ */ #ifndef _MACHINE_MD_VAR_H_ @@ -41,6 +41,7 @@ extern u_int atdevbase; /* offset in virtual memory of ISA io mem */ extern u_long cpu_feature; extern u_long cpu_high; extern u_long cpu_id; +extern u_long cyrix_did; extern char cpu_vendor[]; extern char etext[]; extern char kstack[]; @@ -72,4 +73,9 @@ void userconfig __P((void)); void vm_bounce_init __P((void)); int vm_page_zero_idle __P((void)); +#ifdef PC98 +extern int need_pre_dma_flush; +extern int need_post_dma_flush; +#endif + #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h index 7344d8f..8e4dfc7 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 - * $Id$ + * $Id: specialreg.h,v 1.12 1997/02/22 09:35:15 peter Exp $ */ #ifndef _MACHINE_SPECIALREG_H_ @@ -54,11 +54,12 @@ /* * Bits in 486 special registers: */ -#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ -#define CR0_WP 0x00010000 /* Write Protect (honor page protect in all modes) */ -#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ -#define CR0_NW 0x20000000 /* Not Write-through */ -#define CR0_CD 0x40000000 /* Cache Disable */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in + all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ /* * Bits in PPro special registers @@ -94,26 +95,81 @@ #define CPUID_CMOV 0x8000 /* - * Cyrix 486 DLC special registers, accessible as IO ports. + * Cyrix configuration registers, accessible as IO ports. */ -#define CCR0 0xc0 /* configuration control register 0 */ -#define CCR0_NC0 0x01 /* first 64K of each 1M memory region is - non-cacheable */ -#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ -#define CCR0_A20M 0x04 /* enables A20M# input pin */ -#define CCR0_KEN 0x08 /* enables KEN# input pin */ -#define CCR0_FLUSH 0x10 /* enables FLUSH# input pin */ -#define CCR0_BARB 0x20 /* flushes internal cache when entering hold - state */ -#define CCR0_CO 0x40 /* cache org: 1=direct mapped, 0=2x set assoc */ -#define CCR0_SUSPEND 0x80 /* enables SUSP# and SUSPA# pins */ - -#define CCR1 0xc1 /* configuration control register 1 */ -#define CCR1_RPL 0x01 /* enables RPLSET and RPLVAL# pins */ -/* the remaining 7 bits of this register are reserved */ +#define CCR0 0xc0 /* Configuration control register 0 */ +#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is + non-cacheable */ +#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ +#define CCR0_A20M 0x04 /* Enables A20M# input pin */ +#define CCR0_KEN 0x08 /* Enables KEN# input pin */ +#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */ +#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold + state */ +#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set + assoc */ +#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */ + +#define CCR1 0xc1 /* Configuration control register 1 */ +#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */ +#define CCR1_SMI 0x02 /* Enables SMM pins */ +#define CCR1_SMAC 0x04 /* System management memory access */ +#define CCR1_MMAC 0x08 /* Main memory access */ +#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */ +#define CCR1_SM3 0x80 /* SMM address space address region 3 */ + +#define CCR2 0xc2 +#define CCR2_WB 0x02 /* Enables WB cache interface pins */ +#define CCR2_SADS 0x02 /* Slow ADS */ +#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */ +#define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */ +#define CCR2_WT1 0x10 /* WT region 1 */ +#define CCR2_WPR1 0x10 /* Write-protect region 1 */ +#define CCR2_BARB 0x20 /* Flushes write-back cache when entering + hold state. */ +#define CCR2_BWRT 0x40 /* Enables burst write cycles */ +#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ + +#define CCR3 0xc3 +#define CCR3_SMILOCK 0x01 /* SMM register lock */ +#define CCR3_NMI 0x02 /* Enables NMI during SMM */ +#define CCR3_LINBRST 0x04 /* Linear address burst cycles */ +#define CCR3_SMMMODE 0x08 /* SMM Mode */ +#define CCR3_MAPEN0 0x10 /* Enables Map0 */ +#define CCR3_MAPEN1 0x20 /* Enables Map1 */ +#define CCR3_MAPEN2 0x40 /* Enables Map2 */ +#define CCR3_MAPEN3 0x80 /* Enables Map3 */ + +#define CCR4 0xe8 +#define CCR4_IOMASK 0x07 +#define CCR4_MEM 0x08 /* Enables momory bypassing */ +#define CCR4_DTE 0x10 /* Enables directory table entry cache */ +#define CCR4_FASTFPE 0x20 /* Fast FPU exception */ +#define CCR4_CPUID 0x80 /* Enables CPUID instruction */ + +#define CCR5 0xe9 +#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */ +#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */ +#define CCR5_LBR1 0x10 /* Local bus region 1 */ +#define CCR5_ARREN 0x20 /* Enables ARR region */ + +/* Performance Control Register (5x86 only). */ +#define PCR0 0x20 +#define PCR0_RSTK 0x01 /* Enables return stack */ +#define PCR0_BTB 0x02 /* Enables branch target buffer */ +#define PCR0_LOOP 0x04 /* Enables loop */ +#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to + serialize pipe. */ +#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ +#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ +#define PCR0_LSSER 0x80 /* Disable reorder */ + +/* Device Identification Registers */ +#define DIR0 0xfe +#define DIR1 0xff /* - * the following four 3-byte registers control the non-cacheable regions. + * The following four 3-byte registers control the non-cacheable regions. * These registers must be written as three separate bytes. * * NCRx+0: A31-A24 of starting address @@ -123,26 +179,98 @@ * The non-cacheable region's starting address must be aligned to the * size indicated by the NCR_SIZE_xx field. */ -#define NCR1 0xc4 -#define NCR2 0xc7 -#define NCR3 0xca -#define NCR4 0xcd - -#define NCR_SIZE_0K 0 -#define NCR_SIZE_4K 1 -#define NCR_SIZE_8K 2 -#define NCR_SIZE_16K 3 -#define NCR_SIZE_32K 4 -#define NCR_SIZE_64K 5 -#define NCR_SIZE_128K 6 -#define NCR_SIZE_256K 7 -#define NCR_SIZE_512K 8 -#define NCR_SIZE_1M 9 -#define NCR_SIZE_2M 10 -#define NCR_SIZE_4M 11 -#define NCR_SIZE_8M 12 -#define NCR_SIZE_16M 13 -#define NCR_SIZE_32M 14 -#define NCR_SIZE_4G 15 +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * The address region registers are used to specify the location and + * size for the eight address regions. + * + * ARRx + 0: A31-A24 of start address + * ARRx + 1: A23-A16 of start address + * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx + */ +#define ARR0 0xc4 +#define ARR1 0xc7 +#define ARR2 0xca +#define ARR3 0xcd +#define ARR4 0xd0 +#define ARR5 0xd3 +#define ARR6 0xd6 +#define ARR7 0xd9 + +#define ARR_SIZE_0K 0 +#define ARR_SIZE_4K 1 +#define ARR_SIZE_8K 2 +#define ARR_SIZE_16K 3 +#define ARR_SIZE_32K 4 +#define ARR_SIZE_64K 5 +#define ARR_SIZE_128K 6 +#define ARR_SIZE_256K 7 +#define ARR_SIZE_512K 8 +#define ARR_SIZE_1M 9 +#define ARR_SIZE_2M 10 +#define ARR_SIZE_4M 11 +#define ARR_SIZE_8M 12 +#define ARR_SIZE_16M 13 +#define ARR_SIZE_32M 14 +#define ARR_SIZE_4G 15 + +/* + * The region control registers specify the attributes associated with + * the ARRx addres regions. + */ +#define RCR0 0xdc +#define RCR1 0xdd +#define RCR2 0xde +#define RCR3 0xdf +#define RCR4 0xe0 +#define RCR5 0xe1 +#define RCR6 0xe2 +#define RCR7 0xe3 + +#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ +#define RCR_RCE 0x01 /* Enables caching for ARR7. */ +#define RCR_WWO 0x02 /* Weak write ordering. */ +#define RCR_WL 0x04 /* Weak locking. */ +#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WT 0x10 /* Write-through. */ +#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ + + +#ifndef LOCORE +static __inline u_char +read_cyrix_reg(u_char reg) +{ + outb(0x22, reg); + return inb(0x23); +} + +static __inline void +write_cyrix_reg(u_char reg, u_char data) +{ + outb(0x22, reg); + outb(0x23, data); +} +#endif #endif /* !_MACHINE_SPECIALREG_H_ */ diff --git a/sys/conf/Makefile.pc98 b/sys/conf/Makefile.pc98 index 8fe080c..ecdb567 100644 --- a/sys/conf/Makefile.pc98 +++ b/sys/conf/Makefile.pc98 @@ -3,7 +3,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id$ +# $Id: Makefile.pc98,v 1.11 1997/02/22 09:43:21 peter Exp $ # # Makefile for FreeBSD # @@ -58,7 +58,7 @@ DRIVER_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< SYSTEM_CFILES= ioconf.c param.c vnode_if.c config.c -SYSTEM_SFILES= ${PC98}/i386/locore.s +SYSTEM_SFILES= ${I386}/i386/locore.s SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o config.o SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ @@ -89,7 +89,7 @@ clean: #lint: /tmp param.c # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ -# ${PC98}/i386/Locore.c ${CFILES} ioconf.c param.c | \ +# ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ # grep -v 'struct/union .* never defined' | \ # grep -v 'possible pointer alignment problem' @@ -101,7 +101,7 @@ symbols.sort: ${I386}/i386/symbols.raw grep -v '^#' ${I386}/i386/symbols.raw \ | sed 's/^ //' | sort -u > symbols.sort -locore.o: ${PC98}/i386/locore.s assym.s +locore.o: ${I386}/i386/locore.s assym.s ${NORMAL_S} # everything potentially depends on the Makefile since everything potentially diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 76c4d17..23103b9 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.155 1997/03/16 07:09:01 gibbs Exp $ +# $Id: files.i386,v 1.156 1997/03/16 17:25:53 bde Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/*.[chyl]" \ @@ -47,6 +47,7 @@ i386/i386/i386-gdbstub.c optional ddb i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet +i386/i386/initcpu.c standard # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index 37cf0a9..b5c3dce 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $Id: files.pc98,v 1.16 1997/02/22 09:43:22 peter Exp $ +# $Id: files.pc98,v 1.17 1997/03/19 16:14:25 kato Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/*.[chyl]" \ @@ -49,6 +49,7 @@ i386/i386/i386-gdbstub.c optional ddb i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet +i386/i386/initcpu.c standard # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index eba1a87..cce8411 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.36 1997/02/28 16:56:06 bde Exp $ +# $Id: options.i386,v 1.37 1997/03/12 17:41:35 joerg Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -37,10 +37,23 @@ CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h CLK_USE_I586_CALIBRATION opt_clock.h -I386_CPU opt_cpu.h -I486_CPU opt_cpu.h -I586_CPU opt_cpu.h -I686_CPU opt_cpu.h +CPU_BLUELIGHTNING_FPU_OP_CACHE opt_cpu.h +CPU_BLUELIGHTNING_3X opt_cpu.h +CPU_BTB_EN opt_cpu.h +CPU_DISABLE_5X86_LSSER opt_cpu.h +CPU_FASTER_5X86_FPU opt_cpu.h +CPU_I486_ON_386 opt_cpu.h +CPU_IORT opt_cpu.h +CPU_LOOP_EN opt_cpu.h +CPU_RSTK_EN opt_cpu.h +CPU_SUSP_HLT opt_cpu.h +CPU_UPGRADE_HW_CACHE opt_cpu.h +CYRIX_CACHE_WORKS opt_cpu.h +CYRIX_CACHE_REALLY_WORKS opt_cpu.h +I386_CPU opt_cpu.h +I486_CPU opt_cpu.h +I586_CPU opt_cpu.h +I686_CPU opt_cpu.h SC_SPLASH_SCREEN opt_syscons.h MAXCONS opt_syscons.h diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index cf26896..38d240f 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -1,4 +1,4 @@ -# $Id: options.pc98,v 1.17 1997/03/01 11:06:41 kato Exp $ +# $Id: options.pc98,v 1.18 1997/03/13 17:04:23 kato Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -37,10 +37,21 @@ CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h CLK_USE_I586_CALIBRATION opt_clock.h -I386_CPU opt_cpu.h -I486_CPU opt_cpu.h -I586_CPU opt_cpu.h -I686_CPU opt_cpu.h +CPU_BTB_EN opt_cpu.h +CPU_DISABLE_5X86_LSSER opt_cpu.h +CPU_FASTER_5X86_FPU opt_cpu.h +CPU_I486_ON_386 opt_cpu.h +CPU_IORT opt_cpu.h +CPU_LOOP_EN opt_cpu.h +CPU_RSTK_EN opt_cpu.h +CPU_SUSP_HLT opt_cpu.h +CPU_UPGRADE_HW_CACHE opt_cpu.h +CYRIX_CACHE_WORKS opt_cpu.h +CYRIX_CACHE_REALLY_WORKS opt_cpu.h +I386_CPU opt_cpu.h +I486_CPU opt_cpu.h +I586_CPU opt_cpu.h +I686_CPU opt_cpu.h SC_SPLASH_SCREEN opt_syscons.h MAXCONS opt_syscons.h diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 76c4d17..23103b9 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.155 1997/03/16 07:09:01 gibbs Exp $ +# $Id: files.i386,v 1.156 1997/03/16 17:25:53 bde Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/*.[chyl]" \ @@ -47,6 +47,7 @@ i386/i386/i386-gdbstub.c optional ddb i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet +i386/i386/initcpu.c standard # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386 index eba1a87..cce8411 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.36 1997/02/28 16:56:06 bde Exp $ +# $Id: options.i386,v 1.37 1997/03/12 17:41:35 joerg Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -37,10 +37,23 @@ CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h CLK_USE_I586_CALIBRATION opt_clock.h -I386_CPU opt_cpu.h -I486_CPU opt_cpu.h -I586_CPU opt_cpu.h -I686_CPU opt_cpu.h +CPU_BLUELIGHTNING_FPU_OP_CACHE opt_cpu.h +CPU_BLUELIGHTNING_3X opt_cpu.h +CPU_BTB_EN opt_cpu.h +CPU_DISABLE_5X86_LSSER opt_cpu.h +CPU_FASTER_5X86_FPU opt_cpu.h +CPU_I486_ON_386 opt_cpu.h +CPU_IORT opt_cpu.h +CPU_LOOP_EN opt_cpu.h +CPU_RSTK_EN opt_cpu.h +CPU_SUSP_HLT opt_cpu.h +CPU_UPGRADE_HW_CACHE opt_cpu.h +CYRIX_CACHE_WORKS opt_cpu.h +CYRIX_CACHE_REALLY_WORKS opt_cpu.h +I386_CPU opt_cpu.h +I486_CPU opt_cpu.h +I586_CPU opt_cpu.h +I686_CPU opt_cpu.h SC_SPLASH_SCREEN opt_syscons.h MAXCONS opt_syscons.h diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index b4b8af8..e78382b 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -1,6 +1,7 @@ -/*- +/* * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. + * Copyright (c) 1997 KATO Takenori. * All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -35,7 +36,7 @@ * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp - * $Id$ + * $Id: identcpu.c,v 1.13 1997/02/22 09:32:19 peter Exp $ */ #include "opt_cpu.h" @@ -54,12 +55,18 @@ #include <machine/sysarch.h> #include <machine/md_var.h> +#include <i386/isa/isa_device.h> + /* XXX - should be in header file */ void i486_bzero __P((void *buf, size_t len)); -void identifycpu(void); /* XXX should be in different header file */ +void printcpuinfo(void); /* XXX should be in different header file */ +void finishidentcpu(void); void earlysetcpuclass(void); +void panicifcpuunsupported(void); +static void identifycyrix(void); +u_long cyrix_did; /* Device ID of Cyirx CPU */ int cpu_class = CPUCLASS_386; /* least common denominator */ char machine[] = "i386"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); @@ -74,13 +81,19 @@ static struct cpu_nameclass i386_cpus[] = { { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ { "i486DX", CPUCLASS_486 }, /* CPU_486 */ { "Pentium", CPUCLASS_586 }, /* CPU_586 */ - { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ + { "Cyrix 486", CPUCLASS_486 }, /* CPU_486DLC */ { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ + { "Cyrix 5x86", CPUCLASS_486 }, /* CPU_M1SC */ + { "Cyrix 6x86", CPUCLASS_486 }, /* CPU_M1 */ + { "Blue Lightning", CPUCLASS_486 }, /* CPU_BLUE */ + { "Cyrix 6x86 MMX", CPUCLASS_586 }, /* CPU_M2 (XXX) */ + { "NexGen 586", CPUCLASS_386 }, /* CPU_NX586 (XXX) */ }; void -identifycpu(void) +printcpuinfo(void) { + cpu_class = i386_cpus[cpu].cpu_class; printf("CPU: "); strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); @@ -140,7 +153,6 @@ identifycpu(void) * Values taken from AMD Processor Recognition * http://www.amd.com/html/products/pcd/techdocs/appnotes/20734c.pdf */ - cpu_model[0] = '\0'; strcpy(cpu_model, "AMD "); switch (cpu_id & 0xFF0) { case 0x4E0: @@ -162,8 +174,119 @@ identifycpu(void) strcat(cpu_model, "Unknown"); break; } - } + } else if (strcmp(cpu_vendor,"CyrixInstead") == 0) { + strcpy(cpu_model, "Cyrix "); + switch (cyrix_did & 0xf0) { + case 0x00: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486SLC"); + break; + case 0x01: + strcat(cpu_model, "486DLC"); + break; + case 0x02: + strcat(cpu_model, "486SLC2"); + break; + case 0x03: + strcat(cpu_model, "486DLC2"); + break; + case 0x04: + strcat(cpu_model, "486SRx"); + break; + case 0x05: + strcat(cpu_model, "486DRx"); + break; + case 0x06: + strcat(cpu_model, "486SRx2"); + break; + case 0x07: + strcat(cpu_model, "486DRx2"); + break; + case 0x08: + strcat(cpu_model, "486SRu"); + break; + case 0x09: + strcat(cpu_model, "486DRu"); + break; + case 0x0a: + strcat(cpu_model, "486SRu2"); + break; + case 0x0b: + strcat(cpu_model, "486DRu2"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x10: + switch (cyrix_did & 0x0f) { + case 0x00: + strcat(cpu_model, "486S"); + break; + case 0x01: + strcat(cpu_model, "486S2"); + break; + case 0x02: + strcat(cpu_model, "486Se"); + break; + case 0x03: + strcat(cpu_model, "486S2e"); + break; + case 0x0a: + strcat(cpu_model, "486DX"); + break; + case 0x0b: + strcat(cpu_model, "486DX2"); + break; + case 0x0f: + strcat(cpu_model, "486DX4"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + case 0x20: + if ((cyrix_did & 0x0f) < 8) + strcat(cpu_model, "6x86"); /* Where did you get it? */ + else + strcat(cpu_model, "5x86"); + break; + case 0x30: + strcat(cpu_model, "6x86"); + break; + case 0x40: + /* XXX */ + strcat(cpu_model, "Gx86"); + break; + case 0x50: + strcat(cpu_model, "Enhanced 6x86 with MMX"); + break; + case 0xf0: + switch (cyrix_did & 0x0f) { + case 0x0d: + strcat(cpu_model, "Overdrive CPU"); + case 0x0e: + strcpy(cpu_model, "Texas Instruments 486SXL"); + break; + case 0x0f: + strcat(cpu_model, "486SLC/DLC"); + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + break; + default: + strcat(cpu_model, "Unknown"); + break; + } + } else if (strcmp(cpu_vendor,"IBM") == 0) + strcpy(cpu_model, "Blue Lightning CPU"); #endif + printf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_286: @@ -238,6 +361,14 @@ identifycpu(void) "\020CMOV" ); } + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + printf(" Device ID = 0x%lx", cyrix_did); + printf(" Stepping=%ld", (cyrix_did & 0xf000) >> 12); + printf(" Revision=%ld", (cyrix_did & 0x0fff) >> 8); +#ifndef CYRIX_CACHE_REALLY_WORKS + if (cpu == CPU_M1 && (cyrix_did & 0xff00) < 0x1700) + printf("\n CPU cache: write-through mode"); +#endif } /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) @@ -248,6 +379,11 @@ identifycpu(void) * XXX - Do PPro CPUID level=2 stuff here? */ #endif +} + +void +panicifcpuunsupported(void) +{ /* * Now that we have told the user what they have, @@ -276,6 +412,152 @@ identifycpu(void) } } + +static volatile u_int trap_by_wrmsr; + +/* + * Special exception 16 handler. + * The wrmsr instruction generates invalid opcodes fault on 486-class + * Cyrix CPU. Stacked eip register points the wrmsr instruction in the + * function identblue() when this handler is called. Stacked eip should + * be advanced. + */ +inthand_t bluetrap; +asm +(" + .text +_bluetrap: + ss + movl $0xa8c1d, _trap_by_wrmsr # Don't ask meaning of the number :-). + addl $2, (%esp) # I know wrmsr is a 2-bytes instruction. + iret +"); + +/* + * Distinguish IBM Blue Lightning CPU from Cyrix CPUs that does not + * support cpuid instruction. This function should be called after + * loading interrupt descriptor table register. + * + * I don't like this method that handles fault, but I couldn't get + * information for any other methods. Does blue giant know? + */ +static int +identblue(void) +{ + + trap_by_wrmsr = 0; + /* + * Cyrix 486-class CPU does not support wrmsr instruction. + * The wrmsr instruction causes invalid opcode fault, and exception + * will be trapped by bluetrap() on Cyrix 486-class CPU. The bluetrap() + * set the magic number to tra_by_wrmsr. + */ + setidt(6, bluetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + wrmsr(0x1002, 0x03000000LL); /* Fault on Cyrix 486-class CPU. */ + + if (trap_by_wrmsr == 0xa8c1d) + return 0; /* Cyrix CPU sets the magic number. */ + + return 1; /* IBM Blue Lightnig CPU */ +} + + +/* + * identifycyrix() set lower 16 bits of cyrix_did as follows: + * + * F E D C B A 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+---------------+ + * | SID | RID | Device ID | + * | (DIR 1) | (DIR 0) | + * +-------+-------+---------------+ + */ +static void +identifycyrix(void) +{ + u_long eflags; + int ccr2_test = 0, dir_test = 0; + u_char ccr2, ccr3; + + eflags = read_eflags(); + disable_intr(); + + ccr2 = read_cyrix_reg(CCR2); + write_cyrix_reg(CCR2, ccr2 ^ CCR2_LOCK_NW); + read_cyrix_reg(CCR2); + if (read_cyrix_reg(CCR2) != ccr2) + ccr2_test = 1; + write_cyrix_reg(CCR2, ccr2); + + ccr3 = read_cyrix_reg(CCR3); + write_cyrix_reg(CCR3, ccr3 ^ CCR3_MAPEN3); + read_cyrix_reg(CCR3); + if (read_cyrix_reg(CCR3) != ccr3) + dir_test = 1; /* CPU supports DIRs. */ + write_cyrix_reg(CCR3, ccr3); + + if (dir_test) { + /* Device ID registers are available. */ + cyrix_did = read_cyrix_reg(DIR1) << 8; + cyrix_did += read_cyrix_reg(DIR0); + } else if (ccr2_test) + cyrix_did = 0x0010; /* 486S A-step */ + else + cyrix_did = 0x00ff; /* Old 486SLC/DLC and TI486SXLC/SXL */ + + write_eflags(eflags); +} + +/* + * Final stage of CPU identification. -- Should I check TI? + */ +void +finishidentcpu(void) +{ + + if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + if (cpu == CPU_486) { + /* + * These conditions are equivalent to: + * - CPU does not support cpuid instruction. + * - Cyrix/IBM CPU is detected. + */ + if (identblue()) { + strcpy(cpu_vendor, "IBM"); + cpu = CPU_BLUE; + return; + } + } + identifycyrix(); + /* + * This routine contains a trick. + * Don't check (cpu_id & 0x00f0) == 0x50 to detect M2, now. + */ + switch (cyrix_did & 0x00f0) { + case 0x00: + case 0x10: + case 0xf0: + cpu = CPU_486DLC; + break; + case 0x20: + if ((cyrix_did & 0x00f0) < 8) + cpu = CPU_M1; + else + cpu = CPU_M1SC; + break; + case 0x30: + cpu = CPU_M1; + break; + case 0x40: + cpu = CPU_M1SC; + break; + default: + /* M2 and later CPUs are treated as M2. */ + cpu = CPU_M2; + break; + } + } +} + /* * This routine is called specifically to set up cpu_class before * startrtclock() uses it. Probably this should be rearranged so that @@ -287,5 +569,6 @@ identifycpu(void) void earlysetcpuclass(void) { + cpu_class = i386_cpus[cpu].cpu_class; } diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index 95930fe..5efddc5 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id$ + * $Id: locore.s,v 1.81 1997/02/22 09:32:22 peter Exp $ * * originally from: locore.s, by William F. Jolitz * @@ -192,6 +192,21 @@ _bdb_exists: .long 0 */ NON_GPROF_ENTRY(btext) +#ifdef PC98 + jmp 1f + .globl _pc98_system_parameter + .org 0x400 +_pc98_system_parameter: + .space 0x240 /* BIOS parameter block */ +1: + /* save SYSTEM PARAMETER for resume (NS/T or other) */ + movl $0xa1000,%esi + movl $0x100000,%edi + movl $0x0630,%ecx + cld + rep + movsb +#else /* IBM-PC */ #ifdef BDE_DEBUGGER #ifdef BIOS_STEALS_3K cmpl $0x0375c339,0x95504 @@ -205,6 +220,7 @@ NON_GPROF_ENTRY(btext) /* Tell the bios to warmboot next time */ movw $0x1234,0x472 +#endif /* PC98 */ /* Set up a real frame in case the double return in newboot is executed. */ pushl %ebp @@ -232,6 +248,28 @@ NON_GPROF_ENTRY(btext) */ movl $R(tmpstk),%esp +#ifdef PC98 + testb $0x02,0x100620 /* pc98_machine_type & M_EPSON_PC98 */ + jz 3f + cmpb $0x0b,0x100624 /* epson_machine_id <= 0x0b */ + ja 3f + + /* count up memory */ + movl $0x100000,%eax /* next, talley remaining memory */ + movl $0xFFF-0x100,%ecx +1: movl 0(%eax),%ebx /* save location to check */ + movl $0xa55a5aa5,0(%eax) /* write test pattern */ + cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ + jne 2f + movl %ebx,0(%eax) /* restore memory */ + addl $PAGE_SIZE,%eax + loop 1b +2: subl $0x100000,%eax + shrl $17,%eax + movb %al,0x100401 +3: +#endif + call identify_cpu /* clear bss */ @@ -326,7 +364,7 @@ begin: addl $(13*4),%esp /* back to a frame we can return with */ /* - * now we've run main() and determined what cpu-type we are, we can + * Now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ @@ -524,7 +562,11 @@ olddiskboot: movl %eax,R(_bootdev) #if defined(USERCONFIG_BOOT) && defined(USERCONFIG) +#ifdef PC98 + movl $0x90200, %esi +#else movl $0x10200, %esi +#endif movl $R(_userconfig_from_boot),%edi movl $512,%ecx cld @@ -557,11 +599,29 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz try486 + + /* NexGen CPU does not have aligment check flag. */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jz trynexgen + popfl movl $CPU_386,R(_cpu) jmp 3f -1: /* Try to toggle identification flag; does not exist on early 486s. */ +trynexgen: + movl $CPU_NX586,R(_cpu) + movl $0x4778654e,R(_cpu_vendor) # store vendor string + movl $0x72446e65,R(_cpu_vendor+4) + movl $0x6e657669,R(_cpu_vendor+8) + movl $0,R(_cpu_vendor+12) + jmp 3f + +try486: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx @@ -576,89 +636,40 @@ identify_cpu: popfl testl %eax,%eax - jnz 1f + jnz trycpuid movl $CPU_486,R(_cpu) - /* check for Cyrix 486DLC -- based on check routine */ - /* documented in "Cx486SLC/e SMM Programmer's Guide" */ - xorw %dx,%dx - cmpw %dx,%dx # set flags to known state - pushfw - popw %cx # store flags in ecx - movw $0xffff,%ax - movw $0x0004,%bx - divw %bx - pushfw - popw %ax - andw $0x08d5,%ax # mask off important bits - andw $0x08d5,%cx - cmpw %ax,%cx - - jnz 3f # if flags changed, Intel chip - - movl $CPU_486DLC,R(_cpu) # set CPU value for Cyrix + /* + * Check Cyrix CPU + * Cyrix CPUs do not change the undefined flags following + * execution of the divide instruction which divides 5 by 2. + * + * Note: CPUID is enabled on M2, so it passes another way. + */ + pushfl + movl $0x5555, %eax + xorl %edx, %edx + movl $2, %ecx + clc + divl %ecx + jnc trycyrix + popfl + jmp 3f /* You may use Intel CPU. */ + +trycyrix: + popfl + /* + * IBM Bluelighting CPU also doesn't change the undefined flags. + * Because IBM doesn't disclose the information for Bluelighting + * CPU, we couldn't distinguish it from Cyrix's (including IBM + * brand of Cyrix CPUs). + */ movl $0x69727943,R(_cpu_vendor) # store vendor string - movw $0x0078,R(_cpu_vendor+4) - -#ifndef CYRIX_CACHE_WORKS - /* Disable caching of the ISA hole only. */ - invd - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - orb $(CCR0_NC1|CCR0_BARB),%al - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - invd -#else /* CYRIX_CACHE_WORKS */ - /* Set cache parameters */ - invd # Start with guaranteed clean cache - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - andb $~CCR0_NC0,%al -#ifndef CYRIX_CACHE_REALLY_WORKS - orb $(CCR0_NC1|CCR0_BARB),%al -#else /* CYRIX_CACHE_REALLY_WORKS */ - orb $CCR0_NC1,%al -#endif /* !CYRIX_CACHE_REALLY_WORKS */ - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - /* clear non-cacheable region 1 */ - movb $(NCR1+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 2 */ - movb $(NCR2+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 3 */ - movb $(NCR3+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 4 */ - movb $(NCR4+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* enable caching in CR0 */ - movl %cr0,%eax - andl $~(CR0_CD|CR0_NW),%eax - movl %eax,%cr0 - invd -#endif /* !CYRIX_CACHE_WORKS */ + movl $0x736e4978,R(_cpu_vendor+4) + movl $0x64616574,R(_cpu_vendor+8) jmp 3f -1: /* Use the `cpuid' instruction. */ +trycpuid: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,R(_cpu_high) # highest capability diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index bf3eaa2..c1094ee 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.228 1997/02/22 09:32:26 peter Exp $ + * $Id: machdep.c,v 1.229 1997/02/24 00:37:43 alex Exp $ */ #include "npx.h" @@ -122,8 +122,11 @@ extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); -extern void identifycpu(void); /* XXX header file */ +extern void printcpuinfo(void); /* XXX header file */ extern void earlysetcpuclass(void); /* same header file */ +extern void finishidentcpu(void); +extern void panicifcpuunsupported(void); +extern void initializecpu(void); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) @@ -208,7 +211,8 @@ cpu_startup(dummy) printf(version); earlysetcpuclass(); startrtclock(); - identifycpu(); + printcpuinfo(); + panicifcpuunsupported(); #ifdef PERFMON perfmon_init(); #endif @@ -1059,6 +1063,10 @@ init386(first) Debugger("Boot flags requested debugger"); #endif + finishidentcpu(); /* Final stage of CPU initialization */ + setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + initializecpu(); /* Initialize CPU registers */ + /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. */ diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index 5dd24b1..9cd0351 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: cpufunc.h,v 1.61 1997/02/22 09:34:08 peter Exp $ */ /* @@ -196,6 +196,12 @@ insl(u_int port, void *addr, size_t cnt) } static __inline void +invd(void) +{ + __asm __volatile("invd"); +} + +static __inline void invlpg(u_int addr) { __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory"); @@ -339,6 +345,12 @@ setbits(volatile unsigned *addr, u_int bits) } static __inline void +wbinvd(void) +{ + __asm __volatile("wbinvd"); +} + +static __inline void write_eflags(u_long ef) { __asm __volatile("pushl %0; popfl" : : "r" (ef)); @@ -360,6 +372,7 @@ u_long inl __P((u_int port)); void insb __P((u_int port, void *addr, size_t cnt)); void insl __P((u_int port, void *addr, size_t cnt)); void insw __P((u_int port, void *addr, size_t cnt)); +void invd __P((void)); void invlpg __P((u_int addr)); void invltlb __P((void)); u_short inw __P((u_int port)); @@ -376,6 +389,7 @@ quad_t rdpmc __P((u_int pmc)); quad_t rdtsc __P((void)); u_long read_eflags __P((void)); void setbits __P((volatile unsigned *addr, u_int bits)); +void wbinvd __P((void)); void write_eflags __P((u_long ef)); void wrmsr __P((u_int msr, quad_t newval)); diff --git a/sys/i386/include/cputypes.h b/sys/i386/include/cputypes.h index 4905900..695dafc 100644 --- a/sys/i386/include/cputypes.h +++ b/sys/i386/include/cputypes.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id$ + * $Id: cputypes.h,v 1.7 1997/02/22 09:34:14 peter Exp $ */ #ifndef _MACHINE_CPUTYPES_H_ @@ -52,5 +52,9 @@ #define CPU_586 5 /* Intel P.....m (I hate lawyers; it's TM) */ #define CPU_486DLC 6 /* Cyrix 486DLC */ #define CPU_686 7 /* Pentium Pro */ - +#define CPU_M1SC 8 /* Cyrix M1sc (aka 5x86) */ +#define CPU_M1 9 /* Cyrix M1 (aka 6x86) */ +#define CPU_BLUE 10 /* IBM BlueLighting CPU */ +#define CPU_M2 11 /* Cyrix M2 (aka enhanced 6x86 with MMX */ +#define CPU_NX586 12 /* NexGen (now AMD) 586 */ #endif /* _MACHINE_CPUTYPES_H_ */ diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index c74313f..307257c 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: md_var.h,v 1.12 1997/02/22 09:34:49 peter Exp $ */ #ifndef _MACHINE_MD_VAR_H_ @@ -41,6 +41,7 @@ extern u_int atdevbase; /* offset in virtual memory of ISA io mem */ extern u_long cpu_feature; extern u_long cpu_high; extern u_long cpu_id; +extern u_long cyrix_did; extern char cpu_vendor[]; extern char etext[]; extern char kstack[]; @@ -72,4 +73,9 @@ void userconfig __P((void)); void vm_bounce_init __P((void)); int vm_page_zero_idle __P((void)); +#ifdef PC98 +extern int need_pre_dma_flush; +extern int need_post_dma_flush; +#endif + #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h index 7344d8f..8e4dfc7 100644 --- a/sys/i386/include/specialreg.h +++ b/sys/i386/include/specialreg.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 - * $Id$ + * $Id: specialreg.h,v 1.12 1997/02/22 09:35:15 peter Exp $ */ #ifndef _MACHINE_SPECIALREG_H_ @@ -54,11 +54,12 @@ /* * Bits in 486 special registers: */ -#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ -#define CR0_WP 0x00010000 /* Write Protect (honor page protect in all modes) */ -#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ -#define CR0_NW 0x20000000 /* Not Write-through */ -#define CR0_CD 0x40000000 /* Cache Disable */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in + all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ /* * Bits in PPro special registers @@ -94,26 +95,81 @@ #define CPUID_CMOV 0x8000 /* - * Cyrix 486 DLC special registers, accessible as IO ports. + * Cyrix configuration registers, accessible as IO ports. */ -#define CCR0 0xc0 /* configuration control register 0 */ -#define CCR0_NC0 0x01 /* first 64K of each 1M memory region is - non-cacheable */ -#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ -#define CCR0_A20M 0x04 /* enables A20M# input pin */ -#define CCR0_KEN 0x08 /* enables KEN# input pin */ -#define CCR0_FLUSH 0x10 /* enables FLUSH# input pin */ -#define CCR0_BARB 0x20 /* flushes internal cache when entering hold - state */ -#define CCR0_CO 0x40 /* cache org: 1=direct mapped, 0=2x set assoc */ -#define CCR0_SUSPEND 0x80 /* enables SUSP# and SUSPA# pins */ - -#define CCR1 0xc1 /* configuration control register 1 */ -#define CCR1_RPL 0x01 /* enables RPLSET and RPLVAL# pins */ -/* the remaining 7 bits of this register are reserved */ +#define CCR0 0xc0 /* Configuration control register 0 */ +#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is + non-cacheable */ +#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ +#define CCR0_A20M 0x04 /* Enables A20M# input pin */ +#define CCR0_KEN 0x08 /* Enables KEN# input pin */ +#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */ +#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold + state */ +#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set + assoc */ +#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */ + +#define CCR1 0xc1 /* Configuration control register 1 */ +#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */ +#define CCR1_SMI 0x02 /* Enables SMM pins */ +#define CCR1_SMAC 0x04 /* System management memory access */ +#define CCR1_MMAC 0x08 /* Main memory access */ +#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */ +#define CCR1_SM3 0x80 /* SMM address space address region 3 */ + +#define CCR2 0xc2 +#define CCR2_WB 0x02 /* Enables WB cache interface pins */ +#define CCR2_SADS 0x02 /* Slow ADS */ +#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */ +#define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */ +#define CCR2_WT1 0x10 /* WT region 1 */ +#define CCR2_WPR1 0x10 /* Write-protect region 1 */ +#define CCR2_BARB 0x20 /* Flushes write-back cache when entering + hold state. */ +#define CCR2_BWRT 0x40 /* Enables burst write cycles */ +#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ + +#define CCR3 0xc3 +#define CCR3_SMILOCK 0x01 /* SMM register lock */ +#define CCR3_NMI 0x02 /* Enables NMI during SMM */ +#define CCR3_LINBRST 0x04 /* Linear address burst cycles */ +#define CCR3_SMMMODE 0x08 /* SMM Mode */ +#define CCR3_MAPEN0 0x10 /* Enables Map0 */ +#define CCR3_MAPEN1 0x20 /* Enables Map1 */ +#define CCR3_MAPEN2 0x40 /* Enables Map2 */ +#define CCR3_MAPEN3 0x80 /* Enables Map3 */ + +#define CCR4 0xe8 +#define CCR4_IOMASK 0x07 +#define CCR4_MEM 0x08 /* Enables momory bypassing */ +#define CCR4_DTE 0x10 /* Enables directory table entry cache */ +#define CCR4_FASTFPE 0x20 /* Fast FPU exception */ +#define CCR4_CPUID 0x80 /* Enables CPUID instruction */ + +#define CCR5 0xe9 +#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */ +#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */ +#define CCR5_LBR1 0x10 /* Local bus region 1 */ +#define CCR5_ARREN 0x20 /* Enables ARR region */ + +/* Performance Control Register (5x86 only). */ +#define PCR0 0x20 +#define PCR0_RSTK 0x01 /* Enables return stack */ +#define PCR0_BTB 0x02 /* Enables branch target buffer */ +#define PCR0_LOOP 0x04 /* Enables loop */ +#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to + serialize pipe. */ +#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ +#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ +#define PCR0_LSSER 0x80 /* Disable reorder */ + +/* Device Identification Registers */ +#define DIR0 0xfe +#define DIR1 0xff /* - * the following four 3-byte registers control the non-cacheable regions. + * The following four 3-byte registers control the non-cacheable regions. * These registers must be written as three separate bytes. * * NCRx+0: A31-A24 of starting address @@ -123,26 +179,98 @@ * The non-cacheable region's starting address must be aligned to the * size indicated by the NCR_SIZE_xx field. */ -#define NCR1 0xc4 -#define NCR2 0xc7 -#define NCR3 0xca -#define NCR4 0xcd - -#define NCR_SIZE_0K 0 -#define NCR_SIZE_4K 1 -#define NCR_SIZE_8K 2 -#define NCR_SIZE_16K 3 -#define NCR_SIZE_32K 4 -#define NCR_SIZE_64K 5 -#define NCR_SIZE_128K 6 -#define NCR_SIZE_256K 7 -#define NCR_SIZE_512K 8 -#define NCR_SIZE_1M 9 -#define NCR_SIZE_2M 10 -#define NCR_SIZE_4M 11 -#define NCR_SIZE_8M 12 -#define NCR_SIZE_16M 13 -#define NCR_SIZE_32M 14 -#define NCR_SIZE_4G 15 +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * The address region registers are used to specify the location and + * size for the eight address regions. + * + * ARRx + 0: A31-A24 of start address + * ARRx + 1: A23-A16 of start address + * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx + */ +#define ARR0 0xc4 +#define ARR1 0xc7 +#define ARR2 0xca +#define ARR3 0xcd +#define ARR4 0xd0 +#define ARR5 0xd3 +#define ARR6 0xd6 +#define ARR7 0xd9 + +#define ARR_SIZE_0K 0 +#define ARR_SIZE_4K 1 +#define ARR_SIZE_8K 2 +#define ARR_SIZE_16K 3 +#define ARR_SIZE_32K 4 +#define ARR_SIZE_64K 5 +#define ARR_SIZE_128K 6 +#define ARR_SIZE_256K 7 +#define ARR_SIZE_512K 8 +#define ARR_SIZE_1M 9 +#define ARR_SIZE_2M 10 +#define ARR_SIZE_4M 11 +#define ARR_SIZE_8M 12 +#define ARR_SIZE_16M 13 +#define ARR_SIZE_32M 14 +#define ARR_SIZE_4G 15 + +/* + * The region control registers specify the attributes associated with + * the ARRx addres regions. + */ +#define RCR0 0xdc +#define RCR1 0xdd +#define RCR2 0xde +#define RCR3 0xdf +#define RCR4 0xe0 +#define RCR5 0xe1 +#define RCR6 0xe2 +#define RCR7 0xe3 + +#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ +#define RCR_RCE 0x01 /* Enables caching for ARR7. */ +#define RCR_WWO 0x02 /* Weak write ordering. */ +#define RCR_WL 0x04 /* Weak locking. */ +#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WT 0x10 /* Write-through. */ +#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ + + +#ifndef LOCORE +static __inline u_char +read_cyrix_reg(u_char reg) +{ + outb(0x22, reg); + return inb(0x23); +} + +static __inline void +write_cyrix_reg(u_char reg, u_char data) +{ + outb(0x22, reg); + outb(0x23, data); +} +#endif #endif /* !_MACHINE_SPECIALREG_H_ */ diff --git a/sys/i386/isa/bs/bshw_dma.c b/sys/i386/isa/bs/bshw_dma.c index 22051a9..b5b9238 100644 --- a/sys/i386/isa/bs/bshw_dma.c +++ b/sys/i386/isa/bs/bshw_dma.c @@ -200,9 +200,8 @@ bshw_dmastart(bsc) */ /* set dma channel mode, and reset address ff */ #ifdef __FreeBSD__ -#ifdef CYRIX_5X86 - asm("wbinvd"); -#endif + if (need_pre_dma_flush) + wbinvd(); #else /* NetBSD/pc98 */ if (cpuspec->cpuspec_cache_flush_before) (*cpuspec->cpuspec_cache_flush_before)(); @@ -247,9 +246,8 @@ bshw_dmadone(bsc) (*bsc->sc_hw->dma_stop)(bsc); #ifdef __FreeBSD__ -#if defined(CYRIX_486DLC) || defined(IBM_486SLC) - asm(".byte 0x0f, 0x08"); -#endif + if (need_post_dma_flush) + invd(); #else if (cpuspec->cpuspec_cache_flush_after) (*cpuspec->cpuspec_cache_flush_after)(); diff --git a/sys/i386/isa/bs/bsif.h b/sys/i386/isa/bs/bsif.h index d5b8e71..4904bd8 100644 --- a/sys/i386/isa/bs/bsif.h +++ b/sys/i386/isa/bs/bsif.h @@ -101,6 +101,7 @@ #include <vm/vm_kern.h> #include <machine/clock.h> #include <machine/cpu.h> +#include <machine/md_var.h> #include <machine/vmparam.h> #include <vm/pmap.h> #include <sys/proc.h> diff --git a/sys/pc98/conf/Makefile.pc98 b/sys/pc98/conf/Makefile.pc98 index 8fe080c..ecdb567 100644 --- a/sys/pc98/conf/Makefile.pc98 +++ b/sys/pc98/conf/Makefile.pc98 @@ -3,7 +3,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id$ +# $Id: Makefile.pc98,v 1.11 1997/02/22 09:43:21 peter Exp $ # # Makefile for FreeBSD # @@ -58,7 +58,7 @@ DRIVER_S= ${CC} -c -x assembler-with-cpp -DLOCORE ${COPTS} $< PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< SYSTEM_CFILES= ioconf.c param.c vnode_if.c config.c -SYSTEM_SFILES= ${PC98}/i386/locore.s +SYSTEM_SFILES= ${I386}/i386/locore.s SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o config.o SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ @@ -89,7 +89,7 @@ clean: #lint: /tmp param.c # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ -# ${PC98}/i386/Locore.c ${CFILES} ioconf.c param.c | \ +# ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ # grep -v 'struct/union .* never defined' | \ # grep -v 'possible pointer alignment problem' @@ -101,7 +101,7 @@ symbols.sort: ${I386}/i386/symbols.raw grep -v '^#' ${I386}/i386/symbols.raw \ | sed 's/^ //' | sort -u > symbols.sort -locore.o: ${PC98}/i386/locore.s assym.s +locore.o: ${I386}/i386/locore.s assym.s ${NORMAL_S} # everything potentially depends on the Makefile since everything potentially diff --git a/sys/pc98/conf/files.pc98 b/sys/pc98/conf/files.pc98 index 37cf0a9..b5c3dce 100644 --- a/sys/pc98/conf/files.pc98 +++ b/sys/pc98/conf/files.pc98 @@ -3,7 +3,7 @@ # # modified for PC-9801 # -# $Id: files.pc98,v 1.16 1997/02/22 09:43:22 peter Exp $ +# $Id: files.pc98,v 1.17 1997/03/19 16:14:25 kato Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/*.[chyl]" \ @@ -49,6 +49,7 @@ i386/i386/i386-gdbstub.c optional ddb i386/i386/exception.s standard i386/i386/identcpu.c standard i386/i386/in_cksum.c optional inet +i386/i386/initcpu.c standard # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard diff --git a/sys/pc98/conf/options.pc98 b/sys/pc98/conf/options.pc98 index cf26896..38d240f 100644 --- a/sys/pc98/conf/options.pc98 +++ b/sys/pc98/conf/options.pc98 @@ -1,4 +1,4 @@ -# $Id: options.pc98,v 1.17 1997/03/01 11:06:41 kato Exp $ +# $Id: options.pc98,v 1.18 1997/03/13 17:04:23 kato Exp $ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h @@ -37,10 +37,21 @@ CLK_CALIBRATION_LOOP opt_clock.h CLK_USE_I8254_CALIBRATION opt_clock.h CLK_USE_I586_CALIBRATION opt_clock.h -I386_CPU opt_cpu.h -I486_CPU opt_cpu.h -I586_CPU opt_cpu.h -I686_CPU opt_cpu.h +CPU_BTB_EN opt_cpu.h +CPU_DISABLE_5X86_LSSER opt_cpu.h +CPU_FASTER_5X86_FPU opt_cpu.h +CPU_I486_ON_386 opt_cpu.h +CPU_IORT opt_cpu.h +CPU_LOOP_EN opt_cpu.h +CPU_RSTK_EN opt_cpu.h +CPU_SUSP_HLT opt_cpu.h +CPU_UPGRADE_HW_CACHE opt_cpu.h +CYRIX_CACHE_WORKS opt_cpu.h +CYRIX_CACHE_REALLY_WORKS opt_cpu.h +I386_CPU opt_cpu.h +I486_CPU opt_cpu.h +I586_CPU opt_cpu.h +I686_CPU opt_cpu.h SC_SPLASH_SCREEN opt_syscons.h MAXCONS opt_syscons.h diff --git a/sys/pc98/i386/locore.s b/sys/pc98/i386/locore.s deleted file mode 100644 index 039638f..0000000 --- a/sys/pc98/i386/locore.s +++ /dev/null @@ -1,1084 +0,0 @@ -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id$ - * - * originally from: locore.s, by William F. Jolitz - * - * Substantially rewritten by David Greenman, Rod Grimes, - * Bruce Evans, Wolfgang Solfrank, Poul-Henning Kamp - * and many others. - */ - -#include "apm.h" -#include "opt_cpu.h" -#include "opt_ddb.h" -#include "opt_userconfig.h" - -#include <sys/errno.h> -#include <sys/syscall.h> -#include <sys/reboot.h> - -#include <machine/asmacros.h> -#include <machine/cputypes.h> -#include <machine/psl.h> -#include <machine/pmap.h> -#include <machine/specialreg.h> - -#include "assym.s" - -/* - * XXX - * - * Note: This version greatly munged to avoid various assembler errors - * that may be fixed in newer versions of gas. Perhaps newer versions - * will have more pleasant appearance. - */ - -/* - * PTmap is recursive pagemap at top of virtual address space. - * Within PTmap, the page directory can be found (third indirection). - */ - .globl _PTmap,_PTD,_PTDpde - .set _PTmap,(PTDPTDI << PDRSHIFT) - .set _PTD,_PTmap + (PTDPTDI * PAGE_SIZE) - .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) - -/* - * APTmap, APTD is the alternate recursive pagemap. - * It's used when modifying another process's page tables. - */ - .globl _APTmap,_APTD,_APTDpde - .set _APTmap,APTDPTDI << PDRSHIFT - .set _APTD,_APTmap + (APTDPTDI * PAGE_SIZE) - .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) - -/* - * Access to each processes kernel stack is via a region of - * per-process address space (at the beginning), immediately above - * the user process stack. - */ - .set _kstack,USRSTACK - .globl _kstack - -/* - * Globals - */ - .data - ALIGN_DATA /* just to be sure */ - - .globl tmpstk - .space 0x2000 /* space for tmpstk - temporary stack */ -tmpstk: - - .globl _boothowto,_bootdev - - .globl _cpu,_cpu_vendor,_cpu_id,_bootinfo - .globl _cpu_high, _cpu_feature - -_cpu: .long 0 /* are we 386, 386sx, or 486 */ -_cpu_id: .long 0 /* stepping ID */ -_cpu_high: .long 0 /* highest arg to CPUID */ -_cpu_feature: .long 0 /* features */ -_cpu_vendor: .space 20 /* CPU origin code */ -_bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ - -_KERNend: .long 0 /* phys addr end of kernel (just after bss) */ -physfree: .long 0 /* phys addr of next free page */ -p0upa: .long 0 /* phys addr of proc0's UPAGES */ -p0upt: .long 0 /* phys addr of proc0's UPAGES page table */ - - .globl _IdlePTD -_IdlePTD: .long 0 /* phys addr of kernel PTD */ - -_KPTphys: .long 0 /* phys addr of kernel page tables */ - - .globl _proc0paddr -_proc0paddr: .long 0 /* address of proc 0 address space */ - -#ifdef BDE_DEBUGGER - .globl _bdb_exists /* flag to indicate BDE debugger is present */ -_bdb_exists: .long 0 -#endif - - -/********************************************************************** - * - * Some handy macros - * - */ - -#define R(foo) ((foo)-KERNBASE) - -#define ALLOCPAGES(foo) \ - movl R(physfree), %esi ; \ - movl $((foo)*PAGE_SIZE), %eax ; \ - addl %esi, %eax ; \ - movl %eax, R(physfree) ; \ - movl %esi, %edi ; \ - movl $((foo)*PAGE_SIZE),%ecx ; \ - xorl %eax,%eax ; \ - cld ; \ - rep ; \ - stosb - -/* - * fillkpt - * eax = page frame address - * ebx = index into page table - * ecx = how many pages to map - * base = base address of page dir/table - * prot = protection bits - */ -#define fillkpt(base, prot) \ - shll $2,%ebx ; \ - addl base,%ebx ; \ - orl $PG_V,%eax ; \ - orl prot,%eax ; \ -1: movl %eax,(%ebx) ; \ - addl $PAGE_SIZE,%eax ; /* increment physical address */ \ - addl $4,%ebx ; /* next pte */ \ - loop 1b - -/* - * fillkptphys(prot) - * eax = physical address - * ecx = how many pages to map - * prot = protection bits - */ -#define fillkptphys(prot) \ - movl %eax, %ebx ; \ - shrl $PAGE_SHIFT, %ebx ; \ - fillkpt(R(_KPTphys), prot) - - .text -/********************************************************************** - * - * This is where the bootblocks start us, set the ball rolling... - * - */ -NON_GPROF_ENTRY(btext) - -#ifdef PC98 - jmp 1f - .globl _pc98_system_parameter - .org 0x400 -_pc98_system_parameter: - .space 0x240 /* skip over warm boot shit */ -1: - /* save SYSTEM PARAMETER for resume (NS/T or other) */ - movl $0xa1000,%esi - movl $0x100000,%edi - movl $0x0630,%ecx - cld - rep - movsb -#else /* IBM-PC */ -#ifdef BDE_DEBUGGER -#ifdef BIOS_STEALS_3K - cmpl $0x0375c339,0x95504 -#else - cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ -#endif - jne 1f - movb $1,R(_bdb_exists) -1: -#endif - -/* Tell the bios to warmboot next time */ - movw $0x1234,0x472 -#endif /* PC98 */ - -/* Set up a real frame in case the double return in newboot is executed. */ - pushl %ebp - movl %esp, %ebp - -/* Don't trust what the BIOS gives for eflags. */ - pushl $PSL_KERNEL - popfl - -/* - * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap - * to set %cs, %ds, %es and %ss. - */ - mov %ds, %ax - mov %ax, %fs - mov %ax, %gs - - call recover_bootinfo - -/* Get onto a stack that we can trust. */ -/* - * XXX this step is delayed in case recover_bootinfo needs to return via - * the old stack, but it need not be, since recover_bootinfo actually - * returns via the old frame. - */ - movl $R(tmpstk),%esp - -#ifdef PC98 - testb $0x02,0x100620 /* pc98_machine_type & M_EPSON_PC98 */ - jz 3f - cmpb $0x0b,0x100624 /* epson_machine_id <= 0x0b */ - ja 3f - - /* count up memory */ - movl $0x100000,%eax /* next, talley remaining memory */ - movl $(0xFFF-0x100),%ecx -1: movl 0(%eax),%ebx /* save location to check */ - movl $0xa55a5aa5,0(%eax) /* write test pattern */ - cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ - jne 2f - movl %ebx,0(%eax) /* restore memory */ - addl $ PAGE_SIZE,%eax - loop 1b -2: subl $0x100000,%eax - shrl $17,%eax - movb %al,0x100401 -3: -#endif - - call identify_cpu - -/* clear bss */ -/* - * XXX this should be done a little earlier. - * - * XXX we don't check that there is memory for our bss and page tables - * before using it. - * - * XXX the boot program somewhat bogusly clears the bss. We still have - * to do it in case we were unzipped by kzipboot. Then the boot program - * only clears kzipboot's bss. - * - * XXX the gdt and idt are still somewhere in the boot program. We - * depend on the convention that the boot program is below 1MB and we - * are above 1MB to keep the gdt and idt away from the bss and page - * tables. The idt is only used if BDE_DEBUGGER is enabled. - */ - movl $R(_end),%ecx - movl $R(_edata),%edi - subl %edi,%ecx - xorl %eax,%eax - cld - rep - stosb - -#if NAPM > 0 -/* - * XXX it's not clear that APM can live in the current environonment. - * Only pc-relative addressing works. - */ - call _apm_setup -#endif - - call create_pagetables - -#ifdef BDE_DEBUGGER -/* - * Adjust as much as possible for paging before enabling paging so that the - * adjustments can be traced. - */ - call bdb_prepare_paging -#endif - -/* Now enable paging */ - movl R(_IdlePTD), %eax - movl %eax,%cr3 /* load ptd addr into mmu */ - movl %cr0,%eax /* get control word */ - orl $CR0_PE|CR0_PG,%eax /* enable paging */ - movl %eax,%cr0 /* and let's page NOW! */ - -#ifdef BDE_DEBUGGER -/* - * Complete the adjustments for paging so that we can keep tracing through - * initi386() after the low (physical) addresses for the gdt and idt become - * invalid. - */ - call bdb_commit_paging -#endif - - pushl $begin /* jump to high virtualized address */ - ret - -/* now running relocated at KERNBASE where the system is linked to run */ -begin: - /* set up bootstrap stack */ - movl $_kstack+UPAGES*PAGE_SIZE,%esp /* bootstrap stack end location */ - xorl %eax,%eax /* mark end of frames */ - movl %eax,%ebp - movl _proc0paddr,%eax - movl _IdlePTD, %esi - movl %esi,PCB_CR3(%eax) - - movl physfree, %esi - pushl %esi /* value of first for init386(first) */ - call _init386 /* wire 386 chip for unix operation */ -#ifdef PC98 -#if defined(CYRIX_486DLC) && defined(I486_CPU) - /* Cyrix 486DLC/SLC/DLC2/SLC2 CPU */ - cmpl $CPU_486DLC,_cpu - jne 1f - cli - movl %cr0,%eax - orl $0x40000000,%eax /* disable cache */ - mov %eax,%cr0 - .byte 0x0f,0x08 /* invd */ - - movb $0xc0,%al - outb %al,$0x22 /* Cyrix486[SD]LC cache controler index */ - movb $0x02,%al /* CCR0 = 0x02 (disable cache 640K-1M) */ - outb %al,$0x23 /* window */ - movb $0xc6,%al - outb %al,$0x22 - movb $0x00,%al - outb %al,$0x23 /* NCR1: enable cache in all area */ - movb $0x00,%al - outb %al,$0x22 /* dummy window */ - movb $0x00,%al - outb %al,$0x23 /* dummy write */ - - movl %cr0,%eax - andl $0x9fffffff,%eax /* enable cache !! */ - movl %eax,%cr0 - sti -1: -#endif -#if defined(IBM_486SLC) && defined(I486_CPU) -/* optimization */ - cli - movl %cr0,%eax - orl $0x40000000,%eax # disable cache - mov %eax,%cr0 - .byte 0x0f,0x08 # invd - - movl $0x00000000,%edx - movl $0x00009c92,%eax # If using Intel-FPU,set "1c92" instead. - movl $0x00001000,%ecx - .byte 0x0f,0x30 # wrmsr - - movl $0x000000d0,%edx # 13MB(0x0d) cache.(over1MB-14MB region) - movl $0x000003ff,%eax # 0-640KB cache. (64KB block * 10) - movl $0x00001001,%ecx - .byte 0x0f,0x30 # wrmsr - - movl $0x00000000,%edx - movl $0x03000000,%eax # "3" means double-clock-mode. or set all-zero. - movl $0x00001002,%ecx - .byte 0x0f,0x30 # wrmsr - - movl %cr0,%eax - andl $0x9fffffff,%eax # enable cache !! - movl %eax,%cr0 - sti -#endif -#ifdef CYRIX_5X86 - /* CYRIX 5x86 CPU */ - cli - - outb %al,$0x50 # Reset NMI F/F - mov %cr0,%eax - orl $0x40000000,%eax # disable cache - movl %eax,%cr0 - - wbinvd # flush buffer - - movb $0xc3,%al - outb %al,$0x22 - inb $0x23,%al - - movb $0x0c1,%al # CCR1 - outb %al,$0x22 - movb $0x00,%al # No SMM support - outb %al,$0x23 - movb $0x0c2,%al # CCR2 - outb %al,$0x22 -#ifdef SUSP_HLT - movb $0x0a,%al # USE_WBAK, SUSP_HLT -#else - movb $0x02,%al # USE_WBAK -#endif - outb %al,$0x23 - movb $0xc3,%al # CCR3 - outb %al,$0x22 # - movb $0x10,%al # MAPEN0 (to access CCR4) - outb %al,$0x23 - movb $0x0e8,%al # CCR4 - outb %al,$0x22 - movb $0x18, %al # DTE_EN, MEM_BYP -#ifdef FASTER_5X86_FPU - orb $0x20, %al # UNDOCUMENTED OPTION -#endif -#ifdef CX586_IO - orb $CX586_IO, %al -#endif - outb %al,$0x23 - movb $0x020,%al # PCR0 - outb %al,$0x22 - xorb %al, %al -#ifdef RSTK_EN - orb $0x01, %al # Return Stack Enable -#endif -#ifdef BTB_EN - orb $0x02, %al # Branch Target Buffer enable -#endif -#ifdef LOOP_EN - orb $0x04, %al # Loop Enable -#endif -#ifndef DISABLE_5X86_LSSER - orb $0x80, %al # Reorder -#endif - outb %al,$0x23 - movb $0x0c3,%al # CCR3 - outb %al,$0x22 - movb $0x00,%al - outb %al,$0x23 - movb $0x80,%al # dummy - outb %al,$0x22 - inb $0x23,%al - - movl %cr0,%ebx - andl $0x0bfffffff,%ebx # enable cache - orl $0x020000000,%ebx # write back mode - movl %ebx,%cr0 # go! - - outb %al,$0x52 # Set NMI F/F - sti -#endif /* CYRIX_5X86 */ -#endif /* PC98 */ - popl %esi - - .globl __ucodesel,__udatasel - - pushl $0 /* unused */ - pushl __udatasel /* ss */ - pushl $0 /* esp - filled in by execve() */ - pushl $PSL_USER /* eflags (IOPL 0, int enab) */ - pushl __ucodesel /* cs */ - pushl $0 /* eip - filled in by execve() */ - subl $(12*4),%esp /* space for rest of registers */ - - pushl %esp /* call main with frame pointer */ - call _main /* autoconfiguration, mountroot etc */ - - addl $(13*4),%esp /* back to a frame we can return with */ - - /* - * now we've run main() and determined what cpu-type we are, we can - * enable write protection and alignment checking on i486 cpus and - * above. - */ -#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) - cmpl $CPUCLASS_386,_cpu_class - je 1f - movl %cr0,%eax /* get control word */ - orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ - movl %eax,%cr0 /* and do it */ -1: -#endif - /* - * on return from main(), we are process 1 - * set up address space and stack so that we can 'return' to user mode - */ - movl __ucodesel,%eax - movl __udatasel,%ecx - - movl %cx,%ds - movl %cx,%es - movl %ax,%fs /* double map cs to fs */ - movl %cx,%gs /* and ds to gs */ - iret /* goto user! */ - -#define LCALL(x,y) .byte 0x9a ; .long y ; .word x - -/* - * Signal trampoline, copied to top of user stack - */ -NON_GPROF_ENTRY(sigcode) - call SIGF_HANDLER(%esp) - lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ - /* copy at 8(%esp)) */ - pushl %eax - pushl %eax /* junk to fake return address */ - movl $SYS_sigreturn,%eax /* sigreturn() */ - LCALL(0x7,0) /* enter kernel with args on stack */ - hlt /* never gets here */ - .align 2,0x90 /* long word text-align */ -_esigcode: - - .data - .globl _szsigcode -_szsigcode: - .long _esigcode-_sigcode - .text - -/********************************************************************** - * - * Recover the bootinfo passed to us from the boot program - * - */ -recover_bootinfo: - /* - * This code is called in different ways depending on what loaded - * and started the kernel. This is used to detect how we get the - * arguments from the other code and what we do with them. - * - * Old disk boot blocks: - * (*btext)(howto, bootdev, cyloffset, esym); - * [return address == 0, and can NOT be returned to] - * [cyloffset was not supported by the FreeBSD boot code - * and always passed in as 0] - * [esym is also known as total in the boot code, and - * was never properly supported by the FreeBSD boot code] - * - * Old diskless netboot code: - * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); - * [return address != 0, and can NOT be returned to] - * If we are being booted by this code it will NOT work, - * so we are just going to halt if we find this case. - * - * New uniform boot code: - * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) - * [return address != 0, and can be returned to] - * - * There may seem to be a lot of wasted arguments in here, but - * that is so the newer boot code can still load very old kernels - * and old boot code can load new kernels. - */ - - /* - * The old style disk boot blocks fake a frame on the stack and - * did an lret to get here. The frame on the stack has a return - * address of 0. - */ - cmpl $0,4(%ebp) - je olddiskboot - - /* - * We have some form of return address, so this is either the - * old diskless netboot code, or the new uniform code. That can - * be detected by looking at the 5th argument, if it is 0 - * we are being booted by the new uniform boot code. - */ - cmpl $0,24(%ebp) - je newboot - - /* - * Seems we have been loaded by the old diskless boot code, we - * don't stand a chance of running as the diskless structure - * changed considerably between the two, so just halt. - */ - hlt - - /* - * We have been loaded by the new uniform boot code. - * Let's check the bootinfo version, and if we do not understand - * it we return to the loader with a status of 1 to indicate this error - */ -newboot: - movl 28(%ebp),%ebx /* &bootinfo.version */ - movl BI_VERSION(%ebx),%eax - cmpl $1,%eax /* We only understand version 1 */ - je 1f - movl $1,%eax /* Return status */ - leave - /* - * XXX this returns to our caller's caller (as is required) since - * we didn't set up a frame and our caller did. - */ - ret - -1: - /* - * If we have a kernelname copy it in - */ - movl BI_KERNELNAME(%ebx),%esi - cmpl $0,%esi - je 2f /* No kernelname */ - movl $MAXPATHLEN,%ecx /* Brute force!!! */ - movl $R(_kernelname),%edi - cmpb $'/',(%esi) /* Make sure it starts with a slash */ - je 1f - movb $'/',(%edi) - incl %edi - decl %ecx -1: - cld - rep - movsb - -2: - /* - * Determine the size of the boot loader's copy of the bootinfo - * struct. This is impossible to do properly because old versions - * of the struct don't contain a size field and there are 2 old - * versions with the same version number. - */ - movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ - testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ - je got_bi_size /* no, sizeless version */ - movl BI_SIZE(%ebx),%ecx -got_bi_size: - - /* - * Copy the common part of the bootinfo struct - */ - movl %ebx,%esi - movl $R(_bootinfo),%edi - cmpl $BOOTINFO_SIZE,%ecx - jbe got_common_bi_size - movl $BOOTINFO_SIZE,%ecx -got_common_bi_size: - cld - rep - movsb - -#ifdef NFS - /* - * If we have a nfs_diskless structure copy it in - */ - movl BI_NFS_DISKLESS(%ebx),%esi - cmpl $0,%esi - je olddiskboot - movl $R(_nfs_diskless),%edi - movl $NFSDISKLESS_SIZE,%ecx - cld - rep - movsb - movl $R(_nfs_diskless_valid),%edi - movl $1,(%edi) -#endif - - /* - * The old style disk boot. - * (*btext)(howto, bootdev, cyloffset, esym); - * Note that the newer boot code just falls into here to pick - * up howto and bootdev, cyloffset and esym are no longer used - */ -olddiskboot: - movl 8(%ebp),%eax - movl %eax,R(_boothowto) - movl 12(%ebp),%eax - movl %eax,R(_bootdev) - -#if defined(USERCONFIG_BOOT) && defined(USERCONFIG) -#ifdef PC98 - movl $0x90200, %esi -#else - movl $0x10200, %esi -#endif - movl $R(_userconfig_from_boot),%edi - movl $512,%ecx - cld - rep - movsb -#endif /* USERCONFIG_BOOT */ - - ret - - -/********************************************************************** - * - * Identify the CPU and initialize anything special about it - * - */ -identify_cpu: - - /* Try to toggle alignment check flag; does not exist on 386. */ - pushfl - popl %eax - movl %eax,%ecx - orl $PSL_AC,%eax - pushl %eax - popfl - pushfl - popl %eax - xorl %ecx,%eax - andl $PSL_AC,%eax - pushl %ecx - popfl - - testl %eax,%eax - jnz 1f - movl $CPU_386,R(_cpu) - jmp 3f - -1: /* Try to toggle identification flag; does not exist on early 486s. */ - pushfl - popl %eax - movl %eax,%ecx - xorl $PSL_ID,%eax - pushl %eax - popfl - pushfl - popl %eax - xorl %ecx,%eax - andl $PSL_ID,%eax - pushl %ecx - popfl - - testl %eax,%eax - jnz 1f - movl $CPU_486,R(_cpu) - - /* check for Cyrix 486DLC -- based on check routine */ - /* documented in "Cx486SLC/e SMM Programmer's Guide" */ - xorw %dx,%dx - cmpw %dx,%dx # set flags to known state - pushfw - popw %cx # store flags in ecx - movw $0xffff,%ax - movw $0x0004,%bx - divw %bx - pushfw - popw %ax - andw $0x08d5,%ax # mask off important bits - andw $0x08d5,%cx - cmpw %ax,%cx - - jnz 3f # if flags changed, Intel chip - - movl $CPU_486DLC,R(_cpu) # set CPU value for Cyrix - movl $0x69727943,R(_cpu_vendor) # store vendor string - movw $0x0078,R(_cpu_vendor+4) - -#ifndef CYRIX_CACHE_WORKS - /* Disable caching of the ISA hole only. */ - invd - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - orb $(CCR0_NC1|CCR0_BARB),%al - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - invd -#else /* CYRIX_CACHE_WORKS */ - /* Set cache parameters */ - invd # Start with guaranteed clean cache - movb $CCR0,%al # Configuration Register index (CCR0) - outb %al,$0x22 - inb $0x23,%al - andb $~CCR0_NC0,%al -#ifndef CYRIX_CACHE_REALLY_WORKS - orb $(CCR0_NC1|CCR0_BARB),%al -#else /* CYRIX_CACHE_REALLY_WORKS */ - orb $CCR0_NC1,%al -#endif /* !CYRIX_CACHE_REALLY_WORKS */ - movb %al,%ah - movb $CCR0,%al - outb %al,$0x22 - movb %ah,%al - outb %al,$0x23 - /* clear non-cacheable region 1 */ - movb $(NCR1+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 2 */ - movb $(NCR2+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 3 */ - movb $(NCR3+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* clear non-cacheable region 4 */ - movb $(NCR4+2),%al - outb %al,$0x22 - movb $NCR_SIZE_0K,%al - outb %al,$0x23 - /* enable caching in CR0 */ - movl %cr0,%eax - andl $~(CR0_CD|CR0_NW),%eax - movl %eax,%cr0 - invd -#endif /* !CYRIX_CACHE_WORKS */ - jmp 3f - -1: /* Use the `cpuid' instruction. */ - xorl %eax,%eax - .byte 0x0f,0xa2 # cpuid 0 - movl %eax,R(_cpu_high) # highest capability - movl %ebx,R(_cpu_vendor) # store vendor string - movl %edx,R(_cpu_vendor+4) - movl %ecx,R(_cpu_vendor+8) - movb $0,R(_cpu_vendor+12) - - movl $1,%eax - .byte 0x0f,0xa2 # cpuid 1 - movl %eax,R(_cpu_id) # store cpu_id - movl %edx,R(_cpu_feature) # store cpu_feature - rorl $8,%eax # extract family type - andl $15,%eax - cmpl $5,%eax - jae 1f - - /* less than Pentium; must be 486 */ - movl $CPU_486,R(_cpu) - jmp 3f -1: - /* a Pentium? */ - cmpl $5,%eax - jne 2f - movl $CPU_586,R(_cpu) - jmp 3f -2: - /* Greater than Pentium...call it a Pentium Pro */ - movl $CPU_686,R(_cpu) -3: - ret - - -/********************************************************************** - * - * Create the first page directory and its page tables. - * - */ - -create_pagetables: - - testl $CPUID_PGE, R(_cpu_feature) - jz 1f - movl %cr4, %eax - orl $CR4_PGE, %eax - movl %eax, %cr4 -1: - -/* Find end of kernel image (rounded up to a page boundary). */ - movl $R(_end),%esi - -/* include symbols in "kernel image" if they are loaded and useful */ -#ifdef DDB - movl R(_bootinfo+BI_ESYMTAB),%edi - testl %edi,%edi - je over_symalloc - movl %edi,%esi - movl $KERNBASE,%edi - addl %edi,R(_bootinfo+BI_SYMTAB) - addl %edi,R(_bootinfo+BI_ESYMTAB) -over_symalloc: -#endif - - addl $PAGE_MASK,%esi - andl $~PAGE_MASK,%esi - movl %esi,R(_KERNend) /* save end of kernel */ - movl %esi,R(physfree) /* next free page is at end of kernel */ - -/* Allocate Kernel Page Tables */ - ALLOCPAGES(NKPT) - movl %esi,R(_KPTphys) - -/* Allocate Page Table Directory */ - ALLOCPAGES(1) - movl %esi,R(_IdlePTD) - -/* Allocate UPAGES */ - ALLOCPAGES(UPAGES) - movl %esi,R(p0upa) - addl $KERNBASE, %esi - movl %esi, R(_proc0paddr) - -/* Allocate proc0's page table for the UPAGES. */ - ALLOCPAGES(1) - movl %esi,R(p0upt) - -/* Map read-only from zero to the end of the kernel text section */ - xorl %eax, %eax -#ifdef BDE_DEBUGGER -/* If the debugger is present, actually map everything read-write. */ - cmpl $0,R(_bdb_exists) - jne map_read_write -#endif - xorl %edx,%edx - testl $CPUID_PGE, R(_cpu_feature) - jz 2f - orl $PG_G,%edx - -2: movl $R(_etext),%ecx - addl $PAGE_MASK,%ecx - shrl $PAGE_SHIFT,%ecx - fillkptphys(%edx) - -/* Map read-write, data, bss and symbols */ - movl $R(_etext),%eax - addl $PAGE_MASK, %eax - andl $~PAGE_MASK, %eax -map_read_write: - movl $PG_RW,%edx - testl $CPUID_PGE, R(_cpu_feature) - jz 1f - orl $PG_G,%edx - -1: movl R(_KERNend),%ecx - subl %eax,%ecx - shrl $PAGE_SHIFT,%ecx - fillkptphys(%edx) - -/* Map page directory. */ - movl R(_IdlePTD), %eax - movl $1, %ecx - fillkptphys($PG_RW) - -/* Map proc0's page table for the UPAGES. */ - movl R(p0upt), %eax - movl $1, %ecx - fillkptphys($PG_RW) - -/* Map proc0's UPAGES in the physical way ... */ - movl R(p0upa), %eax - movl $UPAGES, %ecx - fillkptphys($PG_RW) - -/* Map ISA hole */ - movl $ISA_HOLE_START, %eax - movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx - fillkptphys($PG_RW) - -/* Map proc0s UPAGES in the special page table for this purpose ... */ - movl R(p0upa), %eax - movl $KSTKPTEOFF, %ebx - movl $UPAGES, %ecx - fillkpt(R(p0upt), $PG_RW) - -/* ... and put the page table in the pde. */ - movl R(p0upt), %eax - movl $KSTKPTDI, %ebx - movl $1, %ecx - fillkpt(R(_IdlePTD), $PG_RW) - -/* install a pde for temporary double map of bottom of VA */ - movl R(_KPTphys), %eax - xorl %ebx, %ebx - movl $1, %ecx - fillkpt(R(_IdlePTD), $PG_RW) - -/* install pde's for pt's */ - movl R(_KPTphys), %eax - movl $KPTDI, %ebx - movl $NKPT, %ecx - fillkpt(R(_IdlePTD), $PG_RW) - -/* install a pde recursively mapping page directory as a page table */ - movl R(_IdlePTD), %eax - movl $PTDPTDI, %ebx - movl $1,%ecx - fillkpt(R(_IdlePTD), $PG_RW) - - ret - -#ifdef BDE_DEBUGGER -bdb_prepare_paging: - cmpl $0,R(_bdb_exists) - je bdb_prepare_paging_exit - - subl $6,%esp - - /* - * Copy and convert debugger entries from the bootstrap gdt and idt - * to the kernel gdt and idt. Everything is still in low memory. - * Tracing continues to work after paging is enabled because the - * low memory addresses remain valid until everything is relocated. - * However, tracing through the setidt() that initializes the trace - * trap will crash. - */ - sgdt (%esp) - movl 2(%esp),%esi /* base address of bootstrap gdt */ - movl $R(_gdt),%edi - movl %edi,2(%esp) /* prepare to load kernel gdt */ - movl $8*18/4,%ecx - cld - rep /* copy gdt */ - movsl - movl $R(_gdt),-8+2(%edi) /* adjust gdt self-ptr */ - movb $0x92,-8+5(%edi) - lgdt (%esp) - - sidt (%esp) - movl 2(%esp),%esi /* base address of current idt */ - movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ - movw 8(%esi),%ax - movl %eax,R(bdb_dbg_ljmp+1) /* ... immediate offset ... */ - movl 8+2(%esi),%eax - movw %ax,R(bdb_dbg_ljmp+5) /* ... and selector for ljmp */ - movl 24+4(%esi),%eax /* same for bpt descriptor */ - movw 24(%esi),%ax - movl %eax,R(bdb_bpt_ljmp+1) - movl 24+2(%esi),%eax - movw %ax,R(bdb_bpt_ljmp+5) - movl $R(_idt),%edi - movl %edi,2(%esp) /* prepare to load kernel idt */ - movl $8*4/4,%ecx - cld - rep /* copy idt */ - movsl - lidt (%esp) - - addl $6,%esp - -bdb_prepare_paging_exit: - ret - -/* Relocate debugger gdt entries and gdt and idt pointers. */ -bdb_commit_paging: - cmpl $0,_bdb_exists - je bdb_commit_paging_exit - - movl $_gdt+8*9,%eax /* adjust slots 9-17 */ - movl $9,%ecx -reloc_gdt: - movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ - addl $8,%eax /* now KERNBASE>>24 */ - loop reloc_gdt - - subl $6,%esp - sgdt (%esp) - addl $KERNBASE,2(%esp) - lgdt (%esp) - sidt (%esp) - addl $KERNBASE,2(%esp) - lidt (%esp) - addl $6,%esp - - int $3 - -bdb_commit_paging_exit: - ret - -#endif /* BDE_DEBUGGER */ diff --git a/sys/pc98/i386/machdep.c b/sys/pc98/i386/machdep.c index 95c2823..28ebe0e 100644 --- a/sys/pc98/i386/machdep.c +++ b/sys/pc98/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.28 1997/02/22 09:43:27 peter Exp $ + * $Id: machdep.c,v 1.29 1997/02/25 16:36:48 kato Exp $ */ #include "npx.h" @@ -126,12 +126,19 @@ extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); -extern void identifycpu(void); /* XXX header file */ +extern void printcpuinfo(void); /* XXX header file */ extern void earlysetcpuclass(void); /* same header file */ +extern void finishidentcpu(void); +extern void panicifcpuunsupported(void); +extern void initializecpu(void); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) +#ifdef PC98 +int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */ +int need_post_dma_flush; /* If 1, use invd after DMA transfer. */ +#endif #ifdef BOUNCE_BUFFERS extern char *bouncememory; @@ -215,7 +222,8 @@ cpu_startup(dummy) printf(version); earlysetcpuclass(); startrtclock(); - identifycpu(); + printcpuinfo(); + panicifcpuunsupported(); #ifdef PERFMON perfmon_init(); #endif @@ -1041,7 +1049,7 @@ init386(first) setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #else setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); @@ -1077,6 +1085,10 @@ init386(first) Debugger("Boot flags requested debugger"); #endif + finishidentcpu(); /* Final stage of CPU initialization */ + setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + initializecpu(); /* Initialize CPU registers */ + #ifdef PC98 pc98_getmemsize(); biosbasemem = 640; /* 640KB */ diff --git a/sys/pc98/i386/trap.c b/sys/pc98/i386/trap.c index 38680ba..6ae005a 100644 --- a/sys/pc98/i386/trap.c +++ b/sys/pc98/i386/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id$ + * $Id: trap.c,v 1.13 1997/02/22 09:43:28 peter Exp $ */ /* @@ -91,7 +91,7 @@ extern void trap __P((struct trapframe frame)); extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX static int trap_pfault __P((struct trapframe *, int, vm_offset_t)); #else static int trap_pfault __P((struct trapframe *, int)); @@ -192,14 +192,14 @@ trap(frame) #ifdef DEBUG u_long eva; #endif -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX vm_offset_t va; #endif type = frame.tf_trapno; code = frame.tf_err; -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX /* XXX: * CYRIX 486 CPU FIX. * If you use cyrix cpu, you often encouter strange signal 11's? @@ -210,7 +210,7 @@ trap(frame) va = (vm_offset_t)(rcr2()); if( type == T_PAGEFLT && ( frame.tf_eflags & PSL_I ) ) asm("sti"); -#endif /* CYRIX_486DLC || CYRIX_5X86 */ +#endif /* CPU_BUGGY_CYRIX */ if (ISPL(frame.tf_cs) == SEL_UPL) { /* user trap */ @@ -256,7 +256,7 @@ trap(frame) break; case T_PAGEFLT: /* page fault */ -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX i = trap_pfault(&frame, TRUE, va); #else i = trap_pfault(&frame, TRUE); @@ -332,7 +332,7 @@ trap(frame) switch (type) { case T_PAGEFLT: /* page fault */ -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX (void) trap_pfault(&frame, FALSE, va); #else (void) trap_pfault(&frame, FALSE); @@ -495,7 +495,7 @@ out: * debugging code. */ static int -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX trap_pfault(frame, usermode,faultva) struct trapframe *frame; int usermode; @@ -519,7 +519,7 @@ trap_pfault(frame, usermode) else ftype = VM_PROT_READ; -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX eva = faultva; #else eva = rcr2(); @@ -606,7 +606,7 @@ nogo: #endif int -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX trap_pfault(frame, usermode,faultva) struct trapframe *frame; int usermode; @@ -625,7 +625,7 @@ trap_pfault(frame, usermode) int eva; struct proc *p = curproc; -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX eva = faultva; #else eva = rcr2(); diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index 95c2823..28ebe0e 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.28 1997/02/22 09:43:27 peter Exp $ + * $Id: machdep.c,v 1.29 1997/02/25 16:36:48 kato Exp $ */ #include "npx.h" @@ -126,12 +126,19 @@ extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); -extern void identifycpu(void); /* XXX header file */ +extern void printcpuinfo(void); /* XXX header file */ extern void earlysetcpuclass(void); /* same header file */ +extern void finishidentcpu(void); +extern void panicifcpuunsupported(void); +extern void initializecpu(void); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) +#ifdef PC98 +int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */ +int need_post_dma_flush; /* If 1, use invd after DMA transfer. */ +#endif #ifdef BOUNCE_BUFFERS extern char *bouncememory; @@ -215,7 +222,8 @@ cpu_startup(dummy) printf(version); earlysetcpuclass(); startrtclock(); - identifycpu(); + printcpuinfo(); + panicifcpuunsupported(); #ifdef PERFMON perfmon_init(); #endif @@ -1041,7 +1049,7 @@ init386(first) setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#if defined(CYRIX_486DLC) || defined(CYRIX_5X86) +#ifdef CPU_BUGGY_CYRIX setidt(14, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #else setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); @@ -1077,6 +1085,10 @@ init386(first) Debugger("Boot flags requested debugger"); #endif + finishidentcpu(); /* Final stage of CPU initialization */ + setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); + initializecpu(); /* Initialize CPU registers */ + #ifdef PC98 pc98_getmemsize(); biosbasemem = 640; /* 640KB */ diff --git a/sys/pc98/pc98/pc98.c b/sys/pc98/pc98/pc98.c index 594de6b..19eec78 100644 --- a/sys/pc98/pc98/pc98.c +++ b/sys/pc98/pc98/pc98.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id$ + * $Id: pc98.c,v 1.18 1997/02/22 09:43:42 peter Exp $ */ /* @@ -67,6 +67,7 @@ #include <vm/pmap.h> #include <i386/isa/isa_device.h> #ifdef PC98 +#include <machine/cpufunc.h> #include <pc98/pc98/pc98.h> #include <pc98/pc98/pc98_machdep.h> #include <pc98/pc98/epsonio.h> @@ -734,9 +735,9 @@ void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) /* translate to physical */ phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); -#ifdef CYRIX_5X86 - asm("wbinvd"); /* wbinvd (WB cache flush) */ -#endif + if (need_pre_dma_flush) + wbinvd(); /* wbinvd (WB cache flush) */ + #ifndef PC98 if ((chan & 4) == 0) { @@ -814,12 +815,11 @@ void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) { -#if defined(CYRIX_486DLC) || defined(IBM_486SLC) if (flags & B_READ) { /* cache flush only after reading 92/12/9 by A.Kojima */ - asm(" .byte 0x0f,0x08"); /* invd (cache flush) */ + if (need_post_dma_flush) + invd(); } -#endif #ifdef DIAGNOSTIC if (chan & ~VALID_DMA_MASK) |