[-]
[+]
|
Added |
memtest86.changes
|
|
[-]
[+]
|
Changed |
memtest86.spec
^
|
|
[-]
[+]
|
Deleted |
include-gnuhash.patch
^
|
@@ -1,10 +0,0 @@
---- memtest_shared.lds.orig 2008-07-05 19:01:45.000000000 +0200
-+++ memtest_shared.lds 2008-07-05 19:02:41.000000000 +0200
-@@ -19,6 +19,7 @@
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .hash : { *(.hash) }
-+ .gnu.hash : { *(.gnu.hash) }
- .dynamic : { *(.dynamic) }
-
- .rel.text : { *(.rel.text .rel.text.*) }
|
|
Deleted |
memtest86-3.4.tar.gz/Image.nrg
^
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/bootsect.s
^
|
@@ -1,367 +0,0 @@
-# 1 "bootsect.S"
-# 1 "<built-in>"
-# 1 "<command line>"
-# 1 "bootsect.S"
-
-# 16 "bootsect.S"
-
-
-# 1 "defs.h" 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# 18 "bootsect.S" 2
-
-ROOT_DEV = 0
-
-.code16
-.section ".bootsect", "ax", @progbits
-_boot:
-
-
-# ld86 requires an entry symbol. This may as well be the usual one.
-.globl _main
-_main:
- movw $0x07c0, %ax
- movw %ax, %ds
- movw $0x9000, %ax
- movw %ax, %es
- movw $256, %cx
- subw %si, %si
- subw %di, %di
- cld
- rep
- movsw
- ljmp $0x9000, $go - _boot
-
-go:
- movw %cs, %ax
- movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of
- # bootsect + length of setup + room for stack
- # 12 is disk parm size
-
-# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
-# wouldn't have to worry about this if we checked the top of memory. Also
-# my BIOS can be configured to put the wini drive tables in high memory
-# instead of in the vector table. The old stack might have clobbered the
-# drive table.
-
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss # put stack at 0x9000:0x4000-12.
- movw %dx, %sp
-
-
-# 74 "bootsect.S"
- pushw $0
- popw %fs
- movw $0x78, %bx # fs:bx is parameter table address
- lgs %fs:(%bx),%si # gs:si is source
-
- movw %dx, %di # es:di is destination
- movw $6, %cx # copy 12 bytes
- cld
-
- rep movsw %gs:(%si), (%di)
-
- movw %dx, %di
- movb $18, 4(%di) # patch sector count
-
- movw %di, %fs:(%bx)
- movw %es, %fs:2(%bx)
-
- movw %cs, %ax
- movw %ax, %fs
- movw %ax, %gs
-
- xorb %ah, %ah # reset FDC
- xorb %dl, %dl
- int $0x13
-
-# load the setup-sectors directly after the bootblock.
-# Note that 'es' is already set up.
-
-load_setup:
- xorw %dx, %dx # drive 0, head 0
- movw $0x0002, %cx # sector 2, track 0
- movw $0x0200, %bx # address = 512, in 0x9000
- movw $(0x0200 + 4), %ax # service 2, nr of sectors
- # (assume all on head 0, track 0)
- int $0x13 # read it
- jnc ok_load_setup # ok - continue
-
- pushw %ax # dump error code
- call print_nl
- movw %sp, %bp
- call print_hex
- popw %ax
-
- xorb %dl, %dl # reset FDC
- xorb %ah, %ah
- int $0x13
- jmp load_setup
-
-ok_load_setup:
-
-# Get disk drive parameters, specifically nr of sectors/track
-
-
-
-
-
-
-
- xorw %dx, %dx # drive 0, head 0
- movw $0x0012, %cx # sector 18, track 0
- movw $(0x200+(4*0x200)), %bx # address after setup (es = cs)
- movw $0x0201, %ax # service 2, 1 sector
- int $0x13
- jnc got_sectors
- movb $0x0f, %cl # sector 15
- movw $0x0201, %ax # service 2, 1 sector
- int $0x13
- jnc got_sectors
- movb $0x09, %cl
-
-got_sectors:
- movw %cx, %cs:sectors - _boot
- movw $0x9000, %ax
- movw %ax, %es
-
-# Print some inane message
-
- movb $0x03, %ah # read cursor pos
- xorb %bh, %bh
- int $0x10
-
- movw $9, %cx
- movw $0x0007, %bx # page 0, attribute 7 (normal)
- movw $msg1 - _boot, %bp
- movw $0x1301, %ax # write string, move cursor
- int $0x10
-
-# ok, we've written the message, now
-# we want to load the system (at 0x10000)
-
- movw $0x1000, %ax
- movw %ax, %es # segment of 0x010000
- call read_it
- call kill_motor
- call print_nl
-
-# after that (everyting loaded), we jump to
-# the setup-routine loaded directly after
-# the bootblock:
-
- ljmp $(0x9000+0x20),$0
-
-# This routine loads the system at address 0x10000, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-
-# in: es - starting address segment (normally 0x1000)
-
-sread: .word 1+4 # sectors read of current track
-head: .word 0 # current head
-track: .word 0 # current track
-
-read_it:
- movw %es, %ax
- testw $0x0fff, %ax
-die:
- jne die # es must be at 64kB boundary
- xorw %bx,%bx # bx is starting address within segment
-rp_read:
- movw %es, %ax
- subw $0x1000, %ax # have we loaded all yet?
- cmpw syssize - _boot, %ax
- jbe ok1_read
- ret
-ok1_read:
- movw %cs:sectors - _boot, %ax
- subw sread - _boot, %ax
- movw %ax, %cx
- shlw $9, %cx
- addw %bx, %cx
- jnc ok2_read
- je ok2_read
- xorw %ax, %ax
- subw %bx, %ax
- shrw $9, %ax
-ok2_read:
- call read_track
- movw %ax, %cx
- add sread - _boot, %ax
- cmpw %cs:sectors - _boot, %ax
- jne ok3_read
- movw $1, %ax
- subw head - _boot, %ax
- jne ok4_read
- incw track - _boot
-ok4_read:
- movw %ax, head - _boot
- xorw %ax, %ax
-ok3_read:
- movw %ax, sread - _boot
- shlw $9, %cx
- addw %cx, %bx
- jnc rp_read
- movw %es, %ax
- addb $0x10, %ah
- movw %ax, %es
- xorw %bx, %bx
- jmp rp_read
-
-read_track:
- pusha
- pusha
- movw $0xe2e, %ax # loading... message 2e = .
- movw $7, %bx
- int $0x10
- popa
-
- movw track - _boot, %dx
- movw sread - _boot, %cx
- incw %cx
- movb %dl, %ch
- movw head - _boot, %dx
- movb %dl, %dh
- andw $0x0100, %dx
- movb $2, %ah
-
- pushw %dx # save for error dump
- pushw %cx
- pushw %bx
- pushw %ax
-
- int $0x13
- jc bad_rt
- addw $8, %sp
- popa
- ret
-
-bad_rt:
- pushw %ax # save error code
- call print_all # ah = error, al = read
-
- xorb %ah, %ah
- xorb %dl, %dl
- int $0x13
-
- addw $10, %sp
- popa
- jmp read_track
-
-
-# 285 "bootsect.S"
-
-print_all:
- movw $5, %cx # error code + 4 registers
- movw %sp, %bp
-
-print_loop:
- pushw %cx # save count left
- call print_nl # nl for readability
-
- cmpb 5, %cl # see if register name is needed
- jae no_reg
-
- movw $(0xe05 + 'A' - 1), %ax
- subb %cl, %al
- int $0x10
- movb $'X', %al
- int $0x10
- movb $':', %al
- int $0x10
-
-no_reg:
- addw $2, %bp # next register
- call print_hex # print it
- popw %cx
- loop print_loop
- ret
-
-print_nl:
- movw $0xe0d, %ax # CR
- int $0x10
- movb $0x0a, %al # LF
- int $0x10
- ret
-
-
-
-
-
-
-print_hex:
- movw $4, %cx # 4 hex digits
- movw (%bp), %dx # load word into dx
-
-print_digit:
- rolw $4, %dx # rotate so that lowest 4 bits are used
- movb $0xe, %ah
- movb %dl, %al # mask off so we have only next nibble
- andb $0xf, %al
- addb $'0', %al # convert to 0-based digit
- cmpb $'9', %al # check for overflow
- jbe good_digit
- addb $('A' - '0' - 10), %al
-
-good_digit:
- int $0x10
- loop print_digit
- ret
-
-
-
-
-
-
-
-kill_motor:
- pushw %dx
- movw $0x3f2, %dx
- xorb %al, %al
- outb %al, %dx
- popw %dx
- ret
-
-sectors:
- .word 0
-
-msg1:
- .byte 13,10
- .ascii "Loading"
-
-.org 497
-setup_sects:
- .byte 4
-.org 500
-syssize:
- .word _syssize
-.org 508
-root_dev:
- .word ROOT_DEV
-boot_flag:
- .word 0xAA55
-_eboot:
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/controller.c
^
|
@@ -1,2274 +0,0 @@
-/* controller.c - MemTest-86 Version 3.4
- *
- * Released under version 2 of the Gnu Public License.
- * By Chris Brady, cbrady@sgi.com
- * ----------------------------------------------------
- * MemTest86+ V1.70 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.x86-secret.com - http://www.memtest.org
- */
-
-#include "defs.h"
-#include "config.h"
-#include "test.h"
-#include "pci.h"
-#include "controller.h"
-
-int col, col2;
-
-extern ulong extclock;
-extern struct cpu_ident cpu_id;
-
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
-
-/* controller ECC capabilities and mode */
-#define __ECC_UNEXPECTED 1 /* Unknown ECC capability present */
-#define __ECC_DETECT 2 /* Can detect ECC errors */
-#define __ECC_CORRECT 4 /* Can correct some ECC errors */
-#define __ECC_SCRUB 8 /* Can scrub corrected ECC errors */
-#define __ECC_CHIPKILL 16 /* Can corrected multi-errors */
-
-#define ECC_UNKNOWN (~0UL) /* Unknown error correcting ability/status */
-#define ECC_NONE 0 /* Doesnt support ECC (or is BIOS disabled) */
-#define ECC_RESERVED __ECC_UNEXPECTED /* Reserved ECC type */
-#define ECC_DETECT __ECC_DETECT
-#define ECC_CORRECT (__ECC_DETECT | __ECC_CORRECT)
-#define ECC_CHIPKILL (__ECC_DETECT | __ECC_CORRECT | __ECC_CHIPKILL)
-#define ECC_SCRUB (__ECC_DETECT | __ECC_CORRECT | __ECC_SCRUB)
-
-
-static struct ecc_info {
- int index;
- int poll;
- unsigned bus;
- unsigned dev;
- unsigned fn;
- unsigned cap;
- unsigned mode;
-} ctrl =
-{
- .index = 0,
- /* I know of no case where the memory controller is not on the
- * host bridge, and the host bridge is not on bus 0 device 0
- * fn 0. But just in case leave these as variables.
- */
- .bus = 0,
- .dev = 0,
- .fn = 0,
- /* Properties of the current memory controller */
- .cap = ECC_UNKNOWN,
- .mode = ECC_UNKNOWN,
-};
-
-struct pci_memory_controller {
- unsigned vendor;
- unsigned device;
- char *name;
- int tested;
- void (*poll_fsb)(void);
- void (*poll_timings)(void);
- void (*setup_ecc)(void);
- void (*poll_errors)(void);
-};
-
-void print_timings_info(float cas, int rcd, int rp, int ras) {
-
- /* Now, we could print some additionnals timings infos) */
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- // CAS Latency (tCAS)
- if (cas == 1.5) {
- cprint(LINE_CPU+5, col2, "1.5"); col2 += 3;
- } else if (cas == 2.5) {
- cprint(LINE_CPU+5, col2, "2.5"); col2 += 3;
- } else {
- dprint(LINE_CPU+5, col2, cas, 1, 0); col2 += 1;
- }
- cprint(LINE_CPU+5, col2, "-"); col2 += 1;
-
- // RAS-To-CAS (tRCD)
- dprint(LINE_CPU+5, col2, rcd, 1, 0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 +=2;
-
- // RAS Precharge (tRP)
- dprint(LINE_CPU+5, col2, rp, 1, 0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 +=2;
-
- // RAS Active to precharge (tRAS)
- if (ras < 9) {
- dprint(LINE_CPU+5, col2, ras, 1, 0);
- col2 += 2;
- } else {
- dprint(LINE_CPU+5, col2, ras, 2, 0);
- col2 += 3;
- }
-
-}
-
-
-void print_fsb_info(float val, const char *text_fsb) {
-
- cprint(LINE_CPU+5, col2, "Settings: ");
- col2 += 10;
- cprint(LINE_CPU+5, col2, text_fsb);
- col2 += 6;
- dprint(LINE_CPU+5, col2, val ,3 ,0);
- col2 += 3;
- cprint(LINE_CPU+5, col2 +1, "MHz ");
- col2 += 5;
- cprint(LINE_CPU+5, col2, "(DDR");
- col2 += 4;
- dprint(LINE_CPU+5, col2, val*2 ,3 ,0);
- col2 += 3;
- cprint(LINE_CPU+5, col2, ")");
- col2 += 1;
-}
-
-static void poll_fsb_nothing(void)
-{
-/* Code to run for no specific fsb detection */
- return;
-}
-
-static void poll_timings_nothing(void)
-{
-/* Code to run for no specific timings detection */
- return;
-}
-
-
-static void setup_nothing(void)
-{
- ctrl.cap = ECC_NONE;
- ctrl.mode = ECC_NONE;
-}
-
-static void poll_nothing(void)
-{
-/* Code to run when we don't know how, or can't ask the memory
- * controller about memory errors.
- */
- return;
-}
-
-static void setup_amd64(void)
-{
-
- static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_RESERVED, ECC_CHIPKILL };
- unsigned long nbxcfg;
- unsigned int mcgsrl;
- unsigned int mcgsth;
- unsigned long mcanb;
- unsigned long dramcl;
-
- /* All AMD64 support Chipkill */
- ctrl.cap = ECC_CHIPKILL;
-
- /* Check First if ECC DRAM Modules are used */
- pci_conf_read(0, 24, 2, 0x90, 4, &dramcl);
-
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
- /* NEW K8 0Fh Family 90 nm */
-
- if ((dramcl >> 19)&1){
- /* Fill in the correct memory capabilites */
- pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
- ctrl.mode = ddim[(nbxcfg >> 22)&3];
- } else {
- ctrl.mode = ECC_NONE;
- }
- /* Enable NB ECC Logging by MSR Write */
- rdmsr(0x017B, mcgsrl, mcgsth);
- wrmsr(0x017B, 0x10, mcgsth);
-
- /* Clear any previous error */
- pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
- pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
-
- } else {
- /* OLD K8 130 nm */
-
- if ((dramcl >> 17)&1){
- /* Fill in the correct memory capabilites */
- pci_conf_read(0, 24, 3, 0x44, 4, &nbxcfg);
- ctrl.mode = ddim[(nbxcfg >> 22)&3];
- } else {
- ctrl.mode = ECC_NONE;
- }
- /* Enable NB ECC Logging by MSR Write */
- rdmsr(0x017B, mcgsrl, mcgsth);
- wrmsr(0x017B, 0x10, mcgsth);
-
- /* Clear any previous error */
- pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
- pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7F801EFC );
-
-
- }
-}
-
-static void poll_amd64(void)
-{
-
- unsigned long mcanb;
- unsigned long page, offset;
- unsigned long celog_syndrome;
- unsigned long mcanb_add;
-
- pci_conf_read(0, 24, 3, 0x4C, 4, &mcanb);
-
- if (((mcanb >> 31)&1) && ((mcanb >> 14)&1)) {
- /* Find out about the first correctable error */
- /* Syndrome code -> bits use a complex matrix. Will add this later */
- /* Read the error location */
- pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
-
- /* Read the syndrome */
- celog_syndrome = (mcanb >> 15)&0xFF;
-
- /* Parse the error location */
- page = (mcanb_add >> 12);
- offset = (mcanb_add >> 3) & 0xFFF;
-
- /* Report the error */
- print_ecc_err(page, offset, 1, celog_syndrome, 0);
-
- /* Clear the error registers */
- pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFFF );
- }
- if (((mcanb >> 31)&1) && ((mcanb >> 13)&1)) {
- /* Found out about the first uncorrectable error */
- /* Read the error location */
- pci_conf_read(0, 24, 3, 0x50, 4, &mcanb_add);
-
- /* Parse the error location */
- page = (mcanb_add >> 12);
- offset = (mcanb_add >> 3) & 0xFFF;
-
- /* Report the error */
- print_ecc_err(page, offset, 0, 0, 0);
-
- /* Clear the error registers */
- pci_conf_write(0, 24, 3, 0x4C, 4, mcanb & 0x7FFFFFF );
-
- }
-
-}
-
-static void setup_amd751(void)
-{
- unsigned long dram_status;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5a, 2, &dram_status);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = (dram_status & (1 << 2))?ECC_CORRECT: ECC_NONE;
-}
-
-static void poll_amd751(void)
-{
- unsigned long ecc_status;
- unsigned long bank_addr;
- unsigned long bank_info;
- unsigned long page;
- int bits;
- int i;
-
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, &ecc_status);
- if (ecc_status & (3 << 8)) {
- for(i = 0; i < 6; i++) {
- if (!(ecc_status & (1 << i))) {
- continue;
- }
- /* Find the bank the error occured on */
- bank_addr = 0x40 + (i << 1);
-
- /* Now get the information on the erroring bank */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 2, &bank_info);
-
- /* Parse the error location and error type */
- page = (bank_info & 0xFF80) << 4;
- bits = (((ecc_status >> 8) &3) == 2)?1:2;
-
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, 0, 0);
-
- }
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 2, 0);
- }
-}
-
-/* Still waiting for the CORRECT intel datasheet
-static void setup_i85x(void)
-{
- unsigned long drc;
- ctrl.cap = ECC_CORRECT;
-
- pci_conf_read(ctrl.bus, ctrl.dev, 1, 0x70, 4, &drc);
- ctrl.mode = ((drc>>20)&1)?ECC_CORRECT:ECC_NONE;
-
-}
-*/
-
-static void setup_amd76x(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
- unsigned long ecc_mode_status;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(ecc_mode_status >> 10)&3];
-}
-
-static void poll_amd76x(void)
-{
- unsigned long ecc_mode_status;
- unsigned long bank_addr;
- unsigned long bank_info;
- unsigned long page;
-
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, &ecc_mode_status);
- /* Multibit error */
- if (ecc_mode_status & (1 << 9)) {
- /* Find the bank the error occured on */
- bank_addr = 0xC0 + (((ecc_mode_status >> 4) & 0xf) << 2);
-
- /* Now get the information on the erroring bank */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
-
- /* Parse the error location and error type */
- page = (bank_info & 0xFF800000) >> 12;
-
- /* Report the error */
- print_ecc_err(page, 0, 1, 0, 0);
-
- }
- /* Singlebit error */
- if (ecc_mode_status & (1 << 8)) {
- /* Find the bank the error occured on */
- bank_addr = 0xC0 + (((ecc_mode_status >> 0) & 0xf) << 2);
-
- /* Now get the information on the erroring bank */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, bank_addr, 4, &bank_info);
-
- /* Parse the error location and error type */
- page = (bank_info & 0xFF800000) >> 12;
-
- /* Report the error */
- print_ecc_err(page, 0, 0, 0, 0);
-
- }
- /* Clear the error status */
- if (ecc_mode_status & (3 << 8)) {
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x48, 4, ecc_mode_status);
- }
-}
-
-static void setup_cnb20(void)
-{
- /* Fill in the correct memory capabilites */
- ctrl.cap = ECC_CORRECT;
-
- /* FIXME add ECC error polling. I don't have the documentation
- * do it right now.
- */
-}
-
-static void setup_iE7xxx(void)
-{
- unsigned long mchcfgns;
- unsigned long drc;
- unsigned long device;
- unsigned long dvnp;
-
- /* Read the hardare capabilities */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchcfgns);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
-
- /* This is a check for E7205 */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x02, 2, &device);
-
- /* Fill in the correct memory capabilities */
- ctrl.mode = 0;
- ctrl.cap = ECC_CORRECT;
-
- /* checking and correcting enabled */
- if (((drc >> 20) & 3) == 2) {
- ctrl.mode |= ECC_CORRECT;
- }
-
- /* E7205 doesn't support scrubbing */
- if (device != 0x255d) {
- /* scrub enabled */
- /* For E7501, valid SCRUB operations is bit 0 / D0:F0:R70-73 */
- ctrl.cap = ECC_SCRUB;
- if (mchcfgns & 1) {
- ctrl.mode |= __ECC_SCRUB;
- }
-
- /* Now, we can active Dev1/Fun1 */
- /* Thanks to Tyan for providing us the board to solve this */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE0, 2, &dvnp);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xE0, 2, (dvnp & 0xFE));
-
- /* Clear any routing of ECC errors to interrupts that the BIOS might have set up */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x88, 1, 0x0);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8A, 1, 0x0);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x8C, 1, 0x0);
-
-
- }
-
- /* Clear any prexisting error reports */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, 3);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, 3);
-
-
-}
-
-static void setup_iE7520(void)
-{
- unsigned long mchscrb;
- unsigned long drc;
- unsigned long dvnp1;
-
- /* Read the hardare capabilities */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x52, 2, &mchscrb);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
-
- /* Fill in the correct memory capabilities */
- ctrl.mode = 0;
- ctrl.cap = ECC_CORRECT;
-
- /* Checking and correcting enabled */
- if (((drc >> 20) & 3) != 0) {
- ctrl.mode |= ECC_CORRECT;
- }
-
- /* scrub enabled */
- ctrl.cap = ECC_SCRUB;
- if ((mchscrb & 3) == 2) {
- ctrl.mode |= __ECC_SCRUB;
- }
-
- /* Now, we can activate Fun1 */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xF4, 1, &dvnp1);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn , 0xF4, 1, (dvnp1 | 0x20));
-
- /* Clear any prexisting error reports */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, 0x4747);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, 0x4747);
-}
-
-static void poll_iE7xxx(void)
-{
- unsigned long ferr;
- unsigned long nerr;
-
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, &ferr);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, &nerr);
-
- if (ferr & 1) {
- /* Find out about the first correctable error */
- unsigned long celog_add;
- unsigned long celog_syndrome;
- unsigned long page;
-
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4, &celog_add);
- /* Read the syndrome */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xD0, 2, &celog_syndrome);
-
- /* Parse the error location */
- page = (celog_add & 0x0FFFFFC0) >> 6;
-
- /* Report the error */
- print_ecc_err(page, 0, 1, celog_syndrome, 0);
-
- /* Clear Bit */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
- }
-
- if (ferr & 2) {
- /* Found out about the first uncorrectable error */
- unsigned long uccelog_add;
- unsigned long page;
-
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xB0, 4, &uccelog_add);
-
- /* Parse the error location */
- page = (uccelog_add & 0x0FFFFFC0) >> 6;
-
- /* Report the error */
- print_ecc_err(page, 0, 0, 0, 0);
-
- /* Clear Bit */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 1, ferr & 3);
- }
-
- /* Check if DRAM_NERR contains data */
- if (nerr & 3) {
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 1, nerr & 3);
- }
-
-}
-
-static void setup_i440gx(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_DETECT, ECC_CORRECT, ECC_CORRECT };
- unsigned long nbxcfg;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 4, &nbxcfg);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(nbxcfg >> 7)&3];
-}
-
-static void poll_i440gx(void)
-{
- unsigned long errsts;
- unsigned long page;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, &errsts);
- if (errsts & 0x11) {
- unsigned long eap;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, &eap);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFF000) >> 12;
- bits = 0;
- if (eap &3) {
- bits = ((eap & 3) == 1)?1:2;
- }
-
- if (bits) {
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, 0, 0);
- }
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x91, 2, 0x11);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0x80, 4, 3);
- }
-
-}
-static void setup_i840(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
- unsigned long mchcfg;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(mchcfg >> 7)&3];
-}
-
-static void poll_i840(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned long syndrome;
- int channel;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 3) {
- unsigned long eap;
- unsigned long derrctl_sts;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFF800) >> 11;
- channel = eap & 1;
- syndrome = derrctl_sts & 0xFF;
- bits = ((errsts & 3) == 1)?1:2;
-
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, 3 << 10);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
- }
-}
-static void setup_i875(void)
-{
-
- long *ptr;
- ulong dev0, dev6 ;
-
- /* Fill in the correct memory capabilites */
-
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ECC_NONE;
-
- /* From my article : http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm */
- /* Activate Device 6 */
- pci_conf_read( 0, 0, 0, 0xF4, 1, &dev0);
- pci_conf_write( 0, 0, 0, 0xF4, 1, (dev0 | 0x2));
-
- /* Activate Device 6 MMR */
- pci_conf_read( 0, 6, 0, 0x04, 2, &dev6);
- pci_conf_write( 0, 6, 0, 0x04, 2, (dev6 | 0x2));
-
- /* Read the MMR Base Address & Define the pointer*/
- pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
- ptr=(long*)(dev6+0x68);
-
- if (((*ptr >> 18)&1) == 1) { ctrl.mode = ECC_CORRECT; }
-
- /* Reseting state */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
-
-}
-
-
-static void setup_i925(void)
-{
-
- // Activate MMR I/O
- ulong dev0, drc;
- unsigned long tolm;
- long *ptr;
-
- pci_conf_read( 0, 0, 0, 0x54, 4, &dev0);
- dev0 = dev0 | 0x10000000;
- pci_conf_write( 0, 0, 0, 0x54, 4, dev0);
-
- // CDH start
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- if (!(dev0 & 0xFFFFC000)) {
- pci_conf_read( 0, 0, 0, 0x9C, 1, &tolm);
- pci_conf_write( 0, 0, 0, 0x47, 1, tolm & 0xF8);
- }
- // CDH end
-
- // ECC Checking
- ctrl.cap = ECC_CORRECT;
-
- dev0 &= 0xFFFFC000;
- ptr=(long*)(dev0+0x120);
- drc = *ptr & 0xFFFFFFFF;
-
- if (((drc >> 20) & 3) == 2) {
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
- ctrl.mode = ECC_CORRECT;
- } else {
- ctrl.mode = ECC_NONE;
- }
-
-}
-
-
-static void poll_i875(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned long des;
- unsigned long syndrome;
- int channel;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 0x81) {
- unsigned long eap;
- unsigned long derrsyn;
- /* Read the error location, syndrome and channel */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrsyn);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5D, 1, &des);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFF000) >> 12;
- syndrome = derrsyn;
- channel = des & 1;
- bits = (errsts & 0x80)?0:1;
-
- /* Report the error */
- print_ecc_err(page, 0, bits, syndrome, channel);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 0x81);
- }
-}
-
-static void setup_i845(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
- unsigned long drc;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x7C, 4, &drc);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(drc >> 20)&3];
-}
-
-static void poll_i845(void)
-{
- unsigned long errsts;
- unsigned long page, offset;
- unsigned long syndrome;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 3) {
- unsigned long eap;
- unsigned long derrsyn;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x8C, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x86, 1, &derrsyn);
-
- /* Parse the error location and error type */
- offset = (eap & 0xFE) << 4;
- page = (eap & 0x3FFFFFFE) >> 8;
- syndrome = derrsyn;
- bits = ((errsts & 3) == 1)?1:2;
-
- /* Report the error */
- print_ecc_err(page, offset, bits==1?1:0, syndrome, 0);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
- }
-}
-static void setup_i820(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_CORRECT };
- unsigned long mchcfg;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xbe, 2, &mchcfg);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(mchcfg >> 7)&3];
-}
-
-static void poll_i820(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned long syndrome;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 3) {
- unsigned long eap;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xc4, 4, &eap);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFF000) >> 4;
- syndrome = eap & 0xFF;
- bits = ((errsts & 3) == 1)?1:2;
-
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, syndrome, 0);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, 3);
- }
-}
-
-static void setup_i850(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
- unsigned long mchcfg;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(mchcfg >> 7)&3];
-}
-
-static void poll_i850(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned long syndrome;
- int channel;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 3) {
- unsigned long eap;
- unsigned long derrctl_sts;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFF800) >> 11;
- channel = eap & 1;
- syndrome = derrctl_sts & 0xFF;
- bits = ((errsts & 3) == 1)?1:2;
-
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
- }
-}
-
-static void setup_i860(void)
-{
- static const int ddim[] = { ECC_NONE, ECC_RESERVED, ECC_CORRECT, ECC_RESERVED };
- unsigned long mchcfg;
- unsigned long errsts;
-
- /* Fill in the correct memory capabilites */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x50, 2, &mchcfg);
- ctrl.cap = ECC_CORRECT;
- ctrl.mode = ddim[(mchcfg >> 7)&3];
-
- /* Clear any prexisting error reports */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
-}
-
-static void poll_i860(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned char syndrome;
- int channel;
- int bits;
- /* Read the error status */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
- if (errsts & 3) {
- unsigned long eap;
- unsigned long derrctl_sts;
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE4, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xE2, 2, &derrctl_sts);
-
- /* Parse the error location and error type */
- page = (eap & 0xFFFFFE00) >> 9;
- channel = eap & 1;
- syndrome = derrctl_sts & 0xFF;
- bits = ((errsts & 3) == 1)?1:2;
-
- /* Report the error */
- print_ecc_err(page, 0, bits==1?1:0, syndrome, channel);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
- }
-}
-
-static void poll_iE7221(void)
-{
- unsigned long errsts;
- unsigned long page;
- unsigned char syndrome;
- int channel;
- int bits;
- int errocc;
-
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, &errsts);
-
- errocc = errsts & 3;
-
- if ((errocc == 1) || (errocc == 2)) {
- unsigned long eap, offset;
- unsigned long derrctl_sts;
-
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x58, 4, &eap);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, 0x5C, 1, &derrctl_sts);
-
- /* Parse the error location and error type */
- channel = eap & 1;
- eap = eap & 0xFFFFFF80;
- page = eap >> 12;
- offset = eap & 0xFFF;
- syndrome = derrctl_sts & 0xFF;
- bits = errocc & 1;
-
- /* Report the error */
- print_ecc_err(page, offset, bits, syndrome, channel);
-
- /* Clear the error status */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
- }
-
- else if (errocc == 3) {
-
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn, 0xC8, 2, errsts & 3);
-
- }
-}
-
-static void poll_iE7520(void)
-{
- unsigned long ferr;
- unsigned long nerr;
-
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, &ferr);
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, &nerr);
-
- if (ferr & 0x0101) {
- /* Find out about the first correctable error */
- unsigned long celog_add;
- unsigned long celog_syndrome;
- unsigned long page;
-
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA0, 4,&celog_add);
- /* Read the syndrome */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xC4, 2, &celog_syndrome);
-
- /* Parse the error location */
- page = (celog_add & 0x7FFFFFFC) >> 2;
-
- /* Report the error */
- print_ecc_err(page, 0, 1, celog_syndrome, 0);
-
- /* Clear Bit */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr& 0x0101);
- }
-
- if (ferr & 0x4646) {
- /* Found out about the first uncorrectable error */
- unsigned long uccelog_add;
- unsigned long page;
-
- /* Read the error location */
- pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn +1, 0xA4, 4, &uccelog_add);
-
- /* Parse the error location */
- page = (uccelog_add & 0x7FFFFFFC) >> 2;
-
- /* Report the error */
- print_ecc_err(page, 0, 0, 0, 0);
-
- /* Clear Bit */
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x80, 2, ferr & 0x4646);
- }
-
- /* Check if DRAM_NERR contains data */
- if (nerr & 0x4747) {
- pci_conf_write(ctrl.bus, ctrl.dev, ctrl.fn +1, 0x82, 2, nerr & 0x4747);
- }
-}
-
-
-/* ------------------ Here the code for FSB detection ------------------ */
-/* --------------------------------------------------------------------- */
-
-static float athloncoef[] = {11, 11.5, 12.0, 12.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5};
-static float athloncoef2[] = {12, 19.0, 12.0, 20.0, 13.0, 13.5, 14.0, 21.0, 15.0, 22, 16.0, 16.5, 17.0, 18.0, 23.0, 24.0};
-static int p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15};
-
-static int getP4PMmultiplier(void)
-{
- unsigned int msr_lo, msr_hi;
- int coef;
- /* Find multiplier (by MSR) */
-
- if (cpu_id.type == 6) {
- rdmsr(0x2A, msr_lo, msr_hi);
- coef = (msr_lo >> 22) & 0x1F;
- }
- else
- {
- if (cpu_id.model < 2)
- {
- rdmsr(0x2A, msr_lo, msr_hi);
- coef = (msr_lo >> 8) & 0xF;
- coef = p4model1ratios[coef];
- }
- else
- {
- rdmsr(0x2C, msr_lo, msr_hi);
- coef = (msr_lo >> 24) & 0x1F;
- }
- }
- return coef;
-}
-
-static void poll_fsb_amd64(void) {
-
- unsigned int mcgsrl;
- unsigned int mcgsth;
- unsigned long fid, temp2;
- unsigned long dramchr;
- float clockratio;
- double dramclock;
-
- float coef = 10;
-
- /* First, got the FID by MSR */
- /* First look if Cool 'n Quiet is supported to choose the best msr */
- if (((cpu_id.pwrcap >> 1) & 1) == 1) {
- rdmsr(0xc0010042, mcgsrl, mcgsth);
- fid = (mcgsrl & 0x3F);
- } else {
- rdmsr(0xc0010015, mcgsrl, mcgsth);
- fid = ((mcgsrl >> 24)& 0x3F);
- }
-
- /* Extreme simplification. */
- coef = ( fid / 2 ) + 4.0;
-
- /* Support for .5 coef */
- if (fid & 1) { coef = coef + 0.5; }
-
- /* Next, we need the clock ratio */
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
- /* K8 0FH */
- pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
- temp2 = (dramchr & 0x7);
- clockratio = coef;
-
- switch (temp2) {
- case 0x0:
- clockratio = (int)(coef);
- break;
- case 0x1:
- clockratio = (int)(coef * 3.0f/4.0f);
- break;
- case 0x2:
- clockratio = (int)(coef * 3.0f/5.0f);
- break;
- case 0x3:
- clockratio = (int)(coef * 3.0f/6.0f);
- break;
- }
-
- } else {
- /* OLD K8 */
- pci_conf_read(0, 24, 2, 0x94, 4, &dramchr);
- temp2 = (dramchr >> 20) & 0x7;
- clockratio = coef;
-
- switch (temp2) {
- case 0x0:
- clockratio = (int)(coef * 2.0f);
- break;
- case 0x2:
- clockratio = (int)((coef * 3.0f/2.0f) + 0.81f);
- break;
- case 0x4:
- clockratio = (int)((coef * 4.0f/3.0f) + 0.81f);
- break;
- case 0x5:
- clockratio = (int)((coef * 6.0f/5.0f) + 0.81f);
- break;
- case 0x6:
- clockratio = (int)((coef * 10.0f/9.0f) + 0.81f);
- break;
- case 0x7:
- clockratio = (int)(coef + 0.81f);
- break;
- }
- }
-
- /* Compute the final DRAM Clock */
- dramclock = (extclock /1000) / clockratio;
-
- /* ...and print */
- print_fsb_info(dramclock, "RAM : ");
-
-}
-
-static void poll_fsb_i925(void) {
-
- double dramclock, dramratio, fsb;
- unsigned long mchcfg, mchcfg2, dev0, drc, idetect;
- int coef = getP4PMmultiplier();
- long *ptr;
-
- pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
-
- /* Find dramratio */
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- dev0 = dev0 & 0xFFFFC000;
- ptr=(long*)(dev0+0xC00);
- mchcfg = *ptr & 0xFFFF;
- ptr=(long*)(dev0+0x120);
- drc = *ptr & 0xFFFF;
- dramratio = 1;
-
- mchcfg2 = (mchcfg >> 4)&3;
-
- if ((drc&3) != 2) {
- // We are in DDR1 Mode
- if (mchcfg2 == 1) { dramratio = 0.8; } else { dramratio = 1; }
- } else {
- // We are in DDR2 Mode
- if ((mchcfg >> 2)&1) {
- // We are in FSB1066 Mode
- if (mchcfg2 == 2) { dramratio = 0.75; } else { dramratio = 1; }
- } else {
- switch (mchcfg2) {
- case 1:
- dramratio = 0.66667;
- break;
- case 2:
- if (idetect != 0x2590) { dramratio = 1; } else { dramratio = 1.5; }
- break;
- case 3:
- // Checking for FSB533 Mode & Alviso
- if ((mchcfg & 1) == 0) { dramratio = 1.33334; }
- else if (idetect == 0x2590) { dramratio = 2; }
- else { dramratio = 1.5; }
- }
- }
- }
- // Compute RAM Frequency
- fsb = ((extclock / 1000) / coef);
- dramclock = fsb * dramratio;
-
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+4, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
-}
-
-static void poll_fsb_i945(void) {
-
- double dramclock, dramratio, fsb;
- unsigned long mchcfg, dev0;
- int coef = getP4PMmultiplier();
- long *ptr;
-
- /* Find dramratio */
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- dev0 &= 0xFFFFC000;
- ptr=(long*)(dev0+0xC00);
- mchcfg = *ptr & 0xFFFF;
- dramratio = 1;
-
- switch ((mchcfg >> 4)&7) {
- case 1: dramratio = 1.0; break;
- case 2: dramratio = 1.33334; break;
- case 3: dramratio = 1.66667; break;
- case 4: dramratio = 2.0; break;
- }
-
- // Compute RAM Frequency
- fsb = ((extclock / 1000) / coef);
- dramclock = fsb * dramratio;
-
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+4, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
-}
-
-static void poll_fsb_i975(void) {
-
- double dramclock, dramratio, fsb;
- unsigned long mchcfg, dev0, fsb_mch;
- int coef = getP4PMmultiplier();
- long *ptr;
-
- /* Find dramratio */
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- dev0 &= 0xFFFFC000;
- ptr=(long*)(dev0+0xC00);
- mchcfg = *ptr & 0xFFFF;
- dramratio = 1;
-
- switch (mchcfg & 7) {
- case 1: fsb_mch = 533; break;
- case 2: fsb_mch = 800; break;
- case 3: fsb_mch = 667; break;
- default: fsb_mch = 1066; break;
- }
-
-
- switch (fsb_mch) {
- case 533:
- switch ((mchcfg >> 4)&7) {
- case 0: dramratio = 1.25; break;
- case 1: dramratio = 1.5; break;
- case 2: dramratio = 2.0; break;
- }
- break;
-
- default:
- case 800:
- switch ((mchcfg >> 4)&7) {
- case 1: dramratio = 1.0; break;
- case 2: dramratio = 1.33334; break;
- case 3: dramratio = 1.66667; break;
- case 4: dramratio = 2.0; break;
- }
- break;
-
- case 1066:
- switch ((mchcfg >> 4)&7) {
- case 1: dramratio = 0.75; break;
- case 2: dramratio = 1.0; break;
- case 3: dramratio = 1.25; break;
- case 4: dramratio = 1.5; break;
- }
- break;
-}
-
-
- // Compute RAM Frequency
- fsb = ((extclock / 1000) / coef);
- dramclock = fsb * dramratio;
-
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+4, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
-}
-
-static void poll_fsb_i965(void) {
-
- double dramclock, dramratio, fsb;
- unsigned long mchcfg, dev0, fsb_mch;
- int coef = getP4PMmultiplier();
- long *ptr;
-
- /* Find dramratio */
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- dev0 &= 0xFFFFC000;
- ptr=(long*)(dev0+0xC00);
- mchcfg = *ptr & 0xFFFF;
- dramratio = 1;
-
- switch (mchcfg & 7) {
- case 0: fsb_mch = 1066; break;
- case 1: fsb_mch = 533; break;
- default: case 2: fsb_mch = 800; break;
- case 3: fsb_mch = 667; break;
- }
-
-
- switch (fsb_mch) {
- case 533:
- switch ((mchcfg >> 4)&7) {
- case 1: dramratio = 2.0; break;
- case 2: dramratio = 2.5; break;
- case 3: dramratio = 3.0; break;
- }
- break;
-
- default:
- case 800:
- switch ((mchcfg >> 4)&7) {
- case 0: dramratio = 1.0; break;
- case 1: dramratio = 1.33334; break;
- case 2: dramratio = 1.66667; break;
- case 3: dramratio = 2.0; break;
- }
- break;
-
- case 1066:
- switch ((mchcfg >> 4)&7) {
- case 1: dramratio = 1.0; break;
- case 2: dramratio = 1.25; break;
- case 3: dramratio = 1.5; break;
- case 4: dramratio = 2.0; break;
- }
- break;
-}
-
- // Compute RAM Frequency
- fsb = ((extclock / 1000) / coef);
- dramclock = fsb * dramratio;
-
- // Print DRAM Freq
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB (only if ECC is not enabled) */
- cprint(LINE_CPU+4, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
-}
-
-static void poll_fsb_nf4ie(void) {
-
- double dramclock, dramratio, fsb;
- float mratio, nratio;
- unsigned long reg74, reg60;
- int coef = getP4PMmultiplier();
-
- /* Find dramratio */
- pci_conf_read(0, 0, 2, 0x74, 2, ®74);
- pci_conf_read(0, 0, 2, 0x60, 4, ®60);
- mratio = reg74 & 0xF;
- nratio = (reg74 >> 4) & 0xF;
-
- // If M or N = 0, then M or N = 16
- if (mratio == 0) { mratio = 16; }
- if (nratio == 0) { nratio = 16; }
-
- // Check if synchro or pseudo-synchro mode
- if((reg60 >> 22) & 1) {
- dramratio = 1;
- } else {
- dramratio = nratio / mratio;
- }
-
- /* Compute RAM Frequency */
- fsb = ((extclock /1000) / coef);
- dramclock = fsb * dramratio;
-
- /* Print DRAM Freq */
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB */
- cprint(LINE_CPU+4, col, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
-}
-
-static void poll_fsb_i875(void) {
-
- double dramclock, dramratio, fsb;
- unsigned long mchcfg, smfs;
- int coef = getP4PMmultiplier();
-
- /* Find dramratio */
- pci_conf_read(0, 0, 0, 0xC6, 2, &mchcfg);
- smfs = (mchcfg >> 10)&3;
- dramratio = 1;
-
- if ((mchcfg&3) == 3) { dramratio = 1; }
- if ((mchcfg&3) == 2) {
- if (smfs == 2) { dramratio = 1; }
- if (smfs == 1) { dramratio = 1.25; }
- if (smfs == 0) { dramratio = 1.5; }
- }
- if ((mchcfg&3) == 1) {
- if (smfs == 2) { dramratio = 0.6666666666; }
- if (smfs == 1) { dramratio = 0.8; }
- if (smfs == 0) { dramratio = 1; }
- }
- if ((mchcfg&3) == 0) { dramratio = 0.75; }
-
-
- /* Compute RAM Frequency */
- dramclock = ((extclock /1000) / coef) / dramratio;
- fsb = ((extclock /1000) / coef);
-
- /* Print DRAM Freq */
- print_fsb_info(dramclock, "RAM : ");
-
- /* Print FSB (only if ECC is not enabled) */
- if ( ctrl.mode == ECC_NONE ) {
- cprint(LINE_CPU+4, col +1, "- FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
- }
-}
-
-static void poll_fsb_p4(void) {
-
- ulong fsb, idetect;
- int coef = getP4PMmultiplier();
-
- fsb = ((extclock /1000) / coef);
-
- /* Print FSB */
- cprint(LINE_CPU+4, col +1, "/ FSB : ");
- col += 9;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
- col += 4;
-
- /* For synchro only chipsets */
- pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
- if (idetect == 0x2540 || idetect == 0x254C) {
- print_fsb_info(fsb, "RAM : ");
- }
-}
-
-static void poll_fsb_i855(void) {
-
-
- double dramclock, dramratio, fsb ;
- unsigned int msr_lo, msr_hi;
- ulong mchcfg, centri, idetect;
- int coef;
-
- pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
-
- /* Find multiplier (by MSR) */
-
- /* Is it a Pentium M ? */
- if (cpu_id.type == 6) {
- rdmsr(0x2A, msr_lo, msr_hi);
- coef = (msr_lo >> 22) & 0x1F;
-
- /* Is it an i855GM or PM ? */
- if (idetect == 0x3580) {
- cprint(LINE_CPU+4, col-1, "i855GM/GME ");
- col += 10;
- }
- } else {
- rdmsr(0x2C, msr_lo, msr_hi);
- coef = (msr_lo >> 24) & 0x1F;
- cprint(LINE_CPU+4, col-1, "i852PM/GM ");
- col += 9;
- }
-
- fsb = ((extclock /1000) / coef);
-
- /* Print FSB */
- cprint(LINE_CPU+4, col, "/ FSB : "); col += 8;
- dprint(LINE_CPU+4, col, fsb, 3,0); col += 3;
- cprint(LINE_CPU+4, col +1, "MHz"); col += 4;
-
- /* Is it a Centrino platform or only an i855 platform ? */
- pci_conf_read( 2, 2, 0, 0x02, 2, ¢ri);
- if (centri == 0x1043) { cprint(LINE_CPU+4, col +1, "/ Centrino Mobile Platform"); }
- else { cprint(LINE_CPU+4, col +1, "/ Mobile Platform"); }
-
- /* Compute DRAM Clock */
-
- dramratio = 1;
- if (idetect == 0x3580) {
- pci_conf_read( 0, 0, 3, 0xC0, 2, &mchcfg);
- mchcfg = mchcfg & 0x7;
-
- if (mchcfg == 1 || mchcfg == 2 || mchcfg == 4 || mchcfg == 5) { dramratio = 1; }
- if (mchcfg == 0 || mchcfg == 3) { dramratio = 1.333333333; }
- if (mchcfg == 6) { dramratio = 1.25; }
- if (mchcfg == 7) { dramratio = 1.666666667; }
-
- } else {
- pci_conf_read( 0, 0, 0, 0xC6, 2, &mchcfg);
- if (((mchcfg >> 10)&3) == 0) { dramratio = 1; }
- else if (((mchcfg >> 10)&3) == 1) { dramratio = 1.666667; }
- else { dramratio = 1.333333333; }
- }
-
-
- dramclock = fsb * dramratio;
-
- /* ...and print */
- print_fsb_info(dramclock, "RAM : ");
-
-}
-
-static void poll_fsb_amd32(void) {
-
- unsigned int mcgsrl;
- unsigned int mcgsth;
- unsigned long temp;
- double dramclock;
- double coef2;
-
- /* First, got the FID */
- rdmsr(0x0c0010015, mcgsrl, mcgsth);
- temp = (mcgsrl >> 24)&0x0F;
-
- if ((mcgsrl >> 19)&1) { coef2 = athloncoef2[temp]; }
- else { coef2 = athloncoef[temp]; }
-
- if (coef2 == 0) { coef2 = 1; };
-
- /* Compute the final FSB Clock */
- dramclock = (extclock /1000) / coef2;
-
- /* ...and print */
- print_fsb_info(dramclock, "FSB : ");
-
-}
-
-static void poll_fsb_nf2(void) {
-
- unsigned int mcgsrl;
- unsigned int mcgsth;
- unsigned long temp, mempll;
- double dramclock, fsb;
- double mem_m, mem_n;
- float coef;
- coef = 10;
-
- /* First, got the FID */
- rdmsr(0x0c0010015, mcgsrl, mcgsth);
- temp = (mcgsrl >> 24)&0x0F;
-
- if ((mcgsrl >> 19)&1) { coef = athloncoef2[temp]; }
- else { coef = athloncoef[temp]; }
-
- /* Get the coef (COEF = N/M) - Here is for Crush17 */
- pci_conf_read(0, 0, 3, 0x70, 4, &mempll);
- mem_m = (mempll&0x0F);
- mem_n = ((mempll >> 4) & 0x0F);
-
- /* If something goes wrong, the chipset is probably a Crush18 */
- if ( mem_m == 0 || mem_n == 0 ) {
- pci_conf_read(0, 0, 3, 0x7C, 4, &mempll);
- mem_m = (mempll&0x0F);
- mem_n = ((mempll >> 4) & 0x0F);
- }
-
- /* Compute the final FSB Clock */
- dramclock = ((extclock /1000) / coef) * (mem_n/mem_m);
- fsb = ((extclock /1000) / coef);
-
- /* ...and print */
-
- cprint(LINE_CPU+4, col, "/ FSB : ");
- col += 8;
- dprint(LINE_CPU+4, col, fsb, 3,0);
- col += 3;
- cprint(LINE_CPU+4, col +1, "MHz");
-
- print_fsb_info(dramclock, "RAM : ");
-
-}
-
-/* ------------------ Here the code for Timings detection ------------------ */
-/* ------------------------------------------------------------------------- */
-
-static void poll_timings_nf4ie(void) {
-
-
- ulong regd0, reg8c, reg9c, reg80;
- int cas, rcd, rp, ras;
-
- cprint(LINE_CPU+4, col +1, "- Type : DDR-II");
-
- //Now, read Registers
- pci_conf_read( 0, 1, 1, 0xD0, 4, ®d0);
- pci_conf_read( 0, 1, 1, 0x80, 1, ®80);
- pci_conf_read( 0, 1, 0, 0x8C, 4, ®8c);
- pci_conf_read( 0, 1, 0, 0x9C, 4, ®9c);
-
- // Then, detect timings
- cas = (regd0 >> 4) & 0x7;
- rcd = (reg8c >> 24) & 0xF;
- rp = (reg9c >> 8) & 0xF;
- ras = (reg8c >> 16) & 0x3F;
-
- print_timings_info(cas, rcd, rp, ras);
-
- if (reg80 & 0x3) {
- cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
- } else {
- cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
- }
-
-}
-
-static void poll_timings_i925(void) {
-
- // Thanks for CDH optis
- ulong dev0, drt, drc, dcc, idetect, temp;
- long *ptr;
-
- //Now, read MMR Base Address
- pci_conf_read( 0, 0, 0, 0x44, 4, &dev0);
- pci_conf_read( 0, 0, 0, 0x02, 2, &idetect);
- dev0 &= 0xFFFFC000;
-
- //Set pointer for DRT
- ptr=(long*)(dev0+0x114);
- drt = *ptr & 0xFFFFFFFF;
-
- //Set pointer for DRC
- ptr=(long*)(dev0+0x120);
- drc = *ptr & 0xFFFFFFFF;
-
- //Set pointer for DCC
- ptr=(long*)(dev0+0x200);
- dcc = *ptr & 0xFFFFFFFF;
-
- //Determine DDR or DDR-II
- if ((drc & 3) == 2) {
- cprint(LINE_CPU+4, col +1, "- Type : DDR-II");
- } else {
- cprint(LINE_CPU+4, col +1, "- Type : DDR-I");
- }
-
- // Now, detect timings
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- // CAS Latency (tCAS)
- temp = ((drt >> 8)& 0x3);
-
- if ((drc & 3) == 2){
- // Timings DDR-II
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "5-"); }
- else if (temp == 0x1) { cprint(LINE_CPU+5, col2, "4-"); }
- else if (temp == 0x2) { cprint(LINE_CPU+5, col2, "3-"); }
- else { cprint(LINE_CPU+5, col2, "6-"); }
- } else {
- // Timings DDR-I
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "3-"); }
- else if (temp == 0x1) { cprint(LINE_CPU+5, col2, "2.5-"); col2 +=2;}
- else { cprint(LINE_CPU+5, col2, "2-"); }
- }
- col2 +=2;
-
- // RAS-To-CAS (tRCD)
- dprint(LINE_CPU+5, col2, ((drt >> 4)& 0x3)+2, 1 ,0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 +=2;
-
- // RAS Precharge (tRP)
- dprint(LINE_CPU+5, col2, (drt&0x3)+2, 1 ,0);
- cprint(LINE_CPU+5, col2+1, "-");
- col2 +=2;
-
- // RAS Active to precharge (tRAS)
- // If Lakeport, than change tRAS computation (Thanks to CDH, again)
- if (idetect > 0x2700)
- temp = ((drt >> 19)& 0x1F);
- else
- temp = ((drt >> 20)& 0x0F);
-
- dprint(LINE_CPU+5, col2, temp , 1 ,0);
- (temp < 10)?(col2 += 1):(col2 += 2);
-
- cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
-
- temp = (dcc&0x3);
- if (temp == 1) { cprint(LINE_CPU+5, col2, " Dual Channel (Asymmetric)"); }
- else if (temp == 2) { cprint(LINE_CPU+5, col2, " Dual Channel (Interleaved)"); }
- else { cprint(LINE_CPU+5, col2, " Single Channel (64 bits)"); }
-
-}
-
-static void poll_timings_i875(void) {
-
- ulong dev6, dev62;
- ulong temp;
- float cas;
- int rcd, rp, ras;
- long *ptr, *ptr2;
-
- /* Read the MMR Base Address & Define the pointer */
- pci_conf_read( 0, 6, 0, 0x10, 4, &dev6);
-
- /* Now, the PAT ritual ! (Kant and Luciano will love this) */
- pci_conf_read( 0, 6, 0, 0x40, 4, &dev62);
- ptr2=(long*)(dev6+0x68);
-
- if ((dev62&0x3) == 0 && ((*ptr2 >> 14)&1) == 1) {
- cprint(LINE_CPU+4, col +1, "- PAT : Enabled");
- } else {
- cprint(LINE_CPU+4, col +1, "- PAT : Disabled");
- }
-
- /* Now, we could check some additionnals timings infos) */
-
- ptr=(long*)(dev6+0x60);
- // CAS Latency (tCAS)
- temp = ((*ptr >> 5)& 0x3);
- if (temp == 0x0) { cas = 2.5; } else if (temp == 0x1) { cas = 2; } else { cas = 3; }
-
- // RAS-To-CAS (tRCD)
- temp = ((*ptr >> 2)& 0x3);
- if (temp == 0x0) { rcd = 4; } else if (temp == 0x1) { rcd = 3; } else { rcd = 2; }
-
- // RAS Precharge (tRP)
- temp = (*ptr&0x3);
- if (temp == 0x0) { rp = 4; } else if (temp == 0x1) { rp = 3; } else { rp = 2; }
-
- // RAS Active to precharge (tRAS)
- temp = ((*ptr >> 7)& 0x7);
- ras = 10 - temp;
-
- // Print timings
- print_timings_info(cas, rcd, rp, ras);
-
- // Print 64 or 128 bits mode
- if (((*ptr2 >> 21)&3) > 0) {
- cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
- } else {
- cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
- }
-}
-
-static void poll_timings_E7520(void) {
-
- ulong drt, ddrcsr;
- float cas;
- int rcd, rp, ras;
-
- pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
- pci_conf_read( 0, 0, 0, 0x9A, 2, &ddrcsr);
-
- cas = ((drt >> 2) & 3) + 2;
- rcd = ((drt >> 10) & 1) + 3;
- rp = ((drt >> 9) & 1) + 3;
- ras = ((drt >> 14) & 3) + 11;
-
- print_timings_info(cas, rcd, rp, ras);
-
- if ((ddrcsr & 0xF) >= 0xC) {
- cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
- } else {
- cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
- }
-}
-
-
-static void poll_timings_i855(void) {
-
- ulong drt, temp;
-
- pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
-
- /* Now, we could print some additionnals timings infos) */
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- // CAS Latency (tCAS)
- temp = ((drt >> 4)&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "2.5-"); col2 += 4; }
- else { cprint(LINE_CPU+5, col2, "2-"); col2 +=2; }
-
- // RAS-To-CAS (tRCD)
- temp = ((drt >> 2)& 0x1);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "3-"); }
- else { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
-
- // RAS Precharge (tRP)
- temp = (drt&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "3-"); }
- else { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
-
- // RAS Active to precharge (tRAS)
- temp = 7-((drt >> 9)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "7"); }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "6"); }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "5"); }
- col2 +=1;
-
-}
-
-static void poll_timings_E750x(void) {
-
- ulong drt, drc, temp;
- float cas;
- int rcd, rp, ras;
-
- pci_conf_read( 0, 0, 0, 0x78, 4, &drt);
- pci_conf_read( 0, 0, 0, 0x7C, 4, &drc);
-
- if ((drt >> 4) & 1) { cas = 2; } else { cas = 2.5; };
- if ((drt >> 1) & 1) { rcd = 2; } else { rcd = 3; };
- if (drt & 1) { rp = 2; } else { rp = 3; };
-
- temp = ((drt >> 9) & 3);
- if (temp == 2) { ras = 5; } else if (temp == 1) { ras = 6; } else { ras = 7; }
-
- print_timings_info(cas, rcd, rp, ras);
-
- if (((drc >> 22)&1) == 1) {
- cprint(LINE_CPU+5, col2, "/ Dual Channel (128 bits)");
- } else {
- cprint(LINE_CPU+5, col2, "/ Single Channel (64 bits)");
- }
-
-}
-
-static void poll_timings_i852(void) {
-
- ulong drt, temp;
-
- pci_conf_read( 0, 0, 1, 0x60, 4, &drt);
-
- /* Now, we could print some additionnals timings infos) */
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- // CAS Latency (tCAS)
- temp = ((drt >> 5)&0x1);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "2.5-"); col2 += 4; }
- else { cprint(LINE_CPU+5, col2, "2-"); col2 +=2; }
-
- // RAS-To-CAS (tRCD)
- temp = ((drt >> 2)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "3-"); }
- else { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
-
- // RAS Precharge (tRP)
- temp = (drt&0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "4-"); }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "3-"); }
- else { cprint(LINE_CPU+5, col2, "2-"); }
- col2 +=2;
-
- // RAS Active to precharge (tRAS)
- temp = ((drt >> 9)& 0x3);
- if (temp == 0x0) { cprint(LINE_CPU+5, col2, "8"); col2 +=7; }
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "7"); col2 +=6; }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "6"); col2 +=5; }
- if (temp == 0x3) { cprint(LINE_CPU+5, col2, "5"); col2 +=5; }
- col2 +=1;
-
-}
-
-static void poll_timings_amd64(void) {
-
- ulong dramtlr, dramclr;
- int temp;
- int trcd, trp, tras ;
-
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr);
- pci_conf_read(0, 24, 2, 0x90, 4, &dramclr);
-
- if (((cpu_id.ext >> 16) & 0xF) >= 4) {
- /* NEW K8 0Fh Family 90 nm (DDR2) */
-
- // CAS Latency (tCAS)
- temp = (dramtlr & 0x7) + 1;
- dprint(LINE_CPU+5, col2, temp , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS-To-CAS (tRCD)
- trcd = ((dramtlr >> 4) & 0x3) + 3;
- dprint(LINE_CPU+5, col2, trcd , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Precharge (tRP)
- trp = ((dramtlr >> 8) & 0x3) + 3;
- dprint(LINE_CPU+5, col2, trp , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Active to precharge (tRAS)
- tras = ((dramtlr >> 12) & 0xF) + 3;
- if (tras < 10){
- dprint(LINE_CPU+5, col2, tras , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+5, col2, tras , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
-
- // Print 64 or 128 bits mode
-
- if ((dramclr >> 11)&1) {
- cprint(LINE_CPU+5, col2, " DDR-2 (128 bits)");
- col2 +=17;
- } else {
- cprint(LINE_CPU+5, col2, " DDR-2 (64 bits)");
- col2 +=16;
- }
-
- } else {
- /* OLD K8 (DDR1) */
-
- // CAS Latency (tCAS)
- temp = (dramtlr & 0x7);
- if (temp == 0x1) { cprint(LINE_CPU+5, col2, "2-"); col2 +=2; }
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "3-"); col2 +=2; }
- if (temp == 0x5) { cprint(LINE_CPU+5, col2, "2.5-"); col2 +=4; }
-
- // RAS-To-CAS (tRCD)
- trcd = ((dramtlr >> 12) & 0x7);
- dprint(LINE_CPU+5, col2, trcd , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Precharge (tRP)
- trp = ((dramtlr >> 24) & 0x7);
- dprint(LINE_CPU+5, col2, trp , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Active to precharge (tRAS)
- tras = ((dramtlr >> 20) & 0xF);
- if (tras < 10){
- dprint(LINE_CPU+5, col2, tras , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+5, col2, tras , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
-
- // Print 64 or 128 bits mode
-
- if (((dramclr >> 16)&1) == 1) {
- cprint(LINE_CPU+5, col2, " DDR-1 (128 bits)");
- col2 +=17;
- } else {
- cprint(LINE_CPU+5, col2, " DDR-1 (64 bits)");
- col2 +=16;
- }
- }
-}
-
-static void poll_timings_nf2(void) {
-
- ulong dramtlr, dramtlr2, dramtlr3, temp;
- ulong dimm1p, dimm2p, dimm3p;
-
- pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr);
- pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2);
- pci_conf_read(0, 0, 1, 0x84, 4, &dramtlr3);
- pci_conf_read(0, 0, 2, 0x40, 4, &dimm1p);
- pci_conf_read(0, 0, 2, 0x44, 4, &dimm2p);
- pci_conf_read(0, 0, 2, 0x48, 4, &dimm3p);
-
- cprint(LINE_CPU+5, col2 +1, "/ CAS : ");
- col2 += 9;
-
- // CAS Latency (tCAS)
- temp = ((dramtlr2 >> 4) & 0x7);
- if (temp == 0x2) { cprint(LINE_CPU+5, col2, "2-"); col2 +=2; }
- if (temp == 0x3) { cprint(LINE_CPU+5, col2, "3-"); col2 +=2; }
- if (temp == 0x6) { cprint(LINE_CPU+5, col2, "2.5-"); col2 +=4; }
-
- // RAS-To-CAS (tRCD)
- temp = ((dramtlr >> 20) & 0xF);
- dprint(LINE_CPU+5, col2, temp , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Precharge (tRP)
- temp = ((dramtlr >> 28) & 0xF);
- dprint(LINE_CPU+5, col2, temp , 1 ,0);
- cprint(LINE_CPU+5, col2 +1, "-"); col2 +=2;
-
- // RAS Active to precharge (tRAS)
- temp = ((dramtlr >> 15) & 0xF);
- if (temp < 10){
- dprint(LINE_CPU+5, col2, temp , 1 ,0); col2 += 1;
- } else {
- dprint(LINE_CPU+5, col2, temp , 2 ,0); col2 += 2;
- }
- cprint(LINE_CPU+5, col2+1, "/"); col2 +=2;
-
- // Print 64 or 128 bits mode
- // If DIMM1 & DIMM3 or DIMM1 & DIMM2 populated, than Dual Channel.
-
- if ((dimm3p&1) + (dimm2p&1) == 2 || (dimm3p&1) + (dimm1p&1) == 2 ) {
- cprint(LINE_CPU+5, col2, " Dual Channel (128 bits)");
- col2 +=24;
- } else {
- cprint(LINE_CPU+5, col2, " Single Channel (64 bits)");
- col2 +=15;
- }
-
-}
-
-
-
-/* ------------------ Let's continue ------------------ */
-/* ---------------------------------------------------- */
-
-static struct pci_memory_controller controllers[] = {
- /* Default unknown chipset */
- { 0, 0, "", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
-
- /* AMD */
- { 0x1022, 0x7006, "AMD 751", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_amd751 },
- { 0x1022, 0x700c, "AMD 762", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
- { 0x1022, 0x700e, "AMD 761", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_amd76x },
- { 0x1022, 0x0000, "AMD K8", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1022, 0x1100, "AMD 8000", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1022, 0x7454, "AMD 8000", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
-
- /* SiS */
- { 0x1039, 0x0600, "SiS 600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0620, "SiS 620", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x5600, "SiS 5600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0645, "SiS 645", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0646, "SiS 645DX", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0630, "SiS 630", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0650, "SiS 650", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0651, "SiS 651", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0730, "SiS 730", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0735, "SiS 735", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0740, "SiS 740", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0745, "SiS 745", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0755, "SiS 755", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1039, 0x0748, "SiS 748", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0655, "SiS 655", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0648, "SiS 648", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1039, 0x0661, "SiS 661", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
-
- /* ALi */
- { 0x10b9, 0x1531, "Aladdin 4", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10b9, 0x1541, "Aladdin 5", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10b9, 0x1644, "ALi Aladdin M1644", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10b9, 0x1687, "ALi M1687", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10b9, 0x1689, "ALi M1689", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10b9, 0x1695, "ALi M1695", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
-
- /* ATi */
- { 0x1002, 0x5830, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5831, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5832, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5833, "ATi Radeon 9100 IGP", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5954, "ATi Radeon xPress 200", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5A41, "ATi Radeon xPress 200", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1002, 0x5950, "ATi Radeon xPress 200", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1002, 0x5952, "ATi Radeon xPress 3200", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
-
- /* nVidia */
- { 0x10de, 0x01A4, "nVidia nForce", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x10de, 0x01E0, "nVidia nForce2 SPP", 0, poll_fsb_nf2, poll_timings_nf2, setup_nothing, poll_nothing },
- { 0x10de, 0x00D1, "nVidia nForce3", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x00E1, "nForce3 250", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x005E, "nVidia nForce4", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x005F, "nVidia nForce4", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x10de, 0x0071, "nForce4 SLI Intel Edition", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing },
-
- /* VIA */
- { 0x1106, 0x0305, "VIA KT133/KT133A", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0391, "vt8371", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0501, "vt8501", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0585, "vt82c585", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0595, "vt82c595", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0597, "vt82c597", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0598, "VT82C598", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0691, "VT82C691/693A/694X", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0693, "VT82C693", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0601, "VIA PLE133", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3099, "VIA KT266(A)/KT333", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3189, "VIA KT400(A)/600", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0269, "VIA KT880", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3205, "VIA KM400", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3116, "VIA KM266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3156, "VIA KN266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3123, "VIA CLE266", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x0198, "VIA PT800", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3258, "VIA PT880", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x1106, 0x3188, "VIA K8T800", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1106, 0x0282, "VIA K8T800Pro", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
- { 0x1106, 0x3238, "VIA K8T890", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_amd64 },
-
- /* Serverworks */
- { 0x1166, 0x0008, "CNB20HE", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
- { 0x1166, 0x0009, "CNB20LE", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing },
-
- /* Intel */
- { 0x8086, 0x1130, "Intel i815", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x122d, "Intel i430fx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1237, "Intel i440fx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1250, "Intel i430hx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x1A21, "Intel i840", 0, poll_fsb_nothing, poll_timings_nothing, setup_i840, poll_i840 },
- { 0x8086, 0x1A30, "Intel i845", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_i845 },
- { 0x8086, 0x2560, "Intel i845E/G/PE/GE", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_i845 },
- { 0x8086, 0x2500, "Intel i820", 0, poll_fsb_nothing, poll_timings_nothing, setup_i820, poll_i820 },
- { 0x8086, 0x2530, "Intel i850", 0, poll_fsb_p4, poll_timings_nothing, setup_i850, poll_i850 },
- { 0x8086, 0x2531, "Intel i860", 1, poll_fsb_nothing, poll_timings_nothing, setup_i860, poll_i860 },
- { 0x8086, 0x7030, "Intel i430vx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7120, "Intel i810", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7122, "Intel i810", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7124, "Intel i810e", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7180, "Intel i440[le]x", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7190, "Intel i440BX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x7192, "Intel i440BX", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x71A0, "Intel i440gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
- { 0x8086, 0x71A2, "Intel i440gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_i440gx },
- { 0x8086, 0x84C5, "Intel i450gx", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x2540, "Intel E7500", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x254C, "Intel E7501", 1, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x255d, "Intel E7205", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x3592, "Intel E7320", 0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_iE7520 },
- { 0x8086, 0x2588, "Intel E7221", 1, poll_fsb_i925, poll_timings_i925, setup_i925, poll_iE7221 },
- { 0x8086, 0x3590, "Intel E7520", 0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing },
- { 0x8086, 0x2600, "Intel E8500", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing },
- { 0x8086, 0x2570, "Intel i848/i865", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_nothing },
- { 0x8086, 0x2578, "Intel i875P", 0, poll_fsb_i875, poll_timings_i875, setup_i875, poll_i875 },
- { 0x8086, 0x2550, "Intel E7505", 0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_iE7xxx },
- { 0x8086, 0x3580, "Intel ", 0, poll_fsb_i855, poll_timings_i852, setup_nothing, poll_nothing },
- { 0x8086, 0x3340, "Intel i855PM", 0, poll_fsb_i855, poll_timings_i855, setup_nothing, poll_nothing },
- { 0x8086, 0x2580, "Intel i915P/G", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x2590, "Intel i915PM/GM", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x2584, "Intel i925X/XE", 0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_iE7221 },
- { 0x8086, 0x2770, "Intel i945P/G", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing },
- { 0x8086, 0x2774, "Intel i955X", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing},
- { 0x8086, 0x277C, "Intel i975X", 0, poll_fsb_i975, poll_timings_i925, setup_i925, poll_nothing},
- { 0x8086, 0x27A0, "Intel P965/G965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing},
- { 0x8086, 0x2790, "Intel Q963/Q965", 0, poll_fsb_i965, poll_timings_i925, setup_i925, poll_nothing}
-};
-
-static void print_memory_controller(void)
-{
- /* Print memory controller info */
-
- int d;
-
- char *name;
- if (ctrl.index == 0) {
- return;
- }
-
- /* Print the controller name */
- name = controllers[ctrl.index].name;
- col = 10;
- cprint(LINE_CPU+4, col, name);
- /* Now figure out how much I just printed */
- while(name[col - 10] != '\0') {
- col++;
- }
- /* Now print the memory controller capabilities */
- cprint(LINE_CPU+4, col, " "); col++;
- if (ctrl.cap == ECC_UNKNOWN) {
- return;
- }
- if (ctrl.cap & __ECC_DETECT) {
- int on;
- on = ctrl.mode & __ECC_DETECT;
- cprint(LINE_CPU+4, col, "(ECC : ");
- cprint(LINE_CPU+4, col +7, on?"Detect":"Disabled)");
- on?(col += 13):(col += 16);
- }
- if (ctrl.mode & __ECC_CORRECT) {
- int on;
- on = ctrl.mode & __ECC_CORRECT;
- cprint(LINE_CPU+4, col, " / ");
- if (ctrl.cap & __ECC_CHIPKILL) {
- cprint(LINE_CPU+4, col +3, on?"Correct -":"");
- on?(col += 12):(col +=3);
- } else {
- cprint(LINE_CPU+4, col +3, on?"Correct)":"");
- on?(col += 11):(col +=3);
- }
- }
- if (ctrl.mode & __ECC_DETECT) {
- if (ctrl.cap & __ECC_CHIPKILL) {
- int on;
- on = ctrl.mode & __ECC_CHIPKILL;
- cprint(LINE_CPU+4, col, " Chipkill : ");
- cprint(LINE_CPU+4, col +12, on?"On)":"Off)");
- on?(col += 15):(col +=16);
- }}
- if (ctrl.mode & __ECC_SCRUB) {
- int on;
- on = ctrl.mode & __ECC_SCRUB;
- cprint(LINE_CPU+4, col, " Scrub");
- cprint(LINE_CPU+4, col +6, on?"+ ":"- ");
- col += 7;
- }
- if (ctrl.cap & __ECC_UNEXPECTED) {
- int on;
- on = ctrl.mode & __ECC_UNEXPECTED;
- cprint(LINE_CPU+4, col, "Unknown");
- cprint(LINE_CPU+4, col +7, on?"+ ":"- ");
- col += 9;
- }
-
-
- /* Print advanced caracteristics */
- col2 = 0;
- d = get_key();
- /* if F1 is pressed, disable advanced detection */
- if (d != 0x3B) {
- controllers[ctrl.index].poll_fsb();
- controllers[ctrl.index].poll_timings();
- }
-}
-
-
-void find_controller(void)
-{
- unsigned long vendor;
- unsigned long device;
- extern struct cpu_ident cpu_id;
- int i;
- int result;
- result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_VENDOR_ID, 2, &vendor);
- result = pci_conf_read(ctrl.bus, ctrl.dev, ctrl.fn, PCI_DEVICE_ID, 2, &device);
- ctrl.index = 0;
- if (result == 0) {
- for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) {
- if ((controllers[i].vendor == vendor) && (controllers[i].device == device)) {
- ctrl.index = i;
- break;
- }
- }
- }
-
- // AMD K8 use integrated mem controller. If SB not detected, force detection
- if (ctrl.index == 0 && cpu_id.type == 15 && cpu_id.vend_id[0] == 'A') { ctrl.index = 4; }
-
- controllers[ctrl.index].setup_ecc();
- /* Don't enable ECC polling by default unless it has
- * been well tested.
- */
- set_ecc_polling(-1);
- print_memory_controller();
-
-}
-
-void poll_errors(void)
-{
- if (ctrl.poll) {
- controllers[ctrl.index].poll_errors();
- }
-}
-
-void set_ecc_polling(int val)
-{
- int tested = controllers[ctrl.index].tested;
- if (val == -1) {
- val = tested;
- }
- if (val && (ctrl.mode & __ECC_DETECT)) {
- ctrl.poll = 1;
- cprint(LINE_INFO, COL_ECC, tested? " on": " ON");
- } else {
- ctrl.poll = 0;
- cprint(LINE_INFO, COL_ECC, "off");
- }
-}
-
-
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/controller.h
^
|
@@ -1,8 +0,0 @@
-#ifndef MEMTEST_CONTROLLER_H
-#define MEMTEST_CONTROLLER_H
-
-void find_controller(void);
-void poll_errors(void);
-void set_ecc_polling(int val);
-
-#endif /* MEMTEST_CONTROLLER_H */
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/dmi.c
^
|
@@ -1,303 +0,0 @@
-/* dmi.c using the DMI from SMBIOS to read information about the hardware's
- * memory devices capabilities and where they are mapped into the address space
- *
- * Copyright (c) Joachim Deguara, AMD 2006
- *
- * Release under the GPL version 2
- * ----------------------------------------------------
- * Memtest86+ V1.70 - Added compliance with SMBIOS Spec V2.5
- * - Support for FB-DIMM
- */
-
-#include "test.h"
-#include "stdint.h"
-
-#define DMI_SEARCH_START 0x0000F000
-#define DMI_SEARCH_LENGTH 0x000F0FFF
-#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
-#define round_down(x,y) ((x) & ~((y)-1))
-
-
-struct dmi_eps {
- uint8_t anchor[4];
- int8_t checksum;
- uint8_t length;
- uint8_t majorversion;
- uint8_t minorversion;
- uint16_t maxstructsize;
- uint8_t revision;
- uint8_t pad[5];
- uint8_t intanchor[5];
- int8_t intchecksum;
- uint16_t tablelength;
- uint32_t tableaddress;
- uint16_t numstructs;
- uint8_t SMBIOSrev;
-} __attribute__((packed));
-
-struct tstruct_header{
- uint8_t type;
- uint8_t length;
- uint16_t handle;
-} __attribute__((packed));
-
-struct mem_dev {
- struct tstruct_header header;
- uint16_t pma_handle;
- uint16_t err_handle;
- uint16_t tot_width;
- uint16_t dat_width;
- uint16_t size;
- uint8_t form;
- uint8_t set;
- uint8_t dev_locator;
- uint8_t bank_locator;
- uint8_t type;
- uint16_t typedetail;
- uint16_t speed;
- uint8_t manufacturer;
- uint8_t serialnum;
- uint8_t asset;
- uint8_t partnum;
-} __attribute__((packed));
-
-struct md_map{
- struct tstruct_header header;
- uint32_t start;
- uint32_t end;
- uint16_t md_handle;
- uint16_t mama_handle;
- uint8_t row_pos;
- uint8_t interl_pos;
- uint8_t interl_depth;
-} __attribute__((packed));
-
-struct pma{
- struct tstruct_header header;
- uint8_t location;
- uint8_t use;
- uint8_t ecc;
- uint32_t capacity;
- uint16_t errhandle;
- uint16_t numdevs;
-} __attribute__((packed));
-
-static char *form_factors[] = {
- "?",
- "Other", "Unknown", "SIMM", "SIP", "Chip", "DIP", "ZIP",
- "Proprietary Card", "DIMM", "TSOP", "Row of chips", "RIMM",
- "SODIMM", "SRIMM", "FB-DIMM"
-};
-
-static char *memory_types[] = {
- "?",
- "Other", "Unknown", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM",
- "ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM",
- "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB"
-};
-
-
-struct mem_dev * mem_devs[MAX_DMI_MEMDEVS];
-int mem_devs_count=0;
-struct md_map * md_maps[MAX_DMI_MEMDEVS];
-int md_maps_count=0;
-int dmi_err_cnts[MAX_DMI_MEMDEVS];
-short dmi_initialized=0;
-
-int strlen(char * string){
- int i=0;
- while(*string++){i++;};
- return i;
-}
-
-
-char * get_tstruct_string(struct tstruct_header *header, int n){
- if(n<1)
- return 0;
- char * a = (char *)header + header->length;
- n--;
- do{
- if (!*a)
- n--;
- if (!n && *a)
- return a;
- a++;
- }while (!(*a==0 && *(a-1)==0));
- return 0;
-}
-
-
-int dmi_open(void){
- char *dmi, *dmi_search_start, *dmi_start;
- int i, found=0;
- struct dmi_eps *eps;
- char *table_start;
- int tstruct_count=0;
-
- for(i=0; i < MAX_DMI_MEMDEVS; i++)
- dmi_err_cnts[i]=-1;
-
- dmi_search_start = (char *)DMI_SEARCH_START;
-
- //find ancho
- for(dmi = dmi_search_start; dmi < dmi_search_start + 0xf0000; dmi +=16){
- if( *dmi == '_' &&
- *(dmi+1) == 'S' &&
- *(dmi+2) == 'M' &&
- *(dmi+3) == '_'){
- found =1;
- break;
- }
- }
- if (!found) {
- return -1;
- }
- dmi_start=dmi;
- eps=(struct dmi_eps *)dmi;
-
- //check checksum
- int8_t checksum=0;
- for (; dmi < dmi_start + eps->length; dmi++)
- checksum += *dmi;
- if (checksum){
- return -1;
- }
-
- //we need at least revision 2.1 of SMBIOS
- if ( eps->majorversion < 2 &&
- eps->minorversion < 1){
- return -1;
- }
-
-
- table_start=(char *)eps->tableaddress;
- dmi=table_start;
-//look at all structs
- while(dmi < table_start + eps->tablelength){
- struct tstruct_header *header = (struct tstruct_header *)dmi;
- if (header->type == 17) {
- mem_devs[mem_devs_count]=(struct mem_dev *)dmi;
- if (mem_devs[mem_devs_count]->size > 0) {
- dmi_err_cnts[mem_devs_count] = 0;
- mem_devs_count++;
- }
- }
- if (header->type == 20)
- md_maps[md_maps_count++]=(struct md_map *)dmi;
- dmi+=header->length;
- while( ! (*dmi == 0 && *(dmi+1) == 0 ) )
- dmi++;
- dmi+=2;
-
- if (++tstruct_count > eps->numstructs)
- return -1;
- }
- dmi_initialized=1;
- return 0;
-}
-
-void print_dmi_info(void){
- int i,j,page;
- char * string=0;
-
- if(!dmi_initialized)
- dmi_open();
-
- if (mem_devs_count == 0){
- cprint(POP2_Y+1, POP2_X+2, "No valid DMI Memory Devices info found");
- while (get_key() == 0);
- return;
- }
-
- for(page=1; page <= 1 + (mem_devs_count-1)/8; page++){
- pop2clear();
- cprint(POP2_Y+1, POP2_X+2, "DMI Memory Device Info (page ");
- itoa(string,page);
- cprint(POP2_Y+1, POP2_X+32, string);
- cprint(POP2_Y+1, POP2_X+33, "/");
- itoa(string,1 + (mem_devs_count-1)/8);
- cprint(POP2_Y+1, POP2_X+34, string);
- cprint(POP2_Y+1, POP2_X+35, ")");
-
- cprint(POP2_Y+3, POP2_X+4, "Location Size(MB) Speed(MHz) Type Form Errors");
- cprint(POP2_Y+4, POP2_X+4, "--------------------------------------------------------------");
-
- for(i=8*(page-1); i<mem_devs_count && i<8*page; i++){
- int size_in_mb;
- int yof;
-
- yof=POP2_Y+5+2*(i-8*(page-1));
- cprint(yof, POP2_X+4, get_tstruct_string(&(mem_devs[i]->header), mem_devs[i]->dev_locator));
-
- if (mem_devs[i]->size == 0){
- cprint(yof, POP2_X+4+18, "Empty");
- }else if (mem_devs[i]->size == 0xFFFF){
- cprint(yof, POP2_X+4+18, "Unknown");
- }else{
- size_in_mb = 0xEFFF & mem_devs[i]->size;
- if (mem_devs[i]->size & 0x8000)
- size_in_mb = size_in_mb<<10;
- itoa(string, size_in_mb);
- cprint(yof, POP2_X+4+18, string);
- }
-
- //this is the only field that needs to be SMBIOS 2.3+
- if ( mem_devs[i]->speed &&
- mem_devs[i]->header.length > 21){
- itoa(string, mem_devs[i]->speed);
- cprint(yof, POP2_X+4+27, string);
- }else{
- cprint(yof, POP2_X+4+27, "Unknown");
- }
- cprint(yof, POP2_X+4+37, memory_types[mem_devs[i]->type]);
- cprint(yof, POP2_X+4+45, form_factors[mem_devs[i]->form]);
- dprint(yof, POP2_X+4+55, dmi_err_cnts[i], 7, 0);
-
- //print mappings
- int mapped=0,of=0;
- cprint(yof+1, POP2_X+6,"mapped to: ");
- for(j=0; j<md_maps_count; j++){
- if (mem_devs[i]->header.handle != md_maps[j]->md_handle)
- continue;
- if (mapped++){
- cprint(yof+1, POP2_X+17+of, ",");
- of++;
- }
- hprint3(yof+1, POP2_X+17+of, md_maps[j]->start<<10, 12);
- of += 12;
- cprint(yof+1, POP2_X+17+of, "-");
- of++;
- hprint3(yof+1, POP2_X+17+of, md_maps[j]->end<<10, 12);
- of += 12;
- }
- if (!mapped)
- cprint(yof+1, POP2_X+17, "No mapping (unused device)");
-
- }
-
- wait_keyup();
- while (get_key() == 0);
- }
-}
-
-void add_dmi_err(ulong adr){
- int i,j;
-
- if(!dmi_initialized)
- dmi_open();
-
- for(i=0; i < md_maps_count; i++){
- if ( adr < (md_maps[i]->start<<10) ||
- adr > (md_maps[i]->end<<10) )
- continue;
-
- //matching map found, now check find corresponding dev
- for(j=0; j < mem_devs_count; j++){
- if (mem_devs[j]->header.handle == md_maps[i]->md_handle) {
- dmi_err_cnts[j]++;
- break;
- }
- }
- break;
- }
-}
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/head.s
^
|
@@ -1,1051 +0,0 @@
-# 1 "head.S"
-# 1 "<built-in>"
-# 1 "<command line>"
-# 1 "head.S"
-
-
-
-
-
-
-
-
-
-
-
-
-
-.text
-
-
-# 1 "defs.h" 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# 17 "head.S" 2
-
-# 1 "config.h" 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# 18 "head.S" 2
-
-# 1 "test.h" 1
-
-
-
-
-
-
-
-# 16 "test.h"
-
-# 19 "head.S" 2
-
-
-# 33 "head.S"
-
- .code32
- .globl startup_32
-startup_32:
- cld
- cli
-
-
- testl %esp, %esp
- jnz 0f
- movl $(0x00002000 + _GLOBAL_OFFSET_TABLE_), %esp
- leal stack_top@GOTOFF(%esp), %esp
-0:
-
-
- call 0f
-0: popl %ebx
- addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx
-
-
- leal stack_top@GOTOFF(%ebx), %esp
-
-
- leal gdt@GOTOFF(%ebx), %eax
- movl %eax, 2 + gdt_descr@GOTOFF(%ebx)
- lgdt gdt_descr@GOTOFF(%ebx)
- leal flush@GOTOFF(%ebx), %eax
- pushl $0x10
- pushl %eax
- lret
-flush: movl $0x18, %eax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- movw %ax, %ss
-
-
-
-
- cmpl $1, zerobss@GOTOFF(%ebx)
- jnz zerobss_done
- xorl %eax, %eax
- leal _bss@GOTOFF(%ebx), %edi
- leal _end@GOTOFF(%ebx), %ecx
- subl %edi, %ecx
-1: movl %eax, (%edi)
- addl $4, %edi
- subl $4, %ecx
- jnz 1b
- movl $0, zerobss@GOTOFF(%ebx)
-zerobss_done:
-
-
-
-
- cmpl $1, clear_display@GOTOFF(%ebx)
- jnz clear_display_done
- movw $0x0720, %ax
- movl $0xb8000, %edi
- movl $0xc0000, %ecx
-1: movw %ax, (%edi)
- addl $2, %edi
- cmpl %ecx, %edi
- jnz 1b
- movl $0, clear_display@GOTOFF(%ebx)
-clear_display_done:
-
-
-
-
-
- leal idt@GOTOFF(%ebx), %edi
-
- leal vec0@GOTOFF(%ebx), %edx
- movl $(0x10 << 16),%eax
- movw %dx, %ax
- movw $0x8E00, %dx
- movl %eax, (%edi)
- movl %edx, 4(%edi)
- addl $8, %edi
-
- leal vec1@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec2@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec3@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec4@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec5@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec6@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec7@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec8@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec9@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec10@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec11@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec12@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec13@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec14@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec15@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec16@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec17@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec18@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
- leal vec19@GOTOFF(%ebx),%edx
- movl $(0x10 << 16),%eax
- movw %dx,%ax
- movw $0x8E00,%dx
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
-
-
- leal idt@GOTOFF(%ebx), %eax
- movl %eax, 2 + idt_descr@GOTOFF(%ebx)
- lidt idt_descr@GOTOFF(%ebx)
-
-
-
- leal cpu_id@GOTOFF(%ebx), %esi
- movl %ebx, %edi
-
- movl $-1, 4(%esi) # -1 for no CPUID initially
-
-
-
- movl $3, 0(%esi) # at least 386
- pushfl # push EFLAGS
- popl %eax # get EFLAGS
- movl %eax, %ecx # save original EFLAGS
- xorl $0x40000, %eax # flip AC bit in EFLAGS
- pushl %eax # copy to EFLAGS
- popfl # set EFLAGS
- pushfl # get new EFLAGS
- popl %eax # put it in eax
- xorl %ecx, %eax # change in flags
- andl $0x40000, %eax # check if AC bit changed
- je id_done
-
- movl $4, 0(%esi) # at least 486
- movl %ecx, %eax
- xorl $0x200000, %eax # check ID flag
- pushl %eax
- popfl # if we are on a straight 486DX, SX, or
- pushfl # 487SX we can't change it
- popl %eax
- xorl %ecx, %eax
- pushl %ecx # restore original EFLAGS
- popfl
- andl $0x200000, %eax
- jne have_cpuid
-
-
- xorw %ax, %ax # clear ax
- sahf # clear flags
- movw $5, %ax
- movw $2, %bx
- div %bl # do operation that does not change flags
- lahf # get flags
- cmp $2, %ah # check for change in flags
- jne id_done # if not Cyrix
- movl $2, 0(%esi) # Use two to identify as Cyrix
- jmp id_done
-
-have_cpuid:
-
- xorl %eax, %eax # call CPUID with 0 -> return vendor ID
- cpuid
- movl %eax, 4(%esi) # save CPUID level
- movl %ebx, 12(%esi) # first 4 chars
- movl %edx, 12+4(%esi) # next 4 chars
- movl %ecx, 12+8(%esi) # last 4 chars
-
- orl %eax, %eax # do we have processor info as well?
- je id_done
-
- movl $1, %eax # Use the CPUID instruction to get CPU type
- cpuid
-
-
- #
- # CDH start
- # Check FPU, initialize if present
- #
- testl $1, %edx # FPU available?
- jz no_fpu
- finit
-
- no_fpu:
- #
- # CDH end
- #
-
- movl %eax, 44(%esi) #save complete extended CPUID to 44
- movb %al, %cl # save reg for future use
- andb $0x0f, %ah # mask processor family
- movb %ah, 0(%esi)
- andb $0xf0, %al # mask model
- shrb $4, %al
- movb %al, 1(%esi)
- andb $0x0f, %cl # mask mask revision
- movb %cl, 2(%esi)
- movl %edx, 8(%esi)
-
- movl $0, 24(%esi)
- movl $0, 24+4(%esi)
- movl $0, 24+8(%esi)
- movl $0, 24+12(%esi)
-
- movl 12+8(%esi), %eax
- cmpl $0x6c65746e,%eax # Is this an Intel CPU? "GenuineIntel"
- jne not_intel
- movb %bl, 40(%esi) # Store BrandID in AMD PWRCAP if the CPU is from Intel
- movl $2, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %eax, 24(%esi)
- movl %ebx, 24+4(%esi)
- movl %ecx, 24+8(%esi)
- movl %edx, 24+12(%esi)
- jmp id_done
-
-not_intel:
- movl 12+8(%esi),%eax
- cmpl $0x444d4163, %eax # Is this an AMD CPU? "AuthenticAMD"
- jne not_amd
-
- movl $0x80000005, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %ecx, 24(%esi)
- movl %edx, 24+4(%esi)
- movl $0x80000006,%eax # Use the CPUID instruction to get cache info
- cpuid
- movl %ecx,24+8(%esi)
- movl $0x80000007,%eax # Use the CPUID instruction to get AMD Powercap
- cpuid
- movl %edx,40(%esi)
-
-not_amd:
- movl 12+8(%esi), %eax
- cmpl $0x3638784D, %eax # Is this a Transmeta CPU? "GenuineTMx86"
- jne not_transmeta
-
- movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
- cpuid
- cmp $6, %al # Is cache info available?
- jb id_done
-
- movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
- cpuid
- movl %ecx, 24(%esi)
- movl %edx, 24+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, 24+8(%esi)
-
-not_transmeta:
- movl 12+8(%esi), %eax
- cmpl $0x64616574, %eax # Is this a Via/Cyrix CPU? "CyrixInstead"
- jne not_cyrix
-
- movl 4(%esi), %eax # get CPUID level
- cmpl $2, %eax # Is there cache information available ?
- jne id_done
-
- movl $2, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %edx, 24(%esi)
-
-not_cyrix:
- movl 12+8(%esi), %eax
- cmpl $0x736C7561, %eax # Is this a Via/Centaur CPU "CentaurHauls"
- jne not_centaur
-
- movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
- cpuid
- cmp $6, %al # Is cache info available?
- jb id_done
-
- movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
- cpuid
- movl %ecx, 24(%esi)
- movl %edx, 24+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, 24+8(%esi)
-
-
-not_centaur:
-id_done:
- movl %edi, %ebx
-
- leal _dl_start@GOTOFF(%ebx), %eax
- call *%eax
- call do_test
-
- pushfl
- pushl %cs
- call 0f
-0: pushl $0
- pushl $257
- jmp int_hand
-
-vec0:
- pushl $0
- pushl $0
- jmp int_hand
-vec1:
- pushl $0
- pushl $1
- jmp int_hand
-
-vec2:
- pushl $0
- pushl $2
- jmp int_hand
-
-vec3:
- pushl $0
- pushl $3
- jmp int_hand
-
-vec4:
- pushl $0
- pushl $4
- jmp int_hand
-
-vec5:
- pushl $0
- pushl $5
- jmp int_hand
-
-vec6:
- pushl $0
- pushl $6
- jmp int_hand
-
-vec7:
- pushl $0
- pushl $7
- jmp int_hand
-
-vec8:
-
- pushl $8
- jmp int_hand
-
-vec9:
- pushl $0
- pushl $9
- jmp int_hand
-
-vec10:
-
- pushl $10
- jmp int_hand
-
-vec11:
-
- pushl $11
- jmp int_hand
-
-vec12:
-
- pushl $12
- jmp int_hand
-
-vec13:
-
- pushl $13
- jmp int_hand
-
-vec14:
-
- pushl $14
- jmp int_hand
-
-vec15:
- pushl $0
- pushl $15
- jmp int_hand
-
-vec16:
- pushl $0
- pushl $16
- jmp int_hand
-
-vec17:
-
- pushl $17
- jmp int_hand
-
-vec18:
- pushl $0
- pushl $18
- jmp int_hand
-
-vec19:
- pushl $0
- pushl $19
- jmp int_hand
-
-int_hand:
- pushl %eax
- pushl %ebx
- pushl %ecx
- pushl %edx
- pushl %edi
- pushl %esi
- pushl %ebp
-
-
- leal 20(%esp), %eax
- pushl %eax
-
- pushl %esp
- call inter
- addl $8, %esp
-
- popl %ebp
- popl %esi
- popl %edi
- popl %edx
- popl %ecx
- popl %ebx
- popl %eax
- iret
-
-
-
-
-.align 4
-.word 0
-idt_descr:
- .word 20*8-1 # idt contains 32 entries
- .long 0
-
-idt:
- .fill 20,8,0 # idt is uninitialized
-
-gdt_descr:
- .word gdt_end - gdt - 1
- .long 0
-
-.align 4
-.globl gdt, gdt_end
-gdt:
- .quad 0x0000000000000000
- .quad 0x0000000000000000
- .quad 0x00cf9a000000ffff
- .quad 0x00cf92000000ffff
-
- .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB)
- .word 0 # base address = (0x9000+0x20)
- .byte 0x00, 0x9b # code read/exec/accessed
- .byte 0x00, 0x00 # granularity = bytes
-
-
- .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB)
- .word 0 # base address = (0x9000+0x20)
- .byte 0x00, 0x93 # data read/write/accessed
- .byte 0x00, 0x00 # granularity = bytes
-
-gdt_end:
-
-.data
-
-.macro ptes64 start, count=64
-.quad \start + 0x0000000 + 0xE3
-.quad \start + 0x0200000 + 0xE3
-.quad \start + 0x0400000 + 0xE3
-.quad \start + 0x0600000 + 0xE3
-.quad \start + 0x0800000 + 0xE3
-.quad \start + 0x0A00000 + 0xE3
-.quad \start + 0x0C00000 + 0xE3
-.quad \start + 0x0E00000 + 0xE3
-.if \count-1
-ptes64 "(\start+0x01000000)",\count-1
-.endif
-.endm
-
-.macro maxdepth depth=1
-.if \depth-1
-maxdepth \depth-1
-.endif
-.endm
-
-maxdepth
-
-.balign 4096
-.globl pd0
-pd0:
- ptes64 0x0000000000000000
-
-.balign 4096
-.globl pd1
-pd1:
- ptes64 0x0000000040000000
-
-.balign 4096
-.globl pd2
-pd2:
- ptes64 0x0000000080000000
-
-.balign 4096
-.globl pd3
-pd3:
- ptes64 0x00000000C0000000
-
-.balign 4096
-.globl pdp
-pdp:
- .long pd0 + 1
- .long 0
- .long pd1 + 1
- .long 0
-
- .long pd2 + 1
- .long 0
-
- .long pd3 + 1
- .long 0
-.previous
-
-
-
- .globl query_pcbios
-query_pcbios:
-
- pushl %ebx
- pushl %esi
- pushl %edi
- pushl %ebp
- call 1f
-1: popl %ebx
- addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
-
-
- leal startup_32@GOTOFF(%ebx), %esi
-
-
- movl %esi, %eax
- shrl $4, %eax
- movw %ax, 2 + realptr@GOTOFF(%ebx)
-
-
- leal prot@GOTOFF(%ebx), %eax
- movl %eax, protptr@GOTOFF(%ebx)
-
-
- movl %esi, %eax
- shll $16, %eax # Base low
-
- movl %esi, %ecx
- shrl $16, %ecx
- andl $0xff, %ecx
-
- movl %esi, %edx
- andl $0xff000000, %edx
- orl %edx, %ecx
-
-
- andl $0x0000ffff, 0x20 + 0 + gdt@GOTOFF(%ebx)
- orl %eax, 0x20 + 0 + gdt@GOTOFF(%ebx)
- andl $0x00ffff00, 0x20 + 4 + gdt@GOTOFF(%ebx)
- orl %ecx, 0x20 + 4 + gdt@GOTOFF(%ebx)
- andl $0x0000ffff, 0x28 + 0 + gdt@GOTOFF(%ebx)
- orl %eax, 0x28 + 0 + gdt@GOTOFF(%ebx)
- andl $0x00ffff00, 0x28 + 4 + gdt@GOTOFF(%ebx)
- orl %ecx, 0x28 + 4 + gdt@GOTOFF(%ebx)
-
-
- leal gdt@GOTOFF(%ebx), %eax
- movl %eax, 2 + gdt_descr@GOTOFF(%ebx)
-
- lidt idt_real@GOTOFF(%ebx)
-
-
-
-
- movl $0x28, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
- movl %eax, %fs
- movl %eax, %gs
-
-
- leal stack@GOTOFF(%ebx), %ecx
-
- leal mem_info@GOTOFF(%ebx), %edi
-
-
- ljmp $0x20, $1f - startup_32
-1:
- .code16
-
-
- movl %cr0,%eax
- andl $~((1 << 31)|(1<<0)),%eax
- movl %eax,%cr0
-
-
-
-
- ljmp *(realptr - startup_32)
-real:
-
-
-
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- movw %ax, %ss
-
-
- movl %ecx, %eax
- shrl $4, %eax
- movw %ax, %ss
- subl %ecx, %esp
-
-
- pushl %ebx
-
-
- shrl $4, %edi
- movl %edi, %ds
-
-
- sti
-
-# Get memory size (extended mem, kB)
-
-
-
- xorl %eax, %eax
- movl %eax, (0x00)
- movl %eax, (0x04)
- movl %eax, (0x08)
-
-# Try three different memory detection schemes. First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell. e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything. We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [0x0c].
-# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
-
-meme820:
- xorl %ebx, %ebx # continuation counter
- movw $0x0c, %di # point into the whitelist
- # so we can have the bios
- # directly write into it.
-
-jmpe820:
- movl $0x0000e820, %eax # e820, upper word zeroed
- movl $0x534d4150, %edx # ascii 'SMAP'
- movl $20, %ecx # size of the e820rec
- pushw %ds # data record.
- popw %es
- int $0x15 # make the call
- jc bail820 # fall to e801 if it fails
-
- cmpl $0x534d4150, %eax # check the return is `0x534d4150'
- jne bail820 # fall to e801 if it fails
-
-# cmpl $1, 16(%di) # is this usable memory?
-# jne again820
-
- # If this is usable memory, we save it by simply advancing %di by
- # sizeof(e820rec).
- #
-good820:
- movb (0x08), %al # up to 32 entries
- cmpb $32, %al
- jnl bail820
-
- incb (0x08)
- movw %di, %ax
- addw $20, %ax
- movw %ax, %di
-again820:
- cmpl $0, %ebx # check to see if
- jne jmpe820 # %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-
-meme801:
- stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which dont clear/set
- xorw %dx,%dx # carry on pass/error of
- # e801h memory size call
- # or merely pass cx,dx though
- # without changing them.
- movw $0xe801, %ax
- int $0x15
- jc mem88
-
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
- movw %ax, %cx # seems to indicate AX/BX
- movw %bx, %dx # are more reasonable anyway...
-
-e801usecxdx:
- andl $0xffff, %edx # clear sign extend
- shll $6, %edx # and go from 64k to 1k chunks
- movl %edx, (0x04) # store extended memory size
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, (0x04) # and add lower memory into
- # total size.
-
-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
- movb $0x88, %ah
- int $0x15
- movw %ax, (0x00)
-
-
-# check for APM BIOS
- movw $0x5300, %ax # APM BIOS installation check
- xorw %bx, %bx
- int $0x15
- jc done_apm_bios # error -> no APM BIOS
-
- cmpw $0x504d, %bx # check for "PM" signature
- jne done_apm_bios # no signature -> no APM BIOS
-
- movw $0x5304, %ax # Disconnect first just in case
- xorw %bx, %bx
- int $0x15 # ignore return code
-
- movw $0x5301, %ax # Real Mode connect
- xorw %bx, %bx
- int $0x15
- jc done_apm_bios # error
-
- movw $0x5308, %ax # Disable APM
- mov $0xffff, %bx
- xorw %cx, %cx
- int $0x15
-
-done_apm_bios:
-
-
-
- cli
-
-
- popl %ebx
-
-
- movw %cs, %ax
- movw %ax, %ds
-
-
- addr32 lgdt gdt_descr - startup_32
-
-
-
- movl %cr0,%eax
- orl $(1<<0),%eax
- movl %eax,%cr0
-
-
- data32 ljmp *(protptr - startup_32)
-prot:
- .code32
-
- movl $0x18, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %fs
- movl %eax, %gs
- movl %eax, %ss
-
-
- leal stack@GOTOFF(%ebx), %eax
- addl %eax, %esp
-
-
- popl %ebp
- popl %edi
- popl %esi
- popl %ebx
- movl $1, %eax
- ret
-
-realptr:
- .word real - startup_32
- .word 0x0000
-protptr:
- .long 0
- .long 0x10
-
-idt_real:
- .word 0x400 - 1 # idt limit ( 256 entries)
- .word 0, 0 # idt base = 0L
-
-.data
-zerobss: .long 1
-clear_display: .long 1
-.previous
-.data
-.balign 16
- .globl mem_info
-mem_info:
- . = . + 0x28c
-.previous
-.bss
-.balign 16
-stack:
- . = . + 4096
-stack_top:
-.previous
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/pci.c
^
|
@@ -1,160 +0,0 @@
-/* pci.c - MemTest-86 Version 3.2
- *
- * Released under version 2 of the Gnu Public License.
- * By Chris Brady
- * ----------------------------------------------------
- * MemTest86+ V1.51 Specific code (GPL V2.0)
- * By Samuel DEMEULEMEESTER, sdemeule@memtest.org
- * http://www.x86-secret.com - http://www.memtest.org
- */
-
-#include "io.h"
-#include "pci.h"
-#include "test.h"
-
-#define PCI_CONF_TYPE_NONE 0
-#define PCI_CONF_TYPE_1 1
-#define PCI_CONF_TYPE_2 2
-
-extern struct cpu_ident cpu_id;
-
-static unsigned char pci_conf_type = PCI_CONF_TYPE_NONE;
-
-#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
- (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
-
-#define PCI_CONF2_ADDRESS(dev, reg) (unsigned short)(0xC000 | (dev << 8) | reg)
-
-int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long *value)
-{
- int result;
-
- if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -1;
-
- result = -1;
- switch(pci_conf_type) {
- case PCI_CONF_TYPE_1:
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
- switch(len) {
- case 1: *value = inb(0xCFC + (reg & 3)); result = 0; break;
- case 2: *value = inw(0xCFC + (reg & 2)); result = 0; break;
- case 4: *value = inl(0xCFC); result = 0; break;
- }
- break;
- case PCI_CONF_TYPE_2:
- outb(0xF0 | (fn << 1), 0xCF8);
- outb(bus, 0xCFA);
-
- switch(len) {
- case 1: *value = inb(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 2: *value = inw(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 4: *value = inl(PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- }
- outb(0, 0xCF8);
- break;
- }
- return result;
-}
-
-int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg, unsigned len, unsigned long value)
-{
- int result;
-
- if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -1;
-
- result = -1;
- switch(pci_conf_type) {
- case PCI_CONF_TYPE_1:
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
- switch(len) {
- case 1: outb(value, 0xCFC + (reg & 3)); result = 0; break;
- case 2: outw(value, 0xCFC + (reg & 2)); result = 0; break;
- case 4: outl(value, 0xCFC); result = 0; break;
- }
- break;
- case PCI_CONF_TYPE_2:
- outb(0xF0 | (fn << 1), 0xCF8);
- outb(bus, 0xCFA);
-
- switch(len) {
- case 1: outb(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 2: outw(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- case 4: outl(value, PCI_CONF2_ADDRESS(dev, reg)); result = 0; break;
- }
- outb(0, 0xCF8);
- break;
- }
- return result;
-}
-
-static int pci_sanity_check(void)
-{
- unsigned long value;
- int result;
- /* Do a trivial check to make certain we can see a host bridge.
- * There are reportedly some buggy chipsets from intel and
- * compaq where this test does not work, I will worry about
- * that when we support them.
- */
- result = pci_conf_read(0, 0, 0, PCI_CLASS_DEVICE, 2, &value);
- if (result == 0) {
- result = -1;
- if (value == PCI_CLASS_BRIDGE_HOST) {
- result = 0;
- }
- }
- return result;
-}
-
-static int pci_check_direct(void)
-{
- unsigned char tmpCFB;
- unsigned int tmpCF8;
-
- if (cpu_id.vend_id[0] == 'A' && cpu_id.type == 15) {
- pci_conf_type = PCI_CONF_TYPE_1;
- return 0;
- } else {
- /* Check if configuration type 1 works. */
- pci_conf_type = PCI_CONF_TYPE_1;
- tmpCFB = inb(0xCFB);
- outb(0x01, 0xCFB);
- tmpCF8 = inl(0xCF8);
- outl(0x80000000, 0xCF8);
- if ((inl(0xCF8) == 0x80000000) && (pci_sanity_check() == 0)) {
- outl(tmpCF8, 0xCF8);
- outb(tmpCFB, 0xCFB);
- return 0;
- }
- outl(tmpCF8, 0xCF8);
-
- /* Check if configuration type 2 works. */
- pci_conf_type = PCI_CONF_TYPE_2;
- outb(0x00, 0xCFB);
- outb(0x00, 0xCF8);
- outb(0x00, 0xCFA);
- if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && (pci_sanity_check() == 0)) {
- outb(tmpCFB, 0xCFB);
- return 0;
- }
-
- outb(tmpCFB, 0xCFB);
-
- /* Nothing worked return an error */
- pci_conf_type = PCI_CONF_TYPE_NONE;
- return -1;
-
- }
-}
-
-int pci_init(void)
-{
- int result;
- /* For now just make certain we can directly
- * use the pci functions.
- */
- result = pci_check_direct();
- return result;
-}
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/pci.h
^
|
@@ -1,94 +0,0 @@
-#ifndef MEMTEST_PCI_H
-#define MEMTEST_PCI_H
-
-int pci_conf_read(unsigned bus, unsigned dev, unsigned fn, unsigned reg,
- unsigned len, unsigned long *value);
-int pci_conf_write(unsigned bus, unsigned dev, unsigned fn, unsigned reg,
- unsigned len, unsigned long value);
-int pci_init(void);
-
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_VENDOR_ID 0x00 /* 16 bits */
-#define PCI_DEVICE_ID 0x02 /* 16 bits */
-#define PCI_COMMAND 0x04 /* 16 bits */
-#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
-#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
-#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
-#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
-#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
-#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
-#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
-#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
-#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
-
-#define PCI_STATUS 0x06 /* 16 bits */
-#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
-#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
-#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
-#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
-#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
-#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
-#define PCI_STATUS_DEVSEL_FAST 0x000
-#define PCI_STATUS_DEVSEL_MEDIUM 0x200
-#define PCI_STATUS_DEVSEL_SLOW 0x400
-#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
-#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
-#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
-#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
-#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
- revision */
-#define PCI_REVISION_ID 0x08 /* Revision ID */
-#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE 0x0a /* Device class */
-
-#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
-#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
-#define PCI_HEADER_TYPE 0x0e /* 8 bits */
-#define PCI_HEADER_TYPE_NORMAL 0
-#define PCI_HEADER_TYPE_BRIDGE 1
-#define PCI_HEADER_TYPE_CARDBUS 2
-
-#define PCI_BIST 0x0f /* 8 bits */
-#define PCI_BIST_CODE_MASK 0x0f /* Return result */
-#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
-#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back. Only
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
-#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
-#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
-#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
-#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
-#define PCI_BASE_ADDRESS_SPACE_IO 0x01
-#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
-#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
-#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
-#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
-#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
-#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
-#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
-#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-
-/* Device classes and subclasses */
-#define PCI_CLASS_NOT_DEFINED 0x0000
-#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
-
-#define PCI_BASE_CLASS_BRIDGE 0x06
-#define PCI_CLASS_BRIDGE_HOST 0x0600
-
-#endif /* MEMTEST_PCI_H */
|
[-]
[+]
|
Deleted |
memtest86-3.4.tar.gz/setup.s
^
|
@@ -1,149 +0,0 @@
-# 1 "setup.S"
-# 1 "<built-in>"
-# 1 "<command line>"
-# 1 "setup.S"
-
-
-
-
-
-
-
-
-
-
-# 1 "defs.h" 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# 11 "setup.S" 2
-
-.code16
-.section ".setup", "ax", @progbits
-.globl start
-start:
-# ok, the read went well
-# now we want to move to protected mode ...
-
-
- cli # no interrupts allowed #
- movb $0x80, %al # disable NMI for the bootup sequence
- outb %al, $0x70
-
- movb $0x01, %ah # turn off the cursor
- movb $0x00, %bh
- movw $0x2000, %cx
- int $0x10
-
-# The system will move itself to its rightful place.
-
- push %cs
- pop %ds
- lidt idt_48 - start # load idt with 0,0
- lgdt gdt_48 - start # load gdt with whatever appropriate
-
-# that was painless, now we enable A20
-
- call empty_8042
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
-
-
-
-
- movw $0x0001, %ax # protected mode (PE) bit
- lmsw %ax # This is it#
- jmp flush_instr
-flush_instr:
- movw $0x18, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw %ax, %fs
- movw %ax, %gs
-
-data32 ljmp $0x10, $(0x1000 <<4) # jmp offset 2000 of segment 0x10 (cs)
-
-
-
-
-
-
-
-
-empty_8042:
- call delay
- inb $0x64, %al # 8042 status port
- testb $1, %al # output buffer?
- jz no_output
- call delay
- inb $0x60, %al # read it
- jmp empty_8042
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042 # yes - loop
- ret
-
-# Delay is needed after doing i/o
-
-delay:
- .word 0x00eb # jmp $+2
- ret
-
-gdt:
- .word 0,0,0,0 # dummy
-
- .word 0,0,0,0 # unused
-
- .word 0x7FFF # limit 128mb
- .word 0x0000 # base address=0
- .word 0x9A00 # code read/exec
- .word 0x00C0 # granularity=4096, 386
-
- .word 0x7FFF # limit 128mb
- .word 0x0000 # base address=0
- .word 0x9200 # data read/write
- .word 0x00C0 # granularity=4096, 386
-
-idt_48:
- .word 0 # idt limit=0
- .long 0 # idt base=0L
-
-gdt_48:
- .word 0x800 # gdt limit=2048, 256 GDT entries
- .word 512+gdt - start,0x9 # gdt base = 0X9xxxx
-
-msg1:
- .asciz "Setup.S\r\n"
-
-
- .org (4*512)
-
|
|
Deleted |
memtest86-3.5.tar.gz
^
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/Makefile
^
|
@@ -1,4 +1,4 @@
-# Makefile for MemTest-86
+# Makefile for MemTest86+
#
# Author: Chris Brady
# Created: January 1, 1996
@@ -8,16 +8,16 @@
#
FDISK=/dev/fd0
+AS=as -32
CC=gcc
-CFLAGS=-Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin \
- -ffreestanding -fPIC
+CFLAGS= -Wall -march=i486 -m32 -O1 -fomit-frame-pointer -fno-builtin \
+ -ffreestanding -fPIC $(SMP_FL) -fno-stack-protector
OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \
- config.o linuxbios.o memsize.o pci.o controller.o random.o extra.o \
- spd.o error.o dmi.o
+ config.o linuxbios.o memsize.o error.o smp.o cpuid.o vmem.o random.o
-all: memtest.bin memtest
+all: clean memtest.bin memtest
# Link it statically once so I know I don't have undefined
# symbols and then link it dynamically so I have full
@@ -33,6 +33,15 @@
memtest: memtest_shared.bin memtest.lds
$(LD) -s -T memtest.lds -b binary memtest_shared.bin -o $@
+head.s: head.S config.h defs.h test.h
+ $(CC) -E -traditional $< -o $@
+
+bootsect.s: bootsect.S config.h defs.h
+ $(CC) -E -traditional $< -o $@
+
+setup.s: setup.S config.h defs.h
+ $(CC) -E -traditional $< -o $@
+
memtest.bin: memtest_shared.bin bootsect.o setup.o memtest.bin.lds
$(LD) -T memtest.bin.lds bootsect.o setup.o -b binary \
memtest_shared.bin -o memtest.bin
@@ -41,14 +50,25 @@
$(CC) -c $(CFLAGS) -fno-strict-aliasing reloc.c
test.o: test.c
- $(CC) -c -Wall -march=i486 -m32 -Os -fomit-frame-pointer -fno-builtin \
- -ffreestanding test.c
+ $(CC) -c -Wall -march=i486 -m32 -O0 -fomit-frame-pointer -fno-builtin -ffreestanding test.c
+
+random.o: random.c
+ $(CC) -c -Wall -march=i486 -m32 -O3 -fomit-frame-pointer -fno-builtin -ffreestanding random.c
clean:
- rm -f *.o memtest.bin memtest memtest_shared memtest_shared.bin
+ rm -f *.o *.s *.iso memtest.bin memtest memtest_shared \
+ memtest_shared.bin memtest.iso
+
+iso:
+ make all
+ ./makeiso.sh
install: all
dd <memtest.bin >$(FDISK) bs=8192
install-precomp:
dd <precomp.bin >$(FDISK) bs=8192
+
+dos: all
+ cat mt86+_loader memtest.bin > memtest.exe
+
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/README
^
|
@@ -1,6 +1,6 @@
====================
- = MemTest-86 v3.4 =
- = 3 Sep, 2007 =
+ = MemTest-86 v4.0 =
+ = 28 Mar, 2011 =
= Chris Brady =
====================
Table of Contents
@@ -110,15 +110,11 @@
c Enters test configuration menu
Menu options are:
- 1) Cache mode
- 2) Test selection
- 3) Address Range
- 4) Memory Sizing
- 5) Error Summary
- 6) Error Report Mode
- 7) ECC Mode
- 8) Restart
- 9) Adv. Options
+ 1) Test selection
+ 2) Address Range
+ 3) Error Report Mode
+ 4) CPU Selection Mode
+ 5) Refresh Screen
SP Set scroll lock (Stops scrolling of error messages)
Note: Testing is stalled when the scroll lock is
@@ -127,56 +123,7 @@
CR Clear scroll lock (Enables error message scrolling)
-6) Memory Sizing
-================
-The BIOS in modern PC's will often reserve several sections of memory for
-it's use and also to communicate information to the operating system (ie.
-ACPI tables). It is just as important to test these reserved memory blocks
-as it is for the remainder of memory. For proper operation all of memory
-needs to function properly regardless of what the eventual use is. For
-this reason Memtest86 has been designed to test as much memory as is
-possible.
-
-However, safely and reliably detecting all of the available memory has been
-problematic. Versions of Memtest86 prior to v2.9 would probe to find where
-memory is. This works for the vast majority of motherboards but is not 100%
-reliable. Sometimes the memory size is incorrect and worse probing the wrong
-places can in some cases cause the test to hang or crash.
-
-Starting in version 2.9 alternative methods are available for determining the
-memory size. By default the test attempts to get the memory size from the
-BIOS using the "e820" method. With "e820" the BIOS provides a table of memory
-segments and identifies what they will be used for. By default Memtest86
-will test all of the ram marked as available and also the area reserved for
-the ACPI tables. This is safe since the test does not use the ACPI tables
-and the "e820" specifications state that this memory may be reused after the
-tables have been copied. Although this is a safe default some memory will
-not be tested.
-
-Two additional options are available through online configuration options.
-The first option (BIOS-All) also uses the "e820" method to obtain a memory
-map. However, when this option is selected all of the reserved memory
-segments are tested, regardless of what their intended use is. The only
-exception is memory segments that begin above 3gb. Testing has shown that
-these segments are typically not safe to test. The BIOS-All option is more
-thorough but could be unstable with some motherboards.
-
-The second option for memory sizing is the traditional "Probe" method.
-This is a very thorough but not entirely safe method. In the majority of
-cases the BIOS-All and Probe methods will return the same memory map.
-
-For older BIOS's that do not support the "e820" method there are two
-additional methods (e801 and e88) for getting the memory size from the
-BIOS. These methods only provide the amount of extended memory that is
-available, not a memory table. When the e801 and e88 methods are used
-the BIOS-All option will not be available.
-
-The MemMap field on the display shows what memory size method is in use.
-Also the RsvdMem field shows how much memory is reserved and is not being
-tested.
-
-
-7) Error Information
+6) Error Information
======================
Memtest has three options for reporting errors. The default is an an error
summary that displays the most relevant error information. The second option
@@ -215,11 +162,6 @@
ECC Correctable Errors:
The number of errors that have been corrected by ECC hardware.
- Errors per DIMM slot:
- Error counts are reported for each memory module installed in the system.
- Use the “Show DMI Memory Info” runtime option for detailed memory module
- information.
-
Test Errors:
On the right hand side of the screen the number of errors for each test
are displayed.
@@ -230,13 +172,14 @@
hexadecimal.
Tst: Test number
- Failing Address : Failing memory address
+ Failing Address: Failing memory address
Good: Expected data pattern
Bad: Failing data pattern
Err-Bits: Exclusive or of good and bad data (this shows the
position of the failing bit(s))
Count: Number of consecutive errors with the same address
and failing bits
+ CPU: CPU that detected the error
In BadRAM Patterns mode, Lines are printed in a form badram=F1,M1,F2,M2.
In each F/M pair, the F represents a fault address, and the corresponding M
@@ -253,7 +196,7 @@
results.
-8) Trouble-shooting Memory Errors
+7) Trouble-shooting Memory Errors
================================
Please be aware that not all errors reported by Memtest86 are due to
bad memory. The test implicitly tests the CPU, L1 and L2 caches as well as
@@ -325,7 +268,7 @@
Memtest86 to crash in the same way.
-9) Execution Time
+8) Execution Time
==================
The time required for a complete pass of Memtest86 will vary greatly
depending on CPU speed, memory speed and memory size. Memtest86 executes
@@ -334,7 +277,7 @@
catch all but the most obscure errors. However, for complete confidence
when intermittent errors are suspected testing for a longer period is advised.
-10) Memory Testing Philosophy
+9) Memory Testing Philosophy
=============================
There are many good approaches for testing memory. However, many tests
simply throw some patterns at memory without much thought or knowledge
@@ -411,7 +354,7 @@
speed and thoroughness.
-12) Individual Test Descriptions
+11) Individual Test Descriptions
================================
Memtest86 executes a series of numbered test sections to check for
errors. These test sections consist of a combination of test
@@ -424,32 +367,40 @@
address pattern. Errors from this test are not used to calculate
BadRAM patterns.
-Test 1 [Address test, own address]
+Test 1 [Address test, own address Sequential]
Each address is written with its own address and then is checked
for consistency. In theory previous tests should have caught any
memory addressing problems. This test should catch any addressing
- errors that somehow were not previously detected.
+ errors that somehow were not previously detected. This test is done
+ sequentially with each available CPU.
-Test 2 [Moving inversions, ones&zeros]
+Test 2 [Address test, own address Parallel]
+ Same as test 1 but the testing is done in parallel using all CPUs using
+ overlapping addresses.
+
+Test 3 [Moving inversions, ones&zeros Sequential]
This test uses the moving inversions algorithm with patterns of all
ones and zeros. Cache is enabled even though it interferes to some
degree with the test algorithm. With cache enabled this test does not
take long and should quickly find all "hard" errors and some more
- subtle errors. This section is only a quick check.
+ subtle errors. This test is done sequentially with each available CPU.
+
+Test 4 [Moving inversions, ones&zeros Parallel]
+ Same as test 3 but the testing is done in parallel using all CPUs.
-Test 3 [Moving inversions, 8 bit pat]
+Test 5 [Moving inversions, 8 bit pat]
This is the same as test 1 but uses a 8 bit wide pattern of
"walking" ones and zeros. This test will better detect subtle errors
in "wide" memory chips. A total of 20 data patterns are used.
-Test 4 [Moving inversions, random pattern]
+Test 6 [Moving inversions, random pattern]
Test 4 uses the same algorithm as test 1 but the data pattern is a
random number and it's complement. This test is particularly effective
in finding difficult to detect data sensitive errors. A total of 60
patterns are used. The random number sequence is different with each pass
so multiple passes increase effectiveness.
-Test 5 [Block move, 64 moves]
+Test 7 [Block move, 64 moves]
This test stresses memory by using block move (movsl) instructions
and is based on Robert Redelmeier's burnBX test. Memory is initialized
with shifting patterns that are inverted every 8 bytes. Then 4MB blocks
@@ -462,38 +413,36 @@
reported address. Errors from this test are not used to calculate
BadRAM patterns.
-Test 6 [Moving inversions, 32 bit pat]
+Test 8 [Moving inversions, 32 bit pat]
This is a variation of the moving inversions algorithm that shifts the data
pattern left one bit for each successive address. The starting bit position
is shifted left for each pass. To use all possible data patterns 32 passes
are required. This test is quite effective at detecting data sensitive
errors but the execution time is long.
-Test 7 [Random number sequence]
+Test 9 [Random number sequence]
This test writes a series of random numbers into memory. By resetting the
seed for the random number the same sequence of number can be created for
a reference. The initial pattern is checked and then complemented and
checked again on the next pass. However, unlike the moving inversions test
writing and checking can only be done in the forward direction.
-Test 8 [Modulo 20, random pattern]
+Test 10 [Modulo 20, random pattern]
Using the Modulo-X algorithm should uncover errors that are not
detected by moving inversions due to cache and buffering interference
with the the algorithm. A 32 bit random pattern is used.
-Test 9 [Bit fade test, 90 min, 2 patterns]
+Test 11 [Bit fade test, 2 patterns]
The bit fade test initializes all of memory with a pattern and then
- sleeps for 90 minutes. Then memory is examined to see if any memory bits
- have changed. All ones and all zero patterns are used. This test takes
- 3 hours to complete. The Bit Fade test is not included in the normal test
- sequence and must be run manually via the runtime configuration menu.
+ sleeps for 5 minutes. Then memory is examined to see if any memory bits
+ have changed. All ones and all zero patterns are used.
-13) Problem Reporting - Contact Information
+12) Problem Reporting - Contact Information
===========================================
Due to the growing popularity of Memtest86 (more than 200,000 downloads per
month) I have been inundated by, questions, feedback, problem reports and
-requests for enhancements. I simply do not have time to repond to ANY Memtest86
+requests for enhancements. I simply do not have time to respond to ANY Memtest86
emails. Bug reports and suggestions are welcome but will typically not be
responded to.
@@ -532,8 +481,7 @@
help you with.
-
-14) Known Problems
+15) Known Problems
==================
Sometimes when booting from a floppy disk the following messages scroll up
on the screen:
@@ -545,20 +493,17 @@
This the BIOS reporting floppy disk read errors. Either re-write or toss
the floppy disk.
-Memtest86 has no support for multiple CPUs. Memtest86 will run
-without problems, but it will only use one CPU.
-
Memtest86 can not diagnose many types of PC failures. For example a
faulty CPU that causes Windows to crash will most likely just cause
Memtest86 to crash in the same way.
-There have been numerous reports of errors in only tests 5 and 8 on Athlon
-systems. Often the memory works in a different system or the vendor insists
-that it is good. In these cases the memory is not necessarily bad but is
-not able to operate reliably at Athlon speeds. Sometimes more conservative
-memory timings on the motherboard will correct these errors. In other
-cases the only option is to replace the memory with better quality, higher
-speed memory. Don't buy cheap memory and expect it to work with an Athlon!
+There have been numerous reports of errors in only the block move test. Often
+the memory works in a different system or the vendor insists that it is good.
+In these cases the memory is not necessarily bad but is not able to operate
+reliably high speeds. Sometimes more conservative memory timings on the
+motherboard will correct these errors. In other cases the only option is to
+replace the memory with better quality, higher speed memory. Don't buy cheap
+memory and expect it to work at full speed.
Memtest86 supports all types of memory. If fact the test has absolutely
no knowledge of the memory type nor does it need to. This not a problem
@@ -569,19 +514,88 @@
binary image (precomp.bin) of the test is included and may be used if
problems are encountered.
+
15) Planned Features List
=========================
This is a list of enhancements planned for future releases of Memtest86.
-There is no timetable for when these will be implemented, if ever.
+There is no timetable for when these will be implemented.
- - Option to write error information to a floppy disk.
- - Supply Memtest in RPM format.
+ - Testing in 64 bit mode with 64 data patterns
+ - Support for reporting ECC errors was removed in the 4.0 release. A
+ simplified implementation of ECC reporting is planned for a future release.
16) Change Log
==============
+Enhancements in v4.0 (28/Mar/2011)
+
+ Full support for testing with multiple CPUs. All tests except for #11 (Bit
+ Fade) have been multi-threaded. A maximum of 16 CPUs will be used for testing.
+
+ CPU detection has been completely re-written to use the brand ID string
+ rather than the cumbersome, difficult to maintain and often out of date
+ CPUID family information. All new processors will now be correctly
+ identified without requiring code support.
+
+ All code related to controller identification, PCI and DMI has been removed.
+ This may be a controversial decision and was not made lightly. The following
+ are justifications for the decision:
+
+ 1. Controller identification has nothing to do with actual testing of
+ memory, the core purpose of Memtest86.
+ 2. This code needed to be updated with every new chipset. With the ever
+ growing number of chipsets it is not possible to keep up with the
+ changes. The result is that new chipsets were more often than not
+ reported in-correctly. In the authors opinion incorrect information is
+ worse than no information.
+ 3. Probing for chipset information carries the risk of making the program
+ crash.
+ 4. The amount of code involved with controller identification was quite
+ large, making support more difficult.
+
+ Removing this code also had the unfortunate effect of removing reporting of
+ correctable ECC errors. The code to support ECC was hopelessly intertwined
+ the controller identification code. A fresh, streamlined implementation of
+ ECC reporting is planned for a future release.
+
+ A surprising number of conditions existed that potentially cause problems
+ when testing more than 4 GB of memory. Most if not all of these conditions
+ have been identified and corrected.
+
+ A number of cases were corrected where not all of memory was being tested.
+ For most tests the last word of each test block was not tested. In addition
+ an error in the paging code was fixed that omitted from testing the last 256
+ bytes of each block above 2 GB.
+
+ The information display has been simplified and a number of details that were
+ not relevant to testing were removed.
+
+ Memory speed reporting has been parallelized for more accurate reporting for
+ multi channel memory controllers.
+
+ This is a major re-write of the Memtest86 with a large number of minor
+ bug-fixes and substantial cleanup and re-organization of the code.
+
+
+Enhancements in v3.5 (3/Jan/2008)
+
+ Limited support for execution with multiple CPUs. CPUs are selected
+ round-robin or sequential for each test.
+
+ Support for additional chipsets. (from Memtest86+ v2.11).
+
+ Additions and corrections for CPU detection including reporting of L3 cache.
+
+ Reworked information display for better readability and new information.
+
+ Abbreviated iterations for first pass.
+
+ Enhancements to memory sizing.
+
+ Misc fixes.
+
Enhancements in v3.4 (2/Aug/2007)
-
+
A new error summary display with error confidence analysis.
Support for additional chipsets. (from Memtest86+ v1.70).
@@ -644,7 +658,7 @@
Added new "Bit Fade" extended test.
- Fixed a complile time bug with gcc version 3.x.
+ Fixed a compile time bug with gcc version 3.x.
E7500 memory controller ECC support
@@ -667,13 +681,13 @@
Very little slow down at 9600 baud.
You can press ^l or just l to get a screen refresh, when you are
- connecting and unconnecting a serial cable.
+ connecting and UN-connecting a serial cable.
- Netbooting is working again
+ Net-booting is working again
- LinuxBIOS support (To get the memory size)
+ Linux-BIOS support (To get the memory size)
- Many bugfixes and code cleanup.
+ Many bug-fixes and code cleanup.
Enhancements in v2.9 (29/Feb/2002)
@@ -692,7 +706,7 @@
Memory is divided into segments for testing. This allow for frequent
progress updates and responsiveness to interactive commands. The
memory segment size has been increased from 8 to 32mb. This should
- improve testing effectivness but progress reports will be less frequent.
+ improve testing effectiveness but progress reports will be less frequent.
Minor bug fixes.
@@ -701,7 +715,7 @@
to produce a network bootable ELF image.
Re-wrote the memory and cache speed detection code. Previously the
- reported numbers were inaccurate for intel CPU's and completely wrong
+ reported numbers were inaccurate for Intel CPU's and completely wrong
for Athlon/Duron CPU's.
By default the serial console is disabled since this was slowing
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/README.background
^
|
@@ -0,0 +1,156 @@
+ The Anatomy & Physiology of Memtest86-SMP
+ -----------------------------------------
+
+1. Binary layout
+
+ ---------------------------------------------------------------
+ | bootsect.o | setup.o | head.o memtest_shared |
+ ---------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ -----------------------------------------------------------
+addr 0 512 512+4*512 |
+ -----------------------------------------------------------
+
+2. The following steps occur after we power on.
+ a. The bootsect.o code gets loaded at 0x7c00
+ and copies
+ i. itself to 0x90000
+ ii. setup.o to 0x90200
+ iii. everything between _start and _end i.e memtest
+ to 0x10000
+ b. jumps somewhere into the copied bootsect.o code at 0x90000
+ ,does some trivial stuff and jumps to setup.o
+ c. setup.o puts the processor in protected mode, with a basic
+ gdt and idt and does a long jump to the start of the
+ memtest code (startup_32, see 4 below). The code and data
+ segment base address are all set to 0x0. So a linear
+ address range and no paging is enabled.
+ d. From now on we no longer required the bootsect.o and setup.o
+ code.
+3. The code in memtest is compiled as position independent
+ code. Which implies that the code can be moved dynamically in
+ the address space and can still work. Since we are now in head.o,
+ which is compiled with PIC , we no longer should use absolute
+ addresses references while accessing functions or globals.
+ All symbols are stored in a table called Global Offset Table(GOT)
+ and %ebx is set to point to the base of that table. So to get/set
+ the value of a symbol we need to read (%ebx + symbolOffsetIntoGOT) to
+ get the symbol value. For eg. if foo is global varible the assembly
+ code to store %eax value into foo will be changed from
+ mov %eax, foo
+ to
+ mov %eax, foo@GOTOFF(%ebx)
+4. (startup_32) The first step done in head.o is to change
+ the gdtr and idtr register values to point to the final(!)
+ gdt and ldt tables in head.o, since we can no longer use the
+ gdt and ldt tables in setup.o, and call the dynamic linker
+ stub in memtest_shared (see call _dl_start in head.S). This
+ dynamic linker stub relocates all the code in memtest w.r.t
+ the new base location i.e 0x1000. Finally we call the test_start()
+ 'C' routine.
+5. The test_start() C routine is the main routine which lets the BSP
+ bring up the APs from their halt state, relocate the code
+ (if necessary) to new address, move the APs to the newly
+ relocated address and execute the tests. The BSP is the
+ master which controls the execution of the APs, and mostly
+ it is the one which manupulates the global variables.
+ i. we change the stack to a private per cpu stack.
+ (this step happens every time we move to a new location)
+ ii. We kick start the APs in the system by
+ a. Putting a temporary real mode code
+ (_ap_trampoline_start - _ap_trampoline_protmode)
+ at 0x9000, which puts the AP in protected mode and jumps
+ to _ap_trampoline_protmode in head.o. The code in
+ _ap_trampoline_protmode calls start_32 in head.o which
+ reinitialises the AP's gdt and idt to point to the
+ final(!) gdt and idt. (see step 4 above)
+ b. Since the APs also traverse through the same initialisation
+ code(startup_32 in head.o), the APs also call test_start().
+ The APs just spin wait (see AP_SpinWaitStart) till the
+ are instructed by the BSP to jump to a new location,
+ which can either be a test execution or spin wait at a
+ new location.
+ iii. The base address at which memtest tries to execute as far
+ as possible is 0x2000. This is the lowest possible address
+ memtest can put itself at. So the next step is to
+ move to 0x2000, which it cannot directly, since copying
+ code to 0x2000 will override the existing code at 0x1000.
+ 0x2000 +sizeof(memtest) will usually be greater than 0x1000.
+ so we temporarily relocated to 0x200000 and then relocate
+ back to 0x2000. Every time the BSP relocates the code to the
+ new location, it pulls up the APs spin waiting at the old
+ location to spin wait at the corresponding relocated
+ spin wait location, by making them jump to the new
+ statup_32 relocated location(see 4 above).
+ Hence forth during the tests 0x200000 is the only place
+ we relocate to if we need to test a memory window
+ (see v. below to get a description of what a window is)
+ which includes address range 0x2000.
+
+ Address map during normal execution.
+ --------------------------------------------------------------------
+ | head.o memtest_shared | |RAM_END
+ --------------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ --------------------------------------------------------------------
+addr 0x0 0x2000 | Memory that is being tested.. |RAM_END
+ --------------------------------------------------------------------
+
+ Address map during relocated state.
+ --------------------------------------------------------------------
+ | head.o memtest_shared | |RAM_END
+ --------------------------------------------------------------------
+Labels _start<-------memtest---------->_end
+ --------------------------------------------------------------------
+addr memory that is being tested... |0x200000 | |RAM_END
+ --------------------------------------------------------------------
+
+ iv. Once we are at 0x2000 we initialise the system, and
+ determine the memory map ,usually via the bios e820 map.
+ The sorted, and non-overlapping RAM page ranges are
+ placed in v->pmap[] array. This array is the reference
+ of the RAM memory map on the system.
+ v. The memory range(in page numbers) which the
+ memtest86 can test is partitioned into windows.
+ the current version of memtest86-smp has the capability
+ to test the memory from 0x0 - 0xFFFFFFFFF (max address
+ when pae mode is enabled).
+ We then compute the linear memory address ranges(called
+ segments) for the window we are currently about to
+ test. The windows are
+ a. 0 - 640K
+ b. (0x2000 + (_end - _start)) - 4G (since the code is at 0x2000).
+ c. >4G to test pae address range, each window with size
+ of 0x80000(2G), large enough to be mapped in one page directory
+ entry. So a window size of 0x80000 means we can map 1024 page
+ table entries, with page size of 2M(pae mode), with one
+ page directory entry. Something similar to kseg entry
+ in linux. The upper bound page number is 0x1000000 which
+ corresponds to linear address 0xFFFFFFFFF + 1 which uses
+ all the 36 address bits.
+ Each window is compared against the sorted & non-overlapping
+ e820 map which we have stored in v->pmap[] array, since all
+ memory in the selected window address range may correspond to
+ RAM or can be usable. A list of segments within the window is
+ created , which contain the usable portions of the window.
+ This is stored in v->mmap[] array.
+ vi. Once the v->mmap[] array populated, we have the list of
+ non-overlapping segments in the current window which are the
+ final address ranges that can be tested. The BSP executes the
+ test first and lets each AP execute the test one by one. Once
+ all the APs finish execting the same test, the BSP moves to the
+ next window follows the same procedure till all the windows
+ are done. Once all the windows are done, the BSP moves to the
+ next test. Before executing in any window the BSP checks if
+ the window overlaps with the code/data of memtest86, if so
+ tries to relocate to 0x200000. If the window includes both
+ 0x2000 as well as 0x200000 the BSP skips that window.
+ Looking at the window values the only time the memtest
+ relocates is when testing the 0 - 640K window.
+
+Known Issues:
+* Memtest86-smp does not work on IBM-NUMA machines, x440 and friends.
+
+email comments to:
+Kalyan Rajasekharuni<kc_rajasekharuni@yahoo.com>
+Sub: Memtest86-SMP
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/bootsect.S
^
|
@@ -1,375 +1,383 @@
-/*
- * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
- *
- * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
- * itself out of the way to address 0x90000, and jumps there.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts.
- *
- * The loader has been made as simple as possible, and continuos
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole tracks at a time whenever possible.
- *
- * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86.
- */
-
-#include "defs.h"
-
-ROOT_DEV = 0
-
-.code16
-.section ".bootsect", "ax", @progbits
-_boot:
-
-
-# ld86 requires an entry symbol. This may as well be the usual one.
-.globl _main
-_main:
- movw $BOOTSEG, %ax
- movw %ax, %ds
- movw $INITSEG, %ax
- movw %ax, %es
- movw $256, %cx
- subw %si, %si
- subw %di, %di
- cld
- rep
- movsw
- ljmp $INITSEG, $go - _boot
-
-go:
- movw %cs, %ax
- movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of
- # bootsect + length of setup + room for stack
- # 12 is disk parm size
-
-# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
-# wouldn't have to worry about this if we checked the top of memory. Also
-# my BIOS can be configured to put the wini drive tables in high memory
-# instead of in the vector table. The old stack might have clobbered the
-# drive table.
-
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss # put stack at INITSEG:0x4000-12.
- movw %dx, %sp
-
-/*
- * Many BIOS's default disk parameter tables will not
- * recognize multi-sector reads beyond the maximum sector number
- * specified in the default diskette parameter tables - this may
- * mean 7 sectors in some cases.
- *
- * Since single sector reads are slow and out of the question,
- * we must take care of this by creating new parameter tables
- * (for the first disk) in RAM. We will set the maximum sector
- * count to 18 - the most we will encounter on an HD 1.44.
- *
- * High doesn't hurt. Low does.
- *
- * Segments are as follows: ds=es=ss=cs - INITSEG,
- * fs = 0, gs = parameter table segment
- */
- pushw $0
- popw %fs
- movw $0x78, %bx # fs:bx is parameter table address
- lgs %fs:(%bx),%si # gs:si is source
-
- movw %dx, %di # es:di is destination
- movw $6, %cx # copy 12 bytes
- cld
-
- rep movsw %gs:(%si), (%di)
-
- movw %dx, %di
- movb $18, 4(%di) # patch sector count
-
- movw %di, %fs:(%bx)
- movw %es, %fs:2(%bx)
-
- movw %cs, %ax
- movw %ax, %fs
- movw %ax, %gs
-
- xorb %ah, %ah # reset FDC
- xorb %dl, %dl
- int $0x13
-
-# load the setup-sectors directly after the bootblock.
-# Note that 'es' is already set up.
-
-load_setup:
- xorw %dx, %dx # drive 0, head 0
- movw $0x0002, %cx # sector 2, track 0
- movw $0x0200, %bx # address = 512, in INITSEG
- movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors
- # (assume all on head 0, track 0)
- int $0x13 # read it
- jnc ok_load_setup # ok - continue
-
- pushw %ax # dump error code
- call print_nl
- movw %sp, %bp
- call print_hex
- popw %ax
-
- xorb %dl, %dl # reset FDC
- xorb %ah, %ah
- int $0x13
- jmp load_setup
-
-ok_load_setup:
-
-# Get disk drive parameters, specifically nr of sectors/track
-
-
-/* It seems that there is no BIOS call to get the number of sectors. Guess
- * 18 sectors if sector 18 can be read, 15 if sector 15 can be read.
- * Otherwise guess 9
- */
-
- xorw %dx, %dx # drive 0, head 0
- movw $0x0012, %cx # sector 18, track 0
- movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs)
- movw $0x0201, %ax # service 2, 1 sector
- int $0x13
- jnc got_sectors
- movb $0x0f, %cl # sector 15
- movw $0x0201, %ax # service 2, 1 sector
- int $0x13
- jnc got_sectors
- movb $0x09, %cl
-
-got_sectors:
- movw %cx, %cs:sectors - _boot
- movw $INITSEG, %ax
- movw %ax, %es
-
-# Print some inane message
-
- movb $0x03, %ah # read cursor pos
- xorb %bh, %bh
- int $0x10
-
- movw $9, %cx
- movw $0x0007, %bx # page 0, attribute 7 (normal)
- movw $msg1 - _boot, %bp
- movw $0x1301, %ax # write string, move cursor
- int $0x10
-
-# ok, we've written the message, now
-# we want to load the system (at 0x10000)
-
- movw $TSTLOAD, %ax
- movw %ax, %es # segment of 0x010000
- call read_it
- call kill_motor
- call print_nl
-
-# after that (everyting loaded), we jump to
-# the setup-routine loaded directly after
-# the bootblock:
-
- ljmp $SETUPSEG,$0
-
-# This routine loads the system at address 0x10000, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-#
-# in: es - starting address segment (normally 0x1000)
-#
-sread: .word 1+SETUPSECS # sectors read of current track
-head: .word 0 # current head
-track: .word 0 # current track
-
-read_it:
- movw %es, %ax
- testw $0x0fff, %ax
-die:
- jne die # es must be at 64kB boundary
- xorw %bx,%bx # bx is starting address within segment
-rp_read:
- movw %es, %ax
- subw $TSTLOAD, %ax # have we loaded all yet?
- cmpw syssize - _boot, %ax
- jbe ok1_read
- ret
-ok1_read:
- movw %cs:sectors - _boot, %ax
- subw sread - _boot, %ax
- movw %ax, %cx
- shlw $9, %cx
- addw %bx, %cx
- jnc ok2_read
- je ok2_read
- xorw %ax, %ax
- subw %bx, %ax
- shrw $9, %ax
-ok2_read:
- call read_track
- movw %ax, %cx
- add sread - _boot, %ax
- cmpw %cs:sectors - _boot, %ax
- jne ok3_read
- movw $1, %ax
- subw head - _boot, %ax
- jne ok4_read
- incw track - _boot
-ok4_read:
- movw %ax, head - _boot
- xorw %ax, %ax
-ok3_read:
- movw %ax, sread - _boot
- shlw $9, %cx
- addw %cx, %bx
- jnc rp_read
- movw %es, %ax
- addb $0x10, %ah
- movw %ax, %es
- xorw %bx, %bx
- jmp rp_read
-
-read_track:
- pusha
- pusha
- movw $0xe2e, %ax # loading... message 2e = .
- movw $7, %bx
- int $0x10
- popa
-
- movw track - _boot, %dx
- movw sread - _boot, %cx
- incw %cx
- movb %dl, %ch
- movw head - _boot, %dx
- movb %dl, %dh
- andw $0x0100, %dx
- movb $2, %ah
-
- pushw %dx # save for error dump
- pushw %cx
- pushw %bx
- pushw %ax
-
- int $0x13
- jc bad_rt
- addw $8, %sp
- popa
- ret
-
-bad_rt:
- pushw %ax # save error code
- call print_all # ah = error, al = read
-
- xorb %ah, %ah
- xorb %dl, %dl
- int $0x13
-
- addw $10, %sp
- popa
- jmp read_track
-
-/*
- * print_all is for debugging purposes.
- * It will print out all of the registers. The assumption is that this is
- * called from a routine, with a stack frame like
- * dx
- * cx
- * bx
- * ax
- * error
- * ret <- sp
- *
-*/
-
-print_all:
- movw $5, %cx # error code + 4 registers
- movw %sp, %bp
-
-print_loop:
- pushw %cx # save count left
- call print_nl # nl for readability
-
- cmpb 5, %cl # see if register name is needed
- jae no_reg
-
- movw $(0xe05 + 'A' - 1), %ax
- subb %cl, %al
- int $0x10
- movb $'X', %al
- int $0x10
- movb $':', %al
- int $0x10
-
-no_reg:
- addw $2, %bp # next register
- call print_hex # print it
- popw %cx
- loop print_loop
- ret
-
-print_nl:
- movw $0xe0d, %ax # CR
- int $0x10
- movb $0x0a, %al # LF
- int $0x10
- ret
-
-/*
- * print_hex is for debugging purposes, and prints the word
- * pointed to by ss:bp in hexadecmial.
-*/
-
-print_hex:
- movw $4, %cx # 4 hex digits
- movw (%bp), %dx # load word into dx
-
-print_digit:
- rolw $4, %dx # rotate so that lowest 4 bits are used
- movb $0xe, %ah
- movb %dl, %al # mask off so we have only next nibble
- andb $0xf, %al
- addb $'0', %al # convert to 0-based digit
- cmpb $'9', %al # check for overflow
- jbe good_digit
- addb $('A' - '0' - 10), %al
-
-good_digit:
- int $0x10
- loop print_digit
- ret
-
-
-/*
- * This procedure turns off the floppy drive motor, so
- * that we enter the kernel in a known state, and
- * don't have to worry about it later.
- */
-kill_motor:
- pushw %dx
- movw $0x3f2, %dx
- xorb %al, %al
- outb %al, %dx
- popw %dx
- ret
-
-sectors:
- .word 0
-
-msg1:
- .byte 13,10
- .ascii "Loading"
-
-.org 497
-setup_sects:
- .byte SETUPSECS
-.org 500
-syssize:
- .word _syssize
-.org 508
-root_dev:
- .word ROOT_DEV
-boot_flag:
- .word 0xAA55
-_eboot:
+/*
+ * bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
+ * itself out of the way to address 0x90000, and jumps there.
+ *
+ * It then loads 'setup' directly after itself (0x90200), and the system
+ * at 0x10000, using BIOS interrupts.
+ *
+ * The loader has been made as simple as possible, and continuos
+ * read errors will result in a unbreakable loop. Reboot by hand. It
+ * loads pretty fast by getting whole tracks at a time whenever possible.
+ *
+ * 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86.
+ */
+
+#include "defs.h"
+
+ROOT_DEV = 0
+
+.code16
+.section ".bootsect", "ax", @progbits
+_boot:
+
+
+# ld86 requires an entry symbol. This may as well be the usual one.
+.globl _main
+_main:
+ movw $BOOTSEG, %ax
+ movw %ax, %ds
+ movw $INITSEG, %ax
+ movw %ax, %es
+ movw $256, %cx
+ subw %si, %si
+ subw %di, %di
+ cld
+ rep
+ movsw
+ ljmp $INITSEG, $go - _boot
+
+go:
+ movw %cs, %ax
+ movw $(0x4000-12), %dx # 0x4000 is arbitrary value >= length of
+ # bootsect + length of setup + room for stack
+ # 12 is disk parm size
+
+# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
+# wouldn't have to worry about this if we checked the top of memory. Also
+# my BIOS can be configured to put the wini drive tables in high memory
+# instead of in the vector table. The old stack might have clobbered the
+# drive table.
+
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss # put stack at INITSEG:0x4000-12.
+ movw %dx, %sp
+
+/*
+ * Many BIOS's default disk parameter tables will not
+ * recognize multi-sector reads beyond the maximum sector number
+ * specified in the default diskette parameter tables - this may
+ * mean 7 sectors in some cases.
+ *
+ * Since single sector reads are slow and out of the question,
+ * we must take care of this by creating new parameter tables
+ * (for the first disk) in RAM. We will set the maximum sector
+ * count to 18 - the most we will encounter on an HD 1.44.
+ *
+ * High doesn't hurt. Low does.
+ *
+ * Segments are as follows: ds=es=ss=cs - INITSEG,
+ * fs = 0, gs = parameter table segment
+ */
+ pushw $0
+ popw %fs
+ movw $0x78, %bx # fs:bx is parameter table address
+ lgs %fs:(%bx),%si # gs:si is source
+
+ movw %dx, %di # es:di is destination
+ movw $6, %cx # copy 12 bytes
+ cld
+
+ rep movsw %gs:(%si), (%di)
+
+ movw %dx, %di
+ movb $18, 4(%di) # patch sector count
+
+ movw %di, %fs:(%bx)
+ movw %es, %fs:2(%bx)
+
+ movw %cs, %ax
+ movw %ax, %fs
+ movw %ax, %gs
+
+ xorb %ah, %ah # reset FDC
+ xorb %dl, %dl
+ int $0x13
+
+# load the setup-sectors directly after the bootblock.
+# Note that 'es' is already set up.
+
+load_setup:
+ xorw %dx, %dx # drive 0, head 0
+ movw $0x0002, %cx # sector 2, track 0
+ movw $0x0200, %bx # address = 512, in INITSEG
+ movw $(0x0200 + SETUPSECS), %ax # service 2, nr of sectors
+ # (assume all on head 0, track 0)
+ int $0x13 # read it
+ jnc ok_load_setup # ok - continue
+
+ pushw %ax # dump error code
+ call print_nl
+ movw %sp, %bp
+ call print_hex
+ popw %ax
+
+ xorb %dl, %dl # reset FDC
+ xorb %ah, %ah
+ int $0x13
+ jmp load_setup
+
+ok_load_setup:
+
+# Get disk drive parameters, specifically nr of sectors/track
+
+
+/* It seems that there is no BIOS call to get the number of sectors. Guess
+ * 18 sectors if sector 18 can be read, 15 if sector 15 can be read.
+ * Otherwise guess 9
+ */
+
+ xorw %dx, %dx # drive 0, head 0
+ movw $0x0012, %cx # sector 18, track 0
+ movw $(0x200+(SETUPSECS*0x200)), %bx # address after setup (es = cs)
+ movw $0x0201, %ax # service 2, 1 sector
+ int $0x13
+ jnc got_sectors
+ movb $0x0f, %cl # sector 15
+ movw $0x0201, %ax # service 2, 1 sector
+ int $0x13
+ jnc got_sectors
+ movb $0x09, %cl
+
+got_sectors:
+ movw %cx, %cs:sectors - _boot
+ movw $INITSEG, %ax
+ movw %ax, %es
+
+# Print some inane message
+
+ movb $0x03, %ah # read cursor pos
+ xorb %bh, %bh
+ int $0x10
+
+ movw $9, %cx
+ movw $0x0007, %bx # page 0, attribute 7 (normal)
+ movw $msg1 - _boot, %bp
+ movw $0x1301, %ax # write string, move cursor
+ int $0x10
+
+# ok, we've written the message, now
+# we want to load the system (at 0x10000)
+
+ movw $TSTLOAD, %ax
+ movw %ax, %es # segment of 0x010000
+ call read_it
+ call kill_motor
+ call turnoffcursor
+ call print_nl
+
+# after that (everyting loaded), we jump to
+# the setup-routine loaded directly after
+# the bootblock:
+
+ ljmp $SETUPSEG,$0
+
+# This routine loads the system at address 0x10000, making sure
+# no 64kB boundaries are crossed. We try to load it as fast as
+# possible, loading whole tracks whenever we can.
+#
+# in: es - starting address segment (normally 0x1000)
+#
+sread: .word 1+SETUPSECS # sectors read of current track
+head: .word 0 # current head
+track: .word 0 # current track
+
+read_it:
+ movw %es, %ax
+ testw $0x0fff, %ax
+die:
+ jne die # es must be at 64kB boundary
+ xorw %bx,%bx # bx is starting address within segment
+rp_read:
+ movw %es, %ax
+ subw $TSTLOAD, %ax # have we loaded all yet?
+ cmpw syssize - _boot, %ax
+ jbe ok1_read
+ ret
+ok1_read:
+ movw %cs:sectors - _boot, %ax
+ subw sread - _boot, %ax
+ movw %ax, %cx
+ shlw $9, %cx
+ addw %bx, %cx
+ jnc ok2_read
+ je ok2_read
+ xorw %ax, %ax
+ subw %bx, %ax
+ shrw $9, %ax
+ok2_read:
+ call read_track
+ movw %ax, %cx
+ add sread - _boot, %ax
+ cmpw %cs:sectors - _boot, %ax
+ jne ok3_read
+ movw $1, %ax
+ subw head - _boot, %ax
+ jne ok4_read
+ incw track - _boot
+ok4_read:
+ movw %ax, head - _boot
+ xorw %ax, %ax
+ok3_read:
+ movw %ax, sread - _boot
+ shlw $9, %cx
+ addw %cx, %bx
+ jnc rp_read
+ movw %es, %ax
+ addb $0x10, %ah
+ movw %ax, %es
+ xorw %bx, %bx
+ jmp rp_read
+
+read_track:
+ pusha
+ pusha
+ movw $0xe2e, %ax # loading... message 2e = .
+ movw $7, %bx
+ int $0x10
+ popa
+
+ movw track - _boot, %dx
+ movw sread - _boot, %cx
+ incw %cx
+ movb %dl, %ch
+ movw head - _boot, %dx
+ movb %dl, %dh
+ andw $0x0100, %dx
+ movb $2, %ah
+
+ pushw %dx # save for error dump
+ pushw %cx
+ pushw %bx
+ pushw %ax
+
+ int $0x13
+ jc bad_rt
+ addw $8, %sp
+ popa
+ ret
+
+bad_rt:
+ pushw %ax # save error code
+ call print_all # ah = error, al = read
+
+ xorb %ah, %ah
+ xorb %dl, %dl
+ int $0x13
+
+ addw $10, %sp
+ popa
+ jmp read_track
+
+/*
+ * print_all is for debugging purposes.
+ * It will print out all of the registers. The assumption is that this is
+ * called from a routine, with a stack frame like
+ * dx
+ * cx
+ * bx
+ * ax
+ * error
+ * ret <- sp
+ *
+*/
+
+print_all:
+ movw $5, %cx # error code + 4 registers
+ movw %sp, %bp
+
+print_loop:
+ pushw %cx # save count left
+ call print_nl # nl for readability
+
+ cmpb 5, %cl # see if register name is needed
+ jae no_reg
+
+ movw $(0xe05 + 'A' - 1), %ax
+ subb %cl, %al
+ int $0x10
+ movb $'X', %al
+ int $0x10
+ movb $':', %al
+ int $0x10
+
+no_reg:
+ addw $2, %bp # next register
+ call print_hex # print it
+ popw %cx
+ loop print_loop
+ ret
+
+print_nl:
+ movw $0xe0d, %ax # CR
+ int $0x10
+ movb $0x0a, %al # LF
+ int $0x10
+ ret
+
+/*
+ * print_hex is for debugging purposes, and prints the word
+ * pointed to by ss:bp in hexadecmial.
+ */
+
+print_hex:
+ movw $4, %cx # 4 hex digits
+ movw (%bp), %dx # load word into dx
+
+print_digit:
+ rolw $4, %dx # rotate so that lowest 4 bits are used
+ movb $0xe, %ah
+ movb %dl, %al # mask off so we have only next nibble
+ andb $0xf, %al
+ addb $'0', %al # convert to 0-based digit
+ cmpb $'9', %al # check for overflow
+ jbe good_digit
+ addb $('A' - '0' - 10), %al
+
+good_digit:
+ int $0x10
+ loop print_digit
+ ret
+
+
+/*
+ * This procedure turns off the floppy drive motor, so
+ * that we enter the kernel in a known state, and
+ * don't have to worry about it later.
+ */
+kill_motor:
+ pushw %dx
+ movw $0x3f2, %dx
+ xorb %al, %al
+ outb %al, %dx
+ popw %dx
+ ret
+
+turnoffcursor:
+ movb $0x01, %ah # turn off the cursor
+ movb $0x00, %bh
+ movw $0x2000, %cx
+ int $0x10
+ ret
+
+sectors:
+ .word 0
+
+msg1:
+ .byte 13,10
+ .ascii "Loading"
+
+.org 497
+setup_sects:
+ .byte SETUPSECS
+.org 500
+syssize:
+ .word _syssize
+.org 508
+root_dev:
+ .word ROOT_DEV
+boot_flag:
+ .word 0xAA55
+_eboot:
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/config.c
^
|
@@ -9,13 +9,14 @@
*/
#include "test.h"
#include "screen_buffer.h"
-#include "controller.h"
extern int bail;
extern struct tseq tseq[];
extern short e820_nr;
-extern char memsz_mode;
void performance();
+extern volatile short cpu_mode;
+extern volatile int test;
+extern void find_chunks();
char save[2][POP_H][POP_W];
char save2[2][POP2_H][POP2_W];
@@ -29,17 +30,13 @@
popup();
wait_keyup();
while(!flag) {
- cprint(POP_Y+1, POP_X+2, "Configuration:");
+ cprint(POP_Y+1, POP_X+2, "Settings:");
cprint(POP_Y+3, POP_X+6, "(1) Test Selection");
cprint(POP_Y+4, POP_X+6, "(2) Address Range");
- cprint(POP_Y+5, POP_X+6, "(3) Memory Sizing");
- cprint(POP_Y+6, POP_X+6, "(4) Error Report Mode");
- cprint(POP_Y+7, POP_X+6, "(5) Show DMI Memory Info");
- cprint(POP_Y+8, POP_X+6, "(6) ECC Mode");
- cprint(POP_Y+9, POP_X+6, "(7) Restart w/Defaults");
- cprint(POP_Y+10, POP_X+6, "(8) Redraw Screen");
- cprint(POP_Y+11, POP_X+6, "(9) Adv. Options");
- cprint(POP_Y+12,POP_X+6,"(0) Continue");
+ cprint(POP_Y+5, POP_X+6, "(3) Error Report Mode");
+ cprint(POP_Y+6, POP_X+6, "(4) CPU Selection Mode");
+ cprint(POP_Y+7, POP_X+6, "(5) Refresh Screen");
+ cprint(POP_Y+9,POP_X+6,"(0) Continue");
/* Wait for key release */
/* Fooey! This nuts'es up the serial input. */
@@ -52,7 +49,6 @@
cprint(POP_Y+3, POP_X+6, "(1) Default Tests");
cprint(POP_Y+4, POP_X+6, "(2) Skip Current Test");
cprint(POP_Y+5, POP_X+6, "(3) Select Test");
- cprint(POP_Y+6, POP_X+6, "(4) Select Bit Fade Test");
cprint(POP_Y+7, POP_X+6, "(0) Cancel");
if (v->testsel < 0) {
cprint(POP_Y+3, POP_X+5, ">");
@@ -68,9 +64,9 @@
bail++;
}
v->testsel = -1;
- find_ticks();
+ find_ticks_for_pass();
sflag++;
- cprint(LINE_INFO, COL_TST, "Std");
+ cprint(LINE_INFO, 43, "Std");
break;
case 3:
/* Skip test */
@@ -83,33 +79,21 @@
cprint(POP_Y+1, POP_X+3,
"Test Selection:");
cprint(POP_Y+4, POP_X+5,
- "Test Number [0-9]: ");
+ "Test Number [0-11]: ");
i = getval(POP_Y+4, POP_X+24, 0);
- if (i <= 9) {
+ if (i <= 11) {
if (i != v->testsel) {
v->pass = -1;
- v->test = -1;
+ test = -1;
}
v->testsel = i;
+ find_ticks_for_pass();
+ sflag++;
+ bail++;
+ cprint(LINE_INFO, 43, " #");
+ dprint(LINE_INFO, 43, i, 2, 0);
}
- find_ticks();
- sflag++;
- bail++;
- cprint(LINE_INFO, COL_TST, "#");
- dprint(LINE_INFO, COL_TST+1, i, 2, 1);
break;
- case 5:
- if (v->testsel != 9) {
- v->pass = -1;
- v->test = -1;
- }
- v->testsel = 9;
- find_ticks();
- sflag++;
- bail++;
- cprint(LINE_INFO, COL_TST, "#");
- dprint(LINE_INFO, COL_TST+1, 9, 2, 1);
- break;
case 11:
case 57:
sflag++;
@@ -142,11 +126,12 @@
page = getval(POP_Y+6, POP_X+9, 12);
if (page + 1 <= v->plim_upper) {
v->plim_lower = page;
- v->test--;
+ test--;
bail++;
}
adj_mem();
- find_ticks();
+ find_chunks();
+ find_ticks_for_pass();
sflag++;
break;
case 3:
@@ -162,11 +147,12 @@
page = getval(POP_Y+6, POP_X+9, 12);
if (page - 1 >= v->plim_lower) {
v->plim_upper = page;
- v->test--;
bail++;
+ test--;
}
adj_mem();
- find_ticks();
+ find_chunks();
+ find_ticks_for_pass();
sflag++;
break;
case 4:
@@ -174,10 +160,11 @@
v->plim_lower = 0;
v->plim_upper =
v->pmap[v->msegs - 1].end;
- v->test--;
+ test--;
bail++;
adj_mem();
- find_ticks();
+ find_chunks();
+ find_ticks_for_pass();
sflag++;
break;
case 11:
@@ -190,53 +177,7 @@
popclear();
break;
case 4:
- /* 3 - Memory Sizing */
- popclear();
- cprint(POP_Y+1, POP_X+2, "Memory Sizing:");
- cprint(POP_Y+3, POP_X+6, "(1) BIOS - Std");
- if (e820_nr) {
- cprint(POP_Y+4, POP_X+6, "(2) BIOS - All");
- cprint(POP_Y+5, POP_X+6, "(3) Probe");
- cprint(POP_Y+6, POP_X+6, "(0) Continue");
- cprint(POP_Y+2+memsz_mode, POP_X+5, ">");
- } else {
- cprint(POP_Y+4, POP_X+6, "(3) Probe");
- cprint(POP_Y+5, POP_X+6, "(0) Cancel");
- if (memsz_mode == SZ_MODE_BIOS) {
- cprint(POP_Y+3, POP_X+5, ">");
- } else {
- cprint(POP_Y+4, POP_X+5, ">");
- }
- }
- wait_keyup();
- while (!sflag) {
- switch(get_key()) {
- case 2:
- memsz_mode = SZ_MODE_BIOS;
- wait_keyup();
- restart();
- break;
- case 3:
- memsz_mode = SZ_MODE_BIOS_RES;
- wait_keyup();
- restart();
- break;
- case 4:
- memsz_mode = SZ_MODE_PROBE;
- wait_keyup();
- restart();
- break;
- case 11:
- case 57:
- /* 0/CR - Continue */
- sflag++;
- break;
- }
- }
- popclear();
- break;
- case 5:
- /* 5 - Error Mode */
+ /* Error Mode */
popclear();
cprint(POP_Y+1, POP_X+2, "Printing Mode:");
cprint(POP_Y+3, POP_X+6, "(1) Error Summary");
@@ -285,34 +226,35 @@
}
popclear();
break;
- case 6:
- /* Display DMI Memory Info */
- pop2up();
- print_dmi_info();
- pop2down();
- break;
- case 7:
- /* 6 - ECC Polling Mode */
+ case 5:
+ /* CPU Mode */
popclear();
- cprint(POP_Y+1, POP_X+2, "ECC Polling Mode:");
- cprint(POP_Y+3, POP_X+6, "(1) Recommended");
- cprint(POP_Y+4, POP_X+6, "(2) On");
- cprint(POP_Y+5, POP_X+6, "(3) Off");
+ cprint(POP_Y+1, POP_X+2, "CPU Selection Mode:");
+ cprint(POP_Y+3, POP_X+6, "(1) Parallel (All)");
+ cprint(POP_Y+4, POP_X+6, "(2) Round Robin");
+ cprint(POP_Y+5, POP_X+6, "(3) Sequential");
cprint(POP_Y+6, POP_X+6, "(0) Cancel");
+ cprint(POP_Y+2+cpu_mode, POP_X+5, ">");
wait_keyup();
while(!sflag) {
switch(get_key()) {
case 2:
- set_ecc_polling(-1);
+ if (cpu_mode != CPM_ALL) bail++;
+ cpu_mode = CPM_ALL;
sflag++;
+ cprint(7,72,"All ");
break;
case 3:
- set_ecc_polling(1);
+ if (cpu_mode != CPM_RROBIN) bail++;
+ cpu_mode = CPM_RROBIN;
sflag++;
+ cprint(7,72,"RRobin");
break;
case 4:
- set_ecc_polling(0);
+ if (cpu_mode != CPM_SEQ) bail++;
+ cpu_mode = CPM_SEQ;
sflag++;
+ cprint(7,72,"Seq ");
break;
case 11:
case 57:
@@ -323,43 +265,10 @@
}
popclear();
break;
- case 8:
- wait_keyup();
- restart();
- break;
- case 9:
+ case 6:
reprint_screen = 1;
flag++;
break;
- case 10:
- /* 9 - Advanced Options */
- popclear();
- cprint(POP_Y+1, POP_X+2, "Advanced Options:");
- cprint(POP_Y+3, POP_X+6, "(1) Display SPD Info");
- cprint(POP_Y+4, POP_X+6, "(2) Modify Memory Timing");
- cprint(POP_Y+5, POP_X+6, "(0) Cancel");
- wait_keyup();
- while (!sflag) {
- switch(get_key()) {
- case 2:
- popdown();
- show_spd();
- popup();
- sflag++;
- break;
- case 3:
- get_menu();
- sflag++;
- break;
- case 11:
- case 57:
- /* 0/CR - Continue */
- sflag++;
- break;
- }
- }
- popclear();
- break;
case 11:
case 57:
case 28:
@@ -377,57 +286,6 @@
}
}
-void performance()
-{
- extern int l1_cache, l2_cache;
- ulong speed;
- int i;
-
- popclear();
- cprint(POP_Y+1, POP_X+1, " Read Write Copy");
- cprint(POP_Y+3, POP_X+1, "L1 Cache:");
- speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 50, MS_READ);
- dprint(POP_Y+3, POP_X+10, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 50, MS_WRITE);
- dprint(POP_Y+3, POP_X+17, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), (l1_cache/4)*1024, 50, MS_COPY);
- dprint(POP_Y+3, POP_X+24, speed, 6, 0);
-
- if (l2_cache < l1_cache) {
- i = l1_cache / 4 + l2_cache / 4;
- } else {
- i = l1_cache;
- }
- cprint(POP_Y+5, POP_X+1, "L2 Cache:");
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_READ);
- dprint(POP_Y+5, POP_X+10, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_WRITE);
- dprint(POP_Y+5, POP_X+17, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY);
- dprint(POP_Y+5, POP_X+24, speed, 6, 0);
-
- /* Determine memory speed. To find the memory spped we use */
- /* A block size that is 5x the sum of the L1 and L2 caches */
- i = (l2_cache + l1_cache) * 5;
-
- /* Make sure that we have enough memory to do the test */
- if ((1 + (i * 2)) > (v->plim_upper << 2)) {
- i = ((v->plim_upper <<2) - 1) / 2;
- }
- cprint(POP_Y+7, POP_X+1, "Memory:");
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_READ);
- dprint(POP_Y+7, POP_X+10, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_WRITE);
- dprint(POP_Y+7, POP_X+17, speed, 6, 0);
- speed=memspeed((ulong)mapping(0x100), i*1024, 50, MS_COPY);
- dprint(POP_Y+7, POP_X+24, speed, 6, 0);
-
- wait_keyup();
- while (get_key() == 0);
- popclear();
-}
-
-
void popup()
{
int i, j;
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/config.h
^
|
@@ -15,13 +15,11 @@
/* to enable. */
#define SERIAL_CONSOLE_DEFAULT 0
-/* SERIAL_BAUD_RATE - Baud rate for the serial console
- * If this is not defined it is assumed a previous program has set the
- * baud rate, and the baud rate is preserved.
- */
-/*
+/* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1 */
+#define SERIAL_TTY 0
+
+/* SERIAL_BAUD_RATE - Baud rate for the serial console */
#define SERIAL_BAUD_RATE 9600
-*/
/* SCRN_DEBUG - extra check for SCREEN_BUFFER
*/
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/cpuid.c
^
|
@@ -0,0 +1,74 @@
+/*
+ * cpuid.c --
+ *
+ * Implements CPUID querying functions
+ *
+ */
+#include "stdin.h"
+#include "cpuid.h"
+
+struct cpu_ident cpu_id;
+
+void get_cpuid()
+{
+ unsigned int *v, dummy[3];
+ char *p, *q;
+
+ /* Get the largest CPUID number and vendor ID */
+ cpuid(0x00000000, &cpu_id.max_cpuid, &cpu_id.vend_id.uint32_array[0],
+ &cpu_id.vend_id.uint32_array[2], &cpu_id.vend_id.uint32_array[1]);
+ cpu_id.vend_id.char_array[11] = 0;
+
+ /* Get the largest CPUID */
+ cpuid(0x80000000, &cpu_id.max_cpuid, &dummy[0], &dummy[1], &dummy[2]);
+
+ /* Get processor family information */
+ if (cpu_id.max_cpuid >= 1) {
+ cpuid(1, &cpu_id.vers.flat, &cpu_id.info.flat,
+ &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]);
+ }
+
+ /* Get the brand ID */
+ if (cpu_id.max_cpuid >= 4) {
+ v = (unsigned int *)&cpu_id.brand_id;
+ cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+ cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+ cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+ cpu_id.brand_id.char_array[47] = 0;
+ }
+ /*
+ * Intel chips right-justify this string for some dumb reason;
+ * undo that brain damage:
+ */
+ p = q = &cpu_id.brand_id.char_array[0];
+ while (*p == ' ')
+ p++;
+ if (p != q) {
+ while (*p)
+ *q++ = *p++;
+ while (q <= &cpu_id.brand_id.char_array[48])
+ *q++ = '\0'; /* Zero-pad the rest */
+ }
+
+ /* Get cache information */
+ switch(cpu_id.vend_id.char_array[0]) {
+ case 'A':
+ /* AMD Processors */
+ /* The cache information is only in ecx and edx so only save
+ * those registers */
+ if (cpu_id.max_cpuid >= 0x80000005) {
+ cpuid(0x80000005, &dummy[0], &dummy[1],
+ &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]);
+ }
+ if (cpu_id.max_cpuid >= 0x80000006) {
+ cpuid(0x80000006, &dummy[0], &dummy[1],
+ &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]);
+ }
+ break;
+ case 'G':
+ /* Intel Processors */
+ v = (unsigned int *)&cpu_id.cache_info.uint;
+ cpuid(2, &v[0], &v[1], &v[2], &v[3]);
+ break;
+ }
+}
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/cpuid.h
^
|
@@ -0,0 +1,195 @@
+/*
+ * cpuid.h --
+ * contains the data structures required for CPUID
+ * implementation.
+ */
+
+#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */
+#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
+#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */
+#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
+
+static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ /* ecx is often an input as well as an output. */
+ asm volatile("\t"
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (*eax),
+ "=D" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx));
+}
+
+static inline void cpuid(unsigned int op,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = 0;
+ __cpuid(eax, ebx, ecx, edx);
+}
+
+/* Typedef for storing the Cache Information */
+typedef union {
+ unsigned char ch[16];
+ uint32_t uint[4];
+ struct {
+ uint32_t fill1:24; /* Bit 0 */
+ uint32_t l1_i_sz:8;
+ uint32_t fill2:24;
+ uint32_t l1_d_sz:8;
+ uint32_t fill3:16;
+ uint32_t l2_sz:16;
+ uint32_t fill4:18;
+ uint32_t l3_sz:14;
+ } amd;
+} cpuid_cache_info_t;
+
+/* Typedef for storing the CPUID Vendor String */
+typedef union {
+ /* Note: the extra byte in the char array is for '\0'. */
+ char char_array[CPUID_VENDOR_STR_LENGTH];
+ uint32_t uint32_array[CPUID_VENDOR_LENGTH];
+} cpuid_vendor_string_t;
+
+/* Typedef for storing the CPUID Brand String */
+typedef union {
+ /* Note: the extra byte in the char array is for '\0'. */
+ char char_array[CPUID_BRAND_STR_LENGTH];
+ uint32_t uint32_array[CPUID_BRAND_LENGTH];
+} cpuid_brand_string_t;
+
+/* Typedef for storing CPUID Version */
+typedef union {
+ uint32_t flat;
+ struct {
+ uint32_t stepping:4; /* Bit 0 */
+ uint32_t model:4;
+ uint32_t family:4;
+ uint32_t processorType:2;
+ uint32_t reserved1514:2;
+ uint32_t extendedModel:4;
+ uint32_t extendedFamily:8;
+ uint32_t reserved3128:4; /* Bit 31 */
+ } bits;
+} cpuid_version_t;
+
+/* Typedef for storing CPUID Processor Information */
+typedef union {
+ uint32_t flat;
+ struct {
+ uint32_t brandIndex:8; /* Bit 0 */
+ uint32_t cflushLineSize:8;
+ uint32_t logicalProcessorCount:8;
+ uint32_t apicID:8; /* Bit 31 */
+ } bits;
+} cpuid_proc_info_t;
+
+/* Typedef for storing CPUID Feature flags */
+typedef union {
+ uint64_t flat;
+ uint32_t uint32_array[2];
+ struct {
+ uint32_t fpu:1; /* Bit 0 */
+ uint32_t vme:1;
+ uint32_t de:1;
+ uint32_t pse:1;
+ uint32_t tsc:1;
+ uint32_t msr:1;
+ uint32_t pae:1;
+ uint32_t mce:1;
+ uint32_t cx8:1;
+ uint32_t apic:1;
+ uint32_t reserved10:1;
+ uint32_t sep:1;
+ uint32_t mtrr:1;
+ uint32_t pge:1;
+ uint32_t mca:1;
+ uint32_t cmov:1;
+ uint32_t pat:1;
+ uint32_t pse36:1;
+ uint32_t psn:1;
+ uint32_t cflush:1;
+ uint32_t reserved20:1;
+ uint32_t ds:1;
+ uint32_t acpi:1;
+ uint32_t mmx:1;
+ uint32_t fxsr:1;
+ uint32_t sse:1;
+ uint32_t sse2:1;
+ uint32_t ss:1;
+ uint32_t htt:1;
+ uint32_t tm:1;
+ uint32_t reserved30:1;
+ uint32_t pbe:1; /* Bit 31 */
+ uint32_t sse3:1; /* Bit 32 */
+ uint32_t reserved3433:2;
+ uint32_t monitor:1;
+ uint32_t dscpl:1;
+ uint32_t reserved3937:3;
+ uint32_t tm2:1;
+ uint32_t reserved41:1;
+ uint32_t cnxtid:1;
+ uint32_t reserved4443:2;
+ uint32_t cmpxchg16b:1;
+ uint32_t reserved6346:18; /* Bit 63 */
+ } bits;
+} cpuid_feature_flags_t;
+
+/* Feature flags returned by extended CPUID node function 8000_0001. */
+typedef union {
+ uint64_t flat;
+ uint32_t uint32_array[2];
+ struct {
+ uint32_t fpu:1; /* Bit 0 */
+ uint32_t vme:1;
+ uint32_t de:1;
+ uint32_t pse:1;
+ uint32_t tsc:1;
+ uint32_t msr:1;
+ uint32_t pae:1;
+ uint32_t mce:1;
+ uint32_t cx8:1;
+ uint32_t apic:1;
+ uint32_t reserved10:1;
+ uint32_t sep:1;
+ uint32_t mtrr:1;
+ uint32_t pge:1;
+ uint32_t mca:1;
+ uint32_t cmov:1;
+ uint32_t pat:1;
+ uint32_t pse36:1;
+ uint32_t reserved1918:2;
+ uint32_t nx:1;
+ uint32_t reserved21:1;
+ uint32_t mmxamd:1;
+ uint32_t mmx:1;
+ uint32_t fxsr:1;
+ uint32_t ffxsr:1;
+ uint32_t reserved26:1;
+ uint32_t rdtscp:1;
+ uint32_t reserved28:1;
+ uint32_t lm:1;
+ uint32_t threedeenowext:1;
+ uint32_t threedeenow:1; /* Bit 31 */
+ uint32_t lahf:1; /* Bit 32 */
+ uint32_t cmplegacy:1;
+ uint32_t reserved3534:2;
+ uint32_t cr8avail:1;
+ uint32_t reserved6337:27; /* Bit 63 */
+ } bits;
+} cpuid_ext_feature_flags_t;
+
+/* An overall structure to cache all of the CPUID information */
+struct cpu_ident {
+ uint32_t max_cpuid;
+ cpuid_version_t vers;
+ cpuid_proc_info_t info;
+ cpuid_feature_flags_t fid;
+ cpuid_vendor_string_t vend_id;
+ cpuid_brand_string_t brand_id;
+ cpuid_cache_info_t cache_info;
+};
+
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/defs.h
^
|
@@ -13,7 +13,7 @@
* Unlike earlier versions all of the settings are in defs.h
* so the build process should be more robust.
*/
-#define LOW_TEST_ADR 0x00002000 /* Final adrs for test code */
+#define LOW_TEST_ADR 0x00010000 /* Final adrs for test code */
#define BOOTSEG 0x07c0 /* Segment adrs for inital boot */
#define INITSEG 0x9000 /* Segment adrs for relocated boot */
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/error.c
^
|
@@ -3,13 +3,15 @@
* Released under version 2 of the Gnu Public License.
* By Chris Brady
*/
+#include "stddef.h"
#include "test.h"
#include "config.h"
+#include "smp.h"
+extern struct barrier_s *barr;
extern int test_ticks, nticks;
extern struct tseq tseq[];
-extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
-extern short dmi_initialized;
+extern volatile int test;
void poll_errors();
static void update_err_counts(void);
@@ -24,6 +26,7 @@
{
ulong xor;
+ spin_lock(&barr->mutex);
xor = good ^ bad;
#ifdef USB_WAR
/* Skip any errrors that appear to be due to the BIOS using location
@@ -36,6 +39,7 @@
}
#endif
common_err(adr, good, bad, xor, 0);
+ spin_unlock(&barr->mutex);
}
/*
@@ -45,7 +49,9 @@
*/
void ad_err1(ulong *adr1, ulong *mask, ulong bad, ulong good)
{
+ spin_lock(&barr->mutex);
common_err(adr1, good, bad, (ulong)mask, 1);
+ spin_unlock(&barr->mutex);
}
/*
@@ -55,7 +61,9 @@
*/
void ad_err2(ulong *adr, ulong bad)
{
+ spin_lock(&barr->mutex);
common_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad, 0);
+ spin_unlock(&barr->mutex);
}
static void update_err_counts(void)
@@ -65,7 +73,7 @@
" ");
}
++(v->ecount);
- tseq[v->test].errors++;
+ tseq[test].errors++;
}
@@ -76,8 +84,10 @@
if ((v->ecount > 4096) && (v->ecount % 256 != 0)) return;
- dprint(LINE_INFO, COL_ERR, v->ecount, 6, 0);
- dprint(LINE_INFO, COL_ECC_ERR, v->ecc_ecount, 6, 0);
+ dprint(LINE_INFO, 70, v->ecount, 6, 0);
+/*
+ dprint(LINE_INFO, 56, v->ecc_ecount, 6, 0);
+*/
/* Paint the error messages on the screen red to provide a vivid */
/* indicator that an error has occured */
@@ -96,13 +106,12 @@
*/
void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
{
- int i, n, x, j, flag=0;
+ int i, n, x, flag=0;
ulong page, offset;
int patnchg;
ulong mb;
update_err_counts();
- add_dmi_err((ulong)adr);
switch(v->printmode) {
case PRINTMODE_SUMMARY:
@@ -190,23 +199,7 @@
cprint(LINE_HEADER+4, 1, " Bits in Error - Total:");
cprint(LINE_HEADER+4, 29, "Min: Max: Avg:");
cprint(LINE_HEADER+5, 1, " Max Contiguous Errors:");
- cprint(LINE_HEADER+6, 1, "ECC Correctable Errors:");
- cprint(LINE_HEADER+7, 1, "Errors per Memory Slot:");
x = 24;
- if (dmi_initialized) {
- for ( i=0; i < MAX_DMI_MEMDEVS;){
- n = LINE_HEADER+7;
- for (j=0; j<4; j++) {
- if (dmi_err_cnts[i] >= 0) {
- dprint(n, x, i, 2, 0);
- cprint(n, x+2, ": 0");
- }
- i++;
- n++;
- }
- x += 10;
- }
- }
cprint(LINE_HEADER+0, 64, "Test Errors");
v->erri.hdr_flag++;
@@ -241,17 +234,6 @@
dprint(LINE_HEADER+4, 50, v->erri.tbits/v->ecount, 2, 1);
dprint(LINE_HEADER+5, 25, v->erri.maxl, 7, 1);
x = 28;
- for ( i=0; i < MAX_DMI_MEMDEVS;){
- n = LINE_HEADER+7;
- for (j=0; j<4; j++) {
- if (dmi_err_cnts[i] > 0) {
- dprint (n, x, dmi_err_cnts[i], 7, 1);
- }
- i++;
- n++;
- }
- x += 10;
- }
for (i=0; tseq[i].msg != NULL; i++) {
dprint(LINE_HEADER+1+i, 66, i, 2, 0);
@@ -272,7 +254,7 @@
if (v->erri.hdr_flag == 0) {
clear_scroll();
cprint(LINE_HEADER, 0,
-"Tst Pass Failing Address Good Bad Err-Bits Count Chan");
+"Tst Pass Failing Address Good Bad Err-Bits Count CPU");
cprint(LINE_HEADER+1, 0,
"--- ---- ----------------------- -------- -------- -------- ----- ----");
v->erri.hdr_flag++;
@@ -289,7 +271,7 @@
offset = ((unsigned long)adr) & 0xFFF;
}
mb = page >> 8;
- dprint(v->msg_line, 0, v->test, 3, 0);
+ dprint(v->msg_line, 0, test, 3, 0);
dprint(v->msg_line, 4, v->pass, 5, 0);
hprint(v->msg_line, 11, page);
hprint2(v->msg_line, 19, offset, 3);
@@ -311,6 +293,7 @@
hprint(v->msg_line, 46, bad);
hprint(v->msg_line, 56, xor);
dprint(v->msg_line, 66, v->ecount, 5, 0);
+ dprint(v->msg_line, 74, smp_my_cpu_num(), 2,1);
v->erri.exor = xor;
}
v->erri.eadr = (ulong)adr;
@@ -323,7 +306,7 @@
v->erri.hdr_flag++;
}
/* Do not do badram patterns from test 0 or 5 */
- if (v->test == 0 || v->test == 5) {
+ if (test == 0 || test == 5) {
return;
}
/* Only do patterns for data errors */
@@ -366,7 +349,7 @@
{
unsigned long addr;
- if (v->test == 5) {
+ if (test == 5) {
addr = esi;
} else {
addr = edi;
@@ -413,10 +396,32 @@
/*
* Show progress by displaying elapsed time and update bar graphs
*/
-void do_tick(void)
+short spin_idx[MAX_CPUS];
+char spin[4] = {'|','/','-','\\'};
+
+void do_tick(int me)
{
- int i, n, pct;
- ulong h, l, t;
+ int i, pct;
+ ulong h, l, n, t;
+ extern int mstr_cpu;
+
+ if (++spin_idx[me] > 3) {
+ spin_idx[me] = 0;
+ }
+ cplace(8, 2*me+7, spin[spin_idx[me]]);
+
+ /* Check for keyboard input */
+ if (me == mstr_cpu) {
+ check_input();
+ }
+ /* A barrier here holds the other CPUs until the configuration
+ * changes are done */
+ s_barrier();
+
+ /* Only the first selected CPU does the update */
+ if (me != mstr_cpu) {
+ return;
+ }
/* FIXME only print serial error messages from the tick handler */
if (v->ecount) {
@@ -426,25 +431,39 @@
nticks++;
v->total_ticks++;
- pct = 100*nticks/test_ticks;
- dprint(1, COL_MID+4, pct, 3, 0);
+ if (test_ticks) {
+ pct = 100*nticks/test_ticks;
+ if (pct > 100) {
+ pct = 100;
+ }
+ } else {
+ pct = 0;
+ }
+ dprint(2, COL_MID+4, pct, 3, 0);
i = (BAR_SIZE * pct) / 100;
while (i > v->tptr) {
if (v->tptr >= BAR_SIZE) {
break;
}
- cprint(1, COL_MID+9+v->tptr, "#");
+ cprint(2, COL_MID+9+v->tptr, "#");
v->tptr++;
}
- pct = 100*v->total_ticks/v->pass_ticks;
- dprint(0, COL_MID+4, pct, 3, 0);
+ if (v->pass_ticks) {
+ pct = 100*v->total_ticks/v->pass_ticks;
+ if (pct > 100) {
+ pct = 100;
+ }
+ } else {
+ pct = 0;
+ }
+ dprint(1, COL_MID+4, pct, 3, 0);
i = (BAR_SIZE * pct) / 100;
while (i > v->pptr) {
if (v->pptr >= BAR_SIZE) {
break;
}
- cprint(0, COL_MID+9+v->pptr, "#");
+ cprint(1, COL_MID+9+v->pptr, "#");
v->pptr++;
}
@@ -468,7 +487,7 @@
}
pct += n*3;
} else {
- for (i=0, n=0; i<v->test; i++) {
+ for (i=0, n=0; i<test; i++) {
if (tseq[i].errors == 0) {
n++;
}
@@ -515,21 +534,20 @@
t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
t += (l / v->clks_msec) / 1000;
i = t % 60;
- dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0);
- dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0);
+ dprint(LINE_INFO, COL_INF1-2, i%10, 1, 0);
+ dprint(LINE_INFO, COL_INF1-3, i/10, 1, 0);
t /= 60;
i = t % 60;
- dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0);
- dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0);
+ dprint(LINE_INFO, COL_INF1-5, i % 10, 1, 0);
+ dprint(LINE_INFO, COL_INF1-6, i / 10, 1, 0);
t /= 60;
- dprint(LINE_TIME, COL_TIME, t, 4, 0);
+ dprint(LINE_INFO, COL_INF1-11, t, 4, 0);
}
- /* Check for keyboard input */
- check_input();
-
/* Poll for ECC errors */
+/*
poll_errors();
+*/
}
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/head.S
^
|
@@ -17,31 +17,17 @@
#include "config.h"
#include "test.h"
-/*
- * References to members of the boot_cpu_data structure.
- */
-#define CPU_PARAMS cpu_id
-#define X86 0
-#define X86_MODEL 1
-#define X86_MASK 2
-#define X86_CPUID 4
-#define X86_CAPABILITY 8
-#define X86_VENDOR_ID 12
-#define X86_CACHE 24
-#define X86_PWRCAP 40
-#define X86_EXT 44
-
.code32
.globl startup_32
startup_32:
cld
cli
- /* Ensure I have a stack pointer */
+ /* Ensure I have a boot_stack pointer */
testl %esp, %esp
jnz 0f
movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp
- leal stack_top@GOTOFF(%esp), %esp
+ leal boot_stack_top@GOTOFF(%esp), %esp
0:
/* Load the GOT pointer */
@@ -49,8 +35,8 @@
0: popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx
- /* Pick the appropriate stack address */
- leal stack_top@GOTOFF(%ebx), %esp
+ /* Pick the appropriate boot_stack address */
+ leal boot_stack_top@GOTOFF(%ebx), %esp
/* Reload all of the segment registers */
leal gdt@GOTOFF(%ebx), %eax
@@ -84,23 +70,7 @@
zerobss_done:
/*
- * Clear the video display
- */
- cmpl $1, clear_display@GOTOFF(%ebx)
- jnz clear_display_done
- movw $0x0720, %ax
- movl $0xb8000, %edi
- movl $0xc0000, %ecx
-1: movw %ax, (%edi)
- addl $2, %edi
- cmpl %ecx, %edi
- jnz 1b
- movl $0, clear_display@GOTOFF(%ebx)
-clear_display_done:
-
-
-/*
- * Setup and exception handler
+ * Setup an exception handler
*/
leal idt@GOTOFF(%ebx), %edi
@@ -269,183 +239,10 @@
movl %eax, 2 + idt_descr@GOTOFF(%ebx)
lidt idt_descr@GOTOFF(%ebx)
-/* Find out the CPU type */
-
- leal cpu_id@GOTOFF(%ebx), %esi
- movl %ebx, %edi
-
- movl $-1, X86_CPUID(%esi) # -1 for no CPUID initially
-
-/* check if it is 486 or 386. */
-
- movl $3, X86(%esi) # at least 386
- pushfl # push EFLAGS
- popl %eax # get EFLAGS
- movl %eax, %ecx # save original EFLAGS
- xorl $0x40000, %eax # flip AC bit in EFLAGS
- pushl %eax # copy to EFLAGS
- popfl # set EFLAGS
- pushfl # get new EFLAGS
- popl %eax # put it in eax
- xorl %ecx, %eax # change in flags
- andl $0x40000, %eax # check if AC bit changed
- je id_done
-
- movl $4, X86(%esi) # at least 486
- movl %ecx, %eax
- xorl $0x200000, %eax # check ID flag
- pushl %eax
- popfl # if we are on a straight 486DX, SX, or
- pushfl # 487SX we can't change it
- popl %eax
- xorl %ecx, %eax
- pushl %ecx # restore original EFLAGS
- popfl
- andl $0x200000, %eax
- jne have_cpuid
-
- /* Test for Cyrix CPU types */
- xorw %ax, %ax # clear ax
- sahf # clear flags
- movw $5, %ax
- movw $2, %bx
- div %bl # do operation that does not change flags
- lahf # get flags
- cmp $2, %ah # check for change in flags
- jne id_done # if not Cyrix
- movl $2, X86(%esi) # Use two to identify as Cyrix
- jmp id_done
-
-have_cpuid:
- /* get vendor info */
- xorl %eax, %eax # call CPUID with 0 -> return vendor ID
- cpuid
- movl %eax, X86_CPUID(%esi) # save CPUID level
- movl %ebx, X86_VENDOR_ID(%esi) # first 4 chars
- movl %edx, X86_VENDOR_ID+4(%esi) # next 4 chars
- movl %ecx, X86_VENDOR_ID+8(%esi) # last 4 chars
-
- orl %eax, %eax # do we have processor info as well?
- je id_done
-
- movl $1, %eax # Use the CPUID instruction to get CPU type
- cpuid
-
-
- #
- # CDH start
- # Check FPU, initialize if present
- #
- testl $1, %edx # FPU available?
- jz no_fpu
- finit
-
- no_fpu:
- #
- # CDH end
- #
-
- movl %eax, X86_EXT(%esi) #save complete extended CPUID to X86_EXT
- movb %al, %cl # save reg for future use
- andb $0x0f, %ah # mask processor family
- movb %ah, X86(%esi)
- andb $0xf0, %al # mask model
- shrb $4, %al
- movb %al, X86_MODEL(%esi)
- andb $0x0f, %cl # mask mask revision
- movb %cl, X86_MASK(%esi)
- movl %edx, X86_CAPABILITY(%esi)
-
- movl $0, X86_CACHE(%esi)
- movl $0, X86_CACHE+4(%esi)
- movl $0, X86_CACHE+8(%esi)
- movl $0, X86_CACHE+12(%esi)
-
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x6c65746e,%eax # Is this an Intel CPU? "GenuineIntel"
- jne not_intel
- movb %bl, X86_PWRCAP(%esi) # Store BrandID in AMD PWRCAP if the CPU is from Intel
- movl $2, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %eax, X86_CACHE(%esi)
- movl %ebx, X86_CACHE+4(%esi)
- movl %ecx, X86_CACHE+8(%esi)
- movl %edx, X86_CACHE+12(%esi)
- jmp id_done
-
-not_intel:
- movl X86_VENDOR_ID+8(%esi),%eax
- cmpl $0x444d4163, %eax # Is this an AMD CPU? "AuthenticAMD"
- jne not_amd
-
- movl $0x80000005, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %ecx, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006,%eax # Use the CPUID instruction to get cache info
- cpuid
- movl %ecx,X86_CACHE+8(%esi)
- movl $0x80000007,%eax # Use the CPUID instruction to get AMD Powercap
- cpuid
- movl %edx,X86_PWRCAP(%esi)
-
-not_amd:
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x3638784D, %eax # Is this a Transmeta CPU? "GenuineTMx86"
- jne not_transmeta
-
- movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
- cpuid
- cmp $6, %al # Is cache info available?
- jb id_done
-
- movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
- cpuid
- movl %ecx, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, X86_CACHE+8(%esi)
-
-not_transmeta:
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x64616574, %eax # Is this a Via/Cyrix CPU? "CyrixInstead"
- jne not_cyrix
-
- movl X86_CPUID(%esi), %eax # get CPUID level
- cmpl $2, %eax # Is there cache information available ?
- jne id_done
-
- movl $2, %eax # Use the CPUID instruction to get cache info
- cpuid
- movl %edx, X86_CACHE(%esi)
-
-not_cyrix:
- movl X86_VENDOR_ID+8(%esi), %eax
- cmpl $0x736C7561, %eax # Is this a Via/Centaur CPU "CentaurHauls"
- jne not_centaur
-
- movl $0x80000000, %eax # Use the CPUID instruction to check for cache info
- cpuid
- cmp $6, %al # Is cache info available?
- jb id_done
-
- movl $0x80000005, %eax # Use the CPUID instruction to get L1 cache info
- cpuid
- movl %ecx, X86_CACHE(%esi)
- movl %edx, X86_CACHE+4(%esi)
- movl $0x80000006, %eax # Use the CPUID instruction to get L2 cache info
- cpuid
- movl %ecx, X86_CACHE+8(%esi)
-
-
-not_centaur:
-id_done:
- movl %edi, %ebx /* Restore GOT pointer */
-
leal _dl_start@GOTOFF(%ebx), %eax
call *%eax
- call do_test
+
+ call test_start
/* In case we return simulate an exception */
pushfl
pushl %cs
@@ -562,11 +359,13 @@
pushl %esi
pushl %ebp
- /* original stack pointer */
+ /* original boot_stack pointer */
leal 20(%esp), %eax
pushl %eax
- pushl %esp /* pointer to structure on the stack */
+ pushl %esp /* pointer to structure on the boot_stack */
+ pushl %ds
+ pushl %ss
call inter
addl $8, %esp
@@ -738,8 +537,8 @@
movl %eax, %fs
movl %eax, %gs
- /* Compute the stack base */
- leal stack@GOTOFF(%ebx), %ecx
+ /* Compute the boot_stack base */
+ leal boot_stack@GOTOFF(%ebx), %ecx
/* Compute the address of meminfo */
leal mem_info@GOTOFF(%ebx), %edi
@@ -768,7 +567,7 @@
movw %ax, %gs
movw %ax, %ss
- /* Adjust the stack pointer */
+ /* Adjust the boot_stack pointer */
movl %ecx, %eax
shrl $4, %eax
movw %ax, %ss
@@ -941,8 +740,8 @@
movl %eax, %gs
movl %eax, %ss
- /* Adjust the stack pointer */
- leal stack@GOTOFF(%ebx), %eax
+ /* Adjust the boot_stack pointer */
+ leal boot_stack@GOTOFF(%ebx), %eax
addl %eax, %esp
/* Restore the caller saved registers */
@@ -964,9 +763,45 @@
.word 0x400 - 1 # idt limit ( 256 entries)
.word 0, 0 # idt base = 0L
+/* _ap_trampoline_start is the entry point for cpus other than the
+ * bootstrap cpu. The code between _ap_trampoline_start to
+ * _ap_trampoline_protmode is copied to BootCodeStart(0x9000).
+ * The ljmp after turning on CR0.PE will jump to the
+ * relocatable code which usually resides at 0x10000 + _ap_trampoline_protmode.
+ *
+ * The trampoline code uses a temporary GDT. The entries of this temporary
+ * GDT must match the first few entries of the GDT used by the relocatble
+ * memtest code(see 'gdt' sybmol in this file).
+ *
+ */
+ .globl _ap_trampoline_start
+ .globl _ap_trampoline_protmode
+ .code16
+_ap_trampoline_start:
+ lgdt 0x0 /* will be fixed up later, see smp.c:BootAP()*/
+ movl %cr0, %eax
+ orl $1, %eax
+ movl %eax, %cr0
+ data32 ljmp $KERNEL_CS, $_ap_trampoline_protmode
+_ap_trampoline_protmode:
+ .code32
+ movw $KERNEL_DS, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+ movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp
+ leal boot_stack_top@GOTOFF(%esp), %esp
+ pushl $0
+ popf
+ call startup_32
+ /* if we ever return, we'll just loop forever */
+ cli
+2: hlt
+ jmp 2b
.data
zerobss: .long 1
-clear_display: .long 1
.previous
.data
.balign 16
@@ -976,7 +811,9 @@
.previous
.bss
.balign 16
-stack:
+boot_stack:
+ .globl boot_stack
. = . + 4096
-stack_top:
+boot_stack_top:
+ .globl boot_stack_top
.previous
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/init.c
^
|
@@ -1,4 +1,4 @@
-/* init.c - MemTest-86 Version 3.4
+/* init.c - MemTest-86 Version 3.6
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
@@ -8,30 +8,33 @@
* http://www.x86-secret.com - http://www.memtest.org
*/
+#include "stddef.h"
+#include "stdin.h"
+#include "cpuid.h"
#include "test.h"
#include "defs.h"
#include "config.h"
-#include "controller.h"
-#include "pci.h"
+#include "smp.h"
#include "io.h"
extern struct tseq tseq[];
extern short memsz_mode;
-extern short firmware;
-extern short dmi_initialized;
-extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
-
-int l1_cache=0, l2_cache=0;
-struct cpu_ident cpu_id;
-ulong st_low, st_high;
-ulong end_low, end_high;
-ulong cal_low, cal_high;
+extern int num_cpus;
+extern int found_cpus;
+
+/* Here we store all of the cpuid data */
+extern struct cpu_ident cpu_id;
+
+int l1_cache=0, l2_cache=0, l3_cache=0;
+int tsc_invariable = 0;
ulong extclock;
-ulong memspeed(ulong src, ulong len, int iter, int type);
+ulong memspeed(ulong src, ulong len, int iter);
static void cpu_type(void);
-static void cacheable(void);
static int cpuspeed(void);
+static void get_cache_size();
+static void cpu_cache_speed();
+void get_cpuid();
static void display_init(void)
{
@@ -55,7 +58,8 @@
for(i=0, pp=(char *)(SCREEN_ADR+1); i<TITLE_WIDTH; i++, pp+=2) {
*pp = 0x47;
}
- cprint(0, 0, " Memtest-86 v3.4 ");
+
+ cprint(0, 0, " Memtest-86 v4.0 ");
/* Do reverse video for the bottom display line */
for(i=0, pp=(char *)(SCREEN_ADR+1+(24 * 160)); i<80; i++, pp+=2) {
@@ -79,28 +83,41 @@
/* Setup the display */
display_init();
-
- /* Determine the memory map */
- if ((firmware == FIRMWARE_UNKNOWN) &&
- (memsz_mode != SZ_MODE_PROBE)) {
- if (query_linuxbios()) {
- firmware = FIRMWARE_LINUXBIOS;
- }
- else if (query_pcbios()) {
- firmware = FIRMWARE_PCBIOS;
- }
+ cprint(1, COL_MID,"Pass %");
+ cprint(2, COL_MID,"Test %");
+ cprint(3, COL_MID,"Test #");
+ cprint(4, COL_MID,"Testing: ");
+ cprint(5, COL_MID,"Pattern: ");
+ cprint(1, 0, "CPU Clk : ");
+ cprint(2, 0, "L1 Cache: Unknown ");
+ cprint(3, 0, "L2 Cache: Unknown ");
+ cprint(4, 0, "L3 Cache: None ");
+ cprint(5, 0, "Memory : ");
+ cprint(6, 0, "------------------------------------------------------------------------------");
+ cprint(7, 0, "CPU:");
+ cprint(8, 0, "State:");
+ cprint(7, 39, "| CPUs_Started: CPU_Select: All");
+ cprint(8, 39, "| CPUs_Active: CPUs_Found: ");
+ for (i = 0; i <num_cpus; i++) {
+ dprint(7, 2*i+7, i, 1, 0);
+ cprint(8, 2*i+7, "S");
+ }
+ dprint(7, 54, num_cpus, 2, 0);
+ dprint(8, 72, found_cpus, 2, 0);
+ cprint(9, 0, "------------------------------------------------------------------------------");
+ for(i=1; i < 6; i++) {
+ cprint(i, COL_MID-2, "| ");
}
+ cprint(LINE_INFO, 0,
+"Time: 0:00:00 Iterations: Test_Sel: Std Pass: 0 Errors: 0");
+ footer();
- mem_size();
-
- /* setup pci */
- pci_init();
+ aprint(5, 10, v->test_pages);
- v->test = 0;
- v->pass = 0;
- v->msg_line = 0;
- v->ecount = 0;
- v->ecc_ecount = 0;
+ v->pass = 0;
+ v->msg_line = 0;
+ v->ecount = 0;
+ v->ecc_ecount = 0;
v->testsel = -1;
v->msg_line = LINE_SCROLL-1;
v->scroll_start = v->msg_line * 160;
@@ -120,713 +137,423 @@
for (i=0; tseq[i].msg != NULL; i++) {
tseq[i].errors = 0;
}
- if (dmi_initialized) {
- for (i=0; i < MAX_DMI_MEMDEVS; i++){
- if (dmi_err_cnts[i] > 0) {
- dmi_err_cnts[i] = 0;
- }
- }
- }
- cprint(LINE_CPU+1, 0, "L1 Cache: Unknown ");
- cprint(LINE_CPU+2, 0, "L2 Cache: Unknown ");
- cprint(LINE_CPU+3, 0, "Memory : ");
- aprint(LINE_CPU+3, 10, v->test_pages);
- cprint(LINE_CPU+4, 0, "Chipset : ");
-
- /*
- * Need to find out CPU type before seting up pci. This is
- * because AMD Opterons dont have a host bridge on dev 0.
- */
- cpu_type();
+ /* Get the cpu and cache information */
+ get_cpuid();
- /* setup pci */
- pci_init();
+ get_cache_size();
- /* Find the memory controller */
- find_controller();
+ cpu_type();
- if (v->rdtsc) {
- cacheable();
- cprint(LINE_TIME, COL_TIME+4, ": :");
- }
- cprint(0, COL_MID,"Pass %");
- cprint(1, COL_MID,"Test %");
- cprint(2, COL_MID,"Test #");
- cprint(3, COL_MID,"Testing: ");
- cprint(4, COL_MID,"Pattern: ");
- cprint(LINE_INFO-2, 0, " WallTime Cached RsvdMem MemMap Cache ECC Test Pass Errors ECC Errs");
- cprint(LINE_INFO-1, 0, " --------- ------ ------- -------- ----- --- ---- ---- ------ --------");
- cprint(LINE_INFO, COL_TST, "Std");
- cprint(LINE_INFO, COL_PASS, " 0");
- cprint(LINE_INFO, COL_ERR, " 0");
- cprint(LINE_INFO+1, 0, " -----------------------------------------------------------------------------");
+ cpu_cache_speed();
- for(i=0; i < 5; i++) {
- cprint(i, COL_MID-2, "| ");
- }
- footer();
- v->printmode=PRINTMODE_SUMMARY;
+ /* Record the start time */
+ asm __volatile__ ("rdtsc":"=a" (v->startl),"=d" (v->starth));
+ v->snapl = v->startl;
+ v->snaph = v->starth;
+ if (l1_cache == 0) { l1_cache = 66; }
+ if (l2_cache == 0) { l1_cache = 666; }
+ v->printmode=PRINTMODE_ADDRESSES;
v->numpatn=0;
- find_ticks();
-}
-
-#define FLAT 0
-
-static unsigned long mapped_window = 1;
-void paging_off(void)
-{
- if (!v->pae)
- return;
- mapped_window = 1;
- __asm__ __volatile__ (
- /* Disable paging */
- "movl %%cr0, %%eax\n\t"
- "andl $0x7FFFFFFF, %%eax\n\t"
- "movl %%eax, %%cr0\n\t"
- /* Disable pae & pse */
- "movl %%cr4, %%eax\n\t"
- "and $0xCF, %%al\n\t"
- "movl %%eax, %%cr4\n\t"
- :
- :
- : "ax"
- );
}
-static void paging_on(void *pdp)
+/* Get cache sizes for most AMD and Intel CPUs, exceptions are handled
+ * during CPU detection */
+void get_cache_size()
{
- if (!v->pae)
- return;
- __asm__ __volatile__(
- /* Load the page table address */
- "movl %0, %%cr3\n\t"
- /* Enable pae */
- "movl %%cr4, %%eax\n\t"
- "orl $0x00000020, %%eax\n\t"
- "movl %%eax, %%cr4\n\t"
- /* Enable paging */
- "movl %%cr0, %%eax\n\t"
- "orl $0x80000000, %%eax\n\t"
- "movl %%eax, %%cr0\n\t"
- :
- : "r" (pdp)
- : "ax"
- );
-}
-
-int map_page(unsigned long page)
-{
- unsigned long i;
- struct pde {
- unsigned long addr_lo;
- unsigned long addr_hi;
- };
- extern unsigned char pdp[];
- extern struct pde pd2[];
- unsigned long window = page >> 19;
- if (FLAT || (window == mapped_window)) {
- return 0;
- }
- if (window == 0) {
- return 0;
- }
- if (!v->pae || (window >= 32)) {
- /* Fail either we don't have pae support
- * or we want an address that is out of bounds
- * even for pae.
- */
- return -1;
- }
- /* Compute the page table entries... */
- for(i = 0; i < 1024; i++) {
- /*-----------------10/30/2004 12:37PM---------------
- * 0xE3 --
- * Bit 0 = Present bit. 1 = PDE is present
- * Bit 1 = Read/Write. 1 = memory is writable
- * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2)
- * Bit 3 = Writethrough. 0 = writeback cache policy
- * Bit 4 = Cache Disable. 0 = page level cache enabled
- * Bit 5 = Accessed. 1 = memory has been accessed.
- * Bit 6 = Dirty. 1 = memory has been written to.
- * Bit 7 = Page Size. 1 = page size is 2 MBytes
- * --------------------------------------------------*/
- pd2[i].addr_lo = ((window & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3;
- pd2[i].addr_hi = (window >> 1);
- }
- paging_off();
- if (window > 1) {
- paging_on(pdp);
- }
- mapped_window = window;
- return 0;
-}
+ int i;
-void *mapping(unsigned long page_addr)
-{
- void *result;
- if (FLAT || (page_addr < 0x80000)) {
- /* If the address is less that 1GB directly use the address */
- result = (void *)(page_addr << 12);
- }
- else {
- unsigned long alias;
- alias = page_addr & 0x7FFFF;
- alias += 0x80000;
- result = (void *)(alias << 12);
+/* FIXME this should be vendor_id */
+ switch(cpu_id.vend_id.char_array[0]) {
+ /* AMD Processors */
+ case 'A':
+ l1_cache = cpu_id.cache_info.amd.l1_i_sz;
+ l1_cache += cpu_id.cache_info.amd.l1_d_sz;
+ l2_cache = cpu_id.cache_info.amd.l2_sz;
+ l3_cache = cpu_id.cache_info.amd.l3_sz;
+ l3_cache *= 512;
+ break;
+ case 'G':
+ /* Intel Processors */
+ if (cpu_id.vend_id.char_array[7] == 'I') {
+ for (i=0; i<16; i++) {
+ switch(cpu_id.cache_info.ch[i]) {
+ case 0x6:
+ case 0xa:
+ case 0x66:
+ l1_cache = 8;
+ break;
+ case 0x8:
+ case 0xc:
+ case 0x67:
+ case 0x60:
+ l1_cache = 16;
+ break;
+ case 0x9:
+ case 0xd:
+ case 0x68:
+ case 0x2c:
+ case 0x30:
+ l1_cache = 32;
+ break;
+ case 0x40:
+ l2_cache = 0;
+ break;
+ case 0x41:
+ case 0x79:
+ case 0x39:
+ case 0x3b:
+ l2_cache = 128;
+ break;
+ case 0x3a:
+ l2_cache = 192;
+ break;
+ case 0x21:
+ case 0x42:
+ case 0x7a:
+ case 0x82:
+ case 0x3c:
+ case 0x3f:
+ l2_cache = 256;
+ break;
+ case 0x3d:
+ l2_cache = 384;
+ break;
+ case 0x43:
+ case 0x7b:
+ case 0x83:
+ case 0x86:
+ case 0x3e:
+ case 0x7f:
+ case 0x80:
+ l2_cache = 512;
+ break;
+ case 0x44:
+ case 0x7c:
+ case 0x84:
+ case 0x87:
+ case 0x78:
+ l2_cache = 1024;
+ break;
+ case 0x45:
+ case 0x7d:
+ case 0x85:
+ l2_cache = 2048;
+ break;
+ case 0x48:
+ l2_cache = 3072;
+ break;
+ case 0x49:
+ l2_cache = 4096;
+ break;
+ case 0x4e:
+ l2_cache = 6144;
+ break;
+ case 0xd1:
+ case 0xd6:
+ l3_cache = 1024;
+ break;
+ case 0xd2:
+ case 0xd7:
+ case 0xdc:
+ case 0xe2:
+ l3_cache = 2048;
+ break;
+ case 0xd8:
+ case 0xdd:
+ case 0xe3:
+ l3_cache = 4096;
+ break;
+ case 0xde:
+ case 0xe4:
+ l3_cache = 8192;
+ break;
+ }
+ }
+ }
}
- return result;
}
-void *emapping(unsigned long page_addr)
-{
- void *result;
- result = mapping(page_addr -1);
- /* The result needs to be 256 byte alinged... */
- result = ((unsigned char *)result) + 0xf00;
- return result;
-}
-
-unsigned long page_of(void *addr)
-{
- unsigned long page;
- page = ((unsigned long)addr) >> 12;
- if (!FLAT && (page >= 0x80000)) {
- page &= 0x7FFFF;
- page += mapped_window << 19;
- }
-#if 0
- cprint(LINE_SCROLL -2, 0, "page_of( )-> ");
- hprint(LINE_SCROLL -2, 8, ((unsigned long)addr));
- hprint(LINE_SCROLL -2, 20, page);
-#endif
- return page;
-}
-
-
/*
- * Find CPU type and cache sizes
+ * Find CPU type
*/
void cpu_type(void)
{
- int i, off=0;
- ulong speed;
-
v->rdtsc = 0;
v->pae = 0;
-#ifdef CPUID_DEBUG
- dprint(11,0,cpu_id.type,3,1);
- dprint(12,0,cpu_id.model,3,1);
- dprint(13,0,cpu_id.cpuid,3,1);
-#endif
-
- /* If the CPUID instruction is not supported then this is */
- /* a 386, 486 or one of the early Cyrix CPU's */
- if (cpu_id.cpuid < 1) {
- switch (cpu_id.type) {
- case 2:
- /* This is a Cyrix CPU without CPUID */
- i = getCx86(0xfe);
- i &= 0xf0;
- i >>= 4;
- switch(i) {
- case 0:
- case 1:
- cprint(LINE_CPU, 0, "Cyrix Cx486");
- break;
- case 2:
- cprint(LINE_CPU, 0,"Cyrix 5x86");
- break;
- case 3:
- cprint(LINE_CPU, 0,"Cyrix 6x86");
- break;
- case 4:
- cprint(LINE_CPU, 0,"Cyrix MediaGX");
- break;
- case 5:
- cprint(LINE_CPU, 0,"Cyrix 6x86MX");
- break;
- case 6:
- cprint(LINE_CPU, 0,"Cyrix MII");
- break;
- default:
- cprint(LINE_CPU, 0,"Cyrix ???");
- break;
- }
- break;
- case 3:
- cprint(LINE_CPU, 0, "386");
- break;
+ /* See if we have pae support */
+ if (cpu_id.fid.bits.pae) {
+ v->pae = 1;
+ }
- case 4:
- cprint(LINE_CPU, 0, "486");
- l1_cache = 8;
- break;
- }
- return;
+ /* See if we have rdtsc nstruction support */
+ if (cpu_id.fid.bits.tsc) {
+ v->rdtsc = 1;
}
- /* We have cpuid so we can see if we have pae support */
- if (cpu_id.capability & (1 << X86_FEATURE_PAE)) {
- v->pae = 1;
+
+ /* If we can get a brand string use it, and we are done */
+ if (cpu_id.max_cpuid >= 4) {
+ cprint(0, COL_MID, cpu_id.brand_id.char_array);
+ return;
}
- switch(cpu_id.vend_id[0]) {
+
+ /* The brand string is not available so we need to figure out
+ * CPU what we have */
+ switch(cpu_id.vend_id.char_array[0]) {
/* AMD Processors */
case 'A':
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 4:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 3:
- cprint(LINE_CPU, 0, "AMD 486DX2");
+ cprint(0, COL_MID, "AMD 486DX2");
break;
case 7:
- cprint(LINE_CPU, 0, "AMD 486DX2-WB");
+ cprint(0, COL_MID, "AMD 486DX2-WB");
break;
case 8:
- cprint(LINE_CPU, 0, "AMD 486DX4");
+ cprint(0, COL_MID, "AMD 486DX4");
break;
case 9:
- cprint(LINE_CPU, 0, "AMD 486DX4-WB");
+ cprint(0, COL_MID, "AMD 486DX4-WB");
break;
case 14:
- cprint(LINE_CPU, 0, "AMD 5x86-WT");
+ cprint(0, COL_MID, "AMD 5x86-WT");
break;
case 15:
- cprint(LINE_CPU, 0, "AMD 5x86-WB");
+ cprint(0, COL_MID, "AMD 5x86-WB");
break;
}
/* Since we can't get CPU speed or cache info return */
return;
case 5:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
case 2:
case 3:
- cprint(LINE_CPU, 0, "AMD K5");
+ cprint(0, COL_MID, "AMD K5");
l1_cache = 8;
- off = 6;
break;
case 6:
case 7:
- cprint(LINE_CPU, 0, "AMD K6");
- off = 6;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
+ cprint(0, COL_MID, "AMD K6");
break;
case 8:
- cprint(LINE_CPU, 0, "AMD K6-2");
- off = 8;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
+ cprint(0, COL_MID, "AMD K6-2");
break;
case 9:
- cprint(LINE_CPU, 0, "AMD K6-III");
- off = 10;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ cprint(0, COL_MID, "AMD K6-III");
break;
case 13:
- cprint(LINE_CPU, 0, "AMD K6-III+");
- off = 11;
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
+ cprint(0, COL_MID, "AMD K6-III+");
break;
}
break;
case 6:
- /* Get L1 & L2 cache sizes */
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 1:
- cprint(LINE_CPU, 0, "AMD Athlon (0.25)");
- off = 17;
+ cprint(0, COL_MID, "AMD Athlon (0.25)");
break;
case 2:
case 4:
- cprint(LINE_CPU, 0, "AMD Athlon (0.18)");
- off = 17;
+ cprint(0, COL_MID, "AMD Athlon (0.18)");
break;
case 6:
if (l2_cache == 64) {
- cprint(LINE_CPU, 0, "AMD Duron (0.18)");
+ cprint(0, COL_MID, "AMD Duron (0.18)");
} else {
- cprint(LINE_CPU, 0, "Athlon XP (0.18)");
+ cprint(0, COL_MID, "Athlon XP (0.18)");
}
- off = 16;
break;
case 8:
case 10:
if (l2_cache == 64) {
- cprint(LINE_CPU, 0, "AMD Duron (0.13)");
+ cprint(0, COL_MID, "AMD Duron (0.13)");
} else {
- cprint(LINE_CPU, 0, "Athlon XP (0.13)");
+ cprint(0, COL_MID, "Athlon XP (0.13)");
}
- off = 16;
break;
case 3:
case 7:
- cprint(LINE_CPU, 0, "AMD Duron");
- off = 9;
+ cprint(0, COL_MID, "AMD Duron");
/* Duron stepping 0 CPUID for L2 is broken */
/* (AMD errata T13)*/
- if (cpu_id.step == 0) { /* stepping 0 */
+ if (cpu_id.vers.bits.stepping == 0) { /* stepping 0 */
/* Hard code the right L2 size */
l2_cache = 64;
} else {
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
}
break;
}
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
break;
- case 15:
- /* Get L1 & L2 cache sizes */
- l1_cache = cpu_id.cache_info[3];
- l1_cache += cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11] << 8);
- l2_cache += cpu_id.cache_info[10];
- switch(cpu_id.model) {
- default:
- cprint(LINE_CPU, 0, "AMD K8");
- off = 6;
- break;
- case 1:
- case 5:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- cprint(LINE_CPU, 0, "AMD Opteron (0.09)");
- } else {
- cprint(LINE_CPU, 0, "AMD Opteron (0.13)");
- }
- off = 18;
- break;
- case 3:
- case 11:
- cprint(LINE_CPU, 0, "Athlon 64 X2");
- off = 12;
- break;
- case 8:
- cprint(LINE_CPU, 0, "Turion 64 X2");
- off = 12;
- break;
- case 4:
- case 7:
- case 9:
- case 12:
- case 14:
- case 15:
- if (((cpu_id.ext >> 16) & 0xF) != 0) {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.09)");
- } else {
- cprint(LINE_CPU, 0, "Sempron (0.09)");
- }
- } else {
- if (l2_cache > 256) {
- cprint(LINE_CPU, 0, "Athlon 64 (0.13)");
- } else {
- cprint(LINE_CPU, 0, "Sempron (0.13)");
- }
- }
- off = 16;
- break;
- }
- break;
+ /* All AMD family values >= 10 have the Brand ID
+ * feature so we don't need to find the CPU type */
}
break;
/* Intel or Transmeta Processors */
case 'G':
- if ( cpu_id.vend_id[7] == 'T' ) { /* GenuineTMx86 */
- if (cpu_id.type == 5) {
- cprint(LINE_CPU, 0, "TM 5x00");
- off = 7;
- } else if (cpu_id.type == 15) {
- cprint(LINE_CPU, 0, "TM 8x00");
- off = 7;
+ if ( cpu_id.vend_id.char_array[7] == 'T' ) { /* GenuineTMx86 */
+ if (cpu_id.vers.bits.family == 5) {
+ cprint(0, COL_MID, "TM 5x00");
+ } else if (cpu_id.vers.bits.family == 15) {
+ cprint(0, COL_MID, "TM 8x00");
}
- l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7];
- l2_cache = (cpu_id.cache_info[11]*256) + cpu_id.cache_info[10];
+ l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7];
+ l2_cache = (cpu_id.cache_info.ch[11]*256) + cpu_id.cache_info.ch[10];
} else { /* GenuineIntel */
- if (cpu_id.type == 4) {
- switch(cpu_id.model) {
+ if (cpu_id.vers.bits.family == 4) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
- cprint(LINE_CPU, 0, "Intel 486DX");
- off = 11;
+ cprint(0, COL_MID, "Intel 486DX");
break;
case 2:
- cprint(LINE_CPU, 0, "Intel 486SX");
- off = 11;
+ cprint(0, COL_MID, "Intel 486SX");
break;
case 3:
- cprint(LINE_CPU, 0, "Intel 486DX2");
- off = 12;
+ cprint(0, COL_MID, "Intel 486DX2");
break;
case 4:
- cprint(LINE_CPU, 0, "Intel 486SL");
- off = 11;
+ cprint(0, COL_MID, "Intel 486SL");
break;
case 5:
- cprint(LINE_CPU, 0, "Intel 486SX2");
- off = 12;
+ cprint(0, COL_MID, "Intel 486SX2");
break;
case 7:
- cprint(LINE_CPU, 0, "Intel 486DX2-WB");
- off = 15;
+ cprint(0, COL_MID, "Intel 486DX2-WB");
break;
case 8:
- cprint(LINE_CPU, 0, "Intel 486DX4");
- off = 12;
+ cprint(0, COL_MID, "Intel 486DX4");
break;
case 9:
- cprint(LINE_CPU, 0, "Intel 486DX4-WB");
- off = 15;
+ cprint(0, COL_MID, "Intel 486DX4-WB");
break;
}
/* Since we can't get CPU speed or cache info return */
return;
}
- /* Get the cache info */
- for (i=0; i<16; i++) {
-#ifdef CPUID_DEBUG
- dprint(12,i*3,cpu_id.cache_info[i],2,1);
-#endif
- switch(cpu_id.cache_info[i]) {
- case 0x6:
- case 0xa:
- case 0x66:
- l1_cache += 8;
- break;
- case 0x8:
- case 0xc:
- case 0x67:
- case 0x60:
- l1_cache += 16;
- break;
- case 0x68:
- case 0x2c:
- case 0x30:
- l1_cache += 32;
- break;
- case 0x40:
- l2_cache = 0;
- break;
- case 0x41:
- case 0x79:
- case 0x39:
- case 0x3b:
- l2_cache = 128;
- break;
- case 0x3a:
- l2_cache = 192;
- break;
- case 0x42:
- case 0x7a:
- case 0x82:
- case 0x3c:
- l2_cache = 256;
- break;
- case 0x3d:
- l2_cache = 384;
- break;
- case 0x43:
- case 0x7b:
- case 0x83:
- case 0x86:
- case 0x3e:
- case 0x7f:
- l2_cache = 512;
- break;
- case 0x44:
- case 0x7c:
- case 0x84:
- case 0x87:
- case 0x78:
- l2_cache = 1024;
- break;
- case 0x45:
- case 0x7d:
- case 0x85:
- l2_cache = 2048;
- break;
- case 0x49:
- l2_cache = 4096;
- break;
- }
- }
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 5:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
case 2:
case 3:
case 7:
- cprint(LINE_CPU, 0, "Pentium");
+ cprint(0, COL_MID, "Pentium");
if (l1_cache == 0) {
l1_cache = 8;
}
- off = 7;
break;
case 4:
case 8:
- cprint(LINE_CPU, 0, "Pentium-MMX");
+ cprint(0, COL_MID, "Pentium-MMX");
if (l1_cache == 0) {
l1_cache = 16;
}
- off = 11;
break;
}
break;
case 6:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
- cprint(LINE_CPU, 0, "Pentium Pro");
- off = 11;
+ cprint(0, COL_MID, "Pentium Pro");
break;
case 3:
case 4:
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
+ cprint(0, COL_MID, "Pentium II");
break;
case 5:
if (l2_cache == 0) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
+ cprint(0, COL_MID, "Celeron");
} else {
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
+ cprint(0, COL_MID, "Pentium II");
}
break;
case 6:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
- } else {
- if (cpu_id.step == 0 || cpu_id.step == 5) {
- cprint(LINE_CPU, 0, "Celeron-A");
- off = 9;
- } else {
- cprint(LINE_CPU, 0, "Pentium II");
- off = 10;
- }
+ if (l2_cache == 128) {
+ cprint(0, COL_MID, "Celeron");
+ } else {
+ cprint(0, COL_MID, "Pentium II");
+ }
}
break;
case 7:
case 8:
- case 10:
case 11:
if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron");
- off = 7;
+ cprint(0, COL_MID, "Celeron");
} else {
- cprint(LINE_CPU, 0, "Pentium III");
- off = 11;
+ cprint(0, COL_MID, "Pentium III");
}
break;
case 9:
if (l2_cache == 512) {
- cprint(LINE_CPU, 0, "Celeron M (0.13)");
+ cprint(0, COL_MID, "Celeron M (0.13)");
} else {
- cprint(LINE_CPU, 0, "Pentium M (0.13)");
+ cprint(0, COL_MID, "Pentium M (0.13)");
}
- off = 16;
break;
+ case 10:
+ cprint(0, COL_MID, "Pentium III Xeon");
+ break;
+ case 12:
+ l1_cache = 24;
+ cprint(0, COL_MID, "Atom (0.045)");
+ break;
case 13:
if (l2_cache == 1024) {
- cprint(LINE_CPU, 0, "Celeron M (0.09)");
+ cprint(0, COL_MID, "Celeron M (0.09)");
} else {
- cprint(LINE_CPU, 0, "Pentium M (0.09)");
+ cprint(0, COL_MID, "Pentium M (0.09)");
}
- off = 16;
break;
case 14:
- cprint(LINE_CPU, 0, "Intel Core");
- off = 10;
+ cprint(0, COL_MID, "Intel Core");
break;
case 15:
- cprint(LINE_CPU, 0, "Intel Core 2");
- off = 12;
+ if (l2_cache == 1024) {
+ cprint(0, COL_MID, "Pentium E");
+ } else {
+ cprint(0, COL_MID, "Intel Core 2");
+ }
break;
}
break;
case 15:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
case 1:
- if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron (0.18)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.18)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.18)");
- off = 14;
- } else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.18)");
- off = 16;
- }
- break;
case 2:
if (l2_cache == 128) {
- cprint(LINE_CPU, 0, "Celeron (0.13)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.13)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.13)");
- off = 14;
+ cprint(0, COL_MID, "Celeron");
} else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.13)");
- off = 16;
+ cprint(0, COL_MID, "Pentium 4");
}
break;
case 3:
case 4:
if (l2_cache == 256) {
- cprint(LINE_CPU, 0, "Celeron (0.09)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0B) {
- cprint(LINE_CPU, 0, "Xeon DP (0.09)");
- off = 14;
- } else if (cpu_id.pwrcap == 0x0C) {
- cprint(LINE_CPU, 0, "Xeon MP (0.09)");
- off = 14;
- } else if ((cpu_id.step == 0x4 || cpu_id.step == 0x7) && cpu_id.model == 0x4) {
- cprint(LINE_CPU, 0, "Pentium D (0.09)");
- off = 16;
+ cprint(0, COL_MID, "Celeron (0.09)");
} else {
- cprint(LINE_CPU, 0, "Pentium 4 (0.09)");
- off = 16;
+ cprint(0, COL_MID, "Pentium 4 (0.09)");
}
break;
case 6:
- cprint(LINE_CPU, 0, "Pentium D (65nm)");
- off = 16;
+ cprint(0, COL_MID, "Pentium D (65nm)");
break;
default:
- cprint(LINE_CPU, 0, "Unknown Intel");
- off = 13;
+ cprint(0, COL_MID, "Unknown Intel");
break;
- }
break;
}
@@ -835,61 +562,69 @@
/* VIA/Cyrix/Centaur Processors with CPUID */
case 'C':
- if ( cpu_id.vend_id[1] == 'e' ) { /* CentaurHauls */
- switch(cpu_id.type){
+ if ( cpu_id.vend_id.char_array[1] == 'e' ) { /* CentaurHauls */
+ l1_cache = cpu_id.cache_info.ch[3] + cpu_id.cache_info.ch[7];
+ l2_cache = cpu_id.cache_info.ch[11];
+ switch(cpu_id.vers.bits.family){
case 5:
- cprint(LINE_CPU, 0, "Centaur 5x86");
- off = 12;
+ cprint(0, COL_MID, "Centaur 5x86");
break;
case 6: // VIA C3
- if (cpu_id.step < 8) {
- cprint(LINE_CPU, 0, "VIA C3 Samuel2");
- off = 14;
- } else {
- cprint(LINE_CPU, 0, "Via C3 Eden");
- off = 11;
- }
+ switch(cpu_id.vers.bits.model){
+ default:
+ if (cpu_id.vers.bits.stepping < 8) {
+ cprint(0, COL_MID, "VIA C3 Samuel2");
+ } else {
+ cprint(0, COL_MID, "VIA C3 Eden");
+ }
break;
+ case 10:
+ cprint(0, COL_MID, "VIA C7 (C5J)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
+ case 13:
+ cprint(0, COL_MID, "VIA C7 (C5R)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
+ case 15:
+ cprint(0, COL_MID, "VIA Isaiah (CN)");
+ l1_cache = 64;
+ l2_cache = 128;
+ break;
+ }
}
- l1_cache = cpu_id.cache_info[3] + cpu_id.cache_info[7];
- l2_cache = cpu_id.cache_info[11];
} else { /* CyrixInstead */
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 5:
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 0:
- cprint(LINE_CPU, 0, "Cyrix 6x86MX/MII");
- off = 16;
+ cprint(0, COL_MID, "Cyrix 6x86MX/MII");
break;
case 4:
- cprint(LINE_CPU, 0, "Cyrix GXm");
- off = 9;
+ cprint(0, COL_MID, "Cyrix GXm");
break;
}
return;
case 6: // VIA C3
- switch(cpu_id.model) {
+ switch(cpu_id.vers.bits.model) {
case 6:
- cprint(LINE_CPU, 0, "Cyrix III");
- off = 9;
+ cprint(0, COL_MID, "Cyrix III");
break;
case 7:
- if (cpu_id.step < 8) {
- cprint(LINE_CPU, 0, "VIA C3 Samuel2");
- off = 14;
+ if (cpu_id.vers.bits.stepping < 8) {
+ cprint(0, COL_MID, "VIA C3 Samuel2");
} else {
- cprint(LINE_CPU, 0, "VIA C3 Ezra-T");
- off = 13;
+ cprint(0, COL_MID, "VIA C3 Ezra-T");
}
break;
case 8:
- cprint(LINE_CPU, 0, "VIA C3 Ezra-T");
- off = 13;
+ cprint(0, COL_MID, "VIA C3 Ezra-T");
break;
case 9:
- cprint(LINE_CPU, 0, "VIA C3 Nehemiah");
- off = 15;
+ cprint(0, COL_MID, "VIA C3 Nehemiah");
break;
}
// L1 = L2 = 64 KB from Cyrix III to Nehemiah
@@ -899,34 +634,40 @@
}
}
break;
-
/* Unknown processor */
default:
- off = 3;
/* Make a guess at the family */
- switch(cpu_id.type) {
+ switch(cpu_id.vers.bits.family) {
case 5:
- cprint(LINE_CPU, 0, "586");
- return;
+ cprint(0, COL_MID, "586");
case 6:
- cprint(LINE_CPU, 0, "686");
- return;
+ cprint(0, COL_MID, "686");
+ default:
+ cprint(0, COL_MID, "Unidentified Processor");
}
}
+}
+
+#define STEST_ADDR 0x100000 /* Measure memory speed starting at 1MB */
+
+/* Measure and display CPU and cache sizes and speeds */
+void cpu_cache_speed()
+{
+ int i, off = 10;
+ ulong speed;
- /* We are here only if the CPU type supports the rdtsc instruction */
/* Print CPU speed */
if ((speed = cpuspeed()) > 0) {
if (speed < 999499) {
speed += 50; /* for rounding */
- cprint(LINE_CPU, off, " . MHz");
- dprint(LINE_CPU, off+1, speed/1000, 3, 1);
- dprint(LINE_CPU, off+5, (speed/100)%10, 1, 0);
+ cprint(1, off, " . MHz");
+ dprint(1, off+1, speed/1000, 3, 1);
+ dprint(1, off+5, (speed/100)%10, 1, 0);
} else {
speed += 500; /* for rounding */
- cprint(LINE_CPU, off, " MHz");
- dprint(LINE_CPU, off, speed/1000, 5, 0);
+ cprint(1, off, " MHz");
+ dprint(1, off, speed/1000, 5, 0);
}
extclock = speed;
}
@@ -935,12 +676,11 @@
/* To measure L1 cache speed we use a block size that is 1/4th */
/* of the total L1 cache size since half of it is for instructions */
if (l1_cache) {
- cprint(LINE_CPU+1, 0, "L1 Cache: K ");
- dprint(LINE_CPU+1, 11, l1_cache, 3, 0);
- if ((speed=memspeed((ulong)mapping(0x100),
- (l1_cache / 4) * 1024, 50, MS_COPY))) {
- cprint(LINE_CPU+1, 16, " MB/s");
- dprint(LINE_CPU+1, 16, speed, 6, 0);
+ cprint(2, 0, "L1 Cache: K ");
+ dprint(2, 11, l1_cache, 3, 0);
+ if ((speed=memspeed(STEST_ADDR, (l1_cache/4)*1024, 200))) {
+ cprint(2, 16, " MB/s");
+ dprint(2, 16, speed, 6, 0);
}
}
@@ -949,92 +689,85 @@
/* the size of the L1 cache. We have to fudge if the L1 */
/* cache is bigger than the L2 */
if (l2_cache) {
- cprint(LINE_CPU+2, 0, "L2 Cache: K ");
- dprint(LINE_CPU+2, 10, l2_cache, 4, 0);
+ cprint(3, 0, "L2 Cache: K ");
+ dprint(3, 10, l2_cache, 4, 0);
if (l2_cache < l1_cache) {
i = l1_cache / 4 + l2_cache / 4;
} else {
i = l1_cache;
}
- if ((speed=memspeed((ulong)mapping(0x100), i*1024, 50,
- MS_COPY))) {
- cprint(LINE_CPU+2, 16, " MB/s");
- dprint(LINE_CPU+2, 16, speed, 6, 0);
- }
- }
+ if ((speed=memspeed(STEST_ADDR, i*1024, 200))) {
+ cprint(3, 16, " MB/s");
+ dprint(3, 16, speed, 6, 0);
+ }
+ }
+ /* Print out L3 cache info */
+ /* We measure the L3 cache speed by using a block size that is */
+ /* 2X the size of the L2 cache. */
+
+ if (l3_cache) {
+ cprint(4, 0, "L3 Cache: K ");
+ dprint(4, 10, l3_cache, 4, 0);
+ dprint(4, 10, l3_cache, 4, 0);
+
+ i = l2_cache*2;
+
+ if ((speed=memspeed(STEST_ADDR, i*1024, 150))) {
+ cprint(4, 16, " MB/s");
+ dprint(4, 16, speed, 6, 0);
+ }
+ }
+}
+
+/* Measure and display memory speed, multitasked using all CPUs */
+ulong spd[MAX_CPUS];
+void get_mem_speed(int me, int ncpus)
+{
+ int i;
+ ulong speed=0;
+ ulong start, len;
- /* Determine memory speed. To find the memory speed we use */
- /* A block size that is 5x the sum of the L1 and L2 caches */
- i = (l2_cache + l1_cache) * 5;
+ /* Determine memory speed. To find the memory speed we use
+ * A block size that is the sum of all the L1, L2 & L3 caches
+ * in all cpus * 6 */
+ i = (l3_cache + l2_cache*ncpus + l1_cache*ncpus) * 6;
/* Make sure that we have enough memory to do the test */
+ /* If not use all we have */
if ((1 + (i * 2)) > (v->plim_upper << 2)) {
i = ((v->plim_upper <<2) - 1) / 2;
}
- if((speed = memspeed((ulong)mapping(0x100), i*1024, 40, MS_COPY))) {
- cprint(LINE_CPU+3, 16, " MB/s");
- dprint(LINE_CPU+3, 16, speed, 6, 0);
- }
-
- /* Record the sarting time */
- asm __volatile__ ("rdtsc":"=a" (v->startl),"=d" (v->starth));
- v->snapl = v->startl;
- v->snaph = v->starth;
- v->rdtsc = 1;
- if (l1_cache == 0) { l1_cache = 66; }
- if (l2_cache == 0) { l1_cache = 666; }
-}
-
-/* Find cache-able memory size */
-static void cacheable(void)
-{
- ulong speed, pspeed;
- ulong paddr, mem_top, cached;
-
- mem_top = v->pmap[v->msegs - 1].end;
- cached = v->test_pages;
- pspeed = 0;
- for (paddr=0x200; paddr <= mem_top - 64; paddr+=0x400) {
- int i;
- int found;
- /* See if the paddr is at a testable location */
- found = 0;
- for(i = 0; i < v->msegs; i++) {
- if ((v->pmap[i].start >= paddr) &&
- (v->pmap[i].end <= (paddr + 32))) {
- found = 1;
- break;
- }
- }
- if (!found) {
- continue;
- }
- /* Map the range and perform the test */
- map_page(paddr);
- speed = memspeed((ulong)mapping(paddr), 32*4096, 1, MS_COPY);
- if (pspeed) {
- if (speed < pspeed) {
- cached -= 32;
- }
- pspeed = (ulong)((float)speed * 0.7);
+ /* Divide up the memory block among the CPUs */
+ len = i * 1024 / ncpus;
+ start = STEST_ADDR + (len * me);
+
+ barrier();
+ spd[me] = memspeed(start, len, 50);
+ barrier();
+ if (me == 0) {
+ for (i=0; i<ncpus; i++) {
+ speed += spd[i];
}
+ cprint(5, 16, " MB/s");
+ dprint(5, 16, speed, 6, 0);
}
- aprint(LINE_INFO, COL_CACHE_TOP, cached);
- /* Ensure the default set of pages are mapped */
- map_page(0);
- map_page(0x80000);
}
-
/* #define TICKS 5 * 11832 (count = 6376)*/
/* #define TICKS (65536 - 12752) */
#define TICKS 59659 /* 50 ms */
/* Returns CPU clock in khz */
+ulong stlow, sthigh;
static int cpuspeed(void)
{
int loops;
+ ulong end_low, end_high;
+
+ if (v->rdtsc == 0 ) {
+ return(-1);
+ }
/* Setup timer */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
@@ -1042,7 +775,7 @@
outb(TICKS & 0xff, 0x42);
outb(TICKS >> 8, 0x42);
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ asm __volatile__ ("rdtsc":"=a" (stlow),"=d" (sthigh));
loops = 0;
do {
@@ -1051,8 +784,8 @@
asm __volatile__ (
"rdtsc\n\t" \
- "subl st_low,%%eax\n\t" \
- "sbbl st_high,%%edx\n\t" \
+ "subl stlow,%%eax\n\t" \
+ "sbbl sthigh,%%edx\n\t" \
:"=a" (end_low), "=d" (end_high)
);
@@ -1061,16 +794,26 @@
return(-1);
}
v->clks_msec = end_low/50;
+/*
+ if (tsc_invariable) end_low = correct_tsc(end_low);
+*/
return(v->clks_msec);
}
-/* Measure cache/memory speed by copying a block of memory. */
+/* Measure cache speed by copying a block of memory. */
/* Returned value is kbytes/second */
-ulong memspeed(ulong src, ulong len, int iter, int type)
+ulong memspeed(ulong src, ulong len, int iter)
{
- ulong dst;
- ulong wlen;
int i;
+ ulong dst, wlen;
+ ulong st_low, st_high;
+ ulong end_low, end_high;
+ ulong cal_low, cal_high;
+
+ if (v->rdtsc == 0 ) {
+ return(-1);
+ }
+ if (len == 0) return(-2);
dst = src + len;
wlen = len / 4; /* Length is bytes */
@@ -1102,10 +845,20 @@
/* Now measure the speed */
- switch (type) {
- case MS_COPY:
- /* Do the first copy to prime the cache */
- asm __volatile__ (
+ /* Do the first copy to prime the cache */
+ asm __volatile__ (
+ "movl %0,%%esi\n\t" \
+ "movl %1,%%edi\n\t" \
+ "movl %2,%%ecx\n\t" \
+ "cld\n\t" \
+ "rep\n\t" \
+ "movsl\n\t" \
+ :: "g" (src), "g" (dst), "g" (wlen)
+ : "esi", "edi", "ecx"
+ );
+ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
+ for (i=0; i<iter; i++) {
+ asm __volatile__ (
"movl %0,%%esi\n\t" \
"movl %1,%%edi\n\t" \
"movl %2,%%ecx\n\t" \
@@ -1115,63 +868,8 @@
:: "g" (src), "g" (dst), "g" (wlen)
: "esi", "edi", "ecx"
);
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
- for (i=0; i<iter; i++) {
- asm __volatile__ (
- "movl %0,%%esi\n\t" \
- "movl %1,%%edi\n\t" \
- "movl %2,%%ecx\n\t" \
- "cld\n\t" \
- "rep\n\t" \
- "movsl\n\t" \
- :: "g" (src), "g" (dst), "g" (wlen)
- : "esi", "edi", "ecx"
- );
- }
- asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
- break;
- case MS_WRITE:
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
- for (i=0; i<iter; i++) {
- asm __volatile__ (
- "movl %0,%%ecx\n\t" \
- "movl %1,%%edi\n\t" \
- "movl %2,%%eax\n\t" \
- "rep\n\t" \
- "stosl\n\t"
- :: "g" (wlen), "g" (dst), "g" (0)
- : "edi", "ecx", "eax"
- );
- }
- asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
- break;
- case MS_READ:
- asm __volatile__ (
- "movl %0,%%esi\n\t" \
- "movl %1,%%ecx\n\t" \
- "cld\n\t" \
- "L1:\n\t" \
- "lodsl\n\t" \
- "loop L1\n\t" \
- :: "g" (src), "g" (wlen)
- : "esi", "ecx"
- );
- asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high));
- for (i=0; i<iter; i++) {
- asm __volatile__ (
- "movl %0,%%esi\n\t" \
- "movl %1,%%ecx\n\t" \
- "cld\n\t" \
- "L2:\n\t" \
- "lodsl\n\t" \
- "loop L2\n\t" \
- :: "g" (src), "g" (wlen)
- : "esi", "ecx"
- );
- }
- asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
- break;
}
+ asm __volatile__ ("rdtsc":"=a" (end_low),"=d" (end_high));
/* Compute the elapsed time */
asm __volatile__ (
@@ -1192,22 +890,60 @@
/* Make sure that the result fits in 32 bits */
if (end_high) {
- return(0);
- }
-
- /* If this was a copy adjust the time */
- if (type == MS_COPY) {
- end_low /= 2;
+ return(-3);
}
+ end_low /= 2;
/* Convert to clocks/KB */
end_low /= len;
end_low *= 1024;
end_low /= iter;
if (end_low == 0) {
- return(0);
+ return(-4);
}
/* Convert to kbytes/sec */
+/*
+ if (tsc_invariable) end_low = correct_tsc(end_low);
+*/
return((v->clks_msec)/end_low);
}
+
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+/*
+ulong correct_tsc(ulong el_org)
+{
+ float coef_now, coef_max;
+ int msr_lo, msr_hi, is_xe;
+
+ rdmsr(0x198, msr_lo, msr_hi);
+ is_xe = (msr_lo >> 31) & 0x1;
+
+ if(is_xe){
+ rdmsr(0x198, msr_lo, msr_hi);
+ coef_max = ((msr_hi >> 8) & 0x1F);
+ if ((msr_hi >> 14) & 0x1) { coef_max = coef_max + 0.5f; }
+ } else {
+ rdmsr(0x17, msr_lo, msr_hi);
+ coef_max = ((msr_lo >> 8) & 0x1F);
+ if ((msr_lo >> 14) & 0x1) { coef_max = coef_max + 0.5f; }
+ }
+
+ if((cpu_id.feature_flag >> 7) & 1) {
+ rdmsr(0x198, msr_lo, msr_hi);
+ coef_now = ((msr_lo >> 8) & 0x1F);
+ if ((msr_lo >> 14) & 0x1) { coef_now = coef_now + 0.5f; }
+ } else {
+ rdmsr(0x2A, msr_lo, msr_hi);
+ coef_now = (msr_lo >> 22) & 0x1F;
+ }
+ if(coef_max && coef_now) {
+ el_org = (ulong)(el_org * coef_now / coef_max);
+ }
+ return el_org;
+}
+*/
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/lib.c
^
|
@@ -8,10 +8,22 @@
#include "test.h"
#include "config.h"
#include "screen_buffer.h"
+#include "smp.h"
int slock = 0, lsr = 0;
short serial_cons = SERIAL_CONSOLE_DEFAULT;
-char buf[18];
+#if SERIAL_TTY != 0 && SERIAL_TTY != 1
+#error Bad SERIAL_TTY. Only ttyS0 and ttyS1 are supported.
+#endif
+short serial_tty = SERIAL_TTY;
+const short serial_base_ports[] = {0x3f8, 0x2f8};
+
+#if ((115200%SERIAL_BAUD_RATE) != 0)
+#error Bad default baud rate
+#endif
+int serial_baud_rate = SERIAL_BAUD_RATE;
+unsigned char serial_parity = 0;
+unsigned char serial_bits = 8;
struct ascii_map_str {
int ascii;
@@ -40,8 +52,16 @@
" Mch_Chk",
"SIMD FPE"
};
+inline void reboot(void)
+{
+ /* tell the BIOS to do a warm start */
+ *((unsigned short *)0x472) = 0x1234;
+ outb(0xfe,0x64);
+}
struct eregs {
+ ulong ss;
+ ulong ds;
ulong esp;
ulong ebp;
ulong esi;
@@ -69,6 +89,20 @@
return 0;
}
+int strncmp(const char *s1, const char *s2, ulong n) {
+ signed char res = 0;
+ while (n) {
+ res = *s1 - *s2;
+ if (res != 0)
+ return res;
+ if (*s1 == '\0')
+ return 0;
+ ++s1, ++s2;
+ --n;
+ }
+ return res;
+}
+
void *memmove(void *dest, const void *src, ulong n)
{
long i;
@@ -88,6 +122,50 @@
return dest;
}
+char toupper(char c)
+{
+ if (c >= 'a' && c <= 'z')
+ return c + 'A' -'a';
+ else
+ return c;
+}
+
+int isdigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+int isxdigit(char c)
+{
+ return isdigit(c) || (toupper(c) >= 'A' && toupper(c) <= 'F'); }
+
+unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) {
+ unsigned long result = 0, value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X' && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) {
+ if (cp[0] == '0' && toupper(cp[1]) == 'X')
+ cp += 2;
+ }
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
/*
* Scroll the error message area of the screen as needed
* Starts at line LINE_SCROLL and ends at line 23
@@ -140,7 +218,18 @@
}
/*
- * Print characters (n screen
+ * Place a single character on screen
+ */
+void cplace(int y, int x, const char c)
+{
+ char *dptr;
+
+ dptr = (char *)(SCREEN_ADR + (160*y) + (2*x));
+ *dptr = c;
+}
+
+/*
+ * Print characters on screen
*/
void cprint(int y, int x, const char *text)
{
@@ -183,6 +272,19 @@
s[j] = c;
}
}
+void memcpy (void *dst, void *src, int len)
+{
+ char *s = (char*)src;
+ char *d = (char*)dst;
+ int i;
+
+ if (len <= 0) {
+ return;
+ }
+ for (i = 0 ; i < len; i++) {
+ *d++ = *s++;
+ }
+}
/*
* Print a people friendly address
@@ -215,6 +317,7 @@
{
ulong j, k;
int i, flag=0;
+ char buf[18];
if (val > 999999999 || len > 9) {
return;
@@ -272,6 +375,7 @@
{
unsigned long j;
int i, idx, flag = 0;
+ char buf[18];
for (i=0, idx=0; i<8; i++) {
j = val >> (28 - (4 * i));
@@ -305,6 +409,7 @@
{
unsigned long j;
int i, idx, flag = 0;
+ char buf[18];
for (i=0, idx=0; i<digits; i++) {
j = 0xf & val;
@@ -357,6 +462,7 @@
int i, line;
unsigned char *pp;
ulong address = 0;
+ int my_cpu_num = smp_my_cpu_num();
/* Get the page fault address */
if (trap_regs->vect == 14) {
@@ -378,7 +484,8 @@
}
line = LINE_SCROLL-2;
- cprint(line, 0, "Unexpected Interrupt - Halting");
+ cprint(line, 0, "Unexpected Interrupt - Halting CPU");
+ dprint(line, COL_MID + 4, my_cpu_num, 2, 1);
cprint(line+2, 0, " Type: ");
if (trap_regs->vect <= 19) {
cprint(line+2, 7, codes[trap_regs->vect]);
@@ -393,6 +500,10 @@
hprint(line+5, 7, trap_regs->eflag);
cprint(line+6, 0, " Code: ");
hprint(line+6, 7, trap_regs->code);
+ cprint(line+7, 0, " DS: ");
+ hprint(line+7, 7, trap_regs->ds);
+ cprint(line+8, 0, " SS: ");
+ hprint(line+8, 7, trap_regs->ss);
if (trap_regs->vect == 14) {
/* Page fault address */
cprint(line+7, 0, " Addr: ");
@@ -437,20 +548,12 @@
void set_cache(int val)
{
- extern struct cpu_ident cpu_id;
- /* 386's don't have a cache */
- if ((cpu_id.cpuid < 1) && (cpu_id.type == 3)) {
- cprint(LINE_INFO, COL_CACHE, "none");
- return;
- }
switch(val) {
case 0:
cache_off();
- cprint(LINE_INFO, COL_CACHE, "off");
break;
case 1:
cache_on();
- cprint(LINE_INFO, COL_CACHE, " on");
break;
}
}
@@ -487,11 +590,7 @@
case 1:
/* "ESC" key was pressed, bail out. */
cprint(LINE_RANGE, COL_MID+23, "Halting... ");
-
- /* tell the BIOS to do a warm start */
- *((unsigned short *)0x472) = 0x1234;
- cache_on();
- outb(0xfe,0x64);
+ reboot();
break;
case 46:
/* c - Configure */
@@ -625,21 +724,7 @@
shift -= result_shift;
/* Compute our current value */
- val = 0;
- for(i = (base == 16)? 2: 0; i < n; i++) {
- unsigned long digit = 0;
- if ((buf[i] >= '0') && (buf[i] <= '9')) {
- digit = buf[i] - '0';
- }
- else if ((buf[i] >= 'a') && (buf[i] <= 'f')) {
- digit = buf[i] - 'a' + 10;
- }
- else {
- /* It must be a suffix byte */
- break;
- }
- val = (val * base) + digit;
- }
+ val = simple_strtoul(buf, 0, base);
if (shift > 0) {
if (shift >= 32) {
val = 0xffffffff;
@@ -675,20 +760,11 @@
serial_echo_print(p);
}
-#if defined(SERIAL_BAUD_RATE)
-
-#if ((115200%SERIAL_BAUD_RATE) != 0)
-#error Bad ttys0 baud rate
-#endif
-
-#define SERIAL_DIV (115200/SERIAL_BAUD_RATE)
-
-#endif /* SERIAL_BAUD_RATE */
-
void serial_echo_init(void)
{
- int comstat, hi, lo;
-
+ int comstat, hi, lo, serial_div;
+ unsigned char lcr;
+
/* read the Divisor Latch */
comstat = serial_echo_inb(UART_LCR);
serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR);
@@ -697,13 +773,13 @@
serial_echo_outb(comstat, UART_LCR);
/* now do hardwired init */
- serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
-#if defined(SERIAL_BAUD_RATE)
- serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
- serial_echo_outb(SERIAL_DIV & 0xff, UART_DLL); /* baud rate divisor */
- serial_echo_outb((SERIAL_DIV>> 8) & 0xff, UART_DLM);
- serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
-#endif
+ lcr = serial_parity | (serial_bits - 5);
+ serial_echo_outb(lcr, UART_LCR); /* No parity, 8 data bits, 1 stop */
+ serial_div = 115200 / serial_baud_rate;
+ serial_echo_outb(0x80|lcr, UART_LCR); /* Access divisor latch */
+ serial_echo_outb(serial_div & 0xff, UART_DLL); /* baud rate divisor */
+ serial_echo_outb((serial_div >> 8) & 0xff, UART_DLM);
+ serial_echo_outb(lcr, UART_LCR); /* Done with divisor */
/* Prior to disabling interrupts, read the LSR and RBR
* registers */
@@ -928,3 +1004,92 @@
}
}
}
+
+/*
+ * Handles "console=<param>" command line option
+ *
+ * Examples of accepted params:
+ * ttyS0
+ * ttyS1
+ * ttyS0,115200
+ * ttyS0,9600e8
+ */
+void serial_console_setup(char *param)
+{
+ char *option, *end;
+ unsigned long tty;
+ unsigned long baud_rate;
+ unsigned char parity, bits;
+
+ if (strncmp(param, "ttyS", 4))
+ return; /* not a serial port */
+
+ param += 4;
+
+ tty = simple_strtoul(param, &option, 10);
+
+ if (option == param)
+ return; /* there were no digits */
+
+ if (tty > 1)
+ return; /* only ttyS0 and ttyS1 supported */
+
+ if (*option == '\0' || *option == ' ')
+ goto save_tty; /* no options given, just ttyS? */
+
+ if (*option != ',')
+ return; /* missing the comma separator */
+
+ /* baud rate must follow */
+ option++;
+ baud_rate = simple_strtoul(option, &end, 10);
+
+ if (end == option)
+ return; /* no baudrate after comma */
+
+ if (baud_rate == 0 || (115200 % baud_rate) != 0)
+ return; /* wrong baud rate */
+
+ if (*end == '\0' || *end == ' ')
+ goto save_baud_rate; /* no more options given */
+
+ switch (toupper(*end)) {
+ case 'N':
+ parity = 0;
+ break;
+ case 'O':
+ parity = UART_LCR_PARITY;
+ break;
+ case 'E':
+ parity = UART_LCR_PARITY | UART_LCR_EPAR;
+ break;
+ default:
+ /* Unknown parity */
+ return;
+ }
+
+ end++;
+ if (*end == '\0' || *end == ' ')
+ goto save_parity;
+
+ /* word length (bits) */
+ if (*end < '7' || *end > '8')
+ return; /* invalid number of bits */
+
+ bits = *end - '0';
+
+ end++;
+
+ if (*end != '\0' || *end != ' ')
+ return; /* garbage at the end */
+
+ serial_bits = bits;
+ save_parity:
+ serial_parity = parity;
+ save_baud_rate:
+ serial_baud_rate = (int) baud_rate;
+ save_tty:
+ serial_tty = (short) tty;
+ serial_cons = 1;
+}
+
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/main.c
^
|
@@ -1,479 +1,898 @@
-/* main.c - MemTest-86 Version 3.4
+/* main.c - MemTest-86 Version 3.5
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
*/
+#include "stdint.h"
+#include "stddef.h"
#include "test.h"
#include "defs.h"
+#include "smp.h"
#undef TEST_TIMES
-#define DEFTESTS 9
+#define DEFTESTS 12
+
+/* The main stack is allocated during boot time. The stack size should
+ * preferably be a multiple of page size(4Kbytes)
+*/
+#define STACKSIZE (6*1024)
+#define MAX_MEM 0x1000000 /* 64 GB */
+#define TWO_GB 0x80000 /* 2 GB */
extern void bzero();
+extern ulong rand(int cpu);
+extern void get_mem_speed(int cpu, int ncpus);
+extern void rand_seed(unsigned int seed1, unsigned int seed2, int cpu);
const struct tseq tseq[] = {
- {0, 5, 3, 0, 0, "[Address test, walking ones, no cache]"},
- {1, 6, 3, 2, 0, "[Address test, own address] "},
- {1, 0, 3, 14, 0, "[Moving inversions, ones & zeros] "},
- {1, 1, 2, 80, 0, "[Moving inversions, 8 bit pattern] "},
- {1, 10, 60, 300, 0,"[Moving inversions, random pattern] "},
- {1, 7, 64, 66, 0, "[Block move, 64 moves] "},
- {1, 2, 2, 320, 0, "[Moving inversions, 32 bit pattern] "},
- {1, 9, 40, 120, 0, "[Random number sequence] "},
- {1, 11, 6, 1920, 0,"[Modulo 20, Random pattern] "},
- {1, 8, 1, 2, 0, "[Bit fade test, 90 min, 2 patterns] "},
- {0, 0, 0, 0, 0, NULL}
+ {-1, 0, 6, 0, "[Address test, walking ones, no cache] "},
+ {-1, 1, 6, 0, "[Address test, own address Seqential] "},
+ {16, 2, 6, 0, "[Address test, own address Parallel] "},
+ {-1, 3, 6, 0, "[Moving inversions, 1s & 0s] Seqential]"},
+ {16, 4, 6, 0, "[Moving inversions, 1s & 0s] Parallel] "},
+ {16, 5, 3, 0, "[Moving inversions, 8 bit pattern] "},
+ {16, 6, 30, 0, "[Moving inversions, random pattern] "},
+ {16, 7, 81, 0, "[Block move] "},
+ {16, 8, 3, 0, "[Moving inversions, 32 bit pattern] "},
+ {16, 9, 24, 0, "[Random number sequence] "},
+ {16, 10, 6, 0, "[Modulo 20, Random pattern] "},
+ {1, 11, 300, 0, "[Bit fade test, 2 patterns] "},
+ {0, 0, 0, 0, NULL}
};
-char firsttime = 0;
+extern struct barrier_s *barr;
+extern unsigned num_cpus;
+volatile int mstr_cpu;
+volatile int run_cpus;
+volatile int test;
+volatile short cpu_sel = 0;
+bool smp_mode = TRUE;
+bool restart_pending = FALSE;
+uint8_t volatile stacks[MAX_CPUS][STACKSIZE];
+int bitf_seq = 0;
+char cmdline_parsed = 0;
struct vars variables = {};
struct vars * const v = &variables;
-volatile ulong *p = 0;
-ulong p1 = 0, p2 = 0, p0 = 0;
-int segs = 0, bail = 0;
+volatile int bail = 0;
int test_ticks;
+volatile int segs;
int nticks;
-ulong high_test_adr = 0x200000;
-
-static int window = 0;
-static struct pmap windows[] =
-{
- { 0/* Written at startup */, 0x080000 }, /* first 2gb */
- { 0, 0/* Written at startup */ }, /* for relocation */
+ulong high_test_adr;
- { 0x080000, 0x100000 }, /* 2nd 2gb */
- { 0x100000, 0x180000 },
- { 0x180000, 0x200000 },
+volatile short start_seq = 0;
+volatile short cpu_mode = CPM_ALL;
+static int c_iter;
+volatile static int window;
+volatile static unsigned long win_next;
+volatile static ulong win0_start; /* Start test address for window 0 */
+volatile static ulong win1_end; /* End address for relocation */
+volatile static struct pmap winx; /* Window struct for mapping windows */
- { 0x200000, 0x280000 },
- { 0x280000, 0x300000 },
+#if (LOW_TEST_ADR > (400*1024))
+#error LOW_TEST_ADR must be below 400K
+#endif
- { 0x300000, 0x380000 },
- { 0x380000, 0x400000 },
+static int find_ticks_for_test(int test);
+void find_ticks_for_pass(void);
+int find_chunks(int test);
+static void test_setup(void);
+static int compute_segments(struct pmap map);
+int do_test(int cpu);
- { 0x400000, 0x480000 },
- { 0x480000, 0x500000 },
+/* Relocate the test to a new address. Be careful to not overlap! */
+static void run_at(unsigned long addr, int cpu)
+{
+ ulong *ja = (ulong *)(addr + startup_32 - _start);
- { 0x500000, 0x580000 },
- { 0x580000, 0x600000 },
+ /* CPU 0, Copy memtest86 code */
+ if (cpu == 0) {
+ memmove((void *)addr, &_start, _end - _start);
+ }
- { 0x600000, 0x680000 },
- { 0x680000, 0x700000 },
+ /* Wait for the copy */
+ barrier();
- { 0x700000, 0x780000 },
- { 0x780000, 0x800000 },
+ /* We use a lock to insure that only one CPU at a time jumps to
+ * the new code. Some of the startup stuff is not thread safe! */
+ spin_lock(&barr->mutex);
- { 0x800000, 0x880000 },
- { 0x880000, 0x900000 },
+ /* Jump to the start address */
+ goto *ja;
+}
- { 0x900000, 0x980000 },
- { 0x980000, 0xA00000 },
+/* Switch from the boot stack to the main stack. First the main stack
+ * is allocated, then the contents of the boot stack are copied, then
+ * ESP is adjusted to point to the new stack.
+ */
+static void
+switch_to_main_stack(unsigned cpu_num)
+{
+ extern uintptr_t boot_stack;
+ extern uintptr_t boot_stack_top;
+ uintptr_t *src, *dst;
+ int offs;
+ uint8_t * stackAddr, *stackTop;
+
+ stackAddr = (uint8_t *) &stacks[cpu_num][0];
+
+ stackTop = stackAddr + STACKSIZE;
+
+ src = (uintptr_t*)&boot_stack_top;
+ dst = (uintptr_t*)stackTop;
+ do {
+ src--; dst--;
+ *dst = *src;
+ } while ((uintptr_t *)src > (uintptr_t *)&boot_stack);
+
+ offs = (uint8_t *)&boot_stack_top - stackTop;
+ __asm__ __volatile__ (
+ "subl %%eax, %%esp"
+ : /*no output*/
+ : "a" (offs) : "memory"
+ );
+}
- { 0xA00000, 0xA80000 },
- { 0xA80000, 0xB00000 },
+void restart_internal(int cpu)
+{
+ /* clear variables */
+ smp_mode = TRUE;
+ restart_pending = FALSE;
- { 0xB00000, 0xB80000 },
- { 0xB80000, 0xC00000 },
+ run_at(LOW_TEST_ADR, cpu);
+}
- { 0xC00000, 0xC80000 },
- { 0xC80000, 0xD00000 },
+void restart(void)
+{
+ bail++;
+ restart_pending = TRUE;
+}
- { 0xD00000, 0xD80000 },
- { 0xD80000, 0xE00000 },
+void initialise_cpus(void)
+{
+ int cpu_num;
- { 0xE00000, 0xE80000 },
- { 0xE80000, 0xF00000 },
+ smp_init_bsp();
- { 0xF00000, 0xF80000 },
- { 0xF80000, 0x1000000 },
-};
+ /* Initialize the barrier before starting AP's */
+ barrier_init(num_cpus);
-#if (LOW_TEST_ADR > (640*1024))
-#error LOW_TEST_ADR must be below 640K
-#endif
+ /* let the BSP initialise the APs. */
+ for(cpu_num = 1; cpu_num < num_cpus; cpu_num++) {
+ smp_boot_ap(cpu_num);
+ }
+}
-static int find_ticks_for_test(unsigned long chunks, int test);
-static void compute_segments(int win);
+/* command line passing using the 'old' boot protocol */
+#define MK_PTR(seg,off) ((void*)(((unsigned long)(seg) << 4) + (off)))
+#define OLD_CL_MAGIC_ADDR ((unsigned short*) MK_PTR(INITSEG,0x20))
+#define OLD_CL_MAGIC 0xA33F
+#define OLD_CL_OFFSET_ADDR ((unsigned short*) MK_PTR(INITSEG,0x22))
-static void __run_at(unsigned long addr)
+static void parse_command_line(void)
{
- /* Copy memtest86 code */
- memmove((void *)addr, &_start, _end - _start);
- /* Jump to the start address */
- p = (ulong *)(addr + startup_32 - _start);
- goto *p;
-}
+ char *cmdline;
-static unsigned long run_at_addr = 0xffffffff;
-static void run_at(unsigned long addr)
-{
- unsigned long start;
- unsigned long len;
+ if (cmdline_parsed)
+ return;
- run_at_addr = addr;
+ if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC)
+ return;
- start = (unsigned long) &_start;
- len = _end - _start;
- if ( ((start < addr) && ((start + len) >= addr)) ||
- ((addr < start) && ((addr + len) >= start))) {
- /* Handle overlap by doing an extra relocation */
- if (addr + len < high_test_adr) {
- __run_at(high_test_adr);
- }
- else if (start + len < addr) {
- __run_at(LOW_TEST_ADR);
+ unsigned short offset = *OLD_CL_OFFSET_ADDR;
+ cmdline = MK_PTR(INITSEG, offset);
+
+ /* skip leading spaces */
+ while (*cmdline == ' ')
+ cmdline++;
+
+ while (*cmdline) {
+ if (!strncmp(cmdline, "console=", 8)) {
+ cmdline += 8;
+ serial_console_setup(cmdline);
}
+
+ /* go to the next parameter */
+ while (*cmdline && *cmdline != ' ')
+ cmdline++;
+ while (*cmdline == ' ')
+ cmdline++;
}
- __run_at(run_at_addr);
+
+ cmdline_parsed = 1;
}
-void do_test(void)
+/* This is the test entry point. We get here on statup and also whenever
+ * we relocate. */
+void test_start(void)
{
- int i = 0, j = 0;
- unsigned long chunks;
- unsigned long lo, hi;
+ int my_cpu_num, run;
+
+
+ /* First thing, switch to main stack */
+ my_cpu_num = smp_my_cpu_num();
+ switch_to_main_stack(my_cpu_num);
+
+ /* First time initialization */
+ if (start_seq == 0) {
+
+ /* These steps are only done by the boot cpu */
+ if (my_cpu_num == 0) {
+ parse_command_line();
+ mem_size(); /* must be called before initialise_cpus(); */
+ initialise_cpus();
+ init();
+
+ test = 0;
+ win_next = 0;
+ window = 0;
+ bail = 0;
+
+ /* Setup base address for testing */
+ win0_start = (LOW_TEST_ADR+(_end - _start)+8191) >> 12;
+
+ /* Set relocation address to 32Mb if there is enough
+ * memory. Otherwise set it to 3Mb */
+ /* Large reloc addr allows for more testing overlap */
+ if ((ulong)v->pmap[v->msegs-1].end > 0x2f00) {
+ high_test_adr = 0x2000000;
+ } else {
+ high_test_adr = 0x300000;
+ }
+ win1_end = (high_test_adr >> 12);
+
+ /* Adjust the map to not test the page at 939k,
+ * reserved for locks */
+ v->pmap[0].end--;
+
+ find_ticks_for_pass();
+ } else {
+ /* AP only, Register the APs */
+ smp_ap_booted(my_cpu_num);
+ }
+ } else {
+ /* Unlock after a relocation restart */
+ spin_unlock(&barr->mutex);
+ }
+
+ /* A barrier to insure that all of the CPUs are done with startup */
+ barrier();
- /* If we have a partial relocation finish it */
- if (run_at_addr == (unsigned long)&_start) {
- run_at_addr = 0xffffffff;
- } else if (run_at_addr != 0xffffffff) {
- __run_at(run_at_addr);
+ /* Measure memory speed, we do it here because we need all of the
+ * available CPUs */
+ if (start_seq == 0) {
+ get_mem_speed(my_cpu_num, num_cpus);
}
- /* If first time, initialize test */
- if (firsttime == 0) {
- if ((ulong)&_start != LOW_TEST_ADR) {
- restart();
+ /* Set the initialized flag only after all of the CPU's have
+ * Reached the barrier. This insures that relocation has
+ * been completed for each CPU. */
+ start_seq = 1;
+
+ /* Loop through all tests */
+ while (1) {
+ /* Skip tests 2 and 4 if we are using only one CPU */
+ if (tseq[test].pat == 2 || tseq[test].pat == 4) {
+ if (num_cpus == 1 || cpu_mode != CPM_ALL) {
+ test++;
+ continue;
+ }
+ }
+
+ test_setup();
+
+ /* Loop through all possible windows */
+ while (win_next <= ((ulong)v->pmap[v->msegs-1].end + TWO_GB)) {
+
+ /* Main scheduling barrier */
+ cprint(8, 2*my_cpu_num+7, "W");
+ barrier();
+
+ /* Don't go over the 64 GB PAE limit */
+ if (win_next > MAX_MEM) {
+ break;
}
- init();
- windows[0].start =
- ( LOW_TEST_ADR + (_end - _start) + 4095) >> 12;
- /* Set relocation address at 16Mb if there is enough memory */
- if (v->pmap[v->msegs-1].end > 0x1100) {
- high_test_adr = 0x1000000;
+ /* For the bit fade test, #11, we cannot relocate so bump the
+ * window to 1 */
+ if (tseq[test].pat == 11 && window == 0) {
+ window = 1;
}
- windows[1].end = (high_test_adr >> 12);
- firsttime = 1;
- }
- bail = 0;
- /* Find the memory areas I am going to test */
- compute_segments(window);
- if (segs == 0) {
- goto skip_window;
+ /* Relocate if required */
+ if (window != 0 && (ulong)&_start != LOW_TEST_ADR) {
+ run_at(LOW_TEST_ADR, my_cpu_num);
+ }
+ if (window == 0 && (ulong)&_start == LOW_TEST_ADR) {
+ run_at(high_test_adr, my_cpu_num);
+ }
+
+ /* Decide which CPU(s) to use */
+ run = 1;
+ switch(cpu_mode) {
+ case CPM_RROBIN:
+ case CPM_SEQ:
+ /* Select a single CPU */
+ if (my_cpu_num == cpu_sel) {
+ mstr_cpu = cpu_sel;
+ run_cpus = 1;
+ } else {
+ run = 0;
+ }
+ break;
+ case CPM_ALL:
+ /* Use all CPUs */
+ if (tseq[test].cpu_sel == -1) {
+ /* Round robin through all of the CPUs */
+ if (my_cpu_num == cpu_sel) {
+ mstr_cpu = cpu_sel;
+ run_cpus = 1;
+ } else {
+ run = 0;
+ }
+ } else {
+ /* Use the number of CPUs specified by the test,
+ * Starting with zero */
+ if (my_cpu_num >= tseq[test].cpu_sel) {
+ run = 0;
+ }
+ /* Set the master CPU to the highest CPU number
+ * that has been selected */
+ if (num_cpus < tseq[test].cpu_sel) {
+ mstr_cpu = num_cpus-1;
+ run_cpus = num_cpus;
+ } else {
+ mstr_cpu = tseq[test].cpu_sel-1;
+ run_cpus = tseq[test].cpu_sel;
+ }
+ /* Special case for tests 7 & 8 NCPUs must be even */
+ if ((tseq[test].pat == 7 || tseq[test].pat == 8)
+ && (run_cpus % 2)
+ && run_cpus > 1) {
+ if (my_cpu_num == num_cpus-1) {
+ run = 0;
+ }
+ mstr_cpu = num_cpus-2;
+ run_cpus = num_cpus-1;
+ }
+ }
+ }
+ barrier();
+ dprint(8, 54, run_cpus, 2, 0);
+
+ /* Setup a sub barrier for only the selected CPUs */
+ if (my_cpu_num == mstr_cpu) {
+ s_barrier_init(run_cpus);
+ }
+
+ /* Make sure the the sub barrier is ready before proceeding */
+ barrier();
+
+ /* Not selected CPUs go back to the scheduling barrier */
+ if (run == 0 ) {
+ continue;
+ }
+ cprint(8, 2*my_cpu_num+7, "-");
+
+ /* Do we need to exit */
+ if(restart_pending) {
+ restart_internal(my_cpu_num);
+ }
+
+ if (my_cpu_num == mstr_cpu) {
+ switch (window) {
+ /* Special case for relocation */
+ case 0:
+ winx.start = 0;
+ winx.end = win1_end;
+ window++;
+ break;
+ /* Special case for first 2 GB */
+ case 1:
+ winx.start = win0_start;
+ winx.end = TWO_GB;
+ win_next += TWO_GB;
+ window++;
+ break;
+ /* For all other windows */
+ default:
+ winx.start = win_next;
+ win_next += TWO_GB;
+ winx.end = win_next;
+ }
+
+ /* Find the memory areas to test */
+ segs = compute_segments(winx);
+ }
+ s_barrier();
+
+ if (segs == 0) {
+ /* No memory in this window so skip it */
+ continue;
+ }
+
+ /* map in the window... */
+ if (map_page(v->map[0].pbase_addr) < 0) {
+ continue;
+ }
+
+ do_test(my_cpu_num);
+ if (bail) {
+ break;
+ }
+
+ paging_off();
+
+ } /* End of window loop */
+
+ s_barrier();
+
+ /* Setup for the next set of windows */
+ win_next = 0;
+ window = 0;
+ bail = 0;
+
+ /* Only the master CPU does the end of test housekeeping */
+ if (my_cpu_num != mstr_cpu) {
+ continue;
+ }
+
+ /* Special handling for the bit fade test #11 */
+ if (tseq[test].pat == 11 && bitf_seq != 6) {
+ /* Keep going until the sequence is complete. */
+ bitf_seq++;
+ continue;
+ } else {
+ bitf_seq = 0;
+ }
+
+ /* Select advancement of CPUs and next test */
+ switch(cpu_mode) {
+ case CPM_RROBIN:
+ if (++cpu_sel >= num_cpus) {
+ cpu_sel = 0;
+ }
+ test++;
+ break;
+ case CPM_SEQ:
+ if (++cpu_sel >= num_cpus) {
+ cpu_sel = 0;
+ test++;
+ }
+ break;
+ case CPM_ALL:
+ if (tseq[test].cpu_sel == -1) {
+ /* Do the same test for each CPU */
+ if (++cpu_sel >= num_cpus) {
+ cpu_sel = 0;
+ test++;
+ } else {
+ continue;
+ }
+ } else {
+ test++;
+ }
+ }
+
+ /* If this was the last test then we finished a pass */
+ if (test >= DEFTESTS ||
+ (v->testsel >= 0 && cpu_sel == (num_cpus-1))) {
+ v->pass++;
+ dprint(LINE_INFO, 55, v->pass, 5, 0);
+ v->total_ticks = 0;
+ find_ticks_for_pass();
+ cprint(1, COL_MID+8,
+ " ");
+ if (v->ecount == 0 && v->testsel < 0) {
+ cprint(LINE_MSG, COL_MSG,
+ "Pass complete, no errors, press Esc to exit");
+ }
+ }
+ if (test >= DEFTESTS) {
+ test = 0;
+ }
+
+ bail=0;
+ } /* End test loop */
+}
+
+void test_setup()
+{
+ static int ltest = -1;
+
+ /* Only do the setup if this is a new test */
+ if (test == ltest) {
+ return;
}
- /* Now map in the window... */
- if (map_page(v->map[0].pbase_addr) < 0) {
- goto skip_window;
+ ltest = test;
+
+ /* Now setup the test parameters based on the current test number */
+ if (v->pass == 0) {
+ /* Reduce iterations for first pass */
+ c_iter = tseq[test].iter/3;
+ } else {
+ c_iter = tseq[test].iter;
}
- if ((ulong)&_start > LOW_TEST_ADR) {
+ /* Set the number of iterations. We only do half of the iterations */
+ /* on the first pass */
+ dprint(LINE_INFO, 28, c_iter, 3, 0);
+ test_ticks = find_ticks_for_test(test);
+ nticks = 0;
+ v->tptr = 0;
+
+ cprint(LINE_PAT, COL_PAT, " ");
+ cprint(LINE_PAT, COL_PAT-3, " ");
+ dprint(LINE_TST, COL_MID+6, test, 2, 1);
+ cprint(LINE_TST, COL_MID+9, tseq[test].msg);
+ cprint(2, COL_MID+8, " ");
+}
+
+/* A couple static variables for when all cpus share the same pattern */
+static ulong sp1, sp2;
+
+int do_test(int my_cpu)
+{
+ int i=0, j=0;
+ static int bitf_sleep;
+ unsigned long p0=0, p1=0, p2=0;
+
+ if (my_cpu == mstr_cpu) {
+ if ((ulong)&_start > LOW_TEST_ADR) {
/* Relocated so we need to test all selected lower memory */
v->map[0].start = mapping(v->plim_lower);
- cprint(LINE_RANGE, COL_MID+28, " Relocated");
- } else {
- cprint(LINE_RANGE, COL_MID+28, " ");
+ cprint(LINE_PAT, COL_MID+28, " Relocated");
+ } else {
+ cprint(LINE_PAT, COL_MID+28, " ");
+ }
+
+ /* Update display of memory segments being tested */
+ p0 = page_of(v->map[0].start);
+ p1 = page_of(v->map[segs-1].end);
+ aprint(LINE_RANGE, COL_MID+9, p0);
+ cprint(LINE_RANGE, COL_MID+14, " - ");
+ aprint(LINE_RANGE, COL_MID+17, p1);
+ aprint(LINE_RANGE, COL_MID+25, p1-p0);
+ cprint(LINE_RANGE, COL_MID+30, " of ");
+ aprint(LINE_RANGE, COL_MID+34, v->selected_pages);
}
-
- /* Update display of memory segments being tested */
- lo = page_of(v->map[0].start);
- hi = page_of(v->map[segs-1].end);
- aprint(LINE_RANGE, COL_MID+9, lo);
- cprint(LINE_RANGE, COL_MID+14, " - ");
- aprint(LINE_RANGE, COL_MID+17, hi);
- aprint(LINE_RANGE, COL_MID+23, v->selected_pages);
- /* Now setup the test parameters based on the current test number */
- /* Figure out the next test to run */
- if (v->testsel >= 0) {
- v->test = v->testsel;
- }
- dprint(LINE_TST, COL_MID+6, v->test, 2, 1);
- cprint(LINE_TST, COL_MID+9, tseq[v->test].msg);
- set_cache(tseq[v->test].cache);
+ switch(tseq[test].pat) {
- /* Compute the number of SPINSZ memory segments */
- chunks = 0;
- for(i = 0; i < segs; i++) {
- unsigned long len;
- len = v->map[i].end - v->map[i].start;
- chunks += (len + SPINSZ -1)/SPINSZ;
- }
+ /* Do the testing according to the selected pattern */
- test_ticks = find_ticks_for_test(chunks, v->test);
- nticks = 0;
- v->tptr = 0;
- cprint(1, COL_MID+8, " ");
- switch(tseq[v->test].pat) {
+ case 0: /* Address test, walking ones (test #0) */
+ /* Run with cache turned off */
+ set_cache(0);
+ addr_tst1(my_cpu);
+ set_cache(1);
+ BAILOUT;
+ break;
- /* Now do the testing according to the selected pattern */
- case 0: /* Moving inversions, all ones and zeros */
+ case 1:
+ case 2: /* Address test, own address (test #1, 2) */
+ addr_tst2(my_cpu);
+ BAILOUT;
+ break;
+
+ case 3:
+ case 4: /* Moving inversions, all ones and zeros (tests #3, 4) */
p1 = 0;
p2 = ~p1;
- movinv1(tseq[v->test].iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p1,p2,my_cpu);
BAILOUT;
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- movinv1(tseq[v->test].iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p2,p1,my_cpu);
BAILOUT;
break;
- case 1: /* Moving inversions, 8 bit wide walking ones and zeros. */
+ case 5: /* Moving inversions, 8 bit walking ones and zeros (test #5) */
p0 = 0x80;
for (i=0; i<8; i++, p0=p0>>1) {
p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
p2 = ~p1;
- movinv1(tseq[v->test].iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p1,p2, my_cpu);
BAILOUT;
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- movinv1(tseq[v->test].iter,p1,p2);
+ s_barrier();
+ movinv1(c_iter,p2,p1, my_cpu);
BAILOUT
}
break;
- case 2: /* Moving inversions, 32 bit shifting pattern, very long */
+ case 6: /* Random Data (test #6) */
+ /* Seed the random number generator */
+ if (my_cpu == mstr_cpu) {
+ if (v->rdtsc) {
+ asm __volatile__ ("rdtsc":"=a" (sp1),"=d" (sp2));
+ } else {
+ sp1 = 521288629 + v->pass;
+ sp2 = 362436069 - v->pass;
+ }
+ rand_seed(sp1, sp2, 0);
+ }
+
+ s_barrier();
+ for (i=0; i < c_iter; i++) {
+ if (my_cpu == mstr_cpu) {
+ sp1 = rand(0);
+ sp2 = ~p1;
+ }
+ s_barrier();
+ movinv1(2,sp1,sp2, my_cpu);
+ BAILOUT;
+ }
+ break;
+
+ case 7: /* Block move (test #7) */
+ block_move(c_iter, my_cpu);
+ BAILOUT;
+ break;
+
+ case 8: /* Moving inversions, 32 bit shifting pattern (test #8) */
for (i=0, p1=1; p1; p1=p1<<1, i++) {
- movinv32(tseq[v->test].iter,p1, 1, 0x80000000, 0, i);
+ s_barrier();
+ movinv32(c_iter,p1, 1, 0x80000000, 0, i, my_cpu);
BAILOUT
- movinv32(tseq[v->test].iter,~p1, 0xfffffffe,
- 0x7fffffff, 1, i);
+ s_barrier();
+ movinv32(c_iter,~p1, 0xfffffffe,
+ 0x7fffffff, 1, i, my_cpu);
BAILOUT
}
break;
- case 3: /* Modulo 20 check, all ones and zeros */
- p1=0;
- for (i=0; i<MOD_SZ; i++) {
- p2 = ~p1;
- modtst(i, tseq[v->test].iter, p1, p2);
- BAILOUT
-
- /* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- modtst(i, tseq[v->test].iter, p1,p2);
- BAILOUT
+ case 9: /* Random Data Sequence (test #9) */
+ for (i=0; i < c_iter; i++) {
+ s_barrier();
+ movinvr(my_cpu);
+ BAILOUT;
}
break;
- case 4: /* Modulo 20 check, 8 bit pattern */
- p0 = 0x80;
- for (j=0; j<8; j++, p0=p0>>1) {
- p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
+ case 10: /* Modulo 20 check, Random pattern (test #10) */
+ for (j=0; j<c_iter; j++) {
+ p1 = rand(0);
for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- modtst(i, tseq[v->test].iter, p1, p2);
+ s_barrier();
+ modtst(i, 2, p1, p2, my_cpu);
BAILOUT
/* Switch patterns */
- p2 = p1;
- p1 = ~p2;
- modtst(i, tseq[v->test].iter, p1, p2);
+ s_barrier();
+ modtst(i, 2, p2, p1, my_cpu);
BAILOUT
}
}
break;
- case 5: /* Address test, walking ones */
- addr_tst1();
- BAILOUT;
- break;
- case 6: /* Address test, own address */
- addr_tst2();
- BAILOUT;
- break;
-
- case 7: /* Block move test */
- block_move(tseq[v->test].iter);
- BAILOUT;
- break;
- case 8: /* Bit fade test */
- if (window == 0 ) {
- bit_fade();
+ case 11: /* Bit fade test, fill (test #11) */
+ /* Use a sequence to process all windows for each stage */
+ switch(bitf_seq) {
+ case 0: /* Fill all of memory 0's */
+ bit_fade_fill(0, my_cpu);
+ bitf_sleep = 1;
+ break;
+ case 1: /* Sleep for the specified time */
+ /* Only sleep once */
+ if (bitf_sleep) {
+ sleep(c_iter, 1, my_cpu);
+ bitf_sleep = 0;
+ }
+ break;
+ case 2: /* Now check all of memory for changes */
+ bit_fade_chk(0, my_cpu);
+ break;
+ case 3: /* Fill all of memory 1's */
+ bit_fade_fill(-1, my_cpu);
+ bitf_sleep = 1;
+ break;
+ case 4: /* Sleep for the specified time */
+ /* Only sleep once */
+ if (bitf_sleep) {
+ sleep(c_iter, 1, my_cpu);
+ bitf_sleep = 0;
+ }
+ break;
+ case 5: /* Now check all of memory for changes */
+ bit_fade_chk(-1, my_cpu);
+ break;
}
BAILOUT;
break;
- case 9: /* Random Data Sequence */
- for (i=0; i < tseq[v->test].iter; i++) {
- movinvr();
- BAILOUT;
- }
- break;
- case 10: /* Random Data */
- for (i=0; i < tseq[v->test].iter; i++) {
- p1 = rand();
+
+ case 90: /* Modulo 20 check, all ones and zeros (unused) */
+ p1=0;
+ for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- movinv1(2,p1,p2);
- BAILOUT;
+ modtst(i, c_iter, p1, p2, my_cpu);
+ BAILOUT
+
+ /* Switch patterns */
+ p2 = p1;
+ p1 = ~p2;
+ modtst(i, c_iter, p1,p2, my_cpu);
+ BAILOUT
}
break;
- case 11: /* Modulo 20 check, Random pattern */
- for (j=0; j<tseq[v->test].iter; j++) {
- p1 = rand();
+ case 91: /* Modulo 20 check, 8 bit pattern (unused) */
+ p0 = 0x80;
+ for (j=0; j<8; j++, p0=p0>>1) {
+ p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24);
for (i=0; i<MOD_SZ; i++) {
p2 = ~p1;
- modtst(i, tseq[v->test].iter, p1, p2);
+ modtst(i, c_iter, p1, p2, my_cpu);
BAILOUT
/* Switch patterns */
p2 = p1;
p1 = ~p2;
- modtst(i, tseq[v->test].iter, p1, p2);
+ modtst(i, c_iter, p1, p2, my_cpu);
BAILOUT
}
}
break;
}
- skip_window:
- if (bail) {
- goto bail_test;
- }
- /* Rever to the default mapping and enable the cache */
- paging_off();
- set_cache(1);
- window++;
- if (window >= sizeof(windows)/sizeof(windows[0])) {
- window = 0;
- }
- /* We finished the test so clear the pattern */
- cprint(LINE_PAT, COL_PAT, " ");
- if (window != 0) {
- /* Relocate and run the high copy if:
- * - The window overwrites us.
- * The lower limit is less than START_ADR
- * - There is enough memory
- */
- if (windows[window].start <
- ((ulong)&_start + (_end - _start)) >> 12) {
- if (v->pmap[v->msegs-1].end >
- (((high_test_adr + (_end - _start)) >> 12)+1)) {
- /* We need the high copy and we have enough
- * memory so use it.
- */
- run_at(high_test_adr);
- } else {
- /* We can't use this window so skip it */
- goto skip_window;
- }
- } else {
- /* We don't need the high copy for this test */
- run_at(LOW_TEST_ADR);
- }
- } else {
- /* We have run this test in all of the windows
- * advance to the next test.
- */
- skip_test:
- v->test++;
- bail_test:
- /* Revert to the default mapping
- * and enable the cache.
- */
- paging_off();
- set_cache(1);
- check_input();
- window = 0;
- cprint(LINE_PAT, COL_PAT-3, " ");
- /* If this was the last test then we finished a pass */
- if (v->test >= DEFTESTS || v->testsel >= 0) {
- v->pass++;
- dprint(LINE_INFO, COL_PASS, v->pass, 5, 0);
- v->test = 0;
- v->total_ticks = 0;
- v->pptr = 0;
- cprint(0, COL_MID+8,
- " ");
- if (v->ecount == 0 && v->testsel < 0) {
- cprint(LINE_MSG, COL_MSG,
- "Pass complete, no errors, press Esc to exit");
+ return(0);
+}
+
+/* Compute number of SPINSZ chunks being tested */
+int find_chunks(int tst)
+{
+ int i, j, sg, wmax, ch;
+ struct pmap twin={0,0};
+ unsigned long wnxt = TWO_GB;
+ unsigned long len;
+
+ wmax = MAX_MEM/TWO_GB+2; /* The number of 2 GB segments +2 */
+ /* Compute the number of SPINSZ memory segments */
+ ch = 0;
+ for(j = 0; j < wmax; j++) {
+ /* special case for relocation */
+ if (j == 0) {
+ twin.start = 0;
+ twin.end = win1_end;
+ }
+
+ /* special case for first 2 GB */
+ if (j == 1) {
+ twin.start = win0_start;
+ twin.end = TWO_GB;
+ }
+
+ /* For all other windows */
+ if (j > 1) {
+ twin.start = wnxt;
+ wnxt += TWO_GB;
+ twin.end = wnxt;
+ }
+
+ /* Find the memory areas I am going to test */
+ sg = compute_segments(twin);
+ for(i = 0; i < sg; i++) {
+ len = v->map[i].end - v->map[i].start;
+
+ if (cpu_mode == CPM_ALL && num_cpus > 1) {
+ switch(tseq[tst].pat) {
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 9:
+ case 10:
+ len /= num_cpus;
+ break;
+ case 7:
+ case 8:
+ len /= (num_cpus & 0xe);
+ break;
+ }
}
+ ch += (len + SPINSZ -1)/SPINSZ;
}
-
- /* We always start a pass with the low copy */
- run_at(LOW_TEST_ADR);
}
+ return(ch);
}
-void restart()
+/* Compute the total number of ticks per pass */
+void find_ticks_for_pass(void)
{
int i;
- volatile char *pp;
- /* clear variables */
- firsttime = 0;
- v->test = 0;
- v->pass = 0;
- v->msg_line = 0;
- v->ecount = 0;
- v->ecc_ecount = 0;
-
- /* Clear the screen */
- for(i=0, pp=(char *)(SCREEN_ADR+0); i<80*24; i++, pp+=2) {
- *pp = ' ';
- }
- run_at(LOW_TEST_ADR);
+ v->pptr = 0;
+ v->pass_ticks=0;
+ if (v->testsel >= 0) {
+ v->pass_ticks = find_ticks_for_test(v->testsel);
+ } else {
+ for (i=0; i<DEFTESTS; i++) {
+ /* Skip tests 2 and 4 if we are using 1 cpu */
+ if (num_cpus == 1 && (i == 2 || i == 4)) {
+ continue;
+ }
+ v->pass_ticks += find_ticks_for_test(i);
+ }
+ }
}
-
-/* Compute the total number of ticks per pass */
-void find_ticks(void)
+static int find_ticks_for_test(int tst)
{
- int i, j, chunks;
+ int ticks=0, c, ch;
- v->pptr = 0;
+ /* Determine the number of chunks for this test */
+ ch = find_chunks(tst);
- /* Compute the number of SPINSZ memory segments in one pass */
- chunks = 0;
- for(j = 0; j < sizeof(windows)/sizeof(windows[0]); j++) {
- compute_segments(j);
- for(i = 0; i < segs; i++) {
- unsigned long len;
- len = v->map[i].end - v->map[i].start;
- chunks += (len + SPINSZ -1)/SPINSZ;
- }
+ /* Set the number of iterations. We only do 1/3 of the iterations */
+ /* on the first pass */
+ if (v->pass == 0) {
+ c = tseq[tst].iter/3;
+ } else {
+ c = tseq[tst].iter;
}
- compute_segments(window);
- window = 0;
- for (v->pass_ticks=0, i=0; i<DEFTESTS; i++) {
- /* Test to see if this test is selected for execution */
- if (v->testsel >= 0) {
- if (i != v->testsel) {
- continue;
- }
- }
- v->pass_ticks += find_ticks_for_test(chunks, i);
+ switch(tseq[tst].pat) {
+ case 0: /* Address test, walking ones */
+ ticks = 2;
+ break;
+ case 1: /* Address test, own address */
+ case 2:
+ ticks = 2;
+ break;
+ case 3: /* Moving inversions, all ones and zeros */
+ case 4:
+ ticks = 2 + 4 * c;
+ break;
+ case 5: /* Moving inversions, 8 bit walking ones and zeros */
+ ticks = 24 + 24 * c;
+ break;
+ case 6: /* Random Data */
+ ticks = c + 4 * c;
+ break;
+ case 7: /* Block move */
+ ticks = (ch + ch/num_cpus + c*ch);
+ break;
+ case 8: /* Moving inversions, 32 bit shifting pattern */
+ ticks = (1 + c * 2) * 64;
+ break;
+ case 9: /* Random Data Sequence */
+ ticks = 3 * c;
+ break;
+ case 10: /* Modulo 20 check, Random pattern */
+ ticks = 4 * 40 * c;
+ break;
+ case 11: /* Bit fade test */
+ ticks = c * 2 + 4 * ch;
+ break;
+ case 90: /* Modulo 20 check, all ones and zeros (unused) */
+ ticks = (2 + c) * 40;
+ break;
+ case 91: /* Modulo 20 check, 8 bit pattern (unused) */
+ ticks = (2 + c) * 40 * 8;
+ break;
}
-}
-
-static int find_ticks_for_test(unsigned long chunks, int test)
-{
- int ticks;
- ticks = chunks * tseq[test].ticks;
- if (tseq[test].pat == 5) {
- /* Address test, walking ones */
- ticks = 4;
+ if (cpu_mode == CPM_SEQ || tseq[tst].cpu_sel == -1) {
+ ticks *= num_cpus;
+ }
+ if (tseq[tst].pat == 7 || tseq[tst].pat == 11) {
+ return ticks;
}
- return ticks;
+ return ticks*ch;
}
-static void compute_segments(int win)
+static int compute_segments(struct pmap win)
{
unsigned long wstart, wend;
- int i;
+ int i, sg;
/* Compute the window I am testing memory in */
- wstart = windows[win].start;
- wend = windows[win].end;
- segs = 0;
+ wstart = win.start;
+ wend = win.end;
+ sg = 0;
/* Now reduce my window to the area of memory I want to test */
if (wstart < v->plim_lower) {
@@ -483,7 +902,7 @@
wend = v->plim_upper;
}
if (wstart >= wend) {
- return;
+ return(0);
}
/* List the segments being tested */
for (i=0; i< v->msegs; i++) {
@@ -516,9 +935,9 @@
cprint(LINE_SCROLL+(2*i), 64, ") ");
cprint(LINE_SCROLL+(2*i+1), 0, "w(");
- hprint(LINE_SCROLL+(2*i+1), 2, windows[win].start);
+ hprint(LINE_SCROLL+(2*i+1), 2, win.start);
cprint(LINE_SCROLL+(2*i+1), 10, ", ");
- hprint(LINE_SCROLL+(2*i+1), 12, windows[win].end);
+ hprint(LINE_SCROLL+(2*i+1), 12, win.end);
cprint(LINE_SCROLL+(2*i+1), 20, ") ");
cprint(LINE_SCROLL+(2*i+1), 22, "m(");
@@ -529,7 +948,6 @@
cprint(LINE_SCROLL+(2*i+1), 44, "i=");
hprint(LINE_SCROLL+(2*i+1), 46, i);
- init();
cprint(LINE_SCROLL+(2*i+2), 0,
" "
@@ -539,14 +957,27 @@
" ");
#endif
if ((start < end) && (start < wend) && (end > wstart)) {
- v->map[segs].pbase_addr = start;
- v->map[segs].start = mapping(start);
- v->map[segs].end = emapping(end);
+ v->map[sg].pbase_addr = start;
+ v->map[sg].start = mapping(start);
+ v->map[sg].end = emapping(end);
+#if 0
+ hprint(LINE_SCROLL+(sg+1), 0, sg);
+ hprint(LINE_SCROLL+(sg+1), 12, v->map[sg].pbase_addr);
+ hprint(LINE_SCROLL+(sg+1), 22, start);
+ hprint(LINE_SCROLL+(sg+1), 32, end);
+ hprint(LINE_SCROLL+(sg+1), 42, mapping(start));
+ hprint(LINE_SCROLL+(sg+1), 52, emapping(end));
+ cprint(LINE_SCROLL+(sg+2), 0,
+ " "
+ " ");
+#endif
#if 0
- cprint(LINE_SCROLL+(2*i+1), 54, " segs: ");
- hprint(LINE_SCROLL+(2*i+1), 61, segs);
+ cprint(LINE_SCROLL+(2*i+1), 54, ", sg=");
+ hprint(LINE_SCROLL+(2*i+1), 59, sg);
#endif
- segs++;
+ sg++;
}
}
+ return (sg);
}
+
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/makeiso.sh
^
|
@@ -25,15 +25,20 @@
cat memtest.bin fill.tmp >memtest.img
rm -f fill.tmp
-echo "generating iso image ..."
+echo "Generating iso image ..."
mkdir "cd"
mkdir "cd/boot"
mv memtest.img cd/boot
cd cd
-mkisofs -b boot/memtest.img -c boot/boot.catalog -o memtest.iso .
+
+# Create the cd.README
+echo -e "Memtest86 is located on the bootsector of this CD\r\r\n" > README.TXT
+echo -e "Just boot from this CD and Memtest86 will start" >> README.TXT
+
+mkisofs -p "Memtest86 4.0" -publisher "Chris S. Brady - BradyTech Inc." -b boot/memtest.img -c boot/boot.catalog -V "MT350" -o memtest.iso .
mv memtest.iso ..
cd ..
rm -rf cd
-echo "done"
+echo "Done"
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/memsize.c
^
|
@@ -10,35 +10,38 @@
short e820_nr;
short memsz_mode = SZ_MODE_BIOS;
-short firmware = FIRMWARE_UNKNOWN;
static ulong alt_mem_k;
static ulong ext_mem_k;
static struct e820entry e820[E820MAX];
-extern ulong p1, p2;
-extern volatile ulong *p;
+ulong p1, p2;
+ulong *p;
static void sort_pmap(void);
-static int check_ram(void);
-static void memsize_bios(int res);
-static void memsize_820(int res);
+static void memsize_bios(void);
+static void memsize_820(void);
static void memsize_801(void);
-static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios,
- short old_nr, short res);
+static int sanitize_e820_map(struct e820entry *orig_map,
+ struct e820entry *new_bios, short old_nr);
static void memsize_linuxbios();
-static void memsize_probe(void);
-static int check_ram(void);
/*
* Find out how much memory there is.
*/
void mem_size(void)
{
- int i;
- v->reserved_pages = 0;
+ int i, flag=0;
v->test_pages = 0;
+ /* Get the memory size from the BIOS */
+ /* Determine the memory map */
+ if (query_linuxbios()) {
+ flag = 1;
+ } else if (query_pcbios()) {
+ flag = 2;
+ }
+
/* On the first time thru only */
/* Make a copy of the memory info table so that we can re-evaluate */
/* The memory map later */
@@ -52,39 +55,18 @@
e820[i].type = mem_info.e820[i].type;
}
}
-
- switch (memsz_mode) {
- case SZ_MODE_BIOS:
- /* Get the memory size from the BIOS */
- memsize_bios(0);
- break;
- case SZ_MODE_BIOS_RES:
- /* Get the memory size from the BIOS, include reserved mem */
- memsize_bios(1);
- break;
- case SZ_MODE_PROBE:
- /* Probe to find memory */
- memsize_probe();
- cprint(LINE_INFO, COL_MMAP, " Probed ");
- break;
+ if (flag == 1) {
+ memsize_linuxbios();
+ } else if (flag == 2) {
+ memsize_820();
}
+
/* Guarantee that pmap entries are in ascending order */
sort_pmap();
v->plim_lower = 0;
v->plim_upper = v->pmap[v->msegs-1].end;
adj_mem();
- aprint(LINE_INFO, COL_RESERVED, v->reserved_pages);
-}
-
-static void memsize_bios(int res)
-{
- if (firmware == FIRMWARE_PCBIOS) {
- memsize_820(res);
- }
- else if (firmware == FIRMWARE_LINUXBIOS) {
- memsize_linuxbios();
- }
}
static void sort_pmap(void)
@@ -118,6 +100,7 @@
n = 0;
for (i=0; i < e820_nr; i++) {
unsigned long long end;
+
if (e820[i].type != E820_RAM) {
continue;
}
@@ -129,16 +112,16 @@
n++;
}
v->msegs = n;
- cprint(LINE_INFO, COL_MMAP, "LinuxBIOS");
}
-static void memsize_820(int res)
+static void memsize_820()
{
int i, n, nr;
struct e820entry nm[E820MAX];
+ unsigned long long start;
+ unsigned long long end;
/* Clean up, adjust and copy the BIOS-supplied E820-map. */
- /* If the res arg is true reclassify reserved memory as E820_RAM */
- nr = sanitize_e820_map(e820, nm, e820_nr, res);
+ nr = sanitize_e820_map(e820, nm, e820_nr);
/* If there is not a good 820 map use the BIOS 801/88 info */
if (nr < 1 || nr > E820MAX) {
@@ -149,9 +132,7 @@
/* Build the memory map for testing */
n = 0;
for (i=0; i<nr; i++) {
- if (nm[i].type == E820_RAM) {
- unsigned long long start;
- unsigned long long end;
+ if (nm[i].type == E820_RAM || nm[i].type == E820_ACPI) {
start = nm[i].addr;
end = start + nm[i].size;
@@ -169,22 +150,9 @@
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
- } else {
- /* If this is reserved memory starting at the top
- * of memory then don't count it as reserved, since
- * it is very unlikely to be real memory.
- */
- if (nm[i].addr < 0xff000000) {
- v->reserved_pages += nm[i].size >> 12;
- }
}
}
v->msegs = n;
- if (res) {
- cprint(LINE_INFO, COL_MMAP, "e820-All");
- } else {
- cprint(LINE_INFO, COL_MMAP, "e820-Std");
- }
}
static void memsize_801(void)
@@ -196,10 +164,8 @@
if (alt_mem_k < ext_mem_k) {
mem_size = ext_mem_k;
- cprint(LINE_INFO, COL_MMAP, "e88-Std ");
} else {
mem_size = alt_mem_k;
- cprint(LINE_INFO, COL_MMAP, "e801-Std");
}
/* First we map in the first 640k */
v->pmap[0].start = 0;
@@ -221,7 +187,7 @@
*
*/
static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios,
- short old_nr, short res)
+ short old_nr)
{
struct change_member {
struct e820entry *pbios; /* pointer to original bios entry */
@@ -284,22 +250,6 @@
for (i=0; i<old_nr; i++) {
if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
return 0;
- if (res) {
- /* If we want to test the reserved memory include
- * everything except for reserved segments that start
- * at the the top of memory
- */
- if (biosmap[i].type == E820_RESERVED &&
- biosmap[i].addr > 0xff000000) {
- continue;
- }
- biosmap[i].type = E820_RAM;
- } else {
- /* It is always be safe to test ACPI ram */
- if ( biosmap[i].type == E820_ACPI) {
- biosmap[i].type = E820_RAM;
- }
- }
}
/* create pointers for initial change-point information (for sorting) */
@@ -386,130 +336,3 @@
}
return(new_bios_entry);
}
-
-static void memsize_probe(void)
-{
- int i, n;
- ulong m_lim;
- static unsigned long magic = 0x1234569;
-
- /* Since all address bits may not be decoded, the search for memory
- * must be limited. The max address is found by checking for
- * memory wrap from 1MB to 4GB. */
- p1 = (ulong)&magic;
- m_lim = 0xfffffffc;
- for (p2 = 0x100000; p2; p2 <<= 1) {
- p = (ulong *)(p1 + p2);
- if (*p == 0x1234569) {
- m_lim = --p2;
- break;
- }
- }
-
- /* Turn on cache */
- set_cache(1);
-
- /* Find all segments of RAM */
-
- i = 0;
- v->pmap[i].start = ((ulong)&_end + (1 << 12) - 1) >> 12;
- p = (ulong *)(v->pmap[i].start << 12);
-
- /* Limit search for memory to m_lim and make sure we don't
- * overflow the 32 bit size of p. */
- while ((ulong)p < m_lim && (ulong)p >= (ulong)&_end) {
- /*
- * Skip over reserved memory
- */
- if ((ulong)p < RES_END && (ulong)p >= RES_START) {
- v->pmap[i].end = RES_START >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- p = (ulong *)RES_END;
- i++;
- v->pmap[i].start = 0;
- goto fstart;
- }
-
- if (check_ram() == 0) {
- /* ROM or nothing at this address, record end addrs */
- v->pmap[i].end = ((ulong)p) >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- i++;
- v->pmap[i].start = 0;
-fstart:
-
- /* We get here when there is a gap in memory.
- * Loop until we find more ram, the gap is more
- * than 32768k or we hit m_lim */
- n = 32768 >> 2;
- while ((ulong)p < m_lim && (ulong)p >= (ulong)&_end) {
-
- /* Skip over video memory */
- if ((ulong)p < RES_END &&
- (ulong)p >= RES_START) {
- p = (ulong *)RES_END;
- }
- if (check_ram() == 1) {
- /* More RAM, record start addrs */
- v->pmap[i].start = (ulong)p >> 12;
- break;
- }
-
- /* If the gap is 32768k or more then there
- * is probably no more memory so bail out */
- if (--n <= 0) {
- p = (ulong *)m_lim;
- break;
- }
- p += 0x1000;
- }
- }
- p += 0x1000;
- }
-
- /* If there is ram right up to the memory limit this will record
- * the last address. */
- if (v->pmap[i].start) {
- v->pmap[i].end = m_lim >> 12;
- v->test_pages += (v->pmap[i].end - v->pmap[i].start);
- i++;
- }
- v->msegs = i;
-}
-
-/* check_ram - Determine if this address points to memory by checking
- * for a wrap pattern and then reading and then writing the complement.
- * We then check that at least one bit changed in each byte before
- * believing that it really is memory. */
-
-static int check_ram(void)
-{
- int s;
-
- p1 = *p;
-
- /* write the complement */
- *p = ~p1;
- p2 = *p;
- s = 0;
-
- /* Now make sure a bit changed in each byte */
- if ((0xff & p1) != (0xff & p2)) {
- s++;
- }
- if ((0xff00 & p1) != (0xff00 & p2)) {
- s++;
- }
- if ((0xff0000 & p1) != (0xff0000 & p2)) {
- s++;
- }
- if ((0xff000000 & p1) != (0xff000000 & p2)) {
- s++;
- }
- if (s == 4) {
- /* RAM at this address */
- return 1;
- }
-
- return 0;
-}
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/memtest_shared.lds
^
|
@@ -8,7 +8,6 @@
_start = .;
*(.text)
*(.text.*)
- *(.gnu.linkonce.t.__i686.get_pc_thunk.*)
*(.plt)
_etext = . ;
} = 0x9090
@@ -19,6 +18,7 @@
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynamic : { *(.dynamic) }
.rel.text : { *(.rel.text .rel.text.*) }
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/mkusb_img.sh
^
|
@@ -0,0 +1,74 @@
+#!/bin/ksh
+
+DEV="/dev/sdd"
+IDIR=/ptmp/usb
+ISOF=/bradytech/src/boot_files
+BINDIR=/bradytech/src/bin
+NSECT=64 # Number of sectors
+NHDS=32 # Number of heads
+NCYL=1 # Number of cylinders
+NBLKS=2050 # Number of blocks (NSECT*NHDS*NCYL+2)
+
+dir=/bradytech/src/memtest86-3.6
+
+print "Insert USB Key"
+print "Creating image on device $DEV"
+print "Is this correct?"
+read ans
+if [ $ans != "y" ]
+then
+ exit
+fi
+
+$BINDIR/mkdiskimage -4 $DEV $NCYL $NSECT $NHDS
+sync
+sleep 2
+
+mkfs.msdos ${DEV}4
+$BINDIR/syslinux ${DEV}4
+mkdir $IDIR
+mount ${DEV}4 $IDIR
+
+# Copy boot files
+cd $ISOF
+cp boot.txt $IDIR
+cp boot.cfg $IDIR/syslinux.cfg
+cd -
+
+# Create std boot images
+cd $dir
+make
+cp memtest.bin $IDIR/memtest
+make smp
+cp memtest.bin $IDIR/memtest.smp
+cd -
+
+umount $IDIR
+
+# Create image
+dd if=$DEV count=$NBLKS of=memtest86-3.6.usb
+cat <<EOF>README
+Installation instructions for the Memtest86 USB key image (Linux Only).
+=======================================================================
+
+1) Insert a USB key into a USB slot.
+2) Determine which device the USB key is assigned as (ie. /dev/sdc).
+3) As root type: dd if=memtest86-3.5.usb of=dev where dev is the device
+the key is assigned to. Use the base device (ie. /dev/sdc) not a partition
+designation (ie. /dev/sdc1).
+
+Warning: all data on the USB key will be lost.
+Warning Warning: Make sure that the device used in the dd command above
+is correct!!!
+EOF
+tar cvzf memtest86-3.5.usb.tgz memtest86-3.5.usb README
+chown cbrady memtest86-3.5.usb.tgz
+rm memtest86-3.5.usb README
+
+cd -
+# Clean up
+rm -rf $IDIR
+cd $dir
+make clean
+print "## Done!"
+
|
|
Changed |
memtest86-4.0.tar.bz2/precomp.bin
^
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/random.c
^
|
@@ -1,31 +1,36 @@
+/******************************************************************/
+/* Random number generator */
/* concatenation of following two 16-bit multiply with carry generators */
/* x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16, */
/* number and carry packed within the same 32 bit integer. */
/******************************************************************/
+#include "smp.h"
-unsigned int rand( void ); /* returns a random 32-bit integer */
-void rand_seed( unsigned int, unsigned int ); /* seed the generator */
+/* Keep a separate seed for each CPU */
+/* Space the seeds by at least a cache line or performance suffers big time! */
+static unsigned int SEED_X[MAX_CPUS*16];
+static unsigned int SEED_Y[MAX_CPUS*16];
-/* return a random float >= 0 and < 1 */
-#define rand_float ((double)rand() / 4294967296.0)
+unsigned long rand (int cpu)
+{
+ static unsigned int a = 18000, b = 30903;
+ int me;
-static unsigned int SEED_X = 521288629;
-static unsigned int SEED_Y = 362436069;
+ me = cpu*16;
+ SEED_X[me] = a*(SEED_X[me]&65535) + (SEED_X[me]>>16);
+ SEED_Y[me] = b*(SEED_Y[me]&65535) + (SEED_Y[me]>>16);
-unsigned int rand ()
- {
- static unsigned int a = 18000, b = 30903;
+ return ((SEED_X[me]<<16) + (SEED_Y[me]&65535));
+}
- SEED_X = a*(SEED_X&65535) + (SEED_X>>16);
- SEED_Y = b*(SEED_Y&65535) + (SEED_Y>>16);
- return ((SEED_X<<16) + (SEED_Y&65535));
- }
+void rand_seed( unsigned int seed1, unsigned int seed2, int cpu)
+{
+ int me;
+ me = cpu*16;
+ SEED_X[me] = seed1;
+ SEED_Y[me] = seed2;
+}
-void rand_seed( unsigned int seed1, unsigned int seed2 )
- {
- if (seed1) SEED_X = seed1; /* use default seeds if parameter is 0 */
- if (seed2) SEED_Y = seed2;
- }
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/serial.h
^
|
@@ -136,8 +136,8 @@
*/
#include "io.h"
-#define serial_echo_outb(v,a) outb((v),(a)+0x3f8)
-#define serial_echo_inb(a) inb((a)+0x3f8)
+#define serial_echo_outb(v,a) outb((v),(a)+serial_base_ports[serial_tty])
+#define serial_echo_inb(a) inb((a)+serial_base_ports[serial_tty])
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/* Wait for transmitter & holding register to empty */
#define WAIT_FOR_XMITR \
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/setup.S
^
|
@@ -21,19 +21,50 @@
movb $0x80, %al # disable NMI for the bootup sequence
outb %al, $0x70
- movb $0x01, %ah # turn off the cursor
- movb $0x00, %bh
- movw $0x2000, %cx
- int $0x10
-
# The system will move itself to its rightful place.
-
+# reload the segment registers and the stack since the
+# APs also execute this code
+#ljmp $INITSEG, $(reload - start + 0x200)
+reload:
+ movw $INITSEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %ss # reset the stack to INITSEG:0x4000-12.
+ movw %dx, %sp
push %cs
pop %ds
lidt idt_48 - start # load idt with 0,0
lgdt gdt_48 - start # load gdt with whatever appropriate
# that was painless, now we enable A20
+# start from grub-a20.patch
+ /*
+ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
+ * register
+ */
+ mov $0x92, %dx
+ inb %dx, %al
+ /* skip the port92 code if it's unimplemented (read returns 0xff) */
+ cmpb $0xff, %al
+ jz alt_a20_done
+
+ /* set or clear bit1, the ALT_A20_GATE bit */
+ movb 4(%esp), %ah
+ testb %ah, %ah
+ jz alt_a20_cont1
+ orb $2, %al
+ jmp alt_a20_cont2
+alt_a20_cont1:
+ and $0xfd, %al
+
+ /* clear the INIT_NOW bit; don't accidently reset the machine */
+alt_a20_cont2:
+ and $0xfe, %al
+ outb %al, %dx
+
+alt_a20_done:
+# end from grub-a20.patch
call empty_8042
@@ -72,6 +103,8 @@
empty_8042:
call delay
inb $0x64, %al # 8042 status port
+ cmpb $0xff, %al # from grub-a20-patch, skip if not impl
+ jz empty_8042_ret
testb $1, %al # output buffer?
jz no_output
call delay
@@ -81,6 +114,7 @@
no_output:
testb $2, %al # is input buffer full?
jnz empty_8042 # yes - loop
+empty_8042_ret:
ret
#
# Delay is needed after doing i/o
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/smp.c
^
|
@@ -0,0 +1,627 @@
+/*
+ * smp.c --
+ */
+
+#include "stddef.h"
+#include "smp.h"
+#include "cpuid.h"
+#include "test.h"
+#define DELAY_FACTOR 1
+unsigned num_cpus = 1; // There is at least one cpu, the BSP
+unsigned found_cpus = 0;
+
+extern void memcpy(void *dst, void *src , int len);
+extern void test_start(void);
+extern int run_cpus;
+
+struct barrier_s *barr;
+
+void barrier_init(int max)
+{
+ /* Set the adddress of the barrier structure */
+ barr = (struct barrier_s *)0x9ff00;
+ barr->lck.slock = 1;
+ barr->mutex.slock = 1;
+ barr->maxproc = max;
+ barr->count = max;
+ barr->st1.slock = 1;
+ barr->st2.slock = 0;
+}
+
+void s_barrier_init(int max)
+{
+ barr->s_lck.slock = 1;
+ barr->s_maxproc = max;
+ barr->s_count = max;
+ barr->s_st1.slock = 1;
+ barr->s_st2.slock = 0;
+}
+
+/* Spin until var = 1 */
+void spin_wait(spinlock_t *lck)
+{
+ int inc = 0x400;
+
+ asm volatile( "1:\t"
+ "cmpb $0,%1\n\t"
+ "jne 2f\n\t"
+ "rep ; nop\n\t"
+ "jmp 1b\n"
+ "2:"
+ : : "c" (inc), "m" (lck->slock): "memory" );
+}
+
+void barrier()
+{
+ if (num_cpus == 1) {
+ return;
+ }
+ spin_wait(&barr->st1); /* Wait if the barrier is active */
+ spin_lock(&barr->lck); /* Get lock for barr struct */
+ if (--barr->count == 0) { /* Last process? */
+ barr->st1.slock = 0; /* Hold up any processes re-entering */
+ barr->st2.slock = 1; /* Release the other processes */
+ barr->count++;
+ spin_unlock(&barr->lck);
+ } else {
+ spin_unlock(&barr->lck);
+ spin_wait(&barr->st2); /* wait for peers to arrive */
+ spin_lock(&barr->lck);
+ if (++barr->count == barr->maxproc) {
+ barr->st1.slock = 1;
+ barr->st2.slock = 0;
+ }
+ spin_unlock(&barr->lck);
+ }
+}
+
+void s_barrier()
+{
+ if (run_cpus == 1) {
+ return;
+ }
+ spin_wait(&barr->s_st1); /* Wait if the barrier is active */
+ spin_lock(&barr->s_lck); /* Get lock for barr struct */
+ if (--barr->s_count == 0) { /* Last process? */
+ barr->s_st1.slock = 0; /* Hold up any processes re-entering */
+ barr->s_st2.slock = 1; /* Release the other processes */
+ barr->s_count++;
+ spin_unlock(&barr->s_lck);
+ } else {
+ spin_unlock(&barr->s_lck);
+ spin_wait(&barr->s_st2); /* wait for peers to arrive */
+ spin_lock(&barr->s_lck);
+ if (++barr->s_count == barr->s_maxproc) {
+ barr->s_st1.slock = 1;
+ barr->s_st2.slock = 0;
+ }
+ spin_unlock(&barr->s_lck);
+ }
+}
+
+typedef struct {
+ bool started;
+} ap_info_t;
+
+volatile apic_register_t *APIC = NULL;
+/* CPU number to APIC ID mapping table. CPU 0 is the BSP. */
+static unsigned cpu_num_to_apic_id[MAX_CPUS];
+volatile ap_info_t AP[MAX_CPUS];
+
+void PUT_MEM16(uintptr_t addr, uint16_t val)
+{
+ *((volatile uint16_t *)addr) = val;
+}
+
+void PUT_MEM32(uintptr_t addr, uint32_t val)
+{
+ *((volatile uint32_t *)addr) = val;
+}
+
+static void inline
+APIC_WRITE(unsigned reg, uint32_t val)
+{
+ APIC[reg][0] = val;
+}
+
+static inline uint32_t
+APIC_READ(unsigned reg)
+{
+ return APIC[reg][0];
+}
+
+
+static void
+SEND_IPI(unsigned apic_id, unsigned trigger, unsigned level, unsigned mode,
+ uint8_t vector)
+{
+ uint32_t v;
+
+ v = APIC_READ(APICR_ICRHI) & 0x00ffffff;
+ APIC_WRITE(APICR_ICRHI, v | (apic_id << 24));
+
+ v = APIC_READ(APICR_ICRLO) & ~0xcdfff;
+ v |= (APIC_DEST_DEST << APIC_ICRLO_DEST_OFFSET)
+ | (trigger << APIC_ICRLO_TRIGGER_OFFSET)
+ | (level << APIC_ICRLO_LEVEL_OFFSET)
+ | (mode << APIC_ICRLO_DELMODE_OFFSET)
+ | (vector);
+ APIC_WRITE(APICR_ICRLO, v);
+}
+
+
+// Silly way of busywaiting, but we don't have a timer
+void delay(unsigned us)
+{
+ unsigned freq = 1000; // in MHz, assume 1GHz CPU speed
+ uint64_t cycles = us * freq;
+ uint64_t t0 = RDTSC();
+ uint64_t t1;
+ volatile unsigned k;
+
+ do {
+ for (k = 0; k < 1000; k++) continue;
+ t1 = RDTSC();
+ } while (t1 - t0 < cycles);
+}
+
+static inline void
+memset (void *dst,
+ char value,
+ int len)
+{
+ int i;
+ for (i = 0 ; i < len ; i++ ) {
+ *((char *) dst + i) = value;
+ }
+}
+
+void kick_cpu(unsigned cpu_num)
+{
+ unsigned num_sipi, apic_id;
+ apic_id = cpu_num_to_apic_id[cpu_num];
+
+ // clear the APIC ESR register
+ APIC_WRITE(APICR_ESR, 0);
+ APIC_READ(APICR_ESR);
+
+ // asserting the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0);
+ delay(100000 / DELAY_FACTOR);
+
+ // de-assert the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0);
+
+ for (num_sipi = 0; num_sipi < 2; num_sipi++) {
+ unsigned timeout;
+ bool send_pending;
+ unsigned err;
+
+ APIC_WRITE(APICR_ESR, 0);
+
+ SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, (unsigned)startup_32 >> 12);
+
+ timeout = 0;
+ do {
+ delay(10);
+ timeout++;
+ send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0;
+ } while (send_pending && timeout < 1000);
+
+ if (send_pending) {
+ cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ }
+
+ delay(100000 / DELAY_FACTOR);
+
+ err = APIC_READ(APICR_ESR) & 0xef;
+ if (err) {
+ cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
+ hprint(LINE_STATUS+1, COL_MID, err);
+ }
+ }
+}
+
+// These memory locations are used for the trampoline code and data.
+
+#define BOOTCODESTART 0x9000
+#define GDTPOINTERADDR 0x9100
+#define GDTADDR 0x9110
+
+void boot_ap(unsigned cpu_num)
+{
+ unsigned num_sipi, apic_id;
+ extern uint8_t gdt;
+ extern uint8_t _ap_trampoline_start;
+ extern uint8_t _ap_trampoline_protmode;
+ unsigned len = &_ap_trampoline_protmode - &_ap_trampoline_start;
+ apic_id = cpu_num_to_apic_id[cpu_num];
+
+
+ memcpy((uint8_t*)BOOTCODESTART, &_ap_trampoline_start, len);
+
+ // Fixup the LGDT instruction to point to GDT pointer.
+ PUT_MEM16(BOOTCODESTART + 3, GDTPOINTERADDR);
+
+ // Copy a pointer to the temporary GDT to addr GDTPOINTERADDR.
+ // The temporary gdt is at addr GDTADDR
+ PUT_MEM16(GDTPOINTERADDR, 4 * 8);
+ PUT_MEM32(GDTPOINTERADDR + 2, GDTADDR);
+
+ // Copy the first 4 gdt entries from the currently used GDT to the
+ // temporary GDT.
+ memcpy((uint8_t *)GDTADDR, &gdt, 32);
+
+ // clear the APIC ESR register
+ APIC_WRITE(APICR_ESR, 0);
+ APIC_READ(APICR_ESR);
+
+ // asserting the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 1, APIC_DELMODE_INIT, 0);
+ delay(100000 / DELAY_FACTOR);
+
+ // de-assert the INIT IPI
+ SEND_IPI(apic_id, APIC_TRIGGER_LEVEL, 0, APIC_DELMODE_INIT, 0);
+
+ for (num_sipi = 0; num_sipi < 2; num_sipi++) {
+ unsigned timeout;
+ bool send_pending;
+ unsigned err;
+
+ APIC_WRITE(APICR_ESR, 0);
+
+ SEND_IPI(apic_id, 0, 0, APIC_DELMODE_STARTUP, BOOTCODESTART >> 12);
+
+ timeout = 0;
+ do {
+ delay(10);
+ timeout++;
+ send_pending = (APIC_READ(APICR_ICRLO) & APIC_ICRLO_STATUS_MASK) != 0;
+ } while (send_pending && timeout < 1000);
+
+ if (send_pending) {
+ cprint(LINE_STATUS+1, 0, "SMP: STARTUP IPI was never sent");
+ }
+
+ delay(100000 / DELAY_FACTOR);
+
+ err = APIC_READ(APICR_ESR) & 0xef;
+ if (err) {
+ cprint(LINE_STATUS+1, 0, "SMP: After STARTUP IPI: err = 0x");
+ hprint(LINE_STATUS+1, COL_MID, err);
+ }
+ }
+}
+
+static int checksum(unsigned char *mp, int len)
+{
+ int sum = 0;
+
+ while (len--) {
+ sum += *mp++;
+ }
+ return (sum & 0xFF);
+}
+
+/* Parse an MP config table for CPU information */
+bool read_mp_config_table(uintptr_t addr)
+{
+ mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
+ uint8_t *tab_entry_ptr;
+ uint8_t *mpc_table_end;
+
+ if (mpc->signature != MPCSignature) {
+ return FALSE;
+ }
+ if (checksum((unsigned char*)mpc, mpc->length) != 0) {
+ return FALSE;
+ }
+
+ /* FIXME: the uintptr_t cast here works around a compilation problem on
+ * AMD64, but it ignores the real problem, which is that lapic_addr
+ * is only 32 bits. Maybe that's OK, but it should be investigated.
+ */
+ APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
+
+ tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
+ mpc_table_end = ((uint8_t*)mpc) + mpc->length;
+ while (tab_entry_ptr < mpc_table_end) {
+ switch (*tab_entry_ptr) {
+ case MP_PROCESSOR: {
+ mp_processor_entry_t *pe = (mp_processor_entry_t*)tab_entry_ptr;
+
+ if (pe->cpu_flag & CPU_BOOTPROCESSOR) {
+ // BSP is CPU 0
+ cpu_num_to_apic_id[0] = pe->apic_id;
+ } else if (num_cpus < MAX_CPUS) {
+ cpu_num_to_apic_id[num_cpus] = pe->apic_id;
+ num_cpus++;
+ }
+ found_cpus++;
+
+ // we cannot handle non-local 82489DX apics
+ if ((pe->apic_ver & 0xf0) != 0x10) {
+ return 0;
+ }
+
+ tab_entry_ptr += sizeof(mp_processor_entry_t);
+ break;
+ }
+ case MP_BUS: {
+ tab_entry_ptr += sizeof(mp_bus_entry_t);
+ break;
+ }
+ case MP_IOAPIC: {
+ tab_entry_ptr += sizeof(mp_io_apic_entry_t);
+ break;
+ }
+ case MP_INTSRC:
+ tab_entry_ptr += sizeof(mp_interrupt_entry_t);
+ case MP_LINTSRC:
+ tab_entry_ptr += sizeof(mp_local_interrupt_entry_t);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* Search for a Floating Pointer structure */
+floating_pointer_struct_t *
+scan_for_floating_ptr_struct(uintptr_t addr, uint32_t length)
+{
+ floating_pointer_struct_t *fp;
+ uintptr_t end = addr + length;
+
+
+ while ((uintptr_t)addr < end) {
+ fp = (floating_pointer_struct_t*)addr;
+ if (*(unsigned int *)addr == FPSignature && fp->length == 1 &&
+ checksum((unsigned char*)addr, 16) == 0 &&
+ ((fp->spec_rev == 1) || (fp->spec_rev == 4))) {
+
+ return fp;
+ }
+ addr += 4;
+ }
+ return NULL;
+}
+
+/* Search for a Root System Descriptor Pointer */
+rsdp_t *scan_for_rsdp(uintptr_t addr, uint32_t length)
+{
+ rsdp_t *rp;
+ uintptr_t end = addr + length;
+
+
+ while ((uintptr_t)addr < end) {
+ rp = (rsdp_t*)addr;
+ if (*(unsigned int *)addr == RSDPSignature &&
+ checksum((unsigned char*)addr, rp->length) == 0) {
+ return rp;
+ }
+ addr += 4;
+ }
+ return NULL;
+}
+
+/* Parse a MADT table for processor entries */
+int parse_madt(uintptr_t addr) {
+
+ mp_config_table_header_t *mpc = (mp_config_table_header_t*)addr;
+ uint8_t *tab_entry_ptr;
+ uint8_t *mpc_table_end;
+
+ if (checksum((unsigned char*)mpc, mpc->length) != 0) {
+ return FALSE;
+ }
+
+ APIC = (volatile apic_register_t*)(uintptr_t)mpc->lapic_addr;
+
+ tab_entry_ptr = ((uint8_t*)mpc) + sizeof(mp_config_table_header_t);
+ mpc_table_end = ((uint8_t*)mpc) + mpc->length;
+ while (tab_entry_ptr < mpc_table_end) {
+
+ madt_processor_entry_t *pe = (madt_processor_entry_t*)tab_entry_ptr;
+ if (pe->type == MP_PROCESSOR) {
+ if (pe->enabled) {
+ if (num_cpus < MAX_CPUS) {
+ cpu_num_to_apic_id[num_cpus] = pe->apic_id;
+
+ /* the first CPU is the BSP, don't increment */
+ if (found_cpus) {
+ num_cpus++;
+ }
+ }
+ found_cpus++;
+ }
+ }
+ tab_entry_ptr += pe->length;
+ }
+ return TRUE;
+}
+
+/* This is where we search for SMP information in the following order
+ * look for a floating MP pointer
+ * found:
+ * check for a default configuration
+ * found:
+ * setup config, return
+ * check for a MP config table
+ * found:
+ * validate:
+ * good:
+ * parse the MP config table
+ * good:
+ * setup config, return
+ *
+ * find & validate ACPI RSDP (Root System Descriptor Pointer)
+ * found:
+ * find & validate RSDT (Root System Descriptor Table)
+ * found:
+ * find & validate MSDT
+ * found:
+ * parse the MADT table
+ * good:
+ * setup config, return
+ */
+void smp_init_bsp()
+{
+ floating_pointer_struct_t *fp;
+ rsdp_t *rp;
+ rsdt_t *rt;
+ uint8_t *tab_ptr, *tab_end;
+ unsigned int *ptr;
+
+ memset(&AP, 0, sizeof AP);
+
+ /* Search for the Floating MP structure pointer */
+ fp = scan_for_floating_ptr_struct(0x0, 0x400);
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(639*0x400, 0x400);
+ }
+ if (fp == NULL) {
+ fp = scan_for_floating_ptr_struct(0xf0000, 0x10000);
+ }
+ if (fp == NULL) {
+ /* Search the BIOS ESDS area */
+ unsigned int address = *(unsigned short *)0x40E;
+ address <<= 4;
+ if (address) {
+ fp = scan_for_floating_ptr_struct(address, 0x400);
+ }
+ }
+
+ if (fp != NULL) {
+ /* We have a floating MP pointer */
+
+ /* Is this a default configuration? */
+ if (fp->feature[0] > 0 && fp->feature[0] <=7) {
+ /* This is a default config so plug in the numbers */
+ num_cpus = 2;
+ APIC = 0xfee00000;
+ cpu_num_to_apic_id[0] = 0;
+ cpu_num_to_apic_id[1] = 1;
+ return;
+ }
+
+ /* Do we have a pointer to a MP configuration table? */
+ if ( fp->phys_addr != 0) {
+ if (read_mp_config_table(fp->phys_addr)) {
+ /* Found a good MP table, done */
+ return;
+ }
+ }
+ }
+
+ /* No MP table so far, try to find an ACPI MADT table
+ * We try to use the MP table first since there is no way to distinguish
+ * real cores from hyper-threads in the MADT */
+
+ /* Search for the RSDP */
+ rp = scan_for_rsdp(0xe0000, 0x20000);
+ if (rp == NULL) {
+ /* Search the BIOS ESDS area */
+ unsigned int address = *(unsigned short *)0x40E;
+ address <<= 4;
+ if (address) {
+ rp = scan_for_rsdp(address, 0x400);
+ }
+ }
+
+ if (rp == NULL) {
+ /* RSDP not found, give up */
+ return;
+ }
+
+ /* Found the RSDP, now get either the RSDP or XRSDP */
+ if (rp->revision >= 2) {
+ rt = (rsdt_t *)rp->xrsdt[0];
+ if (rt == 0) {
+ return;
+ }
+ /* Validate the XSDT */
+ if (*(unsigned int *)rt != XSDTSignature) {
+ return;
+ }
+ if ( checksum((unsigned char*)rt, rt->length) != 0) {
+ return;
+ }
+ } else {
+ rt = (rsdt_t *)rp->rsdt;
+ if (rt == 0) {
+ return;
+ }
+ /* Validate the RSDT */
+ if (*(unsigned int *)rt != RSDTSignature) {
+ return;
+ }
+ if ( checksum((unsigned char*)rt, rt->length) != 0) {
+ return;
+ }
+ }
+
+ /* Scan the RSDT or XSDT for a pointer to the MADT */
+ tab_ptr = ((uint8_t*)rt) + sizeof(rsdt_t);
+ tab_end = ((uint8_t*)rt) + rt->length;
+
+ while (tab_ptr < tab_end) {
+ ptr = *(unsigned int *)tab_ptr;
+ /* Check for the MADT signature */
+ if (ptr && *ptr == MADTSignature) {
+
+ /* Found it, now parse it */
+ if (parse_madt((uintptr_t)ptr)) {
+ return;
+ }
+ }
+ tab_ptr += 4;
+ }
+}
+
+unsigned my_apic_id()
+{
+ return (APIC[APICR_ID][0]) >> 24;
+}
+
+void smp_ap_booted(unsigned cpu_num)
+{
+ AP[cpu_num].started = TRUE;
+}
+
+void smp_boot_ap(unsigned cpu_num)
+{
+ unsigned timeout;
+ extern bool smp_mode;
+ boot_ap(cpu_num);
+ timeout = 0;
+ do {
+ delay(1000 / DELAY_FACTOR);
+ timeout++;
+ } while (!AP[cpu_num].started && timeout < 100000 / DELAY_FACTOR);
+
+ if (!AP[cpu_num].started) {
+ cprint(LINE_STATUS+1, 0, "SMP: Boot timeout for");
+ dprint(LINE_STATUS+1, COL_MID, cpu_num,2,1);
+ cprint(LINE_STATUS+1, 26, "Turning off SMP");
+ smp_mode = FALSE;
+ }
+}
+
+unsigned smp_my_cpu_num()
+{
+ unsigned apicid = my_apic_id();
+ unsigned i;
+
+ for (i = 0; i < MAX_CPUS; i++) {
+ if (apicid == cpu_num_to_apic_id[i]) {
+ break;
+ }
+ }
+ if (i == MAX_CPUS) {
+ i = 0;
+ }
+ return i;
+}
+
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/smp.h
^
|
@@ -0,0 +1,308 @@
+/* **********************************************************
+ * Copyright 2002 VMware, Inc. All rights reserved. -- VMware Confidential
+ * **********************************************************/
+
+
+#ifndef _SMP_H_
+#define _SMP_H_
+#include "stdint.h"
+#include "defs.h"
+#define MAX_CPUS 16 // "16 CPUs ought to be enough for everybody."
+
+
+#define FPSignature ('_' | ('M' << 8) | ('P' << 16) | ('_' << 24))
+
+typedef struct {
+ uint32_t signature; // "_MP_"
+ uint32_t phys_addr;
+ uint8_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ uint8_t feature[5];
+} floating_pointer_struct_t;
+
+#define MPCSignature ('P' | ('C' << 8) | ('M' << 16) | ('P' << 24))
+typedef struct {
+ uint32_t signature; // "PCMP"
+ uint16_t length;
+ uint8_t spec_rev;
+ uint8_t checksum;
+ char oem[8];
+ char productid[12];
+ uint32_t oem_ptr;
+ uint16_t oem_size;
+ uint16_t oem_count;
+ uint32_t lapic_addr;
+ uint32_t reserved;
+} mp_config_table_header_t;
+
+/* Followed by entries */
+
+#define MP_PROCESSOR 0
+#define MP_BUS 1
+#define MP_IOAPIC 2
+#define MP_INTSRC 3
+#define MP_LINTSRC 4
+
+typedef struct {
+ uint8_t type; /* MP_PROCESSOR */
+ uint8_t apic_id; /* Local APIC number */
+ uint8_t apic_ver; /* Its versions */
+ uint8_t cpu_flag;
+#define CPU_ENABLED 1 /* Processor is available */
+#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
+ uint32_t cpu_signature;
+#define CPU_STEPPING_MASK 0x0F
+#define CPU_MODEL_MASK 0xF0
+#define CPU_FAMILY_MASK 0xF00
+ uint32_t featureflag; /* CPUID feature value */
+ uint32_t reserved[2];
+} mp_processor_entry_t;
+
+typedef struct {
+ uint8_t type; // has value MP_BUS
+ uint8_t busid;
+ char bustype[6];
+} mp_bus_entry_t;
+
+/* We don't understand the others */
+
+typedef struct {
+ uint8_t type; // set to MP_IOAPIC
+ uint8_t apicid;
+ uint8_t apicver;
+ uint8_t flags;
+#define MPC_APIC_USABLE 0x01
+ uint32_t apicaddr;
+} mp_io_apic_entry_t;
+
+
+typedef struct {
+ uint8_t type;
+ uint8_t irqtype;
+ uint16_t irqflag;
+ uint8_t srcbus;
+ uint8_t srcbusirq;
+ uint8_t dstapic;
+ uint8_t dstirq;
+} mp_interrupt_entry_t;
+
+#define MP_INT_VECTORED 0
+#define MP_INT_NMI 1
+#define MP_INT_SMI 2
+#define MP_INT_EXTINT 3
+
+#define MP_IRQDIR_DEFAULT 0
+#define MP_IRQDIR_HIGH 1
+#define MP_IRQDIR_LOW 3
+
+
+typedef struct {
+ uint8_t type;
+ uint8_t irqtype;
+ uint16_t irqflag;
+ uint8_t srcbusid;
+ uint8_t srcbusirq;
+ uint8_t destapic;
+#define MP_APIC_ALL 0xFF
+ uint8_t destapiclint;
+} mp_local_interrupt_entry_t;
+
+#define RSDPSignature ('R' | ('S' << 8) | ('D' << 16) | (' ' << 24))
+typedef struct {
+ char signature[8]; // "RSD "
+ uint8_t checksum;
+ char oemid[6];
+ uint8_t revision;
+ uint32_t rsdt;
+ uint32_t length;
+ uint32_t xrsdt[2];
+ uint8_t xsum;
+} rsdp_t;
+
+#define RSDTSignature ('R' | ('S' << 8) | ('D' << 16) | ('T' << 24))
+#define XSDTSignature ('X' | ('S' << 8) | ('D' << 16) | ('T' << 24))
+typedef struct {
+ char signature[4]; // "RSDT"
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ char oemid[18];
+ char cid[4];
+ char cver[4];
+} rsdt_t;
+
+#define MADTSignature ('A' | ('P' << 8) | ('I' << 16) | ('C' << 24))
+typedef struct {
+ uint8_t type;
+ uint8_t length;
+ uint8_t acpi_id;
+ uint8_t apic_id; /* Local APIC number */
+ uint32_t enabled;
+} madt_processor_entry_t;
+
+/* APIC definitions */
+/*
+ * APIC registers
+ */
+#define APICR_ID 0x02
+#define APICR_ESR 0x28
+#define APICR_ICRLO 0x30
+#define APICR_ICRHI 0x31
+
+/* APIC destination shorthands */
+#define APIC_DEST_DEST 0
+#define APIC_DEST_LOCAL 1
+#define APIC_DEST_ALL_INC 2
+#define APIC_DEST_ALL_EXC 3
+
+/* APIC IPI Command Register format */
+#define APIC_ICRHI_RESERVED 0x00ffffff
+#define APIC_ICRHI_DEST_MASK 0xff000000
+#define APIC_ICRHI_DEST_OFFSET 24
+
+#define APIC_ICRLO_RESERVED 0xfff32000
+#define APIC_ICRLO_DEST_MASK 0x000c0000
+#define APIC_ICRLO_DEST_OFFSET 18
+#define APIC_ICRLO_TRIGGER_MASK 0x00008000
+#define APIC_ICRLO_TRIGGER_OFFSET 15
+#define APIC_ICRLO_LEVEL_MASK 0x00004000
+#define APIC_ICRLO_LEVEL_OFFSET 14
+#define APIC_ICRLO_STATUS_MASK 0x00001000
+#define APIC_ICRLO_STATUS_OFFSET 12
+#define APIC_ICRLO_DESTMODE_MASK 0x00000800
+#define APIC_ICRLO_DESTMODE_OFFSET 11
+#define APIC_ICRLO_DELMODE_MASK 0x00000700
+#define APIC_ICRLO_DELMODE_OFFSET 8
+#define APIC_ICRLO_VECTOR_MASK 0x000000ff
+#define APIC_ICRLO_VECTOR_OFFSET 0
+
+/* APIC trigger types (edge/level) */
+#define APIC_TRIGGER_EDGE 0
+#define APIC_TRIGGER_LEVEL 1
+
+/* APIC delivery modes */
+#define APIC_DELMODE_FIXED 0
+#define APIC_DELMODE_LOWEST 1
+#define APIC_DELMODE_SMI 2
+#define APIC_DELMODE_NMI 4
+#define APIC_DELMODE_INIT 5
+#define APIC_DELMODE_STARTUP 6
+#define APIC_DELMODE_EXTINT 7
+typedef uint32_t apic_register_t[4];
+
+extern volatile apic_register_t *APIC;
+
+unsigned smp_my_cpu_num();
+
+void smp_init_bsp(void);
+void smp_init_aps(void);
+
+void smp_boot_ap(unsigned cpu_num);
+void smp_ap_booted(unsigned cpu_num);
+
+typedef struct {
+ unsigned int slock;
+} spinlock_t;
+
+struct barrier_s
+{
+ spinlock_t mutex;
+ spinlock_t lck;
+ int maxproc;
+ volatile int count;
+ spinlock_t st1;
+ spinlock_t st2;
+ spinlock_t s_lck;
+ int s_maxproc;
+ volatile int s_count;
+ spinlock_t s_st1;
+ spinlock_t s_st2;
+};
+
+void barrier();
+void s_barrier();
+void barrier_init(int max);
+void s_barrier_init(int max);
+
+static inline void
+__GET_CPUID(int ax, uint32_t *regs)
+{
+ __asm__ __volatile__("\t"
+ /* save ebx in case -fPIC is being used */
+ "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+ : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
+ : "a" (ax)
+ : "memory"
+ );
+}
+
+#define GET_CPUID(_ax,_bx,_cx,_dx) { \
+ uint32_t regs[4]; \
+ __GET_CPUID(_ax,regs); \
+ _ax = regs[0]; \
+ _bx = regs[1]; \
+ _cx = regs[2]; \
+ _dx = regs[3]; \
+}
+
+/*
+ * Checked against the Intel manual and GCC --hpreg
+ *
+ * volatile because the tsc always changes without the compiler knowing it.
+ */
+static inline uint64_t
+RDTSC(void)
+{
+ uint64_t tim;
+
+ __asm__ __volatile__(
+ "rdtsc"
+ : "=A" (tim)
+ );
+
+ return tim;
+}
+
+static inline uint64_t __GET_MSR(int cx)
+{
+ uint64_t msr;
+
+ __asm__ __volatile__(
+ "rdmsr"
+ : "=A" (msr)
+ : "c" (cx)
+ );
+
+ return msr;
+}
+
+#define __GCC_OUT(s, s2, port, val) do { \
+ __asm__( \
+ "out" #s " %" #s2 "1, %w0" \
+ : \
+ : "Nd" (port), "a" (val) \
+ ); \
+} while (0)
+#define OUTB(port, val) __GCC_OUT(b, b, port, val)
+
+static inline void spin_lock(spinlock_t *lock)
+{
+ asm volatile("\n1:\t"
+ " ; lock;decb %0\n\t"
+ "jns 3f\n"
+ "2:\t"
+ "rep;nop\n\t"
+ "cmpb $0,%0\n\t"
+ "jle 2b\n\t"
+ "jmp 1b\n"
+ "3:\n\t"
+ : "+m" (lock->slock) : : "memory");
+}
+static inline void spin_unlock(spinlock_t *lock)
+{
+ asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory");
+}
+
+
+#endif /* _SMP_H_ */
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/spd.c
^
|
@@ -1,135 +1,189 @@
-/* Memtest86 SPD extension
- * added by Reto Sonderegger, 2004, reto@swissbit.com
- *
- * Released under version 2 of the Gnu Puclic License
- */
-
-#include "test.h"
-#include "io.h"
-#include "pci.h"
-#include "msr.h"
-#include "screen_buffer.h"
-
-#define SMBHSTSTS smbusbase
-#define SMBHSTCNT smbusbase + 2
-#define SMBHSTCMD smbusbase + 3
-#define SMBHSTADD smbusbase + 4
-#define SMBHSTDAT smbusbase + 5
-
-extern void wait_keyup();
-
-int smbdev, smbfun;
-unsigned short smbusbase;
-unsigned char spd[256];
-char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0};
-
-static void ich5_get_smb(void)
-{
- unsigned long x;
- int result;
- result = pci_conf_read(0, smbdev, smbfun, 0x20, 2, &x);
- if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
-}
-
-unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
-{
- int l1, h1, l2, h2;
- unsigned long long t;
- __outb(0x1f, SMBHSTSTS); // reset SMBus Controller
- __outb(0xff, SMBHSTDAT);
- while(__inb(SMBHSTSTS) & 0x01); // wait until ready
- __outb(cmd, SMBHSTCMD);
- __outb((adr << 1) | 0x01, SMBHSTADD);
- __outb(0x48, SMBHSTCNT);
- rdtsc(l1, h1);
- cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
- while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished
- rdtsc(l2, h2);
- t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
- if (t > 10) break; // break after 10ms
- }
- return __inb(SMBHSTDAT);
-}
-
-static int ich5_read_spd(int dimmadr)
-{
- int x;
- spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
- if (spd[0] == 0xff) return -1; // no spd here
- for (x = 1; x < 256; x++) {
- spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
- }
- return 0;
-}
-
-struct pci_smbus_controller {
- unsigned vendor;
- unsigned device;
- char *name;
- void (*get_adr)(void);
- int (*read_spd)(int dimmadr);
-};
-
-static struct pci_smbus_controller smbcontrollers[] = {
-{0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd},
-{0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd},
-{0, 0, "", NULL, NULL}
-};
-
-int find_smb_controller(void)
-{
- int i = 0;
- unsigned long valuev, valued;
- for (smbdev = 0; smbdev < 32; smbdev++) {
- for (smbfun = 0; smbfun < 8; smbfun++) {
- pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev);
- if (valuev != 0xFFFF) { // if there is something look what's it..
- for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller
- if (valuev == smbcontrollers[i].vendor) {
- pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id
- if (valued == smbcontrollers[i].device) {
- return i;
- }
- }
- }
- }
- }
- }
- return -1;
-}
-
-
-void show_spd(void)
-{
- int index;
- int i, j;
- int flag = 0;
- pop2up();
- wait_keyup();
- index = find_smb_controller();
- if (index == -1) {
- cprint(POP2_Y, POP2_X+1, "SMBus Controller not known");
- while (!get_key());
- wait_keyup();
- pop2down();
- return;
- }
- else cprint(POP2_Y, POP2_X+1, "SPD Data: Slot");
- smbcontrollers[index].get_adr();
- for (j = 0; j < 16; j++) {
- if (smbcontrollers[index].read_spd(j) == 0) {
- dprint(POP2_Y, POP2_X + 15, j, 2, 0);
- for (i = 0; i < 256; i++) {
- hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd[i], 2);
- }
- flag = 0;
- while(!flag) {
- if (get_key()) flag++;
- }
- wait_keyup();
- }
- }
- pop2down();
-}
-
+/* Memtest86 SPD extension
+ * added by Reto Sonderegger, 2004, reto@swissbit.com
+ *
+ * Released under version 2 of the Gnu Puclic License
+ */
+
+#include "test.h"
+#include "io.h"
+#include "pci.h"
+#include "msr.h"
+#include "screen_buffer.h"
+
+#define SMBHSTSTS smbusbase
+#define SMBHSTCNT smbusbase + 2
+#define SMBHSTCMD smbusbase + 3
+#define SMBHSTADD smbusbase + 4
+#define SMBHSTDAT smbusbase + 5
+
+extern void wait_keyup();
+
+int smbdev, smbfun;
+unsigned short smbusbase;
+unsigned char spd[256];
+char s[] = {'/', 0, '-', 0, '\\', 0, '|', 0};
+
+static void ich5_get_smb(void)
+{
+ unsigned long x;
+ int result;
+ result = pci_conf_read(0, smbdev, smbfun, 0x20, 2, &x);
+ if (result == 0) smbusbase = (unsigned short) x & 0xFFFE;
+}
+
+unsigned char ich5_smb_read_byte(unsigned char adr, unsigned char cmd)
+{
+ int l1, h1, l2, h2;
+ unsigned long long t;
+ __outb(0x1f, SMBHSTSTS); // reset SMBus Controller
+ __outb(0xff, SMBHSTDAT);
+ while(__inb(SMBHSTSTS) & 0x01); // wait until ready
+ __outb(cmd, SMBHSTCMD);
+ __outb((adr << 1) | 0x01, SMBHSTADD);
+ __outb(0x48, SMBHSTCNT);
+ rdtsc(l1, h1);
+ cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
+ while (!(__inb(SMBHSTSTS) & 0x02)) { // wait til command finished
+ rdtsc(l2, h2);
+ t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
+ if (t > 10) break; // break after 10ms
+ }
+ return __inb(SMBHSTDAT);
+}
+
+static int ich5_read_spd(int dimmadr)
+{
+ int x;
+ spd[0] = ich5_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd[0] == 0xff) return -1; // no spd here
+ for (x = 1; x < 256; x++) {
+ spd[x] = ich5_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ }
+ return 0;
+}
+
+static void us15w_get_smb(void)
+{
+ unsigned long x;
+ int result;
+ result = pci_conf_read(0, 0x1f, 0, 0x40, 2, &x);
+ if (result == 0) smbusbase = (unsigned short) x & 0xFFC0;
+}
+
+unsigned char us15w_smb_read_byte(unsigned char adr, unsigned char cmd)
+{
+ int l1, h1, l2, h2;
+ unsigned long long t;
+ //__outb(0x00, smbusbase + 1); // reset SMBus Controller
+ //__outb(0x00, smbusbase + 6);
+ //while((__inb(smbusbase + 1) & 0x08) != 0); // wait until ready
+ __outb(0x02, smbusbase + 0); // Byte read
+ __outb(cmd, smbusbase + 5); // Command
+ __outb(0x07, smbusbase + 1); // Clear status
+ __outb((adr << 1) | 0x01, smbusbase + 4); // DIMM address
+ __outb(0x12, smbusbase + 0); // Start
+ //while (((__inb(smbusbase + 1) & 0x08) == 0)) {} // wait til busy
+ rdtsc(l1, h1);
+ cprint(POP2_Y, POP2_X + 16, s + cmd % 8); // progress bar
+ while (((__inb(smbusbase + 1) & 0x01) == 0) ||
+ ((__inb(smbusbase + 1) & 0x08) != 0)) { // wait til command finished
+ rdtsc(l2, h2);
+ t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / v->clks_msec;
+ if (t > 10) break; // break after 10ms
+ }
+ return __inb(smbusbase + 6);
+}
+
+static int us15w_read_spd(int dimmadr)
+{
+ int x;
+ spd[0] = us15w_smb_read_byte(0x50 + dimmadr, 0);
+ if (spd[0] == 0xff) return -1; // no spd here
+ for (x = 1; x < 256; x++) {
+ spd[x] = us15w_smb_read_byte(0x50 + dimmadr, (unsigned char) x);
+ }
+ return 0;
+}
+
+struct pci_smbus_controller {
+ unsigned vendor;
+ unsigned device;
+ char *name;
+ void (*get_adr)(void);
+ int (*read_spd)(int dimmadr);
+};
+
+static struct pci_smbus_controller smbcontrollers[] = {
+{0x8086, 0x3B30, "Intel P55", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x3A60, "Intel ICH10B", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x3A30, "Intel ICH10R", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x2930, "Intel ICH9", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x283E, "Intel ICH8", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x27DA, "Intel ICH7", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x266A, "Intel ICH6", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x24D3, "Intel ICH5", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x24C3, "Intel ICH4", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x25A4, "Intel 6300ESB", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x269B, "Intel ESB2", ich5_get_smb, ich5_read_spd},
+{0x8086, 0x8119, "Intel US15W", us15w_get_smb, us15w_read_spd},
+{0x8086, 0x5032, "Intel EP80579", ich5_get_smb, ich5_read_spd},
+{0, 0, "", 0, 0}
+};
+
+
+int find_smb_controller(void)
+{
+ int i = 0;
+ unsigned long valuev, valued;
+ for (smbdev = 0; smbdev < 32; smbdev++) {
+ for (smbfun = 0; smbfun < 8; smbfun++) {
+ pci_conf_read(0, smbdev, smbfun, 0, 2, &valuev);
+ if (valuev != 0xFFFF) { // if there is something look what's it..
+ for (i = 0; smbcontrollers[i].vendor > 0; i++) { // check if this is a known smbus controller
+ if (valuev == smbcontrollers[i].vendor) {
+ pci_conf_read(0, smbdev, smbfun, 2, 2, &valued); // read the device id
+ if (valued == smbcontrollers[i].device) {
+ return i;
+ }
+ }
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+void show_spd(void)
+{
+ int index;
+ int i, j;
+ int flag = 0;
+ pop2up();
+ wait_keyup();
+ index = find_smb_controller();
+ if (index == -1) {
+ cprint(POP2_Y, POP2_X+1, "SMBus Controller not known");
+ while (!get_key());
+ wait_keyup();
+ pop2down();
+ return;
+ }
+ else cprint(POP2_Y, POP2_X+1, "SPD Data: Slot");
+ smbcontrollers[index].get_adr();
+ for (j = 0; j < 16; j++) {
+ if (smbcontrollers[index].read_spd(j) == 0) {
+ dprint(POP2_Y, POP2_X + 15, j, 2, 0);
+ for (i = 0; i < 256; i++) {
+ hprint2(2 + POP2_Y + i / 16, 3 + POP2_X + (i % 16) * 3, spd[i], 2);
+ }
+ flag = 0;
+ while(!flag) {
+ if (get_key()) flag++;
+ }
+ wait_keyup();
+ }
+ }
+ pop2down();
+}
+
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/stdint.h
^
|
@@ -48,5 +48,13 @@
typedef long long int intmax_t;
typedef unsigned long long uintmax_t;
+typedef char bool;
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
#endif /* I386_STDINT_H */
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/test.c
^
|
@@ -1,18 +1,22 @@
-/* test.c - MemTest-86 Version 3.3
+/* test.c - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
*/
#include "test.h"
#include "config.h"
+#include "smp.h"
-extern int segs, bail;
-extern volatile ulong *p;
-extern ulong p1, p2;
+extern volatile int mstr_cpu;
+extern volatile int run_cpus;
+extern volatile int test;
+extern volatile int segs, bail;
extern int test_ticks, nticks;
extern struct tseq tseq[];
extern void update_err_counts(void);
extern void print_err_counts(void);
+void rand_seed( unsigned int seed1, unsigned int seed2, int me);
+ulong rand(int me);
void poll_errors();
int ecount = 0;
@@ -24,12 +28,11 @@
/*
* Memory address test, walking ones
*/
-void addr_tst1()
+void addr_tst1(int me)
{
int i, j, k;
- volatile ulong *pt;
- volatile ulong *end;
- ulong bad, mask, bank;
+ volatile ulong *p, *pt, *end;
+ ulong bad, mask, bank, p1;
/* Test the global address bits */
for (p1=0, j=0; j<2; j++) {
@@ -42,7 +45,7 @@
/* Now write pattern compliment */
p1 = ~p1;
end = v->map[segs-1].end;
- for (i=0; i<1000; i++) {
+ for (i=0; i<100; i++) {
mask = 4;
do {
pt = (ulong *)((ulong)p | mask);
@@ -62,7 +65,7 @@
mask = mask << 1;
} while(mask);
}
- do_tick();
+ do_tick(me);
BAILR
}
@@ -82,11 +85,12 @@
/* Force start address to be a multiple of 256k */
p = (ulong *)roundup((ulong)p, bank - 1);
end = v->map[j].end;
- while (p < end) {
+ /* Redundant checks for overflow */
+ while (p < end && p > v->map[j].start && p != 0) {
*p = p1;
p1 = ~p1;
- for (i=0; i<200; i++) {
+ for (i=0; i<50; i++) {
mask = 4;
do {
pt = (ulong *)
@@ -116,7 +120,7 @@
p1 = ~p1;
}
}
- do_tick();
+ do_tick(me);
BAILR
p1 = ~p1;
}
@@ -125,13 +129,12 @@
/*
* Memory address test, own address
*/
-void addr_tst2()
+void addr_tst2(int me)
{
int j, done;
- volatile ulong *pe;
- volatile ulong *end, *start;
+ ulong *p, *pe, *end, *start;
- cprint(LINE_PAT, COL_PAT, " ");
+ cprint(LINE_PAT, COL_PAT, "address ");
/* Write each address with it's own address */
for (j=0; j<segs; j++) {
@@ -141,8 +144,11 @@
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -156,24 +162,22 @@
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* *p = (ulong)p;
* }
*/
asm __volatile__ (
- "jmp L90\n\t"
-
+ "jmp L91\n\t"
".p2align 4,,7\n\t"
"L90:\n\t"
- "movl %%edi,(%%edi)\n\t"
"addl $4,%%edi\n\t"
+ "L91:\n\t"
+ "movl %%edi,(%%edi)\n\t"
"cmpl %%edx,%%edi\n\t"
"jb L90\n\t"
- : "=D" (p)
- : "D" (p), "d" (pe)
+ : : "D" (p), "d" (pe)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
@@ -185,12 +189,15 @@
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
- pe += SPINSZ;
- } else {
- pe = end;
- }
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
if (pe >= end) {
pe = end;
done++;
@@ -199,27 +206,27 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* if((bad = *p) != (ulong)p) {
* ad_err2((ulong)p, bad);
* }
* }
*/
asm __volatile__ (
- "jmp L91\n\t"
-
+ "jmp L95\n\t"
".p2align 4,,7\n\t"
- "L91:\n\t"
+ "L99:\n\t"
+ "addl $4,%%edi\n\t"
+ "L95:\n\t"
"movl (%%edi),%%ecx\n\t"
"cmpl %%edi,%%ecx\n\t"
- "jne L93\n\t"
- "L92:\n\t"
- "addl $4,%%edi\n\t"
+ "jne L97\n\t"
+ "L96:\n\t"
"cmpl %%edx,%%edi\n\t"
- "jb L91\n\t"
- "jmp L94\n\t"
+ "jb L99\n\t"
+ "jmp L98\n\t"
- "L93:\n\t"
+ "L97:\n\t"
"pushl %%edx\n\t"
"pushl %%ecx\n\t"
"pushl %%edi\n\t"
@@ -227,15 +234,13 @@
"popl %%edi\n\t"
"popl %%ecx\n\t"
"popl %%edx\n\t"
- "jmp L92\n\t"
+ "jmp L96\n\t"
- "L94:\n\t"
- : "=D" (p)
- : "D" (p), "d" (pe)
+ "L98:\n\t"
+ : : "D" (p), "d" (pe)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
@@ -246,12 +251,13 @@
* produce random numbers in reverse order testing is only done in the forward
* direction.
*/
-void movinvr()
+void movinvr(int me)
{
int i, j, done, seed1, seed2;
- volatile ulong *pe;
- volatile ulong *start,*end;
- ulong num;
+ ulong *p;
+ ulong *pe;
+ ulong *start,*end;
+ ulong num, chunk;
/* Initialize memory with initial sequence of random numbers. */
if (v->rdtsc) {
@@ -262,17 +268,34 @@
}
/* Display the current seed */
- hprint(LINE_PAT, COL_PAT, seed1);
- rand_seed(seed1, seed2);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, seed1);
+ rand_seed(seed1, seed2, me);
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -286,7 +309,7 @@
}
/* Original C code replaced with hand tuned assembly code */
/*
- for (; p < pe; p++) {
+ for (; p <= pe; p++) {
*p = rand();
}
*/
@@ -294,36 +317,53 @@
asm __volatile__ (
"jmp L200\n\t"
".p2align 4,,7\n\t"
+ "L201:\n\t"
+ "addl $4,%%edi\n\t"
"L200:\n\t"
+ "pushl %%ecx\n\t" \
"call rand\n\t"
+ "popl %%ecx\n\t" \
"movl %%eax,(%%edi)\n\t"
- "addl $4,%%edi\n\t"
"cmpl %%ebx,%%edi\n\t"
- "jb L200\n\t"
- : "=D" (p)
- : "D" (p), "b" (pe)
+ "jb L201\n\t"
+ : : "D" (p), "b" (pe), "c" (me)
: "eax"
);
-
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
/* Do moving inversions test. Check for initial pattern and then
- * write the complement for each memory location. Test from bottom
- * up and then from the top down. */
+ * write the complement for each memory location.
+ */
for (i=0; i<2; i++) {
- rand_seed(seed1, seed2);
+ rand_seed(seed1, seed2, me);
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -337,7 +377,7 @@
}
/* Original C code replaced with hand tuned assembly code */
/*
- for (; p < pe; p++) {
+ for (; p <= pe; p++) {
num = rand();
if (i) {
num = ~num;
@@ -354,22 +394,25 @@
num = 0;
}
asm __volatile__ (
+ "pushl %%ebp\n\t"
"jmp L26\n\t" \
-
".p2align 4,,7\n\t" \
+ "L27:\n\t" \
+ "addl $4,%%edi\n\t" \
"L26:\n\t" \
+ "pushl %%edx\n\t" \
"call rand\n\t"
+ "popl %%edx\n\t" \
"xorl %%ebx,%%eax\n\t" \
"movl (%%edi),%%ecx\n\t" \
"cmpl %%eax,%%ecx\n\t" \
"jne L23\n\t" \
"L25:\n\t" \
- "movl $0xffffffff,%%edx\n\t" \
- "xorl %%edx,%%eax\n\t" \
+ "movl $0xffffffff,%%ebp\n\t" \
+ "xorl %%ebp,%%eax\n\t" \
"movl %%eax,(%%edi)\n\t" \
- "addl $4,%%edi\n\t" \
"cmpl %%esi,%%edi\n\t" \
- "jb L26\n\t" \
+ "jb L27\n\t" \
"jmp L24\n" \
"L23:\n\t" \
@@ -385,12 +428,12 @@
"jmp L25\n" \
"L24:\n\t" \
- : "=D" (p)
- : "D" (p), "S" (pe), "b" (num)
- : "eax", "ecx", "edx"
+ "popl %%ebp\n\t"
+ :: "D" (p), "S" (pe), "b" (num),
+ "d" (me)
+ : "eax", "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
@@ -400,26 +443,42 @@
* Test all of memory using a "moving inversions" algorithm using the
* pattern in p1 and it's complement in p2.
*/
-void movinv1(int iter, ulong p1, ulong p2)
+void movinv1(int iter, ulong p1, ulong p2, int me)
{
int i, j, done;
- volatile ulong *pe;
- volatile ulong len;
- volatile ulong *start,*end;
+ ulong *p, *pe, len, chunk, *start, *end;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1);
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set the end addrs for the highest numbers CPU to the
+ * end of the segment to take care of rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
+
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -428,23 +487,21 @@
pe = end;
done++;
}
- len = pe - p;
+ len = pe - p + 1;
if (p == pe ) {
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* *p = p1;
* }
*/
asm __volatile__ (
"rep\n\t" \
"stosl\n\t"
- : "=D" (p)
- : "c" (len), "0" (p), "a" (p1)
+ : : "c" (len), "D" (p), "a" (p1)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
@@ -453,14 +510,31 @@
* up and then from the top down. */
for (i=0; i<iter; i++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set the end addrs for the highest numbers CPU to the
+ * end of the segment to take care of rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -473,7 +547,7 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* if ((bad=*p) != p1) {
* error((ulong*)p, p1, bad);
* }
@@ -482,17 +556,17 @@
*/
asm __volatile__ (
"jmp L2\n\t" \
-
".p2align 4,,7\n\t" \
+ "L0:\n\t" \
+ "addl $4,%%edi\n\t" \
"L2:\n\t" \
"movl (%%edi),%%ecx\n\t" \
"cmpl %%eax,%%ecx\n\t" \
"jne L3\n\t" \
"L5:\n\t" \
"movl %%ebx,(%%edi)\n\t" \
- "addl $4,%%edi\n\t" \
"cmpl %%edx,%%edi\n\t" \
- "jb L2\n\t" \
+ "jb L0\n\t" \
"jmp L4\n" \
"L3:\n\t" \
@@ -510,28 +584,47 @@
"jmp L5\n" \
"L4:\n\t" \
- : "=D" (p)
- : "a" (p1), "0" (p), "d" (pe), "b" (p2)
+ :: "a" (p1), "D" (p), "d" (pe), "b" (p2)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
for (j=segs-1; j>=0; j--) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = end -1;
- p = end -1;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set the end addrs for the highest num CPU to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
+ pe = end;
+ p = end;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for underflow */
- if (pe - SPINSZ < pe) {
+ if (pe - SPINSZ < pe && pe != 0) {
pe -= SPINSZ;
} else {
pe = start;
+ done++;
}
- if (pe <= start) {
+
+ /* Since we are using unsigned addresses a
+ * redundent check is required */
+ if (pe < start || pe > end) {
pe = start;
done++;
}
@@ -544,23 +637,21 @@
* error((ulong*)p, p2, bad);
* }
* *p = p1;
- * } while (p-- > pe);
+ * } while (p-- >= pe);
*/
asm __volatile__ (
- "addl $4, %%edi\n\t"
"jmp L9\n\t"
-
".p2align 4,,7\n\t"
- "L9:\n\t"
+ "L11:\n\t"
"subl $4, %%edi\n\t"
+ "L9:\n\t"
"movl (%%edi),%%ecx\n\t"
"cmpl %%ebx,%%ecx\n\t"
"jne L6\n\t"
"L10:\n\t"
"movl %%eax,(%%edi)\n\t"
"cmpl %%edi, %%edx\n\t"
- "jne L9\n\t"
- "subl $4, %%edi\n\t"
+ "jne L11\n\t"
"jmp L7\n\t"
"L6:\n\t"
@@ -578,39 +669,53 @@
"jmp L10\n"
"L7:\n\t"
- : "=D" (p)
- : "a" (p1), "0" (p), "d" (pe), "b" (p2)
+ :: "a" (p1), "D" (p), "d" (pe), "b" (p2)
: "ecx"
);
- do_tick();
- BAILR
+ p = pe - 1;
} while (!done);
}
}
}
-void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off)
+void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off,int me)
{
- int i, j, k=0, done;
- volatile ulong *pe;
- volatile ulong *start, *end;
- ulong pat = 0;
+ int i, j, k=0, n=0, done;
+ ulong *p, *pe, *start, *end, chunk, pat = 0, p3;
+ p3 = sval << 31;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1);
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = start;
p = start;
done = 0;
k = off;
pat = p1;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -624,7 +729,7 @@
}
/* Do a SPINSZ section of memory */
/* Original C code replaced with hand tuned assembly code
- * while (p < pe) {
+ * while (p <= pe) {
* *p = pat;
* if (++k >= 32) {
* pat = lb;
@@ -637,24 +742,29 @@
* }
*/
asm __volatile__ (
- "jmp L20\n\t"
- ".p2align 4,,7\n\t"
-
-/* CDH start */
- "L20:\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "incb %%bl\n\t"
- "addl $4,%%edi\n\t"
- "roll $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "jb L20\n\t"
- "andb $31,%%bl\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "jmp L20\n\t"
+ ".p2align 4,,7\n\t"
+ "L923:\n\t"
+ "addl $4,%%edi\n\t"
+ "L20:\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "addl $1,%%ebx\n\t"
+ "cmpl $32,%%ebx\n\t"
+ "jne L21\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "xorl %%ebx,%%ebx\n\t"
+ "jmp L22\n"
+ "L21:\n\t"
+ "shll $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L22:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "jb L923\n\t"
+ : "=b" (k), "=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (sval), "S" (lb)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
@@ -663,16 +773,33 @@
* up and then from the top down. */
for (i=0; i<iter; i++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = start;
p = start;
done = 0;
k = off;
pat = p1;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -685,11 +812,14 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * while (p < pe) {
+ * while (1) {
* if ((bad=*p) != pat) {
* error((ulong*)p, pat, bad);
* }
* *p = ~pat;
+ * if (p >= pe) break;
+ * p++;
+ *
* if (++k >= 32) {
* pat = lb;
* k = 0;
@@ -697,100 +827,109 @@
* pat = pat << 1;
* pat |= sval;
* }
- * p++;
* }
*/
asm __volatile__ (
- "pushl %%ebp\n\t"
- "jmp L30\n\t"
-
- ".p2align 4,,7\n\t"
- "L30:\n\t"
- "movl (%%edi),%%ebp\n\t"
- "cmpl %%ecx,%%ebp\n\t"
- "jne L34\n\t"
-
-/* CDH start */
- "L35:\n\t"
- "notl %%ecx\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "notl %%ecx\n\t"
- "addl $4,%%edi\n\t"
- "incb %%bl\n\t"
- "roll $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "jb L30\n\t"
- "jmp L33\n\t"
-/* CDH end */
-
- "L34:\n\t" \
- "pushl %%esi\n\t"
- "pushl %%eax\n\t"
- "pushl %%ebx\n\t"
- "pushl %%edx\n\t"
- "pushl %%ebp\n\t"
- "pushl %%ecx\n\t"
- "pushl %%edi\n\t"
- "call error\n\t"
- "popl %%edi\n\t"
- "popl %%ecx\n\t"
- "popl %%ebp\n\t"
- "popl %%edx\n\t"
- "popl %%ebx\n\t"
- "popl %%eax\n\t"
- "popl %%esi\n\t"
- "jmp L35\n"
-
-/* CDH start */
- "L33:\n\t"
- "andb $31,%%bl\n\t"
- "popl %%ebp\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "pushl %%ebp\n\t"
+ "jmp L30\n\t"
+ ".p2align 4,,7\n\t"
+ "L930:\n\t"
+ "addl $4,%%edi\n\t"
+ "L30:\n\t"
+ "movl (%%edi),%%ebp\n\t"
+ "cmpl %%ecx,%%ebp\n\t"
+ "jne L34\n\t"
+
+ "L35:\n\t"
+ "notl %%ecx\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "notl %%ecx\n\t"
+ "incl %%ebx\n\t"
+ "cmpl $32,%%ebx\n\t"
+ "jne L31\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "xorl %%ebx,%%ebx\n\t"
+ "jmp L32\n"
+ "L31:\n\t"
+ "shll $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L32:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "jb L930\n\t"
+ "jmp L33\n\t"
+
+ "L34:\n\t" \
+ "pushl %%esi\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ebx\n\t"
+ "pushl %%edx\n\t"
+ "pushl %%ebp\n\t"
+ "pushl %%ecx\n\t"
+ "pushl %%edi\n\t"
+ "call error\n\t"
+ "popl %%edi\n\t"
+ "popl %%ecx\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%eax\n\t"
+ "popl %%esi\n\t"
+ "jmp L35\n"
+
+ "L33:\n\t"
+ "popl %%ebp\n\t"
+ : "=b" (k),"=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (sval), "S" (lb)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
- /* Since we already adjusted k and the pattern this
- * code backs both up one step
- */
-/* CDH start */
-/* Original C code replaced with hand tuned assembly code
- * pat = lb;
- * if ( 0 != (k = (k-1) & 31) ) {
- * pat = (pat << k);
- * if ( sval )
- * pat |= ((sval << k) - 1);
- * }
- * k++;
- */
- asm __volatile__ (
- "decl %%ecx\n\t"
- "andl $31,%%ecx\n\t"
- "roll %%cl,%%ebx\n\t"
- "incb %%cl\n\t"
- : "=c" (k), "=b" (pat)
- : "c" (k), "b" (lb)
- );
-/* CDH end */
+ if (--k < 0) {
+ k = 31;
+ }
+ for (pat = lb, n = 0; n < k; n++) {
+ pat = pat << 1;
+ pat |= sval;
+ }
+ k++;
for (j=segs-1; j>=0; j--) {
- start = v->map[j].start;
- end = v->map[j].end;
- p = end -1;
- pe = end -1;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
+ p = end;
+ pe = end;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for underflow */
- if (pe - SPINSZ < pe) {
- pe -= SPINSZ;
- } else {
- pe = start;
- }
- if (pe <= start) {
+ if (pe - SPINSZ < pe && pe != 0) {
+ pe -= SPINSZ;
+ } else {
+ pe = start;
+ done++;
+ }
+ /* We need this redundant check because we are
+ * using unsigned longs for the address.
+ */
+ if (pe < start || pe > end) {
pe = start;
done++;
}
@@ -798,11 +937,13 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * do {
+ * while(1) {
* if ((bad=*p) != ~pat) {
* error((ulong*)p, ~pat, bad);
* }
* *p = pat;
+ if (p >= pe) break;
+ p++;
* if (--k <= 0) {
* pat = hb;
* k = 32;
@@ -810,61 +951,62 @@
* pat = pat >> 1;
* pat |= p3;
* }
- * } while (p-- > pe);
+ * };
*/
asm __volatile__ (
- "pushl %%ebp\n\t"
- "addl $4,%%edi\n\t"
- "jmp L40\n\t"
-
- ".p2align 4,,7\n\t"
- "L40:\n\t"
- "subl $4,%%edi\n\t"
- "movl (%%edi),%%ebp\n\t"
- "notl %%ecx\n\t"
- "cmpl %%ecx,%%ebp\n\t"
- "jne L44\n\t"
-
-/* CDH start */
- "L45:\n\t"
- "notl %%ecx\n\t"
- "movl %%ecx,(%%edi)\n\t"
- "decb %%bl\n\t"
- "rorl $1,%%ecx\n\t"
- "cmpl %%edx,%%edi\n\t"
- "ja L40\n\t"
- "jmp L43\n\t"
-/* CDH end */
-
- "L44:\n\t" \
- "pushl %%esi\n\t"
- "pushl %%eax\n\t"
- "pushl %%ebx\n\t"
- "pushl %%edx\n\t"
- "pushl %%ebp\n\t"
- "pushl %%ecx\n\t"
- "pushl %%edi\n\t"
- "call error\n\t"
- "popl %%edi\n\t"
- "popl %%ecx\n\t"
- "popl %%ebp\n\t"
- "popl %%edx\n\t"
- "popl %%ebx\n\t"
- "popl %%eax\n\t"
- "popl %%esi\n\t"
- "jmp L45\n"
-
-/* CDH start */
- "L43:\n\t"
- "andb $31,%%bl\n\t"
- "subl $4,%%edi\n\t"
- "popl %%ebp\n\t"
- : "=b" (k), "=D" (p), "=c" (pat)
- : "D" (p),"d" (pe),"b" (k),"c" (pat)
-/* CDH end */
+ "pushl %%ebp\n\t"
+ "jmp L40\n\t"
+ ".p2align 4,,7\n\t"
+ "L49:\n\t"
+ "subl $4,%%edi\n\t"
+ "L40:\n\t"
+ "movl (%%edi),%%ebp\n\t"
+ "notl %%ecx\n\t"
+ "cmpl %%ecx,%%ebp\n\t"
+ "jne L44\n\t"
+
+ "L45:\n\t"
+ "notl %%ecx\n\t"
+ "movl %%ecx,(%%edi)\n\t"
+ "decl %%ebx\n\t"
+ "cmpl $0,%%ebx\n\t"
+ "jg L41\n\t"
+ "movl %%esi,%%ecx\n\t"
+ "movl $32,%%ebx\n\t"
+ "jmp L42\n"
+ "L41:\n\t"
+ "shrl $1,%%ecx\n\t"
+ "orl %%eax,%%ecx\n\t"
+ "L42:\n\t"
+ "cmpl %%edx,%%edi\n\t"
+ "ja L49\n\t"
+ "jmp L43\n\t"
+
+ "L44:\n\t" \
+ "pushl %%esi\n\t"
+ "pushl %%eax\n\t"
+ "pushl %%ebx\n\t"
+ "pushl %%edx\n\t"
+ "pushl %%ebp\n\t"
+ "pushl %%ecx\n\t"
+ "pushl %%edi\n\t"
+ "call error\n\t"
+ "popl %%edi\n\t"
+ "popl %%ecx\n\t"
+ "popl %%ebp\n\t"
+ "popl %%edx\n\t"
+ "popl %%ebx\n\t"
+ "popl %%eax\n\t"
+ "popl %%esi\n\t"
+ "jmp L45\n"
+
+ "L43:\n\t"
+ "popl %%ebp\n\t"
+ : "=b" (k), "=c" (pat)
+ : "D" (p),"d" (pe),"b" (k),"c" (pat),
+ "a" (p3), "S" (hb)
);
- do_tick();
- BAILR
+ p = pe - 1;
} while (!done);
}
}
@@ -873,27 +1015,48 @@
/*
* Test all of memory using modulo X access pattern.
*/
-void modtst(int offset, int iter, ulong p1, ulong p2)
+void modtst(int offset, int iter, ulong p1, ulong p2, int me)
{
int j, k, l, done;
- volatile ulong *pe;
- volatile ulong *start, *end;
+ ulong *p;
+ ulong *pe;
+ ulong *start, *end, chunk;
/* Display the current pattern */
- hprint(LINE_PAT, COL_PAT-2, p1);
- cprint(LINE_PAT, COL_PAT+6, "-");
- dprint(LINE_PAT, COL_PAT+7, offset, 2, 1);
+ if (mstr_cpu == me) {
+ hprint(LINE_PAT, COL_PAT-2, p1);
+ cprint(LINE_PAT, COL_PAT+6, "-");
+ dprint(LINE_PAT, COL_PAT+7, offset, 2, 1);
+ }
/* Write every nth location with pattern */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
+ end -= MOD_SZ; /* adjust the ending address */
pe = (ulong *)start;
p = start+offset;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -906,7 +1069,7 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p += MOD_SZ) {
+ * for (; p <= pe; p += MOD_SZ) {
* *p = p1;
* }
*/
@@ -922,23 +1085,38 @@
: "=D" (p)
: "D" (p), "d" (pe), "a" (p1)
);
- do_tick();
- BAILR
} while (!done);
}
/* Write the rest of memory "iter" times with the pattern complement */
for (l=0; l<iter; l++) {
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = (ulong *)start;
p = start;
done = 0;
k = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -951,7 +1129,7 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p++) {
+ * for (; p <= pe; p++) {
* if (k != offset) {
* *p = p2;
* }
@@ -964,6 +1142,8 @@
"jmp L50\n\t" \
".p2align 4,,7\n\t" \
+ "L54:\n\t" \
+ "addl $4,%%edi\n\t" \
"L50:\n\t" \
"cmpl %%ebx,%%ecx\n\t" \
"je L52\n\t" \
@@ -974,29 +1154,45 @@
"jle L53\n\t" \
"xorl %%ebx,%%ebx\n\t" \
"L53:\n\t" \
- "addl $4,%%edi\n\t" \
"cmpl %%edx,%%edi\n\t" \
- "jb L50\n\t" \
- : "=D" (p), "=b" (k)
+ "jb L54\n\t" \
+ : "=b" (k)
: "D" (p), "d" (pe), "a" (p2),
"b" (k), "c" (offset)
);
- do_tick();
- BAILR
+ p = pe + 1;
} while (!done);
}
}
/* Now check every nth location */
for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start+(chunk*me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
pe = (ulong *)start;
p = start+offset;
done = 0;
+ end -= MOD_SZ; /* adjust the ending address */
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ > pe) {
+ if (pe + SPINSZ > pe && pe != 0) {
pe += SPINSZ;
} else {
pe = end;
@@ -1009,7 +1205,7 @@
break;
}
/* Original C code replaced with hand tuned assembly code
- * for (; p < pe; p += MOD_SZ) {
+ * for (; p <= pe; p += MOD_SZ) {
* if ((bad=*p) != p1) {
* error((ulong*)p, p1, bad);
* }
@@ -1046,45 +1242,59 @@
: "D" (p), "d" (pe), "a" (p1)
: "ecx"
);
- do_tick();
- BAILR
} while (!done);
}
- cprint(LINE_PAT, COL_PAT, " ");
}
/*
* Test memory using block moves
* Adapted from Robert Redelmeier's burnBX test
*/
-void block_move(int iter)
+void block_move(int iter, int me)
{
int i, j, done;
ulong len;
- volatile ulong p, pe, pp;
- volatile ulong start, end;
+ ulong *p, *pe, pp;
+ ulong *start, *end, chunk;
cprint(LINE_PAT, COL_PAT-2, " ");
/* Initialize memory with the initial pattern. */
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
#ifdef USB_WAR
- /* We can't do the block move test on low memory beacuase
+ /* We can't do the block move test on low memory because
* BIOS USB support clobbers location 0x410 and 0x4e0
*/
- if (start < 0x4f0) {
- start = 0x4f0;
+ if (start < (ulong *)0x4f0) {
+ start = (ulong *)0x4f0;
}
#endif
- end = (ulong)v->map[j].end;
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
pe = end;
}
@@ -1096,6 +1306,7 @@
break;
}
len = ((ulong)pe - (ulong)p) / 64;
+ len++;
asm __volatile__ (
"jmp L100\n\t"
@@ -1127,46 +1338,62 @@
: "D" (p), "c" (len), "a" (1)
: "edx"
);
- do_tick();
- BAILR
} while (!done);
}
+ s_barrier();
/* Now move the data around
* First move the data up half of the segment size we are testing
* Then move the data to the original location + 32 bytes
*/
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
#ifdef USB_WAR
/* We can't do the block move test on low memory beacuase
* BIOS USB support clobbers location 0x410 and 0x4e0
*/
- if (start < 0x4f0) {
- start = 0x4f0;
+ if (start < (ulong *)0x4f0) {
+ start = (ulong *)0x4f0;
}
#endif
- end = (ulong)v->map[j].end;
pe = start;
p = start;
done = 0;
do {
+
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
- pe = end;
+ pe = (ulong *)((ulong)end & 0xfffffff0);
}
if (pe >= end) {
- pe = end;
+ pe = (ulong *)((ulong)end & 0xfffffff0);
done++;
}
if (p == pe ) {
break;
}
- pp = p + ((pe - p) / 2);
+ pp = (ulong)p + (((ulong)pe - (ulong)p) / 2);
len = ((ulong)pe - (ulong)p) / 8;
for(i=0; i<iter; i++) {
+ do_tick(me);
+ BAILR
asm __volatile__ (
"cld\n"
"jmp L110\n\t"
@@ -1192,35 +1419,51 @@
:: "g" (p), "g" (pp), "g" (len)
: "edi", "esi", "ecx"
);
- do_tick();
- BAILR
}
p = pe;
} while (!done);
}
+ s_barrier();
/* Now check the data
* The error checking is rather crude. We just check that the
* adjacent words are the same.
*/
for (j=0; j<segs; j++) {
- start = (ulong)v->map[j].start;
+ if (run_cpus == 1) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ } else {
+ chunk = v->map[j].end - v->map[j].start;
+ chunk /= run_cpus;
+ chunk++;
+ start = v->map[j].start + (chunk * me);
+ /* Set end addrs for the highest CPU num to the
+ * end of the segment for rounding errors */
+ if (me == mstr_cpu) {
+ end = v->map[j].end;
+ } else {
+ end = start + chunk - 1;
+ }
+ }
#ifdef USB_WAR
/* We can't do the block move test on low memory beacuase
* BIOS USB support clobbers location 0x4e0 and 0x410
*/
- if (start < 0x4f0) {
- start = 0x4f0;
+ if (start < (ulong *)0x4f0) {
+ start = (ulong *)0x4f0;
}
#endif
- end = (ulong)v->map[j].end;
pe = start;
p = start;
done = 0;
do {
+ do_tick(me);
+ BAILR
+
/* Check for overflow */
- if (pe + SPINSZ*4 > pe) {
- pe += SPINSZ*4;
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
} else {
pe = end;
}
@@ -1231,19 +1474,21 @@
if (p == pe ) {
break;
}
+ pe--; /* adjust the end since we are testing pe+1 */
asm __volatile__ (
"jmp L120\n\t"
".p2align 4,,7\n\t"
+ "L124:\n\t"
+ "addl $8,%%edi\n\t"
"L120:\n\t"
"movl (%%edi),%%ecx\n\t"
"cmpl 4(%%edi),%%ecx\n\t"
"jnz L121\n\t"
"L122:\n\t"
- "addl $8,%%edi\n\t"
"cmpl %%edx,%%edi\n\t"
- "jb L120\n"
+ "jb L124\n"
"jmp L123\n\t"
"L121:\n\t"
@@ -1261,74 +1506,100 @@
: "D" (p), "d" (pe)
: "ecx"
);
- do_tick();
- BAILR
} while (!done);
}
}
/*
- * Test memory for bit fade.
+ * Test memory for bit fade, fill memory with pattern.
*/
-#define STIME 5400
-void bit_fade()
+void bit_fade_fill(ulong p1, int me)
{
- int j;
- volatile ulong *pe;
- volatile ulong bad;
- volatile ulong *start,*end;
-
- test_ticks += (STIME * 2);
- v->pass_ticks += (STIME * 2);
+ int j, done;
+ ulong *p, *pe;
+ ulong *start,*end;
- /* Do -1 and 0 patterns */
- p1 = 0;
- while (1) {
+ /* Display the current pattern */
+ hprint(LINE_PAT, COL_PAT, p1);
- /* Display the current pattern */
- hprint(LINE_PAT, COL_PAT, p1);
+ /* Initialize memory with the initial pattern. */
+ for (j=0; j<segs; j++) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ pe = (ulong *)start;
+ p = start;
+ done = 0;
+ do {
+ do_tick(me);
+ BAILR
- /* Initialize memory with the initial pattern. */
- for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = start;
- p = start;
- for (p=end; p<end; p++) {
+ /* Check for overflow */
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
+ if (pe >= end) {
+ pe = end;
+ done++;
+ }
+ if (p == pe ) {
+ break;
+ }
+ for (; p < pe;) {
*p = p1;
+ p++;
}
- do_tick();
+ p = pe + 1;
+ } while (!done);
+ }
+}
+
+void bit_fade_chk(ulong p1, int me)
+{
+ int j, done;
+ ulong *p, *pe, bad;
+ ulong *start,*end;
+
+ /* Make sure that nothing changed while sleeping */
+ for (j=0; j<segs; j++) {
+ start = v->map[j].start;
+ end = v->map[j].end;
+ pe = (ulong *)start;
+ p = start;
+ done = 0;
+ do {
+ do_tick(me);
BAILR
- }
- /* Snooze for 90 minutes */
- sleep (STIME);
- /* Make sure that nothing changed while sleeping */
- for (j=0; j<segs; j++) {
- start = v->map[j].start;
- end = v->map[j].end;
- pe = start;
- p = start;
- for (p=end; p<end; p++) {
+ /* Check for overflow */
+ if (pe + SPINSZ > pe && pe != 0) {
+ pe += SPINSZ;
+ } else {
+ pe = end;
+ }
+ if (pe >= end) {
+ pe = end;
+ done++;
+ }
+ if (p == pe ) {
+ break;
+ }
+ for (; p < pe;) {
if ((bad=*p) != p1) {
error((ulong*)p, p1, bad);
}
+ p++;
}
- do_tick();
- BAILR
- }
- if (p1 == 0) {
- p1=-1;
- } else {
- break;
- }
+ p = pe + 1;
+ } while (!done);
}
}
-void sleep(int n)
+/* Sleep for N seconds */
+void sleep(long n, int flag, int me)
{
- int i, ip=0;
- ulong sh, sl, l, h, t;
+ ulong sh, sl, l, h, t, ip=0;
/* save the starting time */
asm __volatile__(
@@ -1337,6 +1608,7 @@
/* loop for n seconds */
while (1) {
asm __volatile__(
+ "rep ; nop\n\t"
"rdtsc":"=a" (l),"=d" (h));
asm __volatile__ (
"subl %2,%0\n\t"
@@ -1352,20 +1624,15 @@
break;
}
- /* Display the elapsed time on the screen */
- i = t % 60;
- dprint(LINE_TIME, COL_TIME+9, i%10, 1, 0);
- dprint(LINE_TIME, COL_TIME+8, i/10, 1, 0);
- if (i != ip) {
- do_tick();
+ /* Only display elapsed time if flag is set */
+ if (flag == 0) {
+ continue;
+ }
+
+ if (t != ip) {
+ do_tick(me);
BAILR
- ip = i;
+ ip = t;
}
- t /= 60;
- i = t % 60;
- dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0);
- dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0);
- t /= 60;
- dprint(LINE_TIME, COL_TIME, t, 4, 0);
}
}
|
[-]
[+]
|
Changed |
memtest86-4.0.tar.bz2/test.h
^
|
@@ -1,11 +1,11 @@
-/* test.h - MemTest-86 Version 3.3
+/* test.h - MemTest-86 Version 3.4
*
* Released under version 2 of the Gnu Public License.
* By Chris Brady
*/
-
-#define MAX_DMI_MEMDEVS 16
+#ifndef _TEST_H_
+#define _TEST_H_
#define E88 0x00
#define E801 0x04
#define E820NR 0x08 /* # entries in E820MAP */
@@ -36,9 +36,9 @@
};
typedef unsigned long ulong;
-#define SPINSZ 0x1000000 /* 1mb */
+#define SPINSZ 0x4000000 /* 256 MB */
#define MOD_SZ 20
-#define BAILOUT if (bail) goto skip_test;
+#define BAILOUT if (bail) return(1);
#define BAILR if (bail) return;
#define RES_START 0xa0000
@@ -47,40 +47,36 @@
#define SCREEN_END_ADR (SCREEN_ADR + 80*25*2)
#define TITLE_WIDTH 28
-#define LINE_TIME 10
-#define COL_TIME 0
-#define LINE_TST 2
-#define LINE_RANGE 3
-#define LINE_CPU 1
-#define COL_MID 30
-#define LINE_PAT 4
-#define COL_PAT 41
+#define LINE_TST 3
+#define LINE_RANGE 4
+#define LINE_PAT 5
+#define LINE_STATUS 8
#define LINE_INFO 10
-#define COL_CACHE_TOP 13
-#define COL_RESERVED 22
-#define COL_MMAP 29
-#define COL_CACHE 40
-#define COL_ECC 46
-#define COL_TST 52
-#define COL_PASS 56
-#define COL_ERR 63
-#define COL_ECC_ERR 72
#define LINE_HEADER 12
#define LINE_SCROLL 14
-#define BAR_SIZE (78-COL_MID-9)
#define LINE_MSG 18
+#define COL_INF1 15
+#define COL_INF2 32
+#define COL_INF3 51
+#define COL_INF4 70
+#define COL_MID 30
+#define COL_PAT 41
+#define BAR_SIZE (78-COL_MID-9)
#define COL_MSG 18
#define POP_W 34
#define POP_H 15
-#define POP_X 16
+#define POP_X 11
#define POP_Y 8
#define POP2_W 74
#define POP2_H 21
#define POP2_X 3
#define POP2_Y 2
-#define NULL 0
+/* CPU mode types */
+#define CPM_ALL 1
+#define CPM_RROBIN 2
+#define CPM_SEQ 3
/* memspeed operations */
#define MS_COPY 1
@@ -88,12 +84,12 @@
#define MS_READ 3
#define SZ_MODE_BIOS 1
-#define SZ_MODE_BIOS_RES 2
-#define SZ_MODE_PROBE 3
+#define SZ_MODE_PROBE 2
#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); })
int memcmp(const void *s1, const void *s2, ulong count);
void *memmove(void *dest, const void *src, ulong n);
+int strncmp(const char *s1, const char *s2, ulong n);
int query_linuxbios(void);
int query_pcbios(void);
int insertaddress(ulong);
@@ -101,27 +97,28 @@
void printpatn(void);
void itoa(char s[], int n);
void reverse(char *p);
+void serial_console_setup(char *param);
void serial_echo_init(void);
void serial_echo_print(const char *s);
void ttyprint(int y, int x, const char *s);
void ttyprintc(int y, int x, char c);
void cprint(int y,int x, const char *s);
-void hprint(int y,int x,ulong val);
+void cplace(int y,int x, const char s);
+void hprint(int y,int x, ulong val);
void hprint2(int y,int x, ulong val, int len);
void hprint3(int y,int x, ulong val, int len);
void xprint(int y,int x,ulong val);
void aprint(int y,int x,ulong page);
void dprint(int y,int x,ulong val,int len, int right);
-void movinv1(int iter, ulong p1, ulong p2);
-void movinvr();
-void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off);
-void modtst(int off, int iter, ulong p1, ulong p2);
+void movinv1(int iter, ulong p1, ulong p2, int cpu);
+void movinvr(int cpu);
+void movinv32(int iter, ulong p1, ulong lb, ulong mb, int sval, int off,
+ int cpu);
+void modtst(int off, int iter, ulong p1, ulong p2, int cpu);
void error(ulong* adr, ulong good, ulong bad);
void ad_err1(ulong *adr1, ulong *adr2, ulong good, ulong bad);
void ad_err2(ulong *adr, ulong bad);
-void do_tick(void);
-void rand_seed(int seed1, int seed2);
-ulong rand();
+void do_tick();
void init(void);
struct eregs;
void inter(struct eregs *trap_regs);
@@ -139,11 +136,10 @@
void get_config(void);
void get_menu(void);
void get_printmode(void);
-void addr_tst1(void);
-void addr_tst2(void);
-void bit_fade(void);
-void sleep(int sec);
-void block_move(int iter);
+void addr_tst1(int cpu);
+void addr_tst2(int cpu);
+void sleep(long sec, int flag, int cpu);
+void block_move(int iter, int cpu);
void find_ticks(void);
void print_err(ulong *adr, ulong good, ulong bad, ulong xor);
void print_ecc_err(ulong page, ulong offset, int corrected,
@@ -161,13 +157,15 @@
void clear_screen(void);
void paging_off(void);
void show_spd(void);
-void add_dmi_err(ulong adr);
-void print_dmi_info(void);
int map_page(unsigned long page);
void *mapping(unsigned long page_address);
void *emapping(unsigned long page_address);
-ulong memspeed(ulong src, ulong len, int iter, int type);
+ulong memspeed(ulong src, ulong len, int iter);
unsigned long page_of(void *ptr);
+ulong correct_tsc(ulong el_org);
+void bit_fade_fill(unsigned long n, int cpu);
+void bit_fade_chk(unsigned long n, int cpu);
+void find_ticks_for_pass(void);
#define PRINTMODE_SUMMARY 0
#define PRINTMODE_ADDRESSES 1
@@ -181,7 +179,6 @@
ulong mask;
};
-
static inline void cache_off(void)
{
asm(
@@ -192,6 +189,7 @@
"wbinvd\n\t"
"pop %eax\n\t");
}
+
static inline void cache_on(void)
{
asm(
@@ -202,29 +200,6 @@
"pop %eax\n\t");
}
-static inline void reboot(void)
-{
- asm(
- "movl %cr0,%eax\n\t"
- "andl $0x00000011,%eax\n\t"
- "orl $0x60000000,%eax\n\t"
- "movl %eax,%cr0\n\t"
- "movl %eax,%cr3\n\t"
- "movl %cr0,%ebx\n\t"
- "andl $0x60000000,%ebx\n\t"
- "jz f\n\t"
- ".byte 0x0f,0x09\n\t" /* Invalidate and flush cache */
- "f: andb $0x10,%al\n\t"
- "movl %eax,%cr0\n\t"
- "movw $0x0010,%ax\n\t"
- "movw %ax,%ds\n\t"
- "movw %ax,%es\n\t"
- "movw %ax,%fs\n\t"
- "movw %ax,%gs\n\t"
- "movw %ax,%ss\n\t"
- "ljmp $0xffff,$0x0000\n\t");
-}
-
struct mmap {
ulong pbase_addr;
ulong *start;
@@ -237,27 +212,13 @@
};
struct tseq {
- short cache;
+ short cpu_sel;
short pat;
short iter;
- short ticks;
short errors;
char *msg;
};
-struct cpu_ident {
- char type;
- char model;
- char step;
- char fill;
- long cpuid;
- long capability;
- char vend_id[12];
- unsigned char cache_info[16];
- long pwrcap;
- long ext;
-};
-
struct xadr {
ulong page;
ulong offset;
@@ -283,7 +244,6 @@
/* Define common variables accross relocations of memtest86 */
struct vars {
- int test;
int pass;
int msg_line;
int ecount;
@@ -299,7 +259,7 @@
int tptr;
struct err_info erri;
struct pmap pmap[MAX_MEM_SEGMENTS];
- struct mmap map[MAX_MEM_SEGMENTS];
+ volatile struct mmap map[MAX_MEM_SEGMENTS];
ulong plim_lower;
ulong plim_upper;
ulong clks_msec;
@@ -326,3 +286,4 @@
extern struct mem_info_t mem_info;
#endif /* __ASSEMBLY__ */
+#endif /* _TEST_H_ */
|
[-]
[+]
|
Added |
memtest86-4.0.tar.bz2/vmem.c
^
|
@@ -0,0 +1,139 @@
+/* vmem.c - MemTest-86
+ *
+ * Virtual memory handling (PAE)
+ *
+ * Released under version 2 of the Gnu Public License.
+ * By Chris Brady
+ */
+#include "test.h"
+
+static unsigned long mapped_win = 1;
+void paging_off(void)
+{
+ if (!v->pae)
+ return;
+ mapped_win = 1;
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7FFFFFFF, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ /* Disable pae & pse */
+ "movl %%cr4, %%eax\n\t"
+ "and $0xCF, %%al\n\t"
+ "movl %%eax, %%cr4\n\t"
+ :
+ :
+ : "ax"
+ );
+}
+
+static void paging_on(void *pdp)
+{
+ if (!v->pae)
+ return;
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable pae */
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000020, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pdp)
+ : "ax"
+ );
+}
+
+int map_page(unsigned long page)
+{
+ unsigned long i;
+ struct pde {
+ unsigned long addr_lo;
+ unsigned long addr_hi;
+ };
+ extern unsigned char pdp[];
+ extern struct pde pd2[];
+ unsigned long win = page >> 19;
+ if ((win == mapped_win)) {
+ return 0;
+ }
+ /* Less than 2 GB so no mapping is required */
+ if (win == 0) {
+ return 0;
+ }
+ if (!v->pae || (page > 0x1000000)) {
+ /* Fail either we don't have pae support
+ * or we want an address that is out of bounds (> 64GB)
+ * even for pae.
+ */
+ return -1;
+ }
+ /* Compute the page table entries... */
+ for(i = 0; i < 1024; i++) {
+ /*-----------------10/30/2004 12:37PM---------------
+ * 0xE3 --
+ * Bit 0 = Present bit. 1 = PDE is present
+ * Bit 1 = Read/Write. 1 = memory is writable
+ * Bit 2 = Supervisor/User. 0 = Supervisor only (CPL 0-2)
+ * Bit 3 = Writethrough. 0 = writeback cache policy
+ * Bit 4 = Cache Disable. 0 = page level cache enabled
+ * Bit 5 = Accessed. 1 = memory has been accessed.
+ * Bit 6 = Dirty. 1 = memory has been written to.
+ * Bit 7 = Page Size. 1 = page size is 2 MBytes
+ * --------------------------------------------------*/
+ pd2[i].addr_lo = ((win & 1) << 31) + ((i & 0x3ff) << 21) + 0xE3;
+ pd2[i].addr_hi = (win >> 1);
+ }
+ paging_off();
+ if (win > 1) {
+ paging_on(pdp);
+ }
+ mapped_win = win;
+ return 0;
+}
+
+void *mapping(unsigned long page_addr)
+{
+ void *result;
+ if (page_addr < 0x80000) {
+ /* If the address is less that 1GB directly use the address */
+ result = (void *)(page_addr << 12);
+ }
+ else {
+ unsigned long alias;
+ alias = page_addr & 0x7FFFF;
+ alias += 0x80000;
+ result = (void *)(alias << 12);
+ }
+ return result;
+}
+
+void *emapping(unsigned long page_addr)
+{
+ void *result;
+ result = mapping(page_addr -1);
+ /* Fill in the low address bits */
+ result = ((unsigned char *)result) + 0xffc;
+ return result;
+}
+
+unsigned long page_of(void *addr)
+{
+ unsigned long page;
+ page = ((unsigned long)addr) >> 12;
+ if (page >= 0x80000) {
+ page &= 0x7FFFF;
+ page += mapped_win << 19;
+ }
+#if 0
+ cprint(LINE_SCROLL -2, 0, "page_of( )-> ");
+ hprint(LINE_SCROLL -2, 8, ((unsigned long)addr));
+ hprint(LINE_SCROLL -2, 20, page);
+#endif
+ return page;
+}
|