memtest86+-5.01/0000755000000000000000000000000012201432235012036 5ustar rootrootmemtest86+-5.01/linuxbios.c0000644000000000000000000000744712201317426014236 0ustar rootroot#include "linuxbios_tables.h" #include "test.h" static unsigned long ip_compute_csum(void *addr, unsigned long length) { uint16_t *ptr; unsigned long sum; unsigned long len; unsigned long laddr; /* compute an ip style checksum */ laddr = (unsigned long )addr; sum = 0; if (laddr & 1) { uint16_t buffer; unsigned char *ptr; /* copy the first byte into a 2 byte buffer. * This way automatically handles the endian question * of which byte (low or high) the last byte goes in. */ buffer = 0; ptr = addr; memmove(&buffer, ptr, 1); sum += buffer; if (sum > 0xFFFF) sum -= 0xFFFF; length -= 1; addr = ptr +1; } len = length >> 1; ptr = addr; while (len--) { sum += *(ptr++); if (sum > 0xFFFF) sum -= 0xFFFF; } addr = ptr; if (length & 1) { uint16_t buffer; unsigned char *ptr; /* copy the last byte into a 2 byte buffer. * This way automatically handles the endian question * of which byte (low or high) the last byte goes in. */ buffer = 0; ptr = addr; memmove(&buffer, ptr, 1); sum += buffer; if (sum > 0xFFFF) sum -= 0xFFFF; } return (~sum) & 0xFFFF; } #define for_each_lbrec(head, rec) \ for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ (rec->size >= 1) && \ ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \ rec = (struct lb_record *)(((char *)rec) + rec->size)) static int count_lb_records(struct lb_header *head) { struct lb_record *rec; int count; count = 0; for_each_lbrec(head, rec) { count++; } return count; } static struct lb_header * __find_lb_table(unsigned long start, unsigned long end) { unsigned long addr; /* For now be stupid.... */ for(addr = start; addr < end; addr += 16) { struct lb_header *head = (struct lb_header *)addr; struct lb_record *recs = (struct lb_record *)(addr + sizeof(*head)); if (memcmp(head->signature, "LBIO", 4) != 0) continue; if (head->header_bytes != sizeof(*head)) continue; if (ip_compute_csum((unsigned char *)head, sizeof(*head)) != 0) continue; if (ip_compute_csum((unsigned char *)recs, head->table_bytes) != head->table_checksum) continue; if (count_lb_records(head) != head->table_entries) continue; return head; }; return 0; } static struct lb_header * find_lb_table(void) { struct lb_header *head; head = 0; if (!head) { /* First try at address 0 */ head = __find_lb_table(0x00000, 0x1000); } if (!head) { /* Then try at address 0xf0000 */ head = __find_lb_table(0xf0000, 0x100000); } return head; } int query_linuxbios(void) { struct lb_header *head; struct lb_record *rec; struct lb_memory *mem; struct lb_forward *forward; int i, entries; head = find_lb_table(); if (!head) { return 0; } /* coreboot also can forward the table to the high tables area. */ rec = (struct lb_record *)(((char *)head) + sizeof(*head)); if (rec->tag == LB_TAG_FORWARD) { forward = (struct lb_forward *)rec; head = (struct lb_header *)(unsigned long)(forward->forward); if (!head) { return 0; } } mem = 0; for_each_lbrec(head, rec) { if (rec->tag == LB_TAG_MEMORY) { mem = (struct lb_memory *)rec; break; } } if (!mem) { return 1; } entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); if (entries == 0) return 1; mem_info.e820_nr = 0; for(i = 0; i < entries; i++) { unsigned long long start; unsigned long long size; unsigned long type; if (i >= E820MAX) { break; } start = mem->map[i].start; size = mem->map[i].size; type = (mem->map[i].type == LB_MEM_RAM)?E820_RAM: E820_RESERVED; mem_info.e820[mem_info.e820_nr].addr = start; mem_info.e820[mem_info.e820_nr].size = size; mem_info.e820[mem_info.e820_nr].type = type; mem_info.e820_nr++; } return 1; } memtest86+-5.01/linuxbios_tables.h0000644000000000000000000000511012201317426015556 0ustar rootroot#ifndef LINUXBIOS_TABLES_H #define LINUXBIOS_TABLES_H #include "stdint.h" /* The linuxbios table information is for conveying information * from the firmware to the loaded OS image. Primarily this * is expected to be information that cannot be discovered by * other means, such as quering the hardware directly. * * All of the information should be Position Independent Data. * That is it should be safe to relocated any of the information * without it's meaning/correctnes changing. For table that * can reasonably be used on multiple architectures the data * size should be fixed. This should ease the transition between * 32 bit and 64 bit architectures etc. * * The completeness test for the information in this table is: * - Can all of the hardware be detected? * - Are the per motherboard constants available? * - Is there enough to allow a kernel to run that was written before * a particular motherboard is constructed? (Assuming the kernel * has drivers for all of the hardware but it does not have * assumptions on how the hardware is connected together). * * With this test it should be straight forward to determine if a * table entry is required or not. This should remove much of the * long term compatibility burden as table entries which are * irrelevant or have been replaced by better alternatives may be * dropped. Of course it is polite and expidite to include extra * table entries and be backwards compatible, but it is not required. */ struct lb_header { uint8_t signature[4]; /* LBIO */ uint32_t header_bytes; uint32_t header_checksum; uint32_t table_bytes; uint32_t table_checksum; uint32_t table_entries; }; /* Every entry in the boot enviroment list will correspond to a boot * info record. Encoding both type and size. The type is obviously * so you can tell what it is. The size allows you to skip that * boot enviroment record if you don't know what it easy. This allows * forward compatibility with records not yet defined. */ struct lb_record { uint32_t tag; /* tag ID */ uint32_t size; /* size of record (in bytes) */ }; #define LB_TAG_UNUSED 0x0000 #define LB_TAG_MEMORY 0x0001 #define LB_TAG_FORWARD 0x0011 struct lb_memory_range { uint64_t start; uint64_t size; uint32_t type; #define LB_MEM_RAM 1 #define LB_MEM_RESERVED 2 }; struct lb_memory { uint32_t tag; uint32_t size; struct lb_memory_range map[0]; }; #define LB_TAG_HWRPB 0x0002 struct lb_hwrpb { uint32_t tag; uint32_t size; uint64_t hwrpb; }; struct lb_forward { uint32_t tag; uint32_t size; uint64_t forward; }; #endif /* LINUXBIOS_TABLES_H */ memtest86+-5.01/screen_buffer.c0000644000000000000000000000465112201317426015024 0ustar rootroot/* screen_buffer.c - MemTest-86 Version 3.3 * * Released under version 2 of the Gnu Public License. * By Jani Averbach, Jaa@iki.fi, 2001 */ #include "test.h" #include "screen_buffer.h" #define SCREEN_X 80 #define SCREEN_Y 25 #define Y_SIZE SCREEN_Y /* * X-size should by one of by screen size, * so that there is room for ending '\0' */ #define X_SIZE SCREEN_X+1 static char screen_buf[Y_SIZE][X_SIZE]; #ifdef SCRN_DEBUG char *padding = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; #define CHECK_BOUNDS(y,x) do {if (y < 0 || Y_SIZE <= y || x < 0 || X_SIZE <= x) print_error("out of index");}while(0) #else /* ! SCRN_DEBUG */ #define CHECK_BOUNDS(y,x) #endif /* SCRN_DEBUG */ char get_scrn_buf(const int y, const int x) { CHECK_BOUNDS(y,x); return screen_buf[y][x]; } void set_scrn_buf(const int y, const int x, const char val) { CHECK_BOUNDS(y,x); screen_buf[y][x] = val; } void clear_screen_buf() { int y, x; for (y=0; y < SCREEN_Y; ++y){ for (x=0; x < SCREEN_X; ++x){ CHECK_BOUNDS(y,x); screen_buf[y][x] = ' '; } CHECK_BOUNDS(y,SCREEN_X); screen_buf[y][SCREEN_X] = '\0'; } } void tty_print_region(const int pi_top, const int pi_left, const int pi_bottom, const int pi_right) { int y; char tmp; for (y=pi_top; y < pi_bottom; ++y){ CHECK_BOUNDS(y, pi_right); tmp = screen_buf[y][pi_right]; screen_buf[y][pi_right] = '\0'; CHECK_BOUNDS(y, pi_left); ttyprint(y, pi_left, &(screen_buf[y][pi_left])); screen_buf[y][pi_right] = tmp; } } void tty_print_line( int y, int x, const char *text) { for(; *text && (x < SCREEN_X); x++, text++) { if (*text != screen_buf[y][x]) { break; } } /* If there is nothing to do return */ if (*text == '\0') { return; } ttyprint(y, x, text); for(; *text && (x < SCREEN_X); x++, text++) { screen_buf[y][x] = *text; } } void tty_print_screen(void) { #ifdef SCRN_DEBUG int i; for (i=0; i < SCREEN_Y; ++i) ttyprint(i,0, padding); #endif /* SCRN_DEBUG */ tty_print_region(0, 0, SCREEN_Y, SCREEN_X); } void print_error(char *pstr) { #ifdef SCRN_DEBUG ttyprint(0,0, padding); #endif /* SCRN_DEBUG */ ttyprint(0,35, pstr); while(1); } memtest86+-5.01/pci.c0000644000000000000000000001075512201317426012771 0ustar rootroot/* pci.c - MemTest-86 Version 3.2 * * Released under version 2 of the Gnu Public License. * By Chris Brady * ---------------------------------------------------- * MemTest86+ V5.00 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" #include "stdint.h" #include "cpuid.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) #define PCI_CONF3_ADDRESS(bus, dev, fn, reg) \ (0x80000000 | (((reg >> 8) & 0xF) << 24) | (bus << 16) | ((dev & 0x1F) << 11) | (fn << 8) | (reg & 0xFF)) 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 && pci_conf_type != PCI_CONF_TYPE_1)) return -1; result = -1; switch(pci_conf_type) { case PCI_CONF_TYPE_1: if(reg < 256){ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); }else{ outl(PCI_CONF3_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 (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255 && pci_conf_type != PCI_CONF_TYPE_1)) return -1; result = -1; switch(pci_conf_type) { case PCI_CONF_TYPE_1: if(reg < 256){ outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); }else{ outl(PCI_CONF3_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.char_array[0] == 'A' && cpu_id.vers.bits.family == 0xF) { 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; } memtest86+-5.01/smp.c0000644000000000000000000004124512201317426013013 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * ------------------------------------------------ * smp.c - MemTest-86 Version 3.5 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "stddef.h" #include "stdint.h" #include "cpuid.h" #include "smp.h" #include "test.h" #define DELAY_FACTOR 1 unsigned num_cpus = 1; // There is at least one cpu, the BSP int act_cpus; unsigned found_cpus = 0; extern void memcpy(void *dst, void *src , int len); extern void test_start(void); extern int run_cpus; extern int maxcpus; extern char cpu_mask[]; extern struct cpu_ident cpu_id; struct barrier_s *barr; void smp_find_cpus(); 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; } void barrier() { if (num_cpus == 1 || v->fail_safe & 3) { 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 || v->fail_safe & 3) { 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 initialise_cpus(void) { int i; act_cpus = 0; if (maxcpus > 1) { smp_find_cpus(); /* The total number of CPUs may be limited */ if (num_cpus > maxcpus) { num_cpus = maxcpus; } /* Determine how many cpus have been selected */ for(i = 0; i < num_cpus; i++) { if (cpu_mask[i]) { act_cpus++; } } } else { act_cpus = found_cpus = num_cpus = 1; } /* Initialize the barrier before starting AP's */ barrier_init(act_cpus); /* let the BSP initialise the APs. */ for(i = 1; i < num_cpus; i++) { /* Only start this CPU if it is selected by the mask */ if (cpu_mask[i]) { smp_boot_ap(i); } } } 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+3, 0, "SMP: STARTUP IPI was never sent"); } delay(100000 / DELAY_FACTOR); err = APIC_READ(APICR_ESR) & 0xef; if (err) { cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); hprint(LINE_STATUS+3, 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+3, 0, "SMP: STARTUP IPI was never sent"); } delay(100000 / DELAY_FACTOR); err = APIC_READ(APICR_ESR) & 0xef; if (err) { cprint(LINE_STATUS+3, 0, "SMP: After STARTUP IPI: err = 0x"); hprint(LINE_STATUS+3, 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); break; 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_find_cpus() { floating_pointer_struct_t *fp; rsdp_t *rp; rsdt_t *rt; uint8_t *tab_ptr, *tab_end; unsigned int *ptr; unsigned int uiptr; if(v->fail_safe & 3) { return; } memset(&AP, 0, sizeof AP); if(v->fail_safe & 8) { // 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 = (volatile apic_register_t*)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 RSDT or XSDT */ 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) { uiptr = *((unsigned int *)tab_ptr); ptr = (unsigned int *)uiptr; /* 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; 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+3, 0, "SMP: Boot timeout for"); dprint(LINE_STATUS+3, COL_MID, cpu_num,2,1); cprint(LINE_STATUS+3, 26, "Turning off SMP"); } } 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; } /* A set of simple functions used to preserve assigned CPU ordinals since * they are lost after relocation (the stack is reloaded). */ int num_to_ord[MAX_CPUS]; void smp_set_ordinal(int me, int ord) { num_to_ord[me] = ord; } int smp_my_ord_num(int me) { return num_to_ord[me]; } int smp_ord_to_cpu(int me) { int i; for (i=0; i= 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: memtest86+-5.01/memsize.c0000644000000000000000000002250412201317426013662 0ustar rootroot/* memsize.c - MemTest-86 Version 3.3 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "test.h" #include "defs.h" #include "config.h" short e820_nr; short memsz_mode = SZ_MODE_BIOS; static ulong alt_mem_k; static ulong ext_mem_k; static struct e820entry e820[E820MAX]; ulong p1, p2; ulong *p; static void sort_pmap(void); //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); static void memsize_linuxbios(); /* * Find out how much memory there is. */ void mem_size(void) { 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 */ if (e820_nr == 0 && alt_mem_k == 0 && ext_mem_k == 0) { ext_mem_k = mem_info.e88_mem_k; alt_mem_k = mem_info.e801_mem_k; e820_nr = mem_info.e820_nr; for (i=0; i< mem_info.e820_nr; i++) { e820[i].addr = mem_info.e820[i].addr; e820[i].size = mem_info.e820[i].size; e820[i].type = mem_info.e820[i].type; } } 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(); } static void sort_pmap(void) { int i, j; /* Do an insertion sort on the pmap, on an already sorted * list this should be a O(1) algorithm. */ for(i = 0; i < v->msegs; i++) { /* Find where to insert the current element */ for(j = i -1; j >= 0; j--) { if (v->pmap[i].start > v->pmap[j].start) { j++; break; } } /* Insert the current element */ if (i != j) { struct pmap temp; temp = v->pmap[i]; memmove(&v->pmap[j], &v->pmap[j+1], (i -j)* sizeof(temp)); v->pmap[j] = temp; } } } static void memsize_linuxbios(void) { int i, n; /* Build the memory map for testing */ n = 0; for (i=0; i < e820_nr; i++) { unsigned long long end; if (e820[i].type != E820_RAM) { continue; } end = e820[i].addr; end += e820[i].size; v->pmap[n].start = (e820[i].addr + 4095) >> 12; v->pmap[n].end = end >> 12; v->test_pages += v->pmap[n].end - v->pmap[n].start; n++; } v->msegs = n; } 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. */ 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) { memsize_801(); return; } /* Build the memory map for testing */ n = 0; for (i=0; i RES_START && start < RES_END) { if (end < RES_END) { continue; } start = RES_END; } if (end > RES_START && end < RES_END) { end = RES_START; } v->pmap[n].start = (start + 4095) >> 12; v->pmap[n].end = end >> 12; v->test_pages += v->pmap[n].end - v->pmap[n].start; n++; #if 0 int epmap = 0; int lpmap = 0; if(n > 12) { epmap = 34; lpmap = -12; } hprint (11+n+lpmap,0+epmap,v->pmap[n-1].start); hprint (11+n+lpmap,10+epmap,v->pmap[n-1].end); hprint (11+n+lpmap,20+epmap,v->pmap[n-1].end - v->pmap[n-1].start); dprint (11+n+lpmap,30+epmap,nm[i].type,0,0); #endif } } v->msegs = n; } static void memsize_801(void) { ulong mem_size; /* compare results from 88 and 801 methods and take the greater */ /* These sizes are for extended memory in 1k units. */ if (alt_mem_k < ext_mem_k) { mem_size = ext_mem_k; } else { mem_size = alt_mem_k; } /* First we map in the first 640k */ v->pmap[0].start = 0; v->pmap[0].end = RES_START >> 12; v->test_pages = RES_START >> 12; /* Now the extended memory */ v->pmap[1].start = (RES_END + 4095) >> 12; v->pmap[1].end = (mem_size + 1024) >> 2; v->test_pages += mem_size >> 2; v->msegs = 2; } /* * Sanitize the BIOS e820 map. * * Some e820 responses include overlapping entries. The following * replaces the original e820 map with a new one, removing overlaps. * */ static int sanitize_e820_map(struct e820entry *orig_map, struct e820entry *new_bios, short old_nr) { struct change_member { struct e820entry *pbios; /* pointer to original bios entry */ unsigned long long addr; /* address for this change point */ }; struct change_member change_point_list[2*E820MAX]; struct change_member *change_point[2*E820MAX]; struct e820entry *overlap_list[E820MAX]; struct e820entry biosmap[E820MAX]; struct change_member *change_tmp; ulong current_type, last_type; unsigned long long last_addr; int chgidx, still_changing; int overlap_entries; int new_bios_entry; int i; /* Visually we're performing the following (1,2,3,4 = memory types)... Sample memory map (w/overlaps): ____22__________________ ______________________4_ ____1111________________ _44_____________________ 11111111________________ ____________________33__ ___________44___________ __________33333_________ ______________22________ ___________________2222_ _________111111111______ _____________________11_ _________________4______ Sanitized equivalent (no overlap): 1_______________________ _44_____________________ ___1____________________ ____22__________________ ______11________________ _________1______________ __________3_____________ ___________44___________ _____________33_________ _______________2________ ________________1_______ _________________4______ ___________________2____ ____________________33__ ______________________4_ */ /* First make a copy of the map */ for (i=0; iaddr = biosmap[i].addr; change_point[chgidx++]->pbios = &biosmap[i]; change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; change_point[chgidx++]->pbios = &biosmap[i]; } /* sort change-point list by memory addresses (low -> high) */ still_changing = 1; while (still_changing) { still_changing = 0; for (i=1; i < 2*old_nr; i++) { /* if > , swap */ /* or, if current= & last=, swap */ if ((change_point[i]->addr < change_point[i-1]->addr) || ((change_point[i]->addr == change_point[i-1]->addr) && (change_point[i]->addr == change_point[i]->pbios->addr) && (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) ) { change_tmp = change_point[i]; change_point[i] = change_point[i-1]; change_point[i-1] = change_tmp; still_changing=1; } } } /* create a new bios memory map, removing overlaps */ overlap_entries=0; /* number of entries in the overlap table */ new_bios_entry=0; /* index for creating new bios map entries */ last_type = 0; /* start with undefined memory type */ last_addr = 0; /* start with 0 as last starting address */ /* loop through change-points, determining affect on the new bios map */ for (chgidx=0; chgidx < 2*old_nr; chgidx++) { /* keep track of all overlapping bios entries */ if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) { /* add map entry to overlap list (> 1 entry implies an overlap) */ overlap_list[overlap_entries++]=change_point[chgidx]->pbios; } else { /* remove entry from list (order independent, so swap with last) */ for (i=0; ipbios) overlap_list[i] = overlap_list[overlap_entries-1]; } overlap_entries--; } /* if there are overlapping entries, decide which "type" to use */ /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ current_type = 0; for (i=0; itype > current_type) current_type = overlap_list[i]->type; /* continue building up new bios map based on this information */ if (current_type != last_type) { if (last_type != 0) { new_bios[new_bios_entry].size = change_point[chgidx]->addr - last_addr; /* move forward only if the new size was non-zero */ if (new_bios[new_bios_entry].size != 0) if (++new_bios_entry >= E820MAX) break; /* no more space left for new bios entries */ } if (current_type != 0) { new_bios[new_bios_entry].addr = change_point[chgidx]->addr; new_bios[new_bios_entry].type = current_type; last_addr=change_point[chgidx]->addr; } last_type = current_type; } } return(new_bios_entry); } memtest86+-5.01/version.number0000644000000000000000000000005012201317426014734 0ustar rootroot4.99617 - Thu May 3 11:45:57 CEST 2012 memtest86+-5.01/precomp.bin0000755000000000000000000044501012201322643014205 0ustar rootrootظ))Ⱥ?؎Љjxd7׹eEd?dGȎ001ҹsP/4X001ҹ s s .0   u1ی-;v.+ s t1) 4.;u+u1 s1``.aAՋցRQSPraP 00 aQ:sE(X:Yø  ùV$0<9vR0Zô  Loading$Up؎Љ$|[Í>|TNLjP˸؎Ѓdu$1|\V)uǃdffW ffW&ffW,ffW2ffW8ffW>ffWDffWJffWNffWTffWXffW\ffW`ffWdffWhffWnffWtffWxffW~ffWЛ~jhjjjdjj^jjXjjRjjLjjFjj@jj:j6jj 0j ,j (j $j jjjjjj jjjjPSQRWVUD$0PT8u]^_ZY[Xϐ/fSVWU[s:\ffCh сt tx x| | TNp(؎Ў荋|l  f%".Ȏ؎fff)fSff1ffff1ۿ f fPAMSfr f=PAMSu<}fu11Ҹr*u ufffffS1r MPuS1S1r S1f[Ȏg f"f. ؎Ѝ|]_^[ f"f1f؎мe8$|jUWVS[=8T$D @Wu|D$D$ \l$|T$$t>t$!T &1w @v Љ\u+l$D$4thD$B9UwD$HL$@L$8|$ uT$+L$!|$ ul$).T$ +T$+T$9D$D$xx*$@T$0R‰T$T$@RT$ ;D$L$0<hu +L$ l$ ,$ml$,$f}uD$l$ l$L$$zto,$D$17B9UwD$JL$BL$:|$ uT$+T$!|$ ul$)/T$ +T$+T$9D$Ą[^_]ÐUWVS[4B$f<uG$f|t.$lj֋Af<u f|1u⋃$f|uk$f<uG$f|t.$lj֋Af<u f|1u[^_]S[3ffuFf$fxtffPfu$f8uǃǃǃ4ffǀd ǀh ǀH PTXL @@ @ @ @,@0@4@8f@D f@F@H@T@<f@X@@$x t@fPu f$fǀ[Y24B|S[^2 @= ufftOPjjc Pjjc DPjj c Pjj c[UWVS[1H $9s $L 9v;,$xD$$D$H\P`D$9 $sȉ9v9sU9sQ;<$vLL$IT$ T PT$X<$T$\D$F9puD$D$[^_]UWVS<[0D$(D$,D$ |$ uT$,D$$D$(>|$ ul$(D$$D$,|$ D$$T$$D$(T$, jD$8T$ũ[^_]UWVS[-t$0X9t vR H sXX=wǀXPj7j;^Pj7j#^X PLD$D@\$+Ń t$j'j*j Pj,j] Uj/j j +D$Pj7ji Pj낋X9uVt@t1!µ;U+j\Չl$4X9u jD$qVjwE^G9WV*4¸1VWjhjUg"4 VWjhjP1"4 G늿4 VE~G9wD$ jdǾЉD$8 Ut$WjV=&4 # UWt$jV&4 FuD$D$9z@8Vj,-ǃtjVja/ǃ`Vj.PVj,ǃ6t-jVj/ǃVj-4¸ փ t$VUW$4  t$UVW$4 GuD$D$ t$|$D$ |$D$ ǾՃ t$UWVX$4 uB t$WUV4$4 uFtD$ |$ tl$t[^_]UWVS [%Ƌu()PUVFPh8t@tyʉȉɀ?~y ?~)S[E%|T$O[WVS[%ffh8t@tyʉȉɀ?~y ?~fj ‰ )fff)ȍ Q @f)҃ RPf@ff~ ff0Ɖ )ʍfff)Ѝ<@f) j>GPVP$jt$$GPVM\jjt$(GPV8\t$G PVgU t$$GPV[ t$(WV[|$t[Th[^_UWVS,[l#fftƉ 8 D$l,;Pw狃+D$)ċffPT$Bt$jI8p@ uf= ?wf=" G? t4jPWLu WqPjPWLufBfjPW[Luj D$'PW|MDjPW$Lu fjPWKD$ D$ f@D$f8uDk tG<,t PtLu 9t$~$f?,uGt P;LujPWZK?0uU GPK =$f| uu ǃt6t*jjjPh9V u!9H r @u9u-jjjPh@V\ f$TRPjPhEVf ftTf|f~ +f;D$fҋX$f|u>f;D$fҋX$T 9T$ՋT 9~HX@$LIX $TUPjPhnV  jjPjj QX 9D$u Pu|Pt$ jJRPjPhV |8t VX9D$tu]%ǃ@_ǃ@)RPjPhV*VX,TERPjPhVE thT Pxgt$VjPhVt$t$VjPhVm WTX9lRPjPhVǃǃ4X 9D$$f| u@t@@@fftft>fafBffҋ;| fyfBffҋ;|cfGQ$f|u3fBffҋ;ffRPj PhV tuǃE@E jjPj1j M ǃ}u5f8t=ffuPjjE4D$f$$怈D$D$ÃT$ D$T$f$D$$ÃT$ D$T$f$D$$怃ËD$T$‹D$!S~uK T$(XD$ T$(\D$  T$(\T$(X)‰ЉD$~$D$4$D$D$,D$PD$,!ЉD$ T$(X‹D$$D$‹D$~9D$$u% T$(\D$ !D$D$‹D$ D$ PD$ [ÃD$  j@t$0t$|D$,PD$4PO D$D$4D$D$0D$,D$dD$$D$TD$8 t$tx~D$4;D$4v|$4t D$4D$D$4D$9D$4r D$D$4D$,D$0;D$4tm|$0T$4D$$D$ L$8L$D$`t$X\$ L$t& u1 9rȉډT$$D$8D$4D$0|$,1D$ ~9D$ D$D$ > j@t$0t$|D$,PD$4P D$D$4D$D$0D$,D$dD$$D$TD$8 t$tzw~D$4;D$4v|$4t D$4D$D$4D$9D$4r D$D$4D$,D$0;D$4|$0T$4D$$D$ L$8L$D$`t$X\$ L$U/9uщC u1 9rVPSRUQW踆_Y]Z[X^]ȉډT$$D$8D$4D$0|$,D$ ~9D$ L$$|$$yD$$D$XD$8D$(d$8D$` D$8D$(D$(;D$$|D$$~HD$ ? j@t$0t$|D$,PD$4Pj D$D$0D$D$4D$, t$tu~ D$4-;D$4s|$4t l$4 D$D$4D$,D$9D$4r D$9D$4v D$D$4D$,D$0;D$4|$0T$4D$$D$ L$8L$D$ D$ D$ D$D$(D$D$$D$ t$Pp~CD$(;D$(v|$(t D$(D$ D$(D$ 9D$(r D$ D$(D$D$$;D$(ttT$(D$$)D$ \$$L$ ҉GGG WWGGG G$W(W,G0G4W8W<Ѝ@IuʼnD$$|$*D$~9D$D$> j@t$(t$XD$$PD$,P D$ D$ D$D$(D$D$$D$D$(;D$(v|$(t D$(D$ D$(D$ 9D$(r D$ D$(D$D$$;D$(T$(D$$)ȉD$$D$,T$(D$$)ljD$ D$P t$Pn~{|$,t$$L$ |$$ t$,L$ |$$D$D$;D$@|D$(D$$|$ D$~9D$D$ j@t$(t$XD$$PD$,P D$ D$ D$D$(D$D$$D$ t$Pn~D$(;D$(v|$(t D$(D$ D$(D$ 9D$(r D$ D$(D$D$$;D$(tHl$(D$$T$(f;Ou9rRwQW}_ZD$$|$VD$~9D$0[^_Ã,t$4j)j2D$ T$XD$ T$\D$D$D$D$D$D$ t$@l~D$;D$v|$t D$D$D$D$;D$r D$D$D$ D$;D$u/D$T$0D$D$;D$rD$D$|$ kD$~9D$,Ã,D$ T$XD$ T$\D$D$D$D$D$ D$ t$@k~D$;D$v|$t D$D$D$D$;D$r D$D$D$D$ ;D$u2PD$ D$D$;D$0tt$t$8t$/{D$ D$ ;D$rƋD$D$ |$JD$~9D$,Ã>0tf ]~ PB0u FPti(fu[^_]WVS[$ƃƃD$@PWD$@PV $4$ $<$T$t$$[^_S[Ïdu?f8t@(f PQt%ƒ R `¸[VS["xxf>t[^UWVS,[(f Pq%ŃȀy0hL T$Љ}D$ŊD$ȀD$Q,[^_]UWVS [E|$ l$$t$(tɉBBuVUW[^_]UWVS[l$0|$ND4 PCD409+D41!D42 D43D44D45D46D47D48| ~rD49k ~aD4aZ ~PD4bI ~?D4c8 ~.D4d'~D4e~ D4f~ D4uhD$D$ D$ @D$> >` Ut$ PUt$uǠ|$u` D$ 둾Ƅ6` j VjkFPujOjjj[^_]UWVD$T$L$ t$$#l$!|$!! #|$> Љ#^_]ËL$utJWVS[Ùt$0VǃD$PD$Pt$PUt$GEFMuD$D$ |$t"T$ҍBl|$ jMjjj,[^_]UWVS[#D$ F D$Cj Ut$A FFEGMuD$D$ |$t"T$ҍBlt$ jMjjj',[^_]UWVS[ÄD$  ) j VUF-uED$ t |$ j-jj j,[^_]UWVS[D$  D$>PUt$5GEF-uD$D$ |$t#D$T$P|$ j-jj j!,[^_]UWVS[~D$  D$Cj Ut$ FFEG-uD$D$ |$t#D$T$Pt$ j-jj j,[^_]UWVS\[޶HD$D$ v Pj j T Pjj A Pjj . Pjj  Pjj Pjj Pjj Pjj Pjjp9DD\Pj j (Pjj u :Pjj b PPjj O `Pjj< tPjj)xyPjj Pjj  D$D$9w,$fxtffPfuGD$4APjj m Pjj Z jj#j lP b$fxtffHfu$f蟆4[Pjj Pjj Pjj $fxu$fEfPfuT$@@uD$Pj@jj D$ D4PtT40 Pjj + tPjj8ftu 9uPjj -Pjj 0 H jj 7Pjj j jjP;L wH J4=Pjj " -Pjj 0 L jj G 7Pjj j jjP;H rL 4J JAǀH PTXL J4R KPj j 9 ZPjj & lPjj  Pjj Pjj Pjj tPjj0 Pjd P<8tPjj/9wdžd @Lf@Xudžd @Lf@X@ Mdžd f@XD$ /džd f@X<8ʉPj j Pjj Pjj Pjj u tPjjbf Rj PCc tuZ 9ufft4fPj"j fft4fPj"j JBfft4fPj"j DD$.GD$#?58<G|$ t%|$t&\[^_]ÐUWVS[tS[~ N(V$F+t4S[F ~NV>vS[FtS[F=vS[VtxvVƽS[F0~4N8V<S[F@~DNHVLS[FP~TNXV\F_tx0 uxH0A9 tt@09tb1ut@0$&to1D:0*$tBu苓tR`9$wtR`$@$9vtx AuHxvƸS[NdVhtxvƸS[NlVpt`[^_]ÐUWVS,[$Ɖרu&fD$jPD$*PfD$.%OFT$ f)=v-JuŋL$ Nt4fD$jRD$*P5fD$.%D=v-%,[^_]UWVS[]T$9P$Ǎl$ |$jt$WulufD$uT4$W ;GuBG T $9s*At#9rAƉ9sFt 9s;Ot$9|$iD$D$[^_]UWVS,[ÁuP:u B HP T9A99u9u u'9A9sQ̉T$,@D$ |$tjrzt$|$ zAp4zj | lp4|$l$ |lp4L@D$l$9l$,[^_]ÐUWVS[L$l$T$|$ t$(tkbv$MB$<t <9w#  ‰ к 7  ‰% ‰% к |$$t*|$$t<|$$  f ~ |$$t*|$$t;|$$uD - f [^_]UWVS[[L$l$T$|$ t$(v$oB$<t <[w#  ‰ к 7  ‰% ‰% к |$$t2|$$tJ|$$ ‰ f%  |$$t2|$$tI|$$uS ‰4 f%  [^_]S [ÁD$Pjj jjj u|$ t[S[Btx Au@ <uƃ$ƃ$ D$  D$ =u!Wu D$ D$ \ D$ ƃ$u!u u D$  D$ ƃ$[UWVS &[UffD$ D$D$$< %% %4| (qy t| IL;D$uʋ$< $@ Ɖ$D $H 9(r9$P $H׉xh 9r9F9t$ՋT$҉T$0~T$T$(t$0@ 9u|$$($< L$ 4ʋ 8hyiJxh 8hyi9uJL$,rHy|$y9rEw l$9l$,r91|$3|$, u6:o1l$|$,*3} |$u93wl$,3/ t PD$$;D$u|$$u#2|$0~+$,D$(T$0(T$D$(D$$M|$0D$8D$<D$,D$(D$ $(t$4$ $|$DT$l$ D$4,l$$EUD$T$}t$3wD$3 t 6 A-il$T$;P%yH@D@PyPFutEu:[^_]UWVSL[ƃG\,DT KPjj _ cPjj Lt5DD$4D$0D$$ t$ T$4lz t GL$ L$~PjQ$jt$4j t$$lN PQFPFPʼn$$PUj t$$2G RPt$[ u"lJux t %l@ %w PWt$PWt$OPWt$PWt$PWt${PWt$kbPWt$RIPWt$90PWt$ PWt$o l@<uPUt$l`ulQu9Av;G|PUt$yw VUt$e>t EFFuEl$|$|$ lP PUW EFuы|$l$Hl@x<<lxy6PUt$u$jlByPVt$$] lyy wPVt$zPEPt$`u$jlBxPVt$$ lyx wPVt$APEPt$ l u JuPUt$G lxWD$ D$~PUt$$$jt$4EPt$41lGPGP D$,$KD$u $Pt$0Vt$4t$(PVt$$VT$,O ЍʃT$LD$LP$ػH؋L|$NfD$N fD$Ll$L|$l$Nt$贼Ń Pt$$t$$ $Ut$Vt$4<,.G <uPEPt$$VD$@l<uA@HuL$E|T$,;D$lL$D @;Gut$0Ut$$пw VUt$$輿>t EFFuEl$I|$(|$ lPm PUWwEF[uԋ|$(l$G PD$ D$|$L[^_]ÐVS[~0F=~uA jjPjHj d H w!FƄB G@Lu[^UWVS[t$0fr@frf~frpPFPjRX;0ugX;0c0~tF du&Йƃd~d jjVj"j)ƺQ)T$,0F( 9};&~ 4&~-W'Pj菽F(uF(9D$ ̋Nu!F Йƃd~d jjVj"j)ƺQ)T$,0F$ 9~;&~ 4&~-W'PjF$uF$9D$ ̃~hd [FDX~,v-;F4v D$ D$ >uEi$x u$@f8Hu RT$ ,2$Pf:@}9D$ ,HV<%уׁׁfׁׁׁ)DU  jj颋.)Rjj $ t@e1+X T ׉P MbȺP T$ D$ Dm,T$ )պgfff)Ǎ<)9  jjRjLjgjjgfff)RjKjGD$,L$,I )͉jjgfff)ōD)QjIjjjUjHjjjt$ jCj ~ u^ [^_]UWVS[)k0h PPjv螹h YD$XD$\D$ :~ t$WvB l GPvĿ t$ G Pv p G Pv蛿E;h }"t$GPv9h q[^_]UWVS,[ʼnT$|$D<8t hX$0>t~ux PjjcF$fD0d + tK|$H|$Hu |$@3|$|$Hu|$@tFTL$ Uor,9sB,J0D$ ;9u;J0sJ0J8D$ ;B4w D$ B4D$ 9B4u ;J8vJ8D$ A u틓B@JF9}fBFD$ JD9~fBDD$ P<9tD$ ׉x<ǃPLJ9t9u ǃ;PHvPHD$ hLD$fxX0H^Pjj n vPjj [ PjjH Pjj5 Pjj" Pjj Pjjf8tyD$D$N~D5,<x& jjPt$(Wot$ t$ W螵Fu|$6tD$ D$D$렃Pj@j aT$$fBX|$ (E<A uE,D$ u0Pjj 褻jVj!j T$Rj$j $jD$ Pj'j 菻jjD$ Pj-j qE4D$,u8Pjj2jVj!jrt$j$j~$jD$ Pj'j$jjD$ Pj-juu2x@|u#wnPGPjm$jMbT$,L$0l$,t$|$*fD$* fD$(l$(|$,l$*D$,P Wjי ,[^_]UWVS [Qa|$8l$ jjD$4|$"fD$" fD$ l$ |$l$"D$PVjT < jjD$4|$"fD$" fD$ l$ |$l$"D$PVj APVj>xك#D$$EuQFRPjx$j|$"fD$" fD$ D$8l$ |$l$"D$P Vj~ [^S0[FD$$Pjhjjj藟D$< vك#݄jك#d$T$\$D$$8[WS<[æEq2$T$L$l$س#ƒ?T$L$l$؃#D$T$l$؋ \$D$4Pjhjjj躞 D$-@tD$4Pjhjjj薞 D$,vك#݄üjt$L$\$(D$(d$$D[_S0[éDD$$Pjhjjj'D$< vك#݄Üjك#d$T$\$D$$D8[WS4[6Dq2ƒJv݄$T$L$l$س#D$T$l$؃#\$D$4PjhjjjP D$-@tD$4Pjhjjj, D$, vك#݄<jD$T$$D$$d$\$\$,D$,$CD[_UWVS4[2CD$$Pjhjjj谜D$< twutu@@@,q2փD$ PjhjjjWD$8 @t ?D$D$?t ;t$st$D$PCMPVV$F,V95_MP_u#~uu F <t<t 9wο^_]UWVt$l$9s>RSD uVHt 9w^_]UWVS[r t$V t V$F,V9s_€8uCxt=T $w+H͋ $hh0u%f%tjhP tUP Jw1Tǃt PF9uw [^_]UWVS[ÿD$0[^_]ÐYct@@t  %"UWVS[8D$0u tB@B tD$ L =vǁ|$ < l @=uLt@ t@@t60" " t@@t" "[^_]ËD$=w % S[,D$HP[Y D$ =v%ÐVST$ `nÍ4 ) ȍ؉`n`vˉ΍4q44 )ى `v[^Í&'D$ T$`nT$`vq/aiellllwwlluuu Rv9ctUraddress - B S S d _ u M H H H u H , : b&Bb&&4bbbbbbbbbbbbbbbbbbobbbbb bbBbbbBbbbbbbbbP^PoobPo ) )7?bbbbbbbbbbbbbbbbb&bbbbb&BbbbbbbbbbbbbbbbPobbobbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbb )bbb )bbbbb7M[,6'6'6'Gb}6'6'6'6'6'6'7R6'6'6'mh6'h'6''dd6' ! _ !! "P"!k"""" 6'6' ! !6'(!(!C!!\#\#\#####22d2k2r2y222222]222R22222222222222H22222222222222222222222255334444L4d4|4435535554555555K3559354544Z355x3*355555534545i3  HIHIJ3M^OPRRRHIHIRHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIRHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIHIRJJJK*KKJJJJJMJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJM4P4PIPjPPPP4P4P4P4PP4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4P4PPm{mbmIm0mmllllllllll @ @n``6{AAAAAAAAAA A0A@APA`ApACB|BCB|B@AA@AAPAXA`AApAAAAAAAA0A8A@AHA@@@@@@AAAA A(A@ @ @ @`UU@ @ @ @@ @ @ @ @ @ @ @"@ @ @%@`UU%@ @@@@@@`UU@@@@@@@@ @@@@"@@@@`UU%@@@@@(@`UU@@@@@@@@ @?@@@@ @(@0@`UU@@@@@@@@ @@@@"@@@@????????* 5 @@@@???@`UU@ @???@@?@33??@?`UU??@   *??@?@33??@@33@??`UU??@?@* 5 @@@@???@`UU@ @???@@?@33??@?`UU??@ ??@?-R\U?іs)?@?????`UU?????@33????-R\U?іs)?@hBoot Trace Enabled R - of console=btracemaxcpus=onepasststlist=cpumask=Begin BeforeInitAP_Start AP_Done Reloc_Done1st Barr Mem Mgmnt (PAE Mode)(X64 Mode)Start DoneSched_BarrSched_RelLSched_RelHSched_CPU0Sched_CPU1Sched_Win0Sched_Win1Sched_Win2Strt_Test End_Test End_Win Next_CPU Press any key to advance to next trace pointCPU Line Message Param #1 Param #2 CPU Line Message Param #1 Param #2--- ---- ----------- -------- -------- --- ---- ----------- -------- -------- ** Pass complete, no errors, press Esc to exit **[Address test, walking ones, no cache] [Address test, own address Sequential] [Address test, own address Parallel] [Moving inversions, 1s & 0s Parallel] [Moving inversions, 8 bit pattern] [Moving inversions, random pattern] [Block move] [Moving inversions, 32 bit pattern] [Random number sequence] [Modulo 20, Random pattern] [Bit fade test, 2 patterns] MB/s . MHz MHzL1 Cache: K L2 Cache: K L3 Cache: K INE_SCROLL;24r Memtest86 5.01 | Time: 0:00:00Pass %Test %Test #Testing: Pattern: CLK: (32b Mode)L1 Cache: Unknown L2 Cache: Unknown L3 Cache: None Memory : Core#:State:| Chipset : Unknown| Memory Type : Unknown| AMD 486DX2AMD 486DX2-WBAMD 486DX4AMD 486DX4-WBAMD 5x86-WTAMD 5x86-WBAMD K5AMD K6AMD K6-2AMD K6-IIIAMD K6-III+AMD Athlon (0.25)AMD Athlon (0.18)AMD Duron (0.18)Athlon XP (0.18)AMD Duron (0.13)Athlon XP (0.13)AMD DuronTM 5x00TM 8x00Intel 486DXIntel 486SXIntel 486DX2Intel 486SLIntel 486SX2Intel 486DX2-WBIntel 486DX4Intel 486DX4-WBPentiumPentium-MMXPentium ProPentium IICeleronPentium IIICeleron M (0.13)Pentium M (0.13)Pentium III XeonAtom (0.045)Celeron M (0.09)Pentium M (0.09)Intel CorePentium EIntel Core 2Pentium 4Celeron (0.09)Pentium 4 (0.09)Pentium D (65nm)Unknown IntelCentaur 5x86VIA C3 Samuel2VIA C3 EdenVIA C7 (C5J)VIA C7 (C5R)VIA Isaiah (CN)Cyrix 6x86MX/MIICyrix GXmCyrix IIIVIA C3 Ezra-TVIA C3 Nehemiah586686Unidentified Processor(SMP: Disabled)Running...| CPU Temp| COpteronGenuine Intel==> Press F1 to enter Fail-Safe Mode <====> Press F2 to force Multi-Threading (SMP) <== ------------------------------------------------------------------------------Cores: Active / Total (Run: All) | Pass: 0 Errors: 0 **** FAIL SAFE **** FAIL SAFE **** No detection, same reliability ?ttySockedHalting... Type: PC: CS: Eflag: Code: DS: SS: Addr: eax: ebx: ecx: edx: edi: esi: ebp: esp: Stack:K Divide Debug NMI BrkpntOverflow Bound Inv_Op No_MathDouble_FaultSeg_Over Inv_TSS Seg_NPStack_FaultGen_ProtPage_Fault Resvd FPEAlignment Mch_ChkSIMD FPE(ESC)exit (c)configuration (SP)scroll_lock (CR)scroll_unlockUnexpected Interrupt - Halting CPUCS:EIP: Settings:(1) Test Selection(2) Address Range(3) Error Report Mode(4) Core Selection(5) Refresh Screen(6) Display DMI Data(7) Display SPD Data(0) ContinueTest Selection:(1) Default Tests(2) Skip Current Test(3) Select Test(4) Enter Test List(0) Cancel>Test Number [1-11]: Enter a comma separated listof tests to execute:List: Test Address Range:(1) Set Lower Limit(2) Set Upper Limit(3) Test All MemoryLower Limit: Current: New: Upper Limit: Printing Mode:(1) Error Summary(2) Individual Errors(3) BadRAM Patterns(4) Error Counts Only(5) Beep on ErrorCPU Selection Mode:(1) Parallel (All)(2) Round Robin (RRb)(3) Sequential (Seq)AllRRbSeqLBIOSMBus Controller not knownSPD Data: SlotMemory SPD Informations-------------------------- - Slot :DDR3-????DDR3-800DDR3-1066DDR3-1333DDR3-1600DDR3-1866DDR3-2133DDR3-2400DDR3-2533DDR3-2666ECC(W'*XMP*DDR2-Intel HSW-ULTIntel HSWIntel Z77Intel P67Intel P55Intel ICH10BIntel ICH10RIntel ICH9Intel ICH8Intel ICH7Intel ICH6Intel ICH5Intel ICH4Intel 6300ESBIntel ESB2Intel US15WIntel EP80579AMD SB600/700AMD SB800/900AMDAMIFairchildFujitsuHarrisHitachiInmosI.T.T.IntersilMonolithic MemoriesMostekFreescaleNationalNECRCARaytheonConexantNXPSynertekTexas InstrumentsToshibaXicorZilogMitsubishiLucent (AT&T)AtmelSGS/ThomsonNCRIBMTristarIntl. CMOS TechnologyMicrochipTechnologyHynixOKI SemiconductorSharpCatalystPanasonicIDTCypressDECLSI LogicUTMCThomson CSFTektronixProMos/MoselInfineonXeroxSanDiskApple ComputerXilinxCompaqSeiko InstrumentsSamsungHewlett-PackardIntegrated Silicon SolutionsWinbond ElectronicExarLGSanyoAnalog DevicesCannonSonyAllied-SignalDialogMedia VisionCirrus LogicNational InstrumentsDATARAMSmart ModularKingstonMushkinAdaptecPNYTransmetaMicron CMSTower SemiconductorMaxim Integrated ProductUnigenTranscendMemory CardMSCDane-ElecItec MemoryWintecIntegrated Memory SystemLeCroyApacer TechnologyFOXCONNCorsairMIPS TechnologiesKentron TechnologiesSiemens AGSpecTekESS TechnologyAgilent TechnologiesMDTElpidaOptosys TechnologiesBuffaloPrincetonNanyaATINetlistCentonTyco ElectronicsKingmaxeMemory TechnologyMemory ExpertsViasystems GroupSimtekPLX TechnologyJade StartakeMSSwissbitMitac InternationalnVidiaAcctonRAM ComponentsUtronTeraChipT-RAMSilicon Mountain MemoryScaleo ChipRenesasOCZAltiumARMPericomRamaxelLegacy ElectronicsExcel SemiconductorA-DATAG.SkillKingboxMicrosoftSimmtecTeam GroupThomson SCPatriot MemoryCompuRAMNovaTechCOS MemoryCrucialULiPQISigma DesignsMSIQimondaWalton ChaintechAENEONHexonGoldenmarsKretonAvant TechnologyAsrockMolexAvexirMemory Corp NVSiSTridentSuper TalentGingleASintRamtronTOPRAMKinglifeSandForceLexar MediaMemory Exchange Corp.AvantiumTwinMOSSilicon SystemsInnoDiskMuscle PowerStrontiumEKMemoryNokiaKing TigerHT MicronAlbatronMercyPowerTopowerRitekMemorightUltronTMT Memory?@Fbadram=,0x,Error Confidence Value: Lowest Error Address: Highest Error Address: Bits in Error Mask: Bits in Error - Total:Min: Max: Avg: Max Contiguous Errors:: 0Test Errors - . MBuncorrected corrected Tst Pass Failing Address Good Bad Err-Bits Count CPU--- ---- ----------------------- -------- -------- -------- ----- ----Parity error detected Bad Memory Devices: , /Emptymapped to: OtherEDRAMVRAMSRAMFLASHEEPROMFEPROMCDRAM3DRAMSGRAMRDRAMDDR2DDR2 FBRSVDDDR3FBD2SIMMSIPDIPZIPProprietary CardTSOPRow of chipsSODIMMSRIMMFB-DIMMNo valid DMI Memory Devices info foundDMI Memory Device Info (page Location Size(MB) Speed(MHz) Type FormNo mapping (Interleaved Device)RAM Type: Chipset: - FSB : 1.52.5 @ 64-bit Mode @ 128-bit Mode @ 192-bit Mode @ 256-bit Mode/ CAS : MHz (DDR-DDR3- - BCLK: AMD 751SDRAM PC-100AMD 762DDR-SDRAMAMD 761SiS 600EDO/SDRAMSiS 620SiS 5600SiS 645SiS 645DXSiS 630SiS 650SiS 651SiS 730SiS 735SiS 740SiS 745SiS 748SiS 655SiS 656DDR/DDR2-SDRAMSiS 648SiS 649SiS 661SiS 671SiS 672ALi Aladdin 4ALi Aladdin 5ALi Aladdin M1644ATi Radeon 9100 IGPATi Xpress 200nVidia nForcenVidia nForce2 SPPnForce4 SLIVIA KT133/KT133AVIA KX133VIA MVP4VIA VP/VPXVIA VP2VIA VP3VIA MVP3VIA Apollo Pro 133(A)VIA Apollo Pro+VIA PLE133VIA KT266(A)/KT333VIA KT400(A)/600VIA KT880VIA KM400VIA KM266VIA KN266VIA CLE266VIA PT800VIA PT880CNB20HECNB20LEIntel i815Intel i430FXEDO DRAMIntel i430MXIntel i440FXIntel i430HXIntel i840Intel i845SDR/DDRIntel i845E/G/PE/GEIntel i820Intel i850Intel i860Intel i430VXIntel i430TXIntel i810Intel i810EIntel i440[LE]XIntel i440BXIntel i440GXIntel i450GXIntel E7500Intel E7501Intel E7205Intel E7320Intel E7221Intel E7520Intel E8500Intel i848/i865Intel i875PIntel E7505Intel i852P/i855GIntel i855PMIntel i915P/GIntel i915PM/GMIntel i925X/XEIntel i945P/GIntel i945GM/PMIntel i945GMEIntel i955XIntel i975XIntel i946PL/GZIntel Q963/Q965Intel P965/G965Intel GM965/GL960Intel GME965/GLE960Intel PM/GM45/47Intel Q35Intel P35/G33Intel Q33Intel X38/X48Intel 3200/3210Intel Q45/Q43Intel P45/G45Intel G41Intel 5400AIntel 5400BIntel 5000PIntel 5000VIntel 5000XIntel 5000ZIntel UL11L/US15LCore IMCSNB IMCSNB-E IMCIVB IMCHSW IMCPineView IMCCedarTrail IMCAMD K8 IMCAMD K10 IMCAMD K12 IMCAMD K14 IMCAMD K15 IMCAMD K16 IMCTimings: CAS RAM: @? @ A@@@@@ACUUU@BzDA>)\O?ڬ?ڬ*?C@D?@?>Em>UUU??(%?+LUUU??-R\U?-R\U?SMP: STARTUP IPI was never sentSMP: After STARTUP IPI: err = 0xSMP: Boot timeout forTurning off SMP[ `&f`~ @( S1kN k1&S @ _os2t` xPMHy0@ta x E~ \[ l &pkv]@ $ +Di^ KkL8V,  A N| K#1Em P T| 8 ^(Gl>A!8~ o|O p[ l%M t[  YE7^ ;FJ[d~ kp3@  4`~  S .,=s D?( Mv K$́" i_O~=ma@" 0D) ` FP 9,^|[  K $XEQ >.Zwax[ G '+@P `+D g~ #A p@ /HW~u!v~  @ 1h~ d P m~ Y'r1SpV  !w  w hXv>  @7v}hP  G_"Spm8[ W ~ WN!!  B $ #8V aR! s:`(LP *DP [ K  ~ !0   16m l[ `P  hxo,9tx 7g[  am ۄeđ 6 m tTNQn| Fx K v>> $  $|lHoF-WL  U3 m !"~ ~ n*Wi'j $` &P9R'   @ <&$ Yl#B x G[ MNMr>3l~ ~  HP _sq l!   ăg=[ i8o'%m @ av(kuW ol3,l-{~ = L>5@8 ? [!?xn 2\@ <kRjstartup_32boot_stack_topgdt_bss_dl_starttest_startintergdt_endpd0pd1pd2pd3pdppml4query_pcbiosboot_stackmem_info_ap_trampoline_start_ap_trampoline_protmodenext_testtseqset_defaultsstart_seqonepassbailcpu_modecpu_selvariablesrestart_flagrelocreloc_pendingclear_screenbtflagcprintemappingfind_chunksnum_cpusact_cpusfind_ticks_for_passdo_testmstr_cpupage_ofsegsaprintset_cacheaddr_tst1addr_tst2s_barriermovinv1cpu_idrand_seedrandblock_movemovinv32movinvrmodtstbitf_seqbit_fade_fillsleepbit_fade_chkmemmovebarrreloc_internalbtracetidxcplacedprinthprintwait_keyupsmp_my_cpu_numstackscpu_ordsmp_set_ordinalcmdline_parsedcpu_maskstrncmpserial_console_setupsimple_strtoulmaxcpusisdigittoupperbin_maskisxdigitmem_sizeget_cpuidhigh_test_adrsmp_ap_bootedsmp_my_ord_numget_mem_speedtest_ticksnticksrun_cpuss_barrier_initmap_pagepaging_offrebootcalculate_chunkad_err1do_tickad_err2beepdetect_imcimc_typetsc_invariablecorrect_tscmemspeedl2_cachel3_cachel1_cachesmp_default_modestrstrstlowsthighextclockfailsafeget_keyserial_echo_initserial_echo_printfooterdmi_initializeddmi_err_cntsbeepmodepci_initinitialise_cpusfind_controllerget_spd_speccoretempstrlenmemcmpclear_scrollreverseitoamemcpygetnumascii_to_keycodeser_mapserial_parityserial_baud_rateserial_ttyserial_consserial_base_portslsrttyprintserial_bitsclear_screen_buftty_print_lineget_listgetvaltty_print_screenslockcheck_inputget_confighprint3hprint2parity_errcodesxprintget_scrn_bufset_scrn_buftty_print_regioncombineaddressescombicostcheapindexrelocateidxrelocateiffreeinsertaddressprint_erroradj_mempop2clearpop2downsave2pop2uppopclearpopdownsavepopupprint_dmi_infoshow_spdprintpatnquery_linuxbiospci_conf_writepci_conf_reade820_nrmemsz_modep1p2sb800_get_smbsmbusbaseich5_smb_read_bytespd_rawget_ddr3_module_sizeget_ddr2_module_sizeconvert_hex_to_charus15w_smb_read_bytesmbfunsmbdevfind_smb_controllerspin_idxspinprint_ecc_errget_tstruct_stringopen_dmimem_devs_countmd_maps_countmem_devsmd_mapsdmi_system_infodmi_cpu_infoinit_dmiadd_dmi_errprint_dmi_errprint_dmi_startup_infopoll_errorscontrollersnhm_busprint_ram_linecol2print_cpu_linecolPUT_MEM16PUT_MEM32APICdelayread_mp_config_tablefound_cpusscan_for_floating_ptr_structscan_for_rsdpparse_madtsmp_find_cpusAPmy_apic_idnum_to_ordsmp_ord_to_cpusmp_boot_apkick_cpu_etext_data_edataKp7Y8O{)QGfgxF?oc@q%u;`H*zbVeAy=mhkUaD"v +30#$,19!426 WZT-C'sPM< RNnEJt}~i> wrI.\ _BS/|5^XljL[(&]d:|sy>)??L@k@@ABCyCDUDvDDGEkEEE~FFFGXGGNN'''(N(Y( ,<L\lh+l+t+x+|++++++++++++++++++++++,, ,,, ,(,,,0,4,@,D,L,P,T,X,d,h,p,t,x,|,,,,,,,,,,,,,,,,,,,,,--- ---$-(-,-0-<-@-H-L-P-T-`-d-l-p-t-x----------------------..... .$.(.,.8.<.D.H.L.P.\.`.h.l.p.t.......................///// /$/(/4/8/@/D/H/L/X/\/d/h/l/p/|///////////////////////0 0000 0$00040<0@0D0H0T0X0`0d0h0l0x0|000000000000000000000001 1111 1,10181<1@1D1P1T1\1`1d1h1t1x11111111111111111111111222222(2,24282<2@2L2P2X2\2`2d2p2t2|222222222222222222222233 3333$3(3034383<3H3L3T3X3\3`3l3p3x3|333333333333333333333344 444 4$4,4044484D4H4P4T4X4\4h4l4t4x4|444444444444444444444455 555 5(5,50545@5D5L5P5T5X5d5h5p5t5x5|555555555555555555555666 666$6(6,606<6@6H6L6P6T6`6d6l6p6t6x666666666666666666666677777 7$7(7,787<7D7H7L7P7\7`7h7l7p7t7777777777777777777777788888 8$8(84888@8D8H8L8X8\8d8h8l8p8|888888888888888888888889 9999 9$90949<9@9D9H9T9X9`9d9h9l9x9|99999999999999999999999: :::: :,:0:8:<:@:D:P:T:\:`:d:h:t:x:::::::::::::::::::::::;;;;;;(;,;4;8;<;@;L;P;X;\;`;d;p;t;|;;;;;;;;;;;;;;;;;;;;;;<< <<<<$<(<0<4<8<<<H<L<T<X<\<`<l<p<x<|<<<<<<<<<<<<<<<<<<<<<<== === =$=,=0=4=8=D=H=P=T=X=\=h=l=t=x=|======================>> >>> >(>,>0>4>@>D>L>P>T>X>d>h>p>t>x>|>>>>>>>     $ 0 4 8 D H L X \ ` l p t                     ! !!! !$!(!4!8!>>>>>>>>>>>>>>>>>>>??? ????? ?$?(?,?0?4?8? >@>`>>>>>? ?@?`?????@ @@@`@@@@@A A@A`AAAAAB B@B`BBBBBC C@C`CCCCCD D@D`DDDDDE E@E`EEEEEF F@F`FFFFFG G@G`GGGGGH H@H`HHHHHI I@I`IIIIIJ J@J`JJJJJK K@K`KKKKKL L@L`LLLLLM M@M`MMMMMN N@N`NNNNNO O@O`OOOOOP P@P`PPPPPQ Q@Q`QQQQQR R@R`RRRRRS S@S`SSSSST T@T`TTTTTU U@U`UUUUUV V@V`VVVVVW W@W`WWWWWX X@X`XXXXXY Y@Y`YYYYYZ Z@Z`ZZZZZ[ [@[`[[[[[\ \@\`\\\\\] ]@]`]]]]]^ ^@^`^^^^^_ _@_`_____` `@```````a a@a`aaaaab b@b`bbbbbc c@c`cccccd d@d`ddddde e@e`eeeeef f@f`fffffg g@g`gggggh h@h`hhhhhi i@i`iiiiij j@j`jjjjjk k@k`kkkkkl l@l`lllllm m@m`mmmmmn n@n`nnnnno o@o`ooooop p@p`pppppq q@q`qqqqqr r@r`rrrrrs s@s`ssssst t@t`tttttu u@u`uuuuuv v@v`vvvvvw w@w`wwwwwx x@x`xxxxxy y@y`yyyyyz z@z`zzzzz{ {@{`{{{{{| |@|`|||||} }@}`}}}}}~ ~@~`~~~~~ @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` @` %   9 9aAb0B00c.C..d D  eEf!F!!g"G""h#H##iI j$J$ $k%K% %l&L& &m2M2 2n1N11oOpPqQrRsStTuUv/V//wWx-X--yYz,Z,,- _  = + [{]};':''("(`)~)\+|++,3<3.4>4/5?51!2@3#4$5%6^7&8 * 9 ( 0 ) /-\| |/-\?AB 8B `B B B QBC 0(C PC xC`PwHFHJJJJJK KKK+K4K=KFKRK[KfKoKxKKK"OSݣ"OSݣ"OSݣ"OSݣ0;OSݣ`:OSݣ0:OSݣ0)OSݣ>(PSݣ' PSݣj&PSݣ$"PSݣ$-PSݣ%8PSݣ&FPSݣQP2P]PSݣCkPݣ" xyPݣS[PPPPPPPHP PP PPPPPPQQQQ-Q5Q;QAQLQZQ `QlQpQ%tQ|Q)Q,WQQQ1Q2QQ4QQQ8QQ=R@ RRC"RE(R0RI?RJFRMR_RTgRwRR^RRbRRmRRR|RRRRSS*S23S4;SCSGSEQS\SpSSOSSSS^SaShSSzS|ST T*T/0T;T;CTRTdgTkTrTTT TT3STTT%T)TTTTUUXU%U.UkBUIUsPUy_UeUnUtUU#UUU;UUCUFUJUUUQUUVV-QvV%V4V=VFVQVYV>]VaVFoVQsV{VWVVbVVVVVVVVV4VVVWO WQW]W^'W3WbIWkRWZWjWsWW WWWWW)WW2W4W;WW S[6OY3OA^YYYpUYYYZYZZ\ZZ^ Z%Z-Z-Z-Z2Z7Z6OYE $(BUILD_NUMBER_FILE); fi @echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE) memtest86+-5.01/jedec_id.h0000644000000000000000000007737412201317426013763 0ustar rootroot/* MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * ------------------------------------------------ * Based on JEDEC JEP106-AG - January 2012 * All mo */ struct spd_jedec_manufacturer { unsigned cont_code; unsigned hex_byte; char *name; }; static struct spd_jedec_manufacturer jep106[] = { { 0, 0x01, "AMD"}, { 0, 0x02, "AMI"}, { 0, 0x83, "Fairchild"}, { 0, 0x04, "Fujitsu"}, // { 0, 0x85, "GTE"}, { 0, 0x86, "Harris"}, { 0, 0x07, "Hitachi"}, { 0, 0x08, "Inmos"}, { 0, 0x89, "Intel"}, { 0, 0x8a, "I.T.T."}, { 0, 0x0b, "Intersil"}, { 0, 0x8c, "Monolithic Memories"}, { 0, 0x0d, "Mostek"}, { 0, 0x0e, "Freescale"}, { 0, 0x8f, "National"}, { 0, 0x10, "NEC"}, { 0, 0x91, "RCA"}, { 0, 0x92, "Raytheon"}, { 0, 0x13, "Conexant"}, // { 0, 0x94, "Seeq"}, { 0, 0x15, "NXP"}, { 0, 0x16, "Synertek"}, { 0, 0x97, "Texas Instruments"}, { 0, 0x98, "Toshiba"}, { 0, 0x19, "Xicor"}, { 0, 0x1a, "Zilog"}, // { 0, 0x9b, "Eurotechnique"}, { 0, 0x1c, "Mitsubishi"}, { 0, 0x9d, "Lucent (AT&T)"}, // { 0, 0x9e, "Exel"}, { 0, 0x1f, "Atmel"}, { 0, 0x20, "SGS/Thomson"}, // { 0, 0xa1, "Lattice Semi."}, { 0, 0xa2, "NCR"}, // { 0, 0x23, "Wafer Scale Integration"}, { 0, 0xa4, "IBM"}, { 0, 0x25, "Tristar"}, // { 0, 0x26, "Visic"}, { 0, 0xa7, "Intl. CMOS Technology"}, // { 0, 0xa8, "SSSI"}, { 0, 0x29, "MicrochipTechnology"}, // { 0, 0x2a, "Ricoh"}, // { 0, 0xab, "VLSI"}, { 0, 0x2c, "Micron"}, { 0, 0xad, "Hynix"}, { 0, 0xae, "OKI Semiconductor"}, // { 0, 0x2f, "ACTEL"}, { 0, 0xb0, "Sharp"}, { 0, 0x31, "Catalyst"}, { 0, 0x32, "Panasonic"}, { 0, 0xb3, "IDT"}, { 0, 0x34, "Cypress"}, { 0, 0xb5, "DEC"}, { 0, 0xb6, "LSI Logic"}, // { 0, 0x37, "Zarlink (Plessey)"}, { 0, 0x38, "UTMC"}, // { 0, 0xb9, "Thinking Machine"}, { 0, 0xba, "Thomson CSF"}, // { 0, 0x3b, "Integrated CMOS (Vertex)"}, // { 0, 0xbc, "Honeywell"}, { 0, 0x3d, "Tektronix"}, // { 0, 0x3e, "Oracle"}, // { 0, 0xbf, "Silicon Storage Technology"}, { 0, 0x40, "ProMos/Mosel"}, { 0, 0xc1, "Infineon"}, // { 0, 0xc2, "Macronix"}, { 0, 0x43, "Xerox"}, // { 0, 0xc4, "Plus Logic"}, { 0, 0x45, "SanDisk"}, // { 0, 0x46, "Elan Circuit Tech."}, // { 0, 0xc7, "European Silicon Str."}, { 0, 0xc8, "Apple Computer"}, { 0, 0x49, "Xilinx"}, { 0, 0x4a, "Compaq"}, // { 0, 0xcb, "Protocol Engines"}, // { 0, 0x4c, "SCI"}, { 0, 0xcd, "Seiko Instruments"}, { 0, 0xce, "Samsung"}, // { 0, 0x4f, "I3 Design System"}, // { 0, 0xd0, "Klic"}, // { 0, 0x51, "Crosspoint Solutions"}, // { 0, 0x52, "Alliance Semiconductor"}, // { 0, 0xd3, "Tandem"}, { 0, 0x54, "Hewlett-Packard"}, { 0, 0xd5, "Integrated Silicon Solutions"}, // { 0, 0xd6, "Brooktree"}, // { 0, 0x57, "New Media"}, // { 0, 0x58, "MHS Electronic"}, // { 0, 0xd9, "Performance Semi."}, { 0, 0xda, "Winbond Electronic"}, // { 0, 0x5b, "Kawasaki Steel"}, // { 0, 0xdc, "Bright Micro"}, // { 0, 0x5d, "TECMAR"}, { 0, 0x5e, "Exar"}, // { 0, 0xdf, "PCMCIA"}, { 0, 0xe0, "LG"}, // { 0, 0x61, "Northern Telecom"}, { 0, 0x62, "Sanyo"}, // { 0, 0xe3, "Array Microsystems"}, // { 0, 0x64, "Crystal Semiconductor"}, { 0, 0xe5, "Analog Devices"}, // { 0, 0xe6, "PMC-Sierra"}, // { 0, 0x67, "Asparix"}, // { 0, 0x68, "Convex Computer"}, // { 0, 0xe9, "Quality Semiconductor"}, // { 0, 0xea, "Nimbus Technology"}, // { 0, 0x6b, "Transwitch"}, // { 0, 0xec, "Micronas (ITT Intermetall)"}, { 0, 0x6d, "Cannon"}, // { 0, 0x6e, "Altera"}, // { 0, 0xef, "NEXCOM"}, // { 0, 0x70, "QUALCOMM"}, { 0, 0xf1, "Sony"}, // { 0, 0xf2, "Cray Research"}, // { 0, 0x73, "AMS(Austria Micro)"}, // { 0, 0xf4, "Vitesse"}, // { 0, 0x75, "Aster Electronics"}, // { 0, 0x76, "Bay Networks (Synoptic)"}, // { 0, 0xf7, "Zentrum/ZMD"}, // { 0, 0xf8, "TRW"}, // { 0, 0x79, "Thesys"}, // { 0, 0x7a, "Solbourne Computer"}, { 0, 0xfb, "Allied-Signal"}, { 0, 0x7c, "Dialog"}, { 0, 0xfd, "Media Vision"}, // { 0, 0xfe, "Numonyx"}, { 1, 0x01, "Cirrus Logic"}, { 1, 0x02, "National Instruments"}, // { 1, 0x83, "ILC Data Device"}, // { 1, 0x04, "Alcatel Mietec"}, // { 1, 0x85, "Micro Linear"}, // { 1, 0x86, "Univ. of NC"}, // { 1, 0x07, "JTAG Technologies"}, // { 1, 0x08, "BAE Systems (Loral)"}, // { 1, 0x89, "Nchip"}, // { 1, 0x8a, "Galileo Tech"}, // { 1, 0x0b, "Bestlink Systems"}, // { 1, 0x8c, "Graychip"}, // { 1, 0x0d, "GENNUM"}, // { 1, 0x0e, "VideoLogic"}, // { 1, 0x8f, "Robert Bosch"}, // { 1, 0x10, "Chip Express"}, { 1, 0x91, "DATARAM"}, // { 1, 0x92, "United Microelectronics Corp."}, // { 1, 0x13, "TCSI"}, { 1, 0x94, "Smart Modular"}, // { 1, 0x15, "Hughes Aircraft"}, // { 1, 0x16, "Lanstar Semiconductor"}, // { 1, 0x97, "Qlogic"}, { 1, 0x98, "Kingston"}, // { 1, 0x19, "Music Semi"}, // { 1, 0x1a, "Ericsson Components"}, // { 1, 0x9b, "SpaSE"}, // { 1, 0x1c, "Eon Silicon Devices"}, // { 1, 0x9d, "Programmable Micro Corp"}, // { 1, 0x9e, "DoD"}, // { 1, 0x1f, "Integ. Memories Tech."}, // { 1, 0x20, "Corollary"}, // { 1, 0xa1, "Dallas Semiconductor"}, // { 1, 0xa2, "Omnivision"}, // { 1, 0x23, "EIV(Switzerland)"}, // { 1, 0xa4, "Novatel Wireless"}, // { 1, 0x25, "Zarlink (Mitel)"}, // { 1, 0x26, "Clearpoint"}, // { 1, 0xa7, "Cabletron"}, // { 1, 0xa8, "STEC (Silicon Tech)"}, // { 1, 0x29, "Vanguard"}, // { 1, 0x2a, "Hagiwara Sys-Com"}, // { 1, 0xab, "Vantis"}, // { 1, 0x2c, "Celestica"}, // { 1, 0xad, "Century"}, // { 1, 0xae, "Hal Computers"}, // { 1, 0x2f, "Rohm Company"}, // { 1, 0xb0, "Juniper Networks"}, // { 1, 0x31, "Libit Signal Processing"}, { 1, 0x32, "Mushkin"}, // { 1, 0xb3, "Tundra Semiconductor"}, { 1, 0x34, "Adaptec"}, // { 1, 0xb5, "LightSpeed Semi."}, // { 1, 0xb6, "ZSP Corp."}, // { 1, 0x37, "AMIC Technology"}, // { 1, 0x38, "Adobe Systems"}, // { 1, 0xb9, "Dynachip"}, { 1, 0xba, "PNY"}, // { 1, 0x3b, "Newport Digital"}, // { 1, 0xbc, "MMC Networks"}, // { 1, 0x3d, "T Square"}, // { 1, 0x3e, "Seiko Epson"}, // { 1, 0xbf, "Broadcom"}, // { 1, 0x40, "Viking Components"}, // { 1, 0xc1, "V3 Semiconductor"}, // { 1, 0xc2, "Flextronics (Orbit Semiconductor)"}, // { 1, 0x43, "Suwa Electronics"}, { 1, 0xc4, "Transmeta"}, { 1, 0x45, "Micron CMS"}, // { 1, 0x46, "American Computer & Digital Components"}, // { 1, 0xc7, "Enhance 3000"}, { 1, 0xc8, "Tower Semiconductor"}, // { 1, 0x49, "CPU Design"}, // { 1, 0x4a, "Price Point"}, { 1, 0xcb, "Maxim Integrated Product"}, // { 1, 0x4c, "Tellabs"}, // { 1, 0xcd, "Centaur Technology"}, { 1, 0xce, "Unigen"}, { 1, 0x4f, "Transcend"}, { 1, 0xd0, "Memory Card"}, // { 1, 0x51, "CKD"}, // { 1, 0x52, "Capital Instruments"}, // { 1, 0xd3, "Aica Kogyo"}, // { 1, 0x54, "Linvex Technology"}, { 1, 0xd5, "MSC"}, // { 1, 0xd6, "AKM Company"}, // { 1, 0x57, "Dynamem"}, // { 1, 0x58, "NERA ASA"}, // { 1, 0xd9, "GSI Technology"}, { 1, 0xda, "Dane-Elec"}, // { 1, 0x5b, "Acorn Computers"}, // { 1, 0xdc, "Lara Technology"}, // { 1, 0x5d, "Oak Technology"}, { 1, 0x5e, "Itec Memory"}, // { 1, 0xdf, "Tanisys Technology"}, // { 1, 0xe0, "Truevision"}, { 1, 0x61, "Wintec"}, // { 1, 0x62, "Super PC Memory"}, // { 1, 0xe3, "MGV Memory"}, // { 1, 0x64, "Galvantech"}, // { 1, 0xe5, "Gadzoox Networks"}, // { 1, 0xe6, "Multi Dimensional Cons."}, // { 1, 0x67, "GateField"}, { 1, 0x68, "Integrated Memory System"}, // { 1, 0xe9, "Triscend"}, // { 1, 0xea, "XaQti"}, // { 1, 0x6b, "Goldenram"}, // { 1, 0xec, "Clear Logic"}, // { 1, 0x6d, "Cimaron Communications"}, // { 1, 0x6e, "Nippon Steel Semi. Corp."}, // { 1, 0xef, "Advantage Memory"}, // { 1, 0x70, "AMCC"}, { 1, 0xf1, "LeCroy"}, // { 1, 0xf2, "Yamaha"}, // { 1, 0x73, "Digital Microwave"}, // { 1, 0xf4, "NetLogic Microsystems"}, // { 1, 0x75, "MIMOS Semiconductor"}, // { 1, 0x76, "Advanced Fibre"}, // { 1, 0xf7, "BF Goodrich Data."}, // { 1, 0xf8, "Epigram"}, // { 1, 0x79, "Acbel Polytech"}, { 1, 0x7a, "Apacer Technology"}, // { 1, 0xfb, "Admor Memory"}, { 1, 0x7c, "FOXCONN"}, // { 1, 0xfd, "Quadratics Superconductor"}, // { 1, 0xfe, "3COM"}, // { 2, 0x01, "Camintonn"}, // { 2, 0x02, "ISOA"}, // { 2, 0x83, "Agate Semiconductor"}, // { 2, 0x04, "ADMtek"}, // { 2, 0x85, "HYPERTEC"}, // { 2, 0x86, "Adhoc Technologies"}, // { 2, 0x07, "MOSAID Technologies"}, // { 2, 0x08, "Ardent Technologies"}, // { 2, 0x89, "Switchcore"}, // { 2, 0x8a, "Cisco Systems"}, // { 2, 0x0b, "Allayer Technologies"}, // { 2, 0x8c, "WorkX AG (Wichman)"}, // { 2, 0x0d, "Oasis Semiconductor"}, // { 2, 0x0e, "Novanet Semiconductor"}, // { 2, 0x8f, "E-M Solutions"}, // { 2, 0x10, "Power General"}, // { 2, 0x91, "Advanced Hardware Arch."}, // { 2, 0x92, "Inova Semiconductors"}, // { 2, 0x13, "Telocity"}, // { 2, 0x94, "Delkin Devices"}, // { 2, 0x15, "Symagery Microsystems"}, // { 2, 0x16, "C-Port"}, // { 2, 0x97, "SiberCore Technologies"}, // { 2, 0x98, "Southland Microsystems"}, // { 2, 0x19, "Malleable Technologies"}, // { 2, 0x1a, "Kendin Communications"}, // { 2, 0x9b, "Great Technology Microcomputer"}, // { 2, 0x1c, "Sanmina"}, // { 2, 0x9d, "HADCO"}, { 2, 0x9e, "Corsair"}, // { 2, 0x1f, "Actrans System"}, // { 2, 0x20, "ALPHA Technologies"}, // { 2, 0xa1, "Silicon Laboratories (Cygnal)"}, // { 2, 0xa2, "Artesyn Technologies"}, // { 2, 0x23, "Align Manufacturing"}, // { 2, 0xa4, "Peregrine Semiconductor"}, // { 2, 0x25, "Chameleon Systems"}, // { 2, 0x26, "Aplus Flash Technology"}, { 2, 0xa7, "MIPS Technologies"}, // { 2, 0xa8, "Chrysalis ITS"}, // { 2, 0x29, "ADTEC"}, { 2, 0x2a, "Kentron Technologies"}, // { 2, 0xab, "Win Technologies"}, // { 2, 0x2c, "Tachyon Semiconductor (ASIC)"}, // { 2, 0xad, "Extreme Packet Devices"}, // { 2, 0xae, "RF Micro Devices"}, { 2, 0x2f, "Siemens AG"}, // { 2, 0xb0, "Sarnoff"}, // { 2, 0x31, "Itautec SA"}, // { 2, 0x32, "Radiata"}, // { 2, 0xb3, "Benchmark Elect. (AVEX)"}, // { 2, 0x34, "Legend"}, { 2, 0xb5, "SpecTek"}, // { 2, 0xb6, "Hi/fn"}, // { 2, 0x37, "Enikia"}, // { 2, 0x38, "SwitchOn Networks"}, // { 2, 0xb9, "AANetcom"}, // { 2, 0xba, "Micro Memory Bank"}, { 2, 0x3b, "ESS Technology"}, // { 2, 0xbc, "Virata"}, // { 2, 0x3d, "Excess Bandwidth"}, // { 2, 0x3e, "West Bay Semiconductor"}, // { 2, 0xbf, "DSP Group"}, // { 2, 0x40, "Newport Communications"}, // { 2, 0xc1, "Chip2Chip"}, // { 2, 0xc2, "Phobos"}, // { 2, 0x43, "Intellitech"}, // { 2, 0xc4, "Nordic VLSI ASA"}, // { 2, 0x45, "Ishoni Networks"}, // { 2, 0x46, "Silicon Spice"}, // { 2, 0xc7, "Alchemy Semiconductor"}, { 2, 0xc8, "Agilent Technologies"}, // { 2, 0x49, "Centillium Communications"}, // { 2, 0x4a, "W.L. Gore"}, // { 2, 0xcb, "HanBit Electronics"}, // { 2, 0x4c, "GlobeSpan"}, // { 2, 0xcd, "Element 14"}, // { 2, 0xce, "Pycon"}, // { 2, 0x4f, "Saifun Semiconductors"}, // { 2, 0xd0, "Sibyte,"}, // { 2, 0x51, "MetaLink Technologies"}, // { 2, 0x52, "Feiya Technology"}, // { 2, 0xd3, "I & C Technology"}, // { 2, 0x54, "Shikatronics"}, // { 2, 0xd5, "Elektrobit"}, // { 2, 0xd6, "Megic"}, // { 2, 0x57, "Com-Tier"}, // { 2, 0x58, "Malaysia Micro Solutions"}, // { 2, 0xd9, "Hyperchip"}, // { 2, 0xda, "Gemstone Communications"}, // { 2, 0x5b, "Anadigm (Anadyne)"}, // { 2, 0xdc, "3ParData"}, // { 2, 0x5d, "Mellanox Technologies"}, // { 2, 0x5e, "Tenx Technologies"}, // { 2, 0xdf, "Helix AG"}, // { 2, 0xe0, "Domosys"}, // { 2, 0x61, "Skyup Technology"}, // { 2, 0x62, "HiNT"}, // { 2, 0xe3, "Chiaro"}, { 2, 0x64, "MDT"}, // { 2, 0xe5, "Exbit Technology A/S"}, // { 2, 0xe6, "Integrated Technology Express"}, // { 2, 0x67, "AVED Memory"}, // { 2, 0x68, "Legerity"}, // { 2, 0xe9, "Jasmine Networks"}, // { 2, 0xea, "Caspian Networks"}, // { 2, 0x6b, "nCUBE"}, // { 2, 0xec, "Silicon Access Networks"}, // { 2, 0x6d, "FDK"}, // { 2, 0x6e, "High Bandwidth Access"}, // { 2, 0xef, "MultiLink Technology"}, // { 2, 0x70, "BRECIS"}, // { 2, 0xf1, "World Wide Packets"}, // { 2, 0xf2, "APW"}, // { 2, 0x73, "Chicory Systems"}, // { 2, 0xf4, "Xstream Logic"}, // { 2, 0x75, "Fast-Chip"}, // { 2, 0x76, "Zucotto Wireless"}, // { 2, 0xf7, "Realchip"}, // { 2, 0xf8, "Galaxy Power"}, // { 2, 0x79, "eSilicon"}, // { 2, 0x7a, "Morphics Technology"}, // { 2, 0xfb, "Accelerant Networks"}, // { 2, 0x7c, "Silicon Wave"}, // { 2, 0xfd, "SandCraft"}, { 2, 0xfe, "Elpida"}, // { 3, 0x01, "Solectron"}, { 3, 0x02, "Optosys Technologies"}, { 3, 0x83, "Buffalo"}, // { 3, 0x04, "TriMedia Technologies"}, // { 3, 0x85, "Cyan Technologies"}, // { 3, 0x86, "Global Locate"}, // { 3, 0x07, "Optillion"}, // { 3, 0x08, "Terago Communications"}, // { 3, 0x89, "Ikanos Communications"}, { 3, 0x8a, "Princeton"}, { 3, 0x0b, "Nanya"}, // { 3, 0x8c, "Elite Flash Storage"}, // { 3, 0x0d, "Mysticom"}, // { 3, 0x0e, "LightSand Communications"}, { 3, 0x8f, "ATI"}, // { 3, 0x10, "Agere Systems"}, // { 3, 0x91, "NeoMagic"}, // { 3, 0x92, "AuroraNetics"}, // { 3, 0x13, "Golden Empire"}, { 3, 0x94, "Mushkin"}, // { 3, 0x15, "Tioga Technologies"}, { 3, 0x16, "Netlist"}, // { 3, 0x97, "TeraLogic"}, // { 3, 0x98, "Cicada Semiconductor"}, { 3, 0x19, "Centon"}, { 3, 0x1a, "Tyco Electronics"}, // { 3, 0x9b, "Magis Works"}, // { 3, 0x1c, "Zettacom"}, // { 3, 0x9d, "Cogency Semiconductor"}, // { 3, 0x9e, "Chipcon AS"}, // { 3, 0x1f, "Aspex Technology"}, // { 3, 0x20, "F5 Networks"}, // { 3, 0xa1, "Programmable Silicon Solutions"}, // { 3, 0xa2, "ChipWrights"}, // { 3, 0x23, "Acorn Networks"}, // { 3, 0xa4, "Quicklogic"}, { 3, 0x25, "Kingmax"}, // { 3, 0x26, "BOPS"}, // { 3, 0xa7, "Flasys"}, // { 3, 0xa8, "BitBlitz Communications"}, { 3, 0x29, "eMemory Technology"}, // { 3, 0x2a, "Procket Networks"}, // { 3, 0xab, "Purple Ray"}, // { 3, 0x2c, "Trebia Networks"}, // { 3, 0xad, "Delta Electronics"}, // { 3, 0xae, "Onex Communications"}, // { 3, 0x2f, "Ample Communications"}, { 3, 0xb0, "Memory Experts"}, // { 3, 0x31, "Astute Networks"}, // { 3, 0x32, "Azanda Network Devices"}, // { 3, 0xb3, "Dibcom"}, // { 3, 0x34, "Tekmos"}, // { 3, 0xb5, "API NetWorks"}, // { 3, 0xb6, "Bay Microsystems"}, // { 3, 0x37, "Firecron"}, // { 3, 0x38, "Resonext Communications"}, // { 3, 0xb9, "Tachys Technologies"}, // { 3, 0xba, "Equator Technology"}, // { 3, 0x3b, "Concept Computer"}, // { 3, 0xbc, "SILCOM"}, // { 3, 0x3d, "3Dlabs"}, // { 3, 0x3e, "ct Magazine"}, // { 3, 0xbf, "Sanera Systems"}, // { 3, 0x40, "Silicon Packets"}, { 3, 0xc1, "Viasystems Group"}, { 3, 0xc2, "Simtek"}, // { 3, 0x43, "Semicon Devices Singapore"}, // { 3, 0xc4, "Satron Handelsges"}, // { 3, 0x45, "Improv Systems"}, // { 3, 0x46, "INDUSYS"}, // { 3, 0xc7, "Corrent"}, // { 3, 0xc8, "Infrant Technologies"}, // { 3, 0x49, "Ritek Corp"}, // { 3, 0x4a, "empowerTel Networks"}, // { 3, 0xcb, "Hypertec"}, // { 3, 0x4c, "Cavium Networks"}, { 3, 0xcd, "PLX Technology"}, // { 3, 0xce, "Massana Design"}, // { 3, 0x4f, "Intrinsity"}, // { 3, 0xd0, "Valence Semiconductor"}, // { 3, 0x51, "Terawave Communications"}, // { 3, 0x52, "IceFyre Semiconductor"}, // { 3, 0xd3, "Primarion"}, // { 3, 0x54, "Picochip Designs"}, // { 3, 0xd5, "Silverback Systems"}, { 3, 0xd6, "Jade Star"}, // { 3, 0x57, "Pijnenburg Securealink"}, { 3, 0x58, "takeMS"}, // { 3, 0xd9, "Cambridge Silicon Radio"}, { 3, 0xda, "Swissbit"}, // { 3, 0x5b, "Nazomi Communications"}, // { 3, 0xdc, "eWave System"}, // { 3, 0x5d, "Rockwell Collins"}, // { 3, 0x5e, "Picocel (Paion)"}, // { 3, 0xdf, "Alphamosaic"}, // { 3, 0xe0, "Sandburst"}, // { 3, 0x61, "SiCon Video"}, // { 3, 0x62, "NanoAmp Solutions"}, // { 3, 0xe3, "Ericsson Technology"}, // { 3, 0x64, "PrairieComm"}, { 3, 0xe5, "Mitac International"}, // { 3, 0xe6, "Layer N Networks"}, // { 3, 0x67, "MtekVision (Atsana)"}, // { 3, 0x68, "Allegro Networks"}, // { 3, 0xe9, "Marvell Semiconductors"}, // { 3, 0xea, "Netergy Microelectronic"}, { 3, 0x6b, "nVidia"}, // { 3, 0xec, "Internet Machines"}, // { 3, 0x6d, "Peak Electronics"}, // { 3, 0x6e, "Litchfield Communication"}, { 3, 0xef, "Accton"}, // { 3, 0x70, "Teradiant Networks"}, // { 3, 0xf1, "Scaleo Chip"}, // { 3, 0xf2, "Cortina Systems"}, { 3, 0x73, "RAM Components"}, // { 3, 0xf4, "Raqia Networks"}, // { 3, 0x75, "ClearSpeed"}, // { 3, 0x76, "Matsushita Battery"}, // { 3, 0xf7, "Xelerated"}, // { 3, 0xf8, "SimpleTech"}, { 3, 0x79, "Utron"}, // { 3, 0x7a, "Astec International"}, // { 3, 0xfb, "AVM"}, // { 3, 0x7c, "Redux Communications"}, // { 3, 0xfd, "Dot Hill Systems"}, { 3, 0xfe, "TeraChip"}, { 4, 0x01, "T-RAM"}, // { 4, 0x02, "Innovics Wireless"}, // { 4, 0x83, "Teknovus"}, // { 4, 0x04, "KeyEye Communications"}, // { 4, 0x85, "Runcom Technologies"}, // { 4, 0x86, "RedSwitch"}, // { 4, 0x07, "Dotcast"}, { 4, 0x08, "Silicon Mountain Memory"}, // { 4, 0x89, "Signia Technologies"}, // { 4, 0x8a, "Pixim"}, // { 4, 0x0b, "Galazar Networks"}, // { 4, 0x8c, "White Electronic Designs"}, // { 4, 0x0d, "Patriot Scientific"}, // { 4, 0x0e, "Neoaxiom"}, // { 4, 0x8f, "3Y Power Technology"}, { 4, 0x10, "Scaleo Chip"}, // { 4, 0x91, "Potentia Power Systems"}, // { 4, 0x92, "C-guys"}, // { 4, 0x13, "Digital Communications Technology"}, // { 4, 0x94, "Silicon-Based Technology"}, // { 4, 0x15, "Fulcrum Microsystems"}, // { 4, 0x16, "Positivo Informatica"}, // { 4, 0x97, "XIOtech"}, // { 4, 0x98, "PortalPlayer"}, // { 4, 0x19, "Zhiying Software"}, // { 4, 0x1a, "ParkerVision"}, // { 4, 0x9b, "Phonex Broadband"}, // { 4, 0x1c, "Skyworks Solutions"}, // { 4, 0x9d, "Entropic Communications"}, // { 4, 0x9e, "Pacific Force Technology"}, // { 4, 0x1f, "Zensys A/S"}, // { 4, 0x20, "Legend Silicon Corp."}, // { 4, 0xa1, "Sci-worx"}, // { 4, 0xa2, "SMSC (Standard Microsystems)"}, { 4, 0x23, "Renesas"}, // { 4, 0xa4, "Raza Microelectronics"}, // { 4, 0x25, "Phyworks"}, // { 4, 0x26, "MediaTek"}, // { 4, 0xa7, "Non-cents Productions"}, // { 4, 0xa8, "US Modular"}, // { 4, 0x29, "Wintegra"}, // { 4, 0x2a, "Mathstar"}, // { 4, 0xab, "StarCore"}, // { 4, 0x2c, "Oplus Technologies"}, // { 4, 0xad, "Mindspeed"}, // { 4, 0xae, "Just Young Computer"}, // { 4, 0x2f, "Radia Communications"}, { 4, 0xb0, "OCZ"}, // { 4, 0x31, "Emuzed"}, // { 4, 0x32, "LOGIC Devices"}, // { 4, 0xb3, "Inphi"}, // { 4, 0x34, "Quake Technologies"}, // { 4, 0xb5, "Vixel"}, // { 4, 0xb6, "SolusTek"}, // { 4, 0x37, "Kongsberg Maritime"}, // { 4, 0x38, "Faraday Technology"}, { 4, 0xb9, "Altium"}, // { 4, 0xba, "Insyte"}, { 4, 0x3b, "ARM"}, // { 4, 0xbc, "DigiVision"}, // { 4, 0x3d, "Vativ Technologies"}, // { 4, 0x3e, "Endicott Interconnect Technologies"}, { 4, 0xbf, "Pericom"}, // { 4, 0x40, "Bandspeed"}, // { 4, 0xc1, "LeWiz Communications"}, // { 4, 0xc2, "CPU Technology"}, { 4, 0x43, "Ramaxel"}, // { 4, 0xc4, "DSP Group"}, // { 4, 0x45, "Axis Communications"}, { 4, 0x46, "Legacy Electronics"}, // { 4, 0xc7, "Chrontel"}, // { 4, 0xc8, "Powerchip Semiconductor"}, // { 4, 0x49, "MobilEye Technologies"}, { 4, 0x4a, "Excel Semiconductor"}, { 4, 0xcb, "A-DATA"}, // { 4, 0x4c, "VirtualDigm"}, { 4, 0xcd, "G.Skill"}, // { 4, 0xce, "Quanta Computer"}, // { 4, 0x4f, "Yield Microelectronics"}, // { 4, 0xd0, "Afa Technologies"}, { 4, 0x51, "Kingbox"}, // { 4, 0x52, "Ceva"}, // { 4, 0xd3, "iStor Networks"}, // { 4, 0x54, "Advance Modules"}, { 4, 0xd5, "Microsoft"}, // { 4, 0xd6, "Open-Silicon"}, // { 4, 0x57, "Goal Semiconductor"}, // { 4, 0x58, "ARC International"}, { 4, 0xd9, "Simmtec"}, // { 4, 0xda, "Metanoia"}, // { 4, 0x5b, "Key Stream"}, // { 4, 0xdc, "Lowrance Electronics"}, // { 4, 0x5d, "Adimos"}, // { 4, 0x5e, "SiGe Semiconductor"}, // { 4, 0xdf, "Fodus Communications"}, // { 4, 0xe0, "Credence Systems Corp."}, // { 4, 0x61, "Genesis Microchip"}, // { 4, 0x62, "Vihana"}, // { 4, 0xe3, "WIS Technologies"}, // { 4, 0x64, "GateChange Technologies"}, // { 4, 0xe5, "High Density Devices AS"}, // { 4, 0xe6, "Synopsys"}, // { 4, 0x67, "Gigaram"}, // { 4, 0x68, "Enigma Semiconductor"}, // { 4, 0xe9, "Century Micro"}, // { 4, 0xea, "Icera Semiconductor"}, // { 4, 0x6b, "Mediaworks Integrated Systems"}, // { 4, 0xec, "ONeil Product Development"}, // { 4, 0x6d, "Supreme Top Technology"}, // { 4, 0x6e, "MicroDisplay"}, { 4, 0xef, "Team Group"}, // { 4, 0x70, "Sinett"}, { 4, 0xf1, "Toshiba"}, // { 4, 0xf2, "Tensilica"}, // { 4, 0x73, "SiRF Technology"}, // { 4, 0xf4, "Bacoc"}, // { 4, 0x75, "SMaL Camera Technologies"}, { 4, 0x76, "Thomson SC"}, // { 4, 0xf7, "Airgo Networks"}, // { 4, 0xf8, "Wisair"}, // { 4, 0x79, "SigmaTel"}, // { 4, 0x7a, "Arkados"}, // { 4, 0xfb, "Compete IT KG"}, // { 4, 0x7c, "Eudar Technology"}, // { 4, 0xfd, "Focus Enhancements"}, // { 4, 0xfe, "Xyratex"}, // { 5, 0x01, "Specular Networks"}, { 5, 0x02, "Patriot Memory"}, // { 5, 0x83, "U-Chip Technology Corp."}, // { 5, 0x04, "Silicon Optix"}, // { 5, 0x85, "Greenfield Networks"}, { 5, 0x86, "CompuRAM"}, // { 5, 0x07, "Stargen"}, // { 5, 0x08, "NetCell"}, // { 5, 0x89, "Excalibrus Technologies"}, // { 5, 0x8a, "SCM Microsystems"}, // { 5, 0x0b, "Xsigo Systems"}, // { 5, 0x8c, "CHIPS & Systems"}, // { 5, 0x0d, "Tier"}, // { 5, 0x0e, "CWRL Labs"}, // { 5, 0x8f, "Teradici"}, // { 5, 0x10, "Gigaram"}, // { 5, 0x91, "g2 Microsystems"}, // { 5, 0x92, "PowerFlash Semiconductor"}, // { 5, 0x13, "P.A. Semi"}, { 5, 0x94, "NovaTech"}, // { 5, 0x15, "c2 Microsystems"}, // { 5, 0x16, "Level5 Networks"}, { 5, 0x97, "COS Memory"}, // { 5, 0x98, "Innovasic Semiconductor"}, // { 5, 0x19, "02IC"}, // { 5, 0x1a, "Tabula"}, { 5, 0x9b, "Crucial"}, // { 5, 0x1c, "Chelsio Communications"}, // { 5, 0x9d, "Solarflare Communications"}, // { 5, 0x9e, "Xambala"}, // { 5, 0x1f, "EADS Astrium"}, // { 5, 0x20, "Terra Semiconductor"}, // { 5, 0xa1, "Imaging Works"}, // { 5, 0xa2, "Astute Networks"}, // { 5, 0x23, "Tzero"}, // { 5, 0xa4, "Emulex"}, // { 5, 0x25, "Power-One"}, // { 5, 0x26, "Pulse~LINK"}, // { 5, 0xa7, "Hon Hai Precision Industry"}, // { 5, 0xa8, "White Rock Networks"}, // { 5, 0x29, "Telegent Systems USA"}, // { 5, 0x2a, "Atrua Technologies"}, // { 5, 0xab, "Acbel Polytech"}, // { 5, 0x2c, "eRide"}, { 5, 0xad, "ULi"}, // { 5, 0xae, "Magnum Semiconductor"}, // { 5, 0x2f, "neoOne Technology"}, // { 5, 0xb0, "Connex Technology"}, // { 5, 0x31, "Stream Processors"}, // { 5, 0x32, "Focus Enhancements"}, // { 5, 0xb3, "Telecis Wireless"}, // { 5, 0x34, "uNav Microelectronics"}, // { 5, 0xb5, "Tarari"}, // { 5, 0xb6, "Ambric"}, // { 5, 0x37, "Newport Media"}, // { 5, 0x38, "VMTS"}, // { 5, 0xb9, "Enuclia Semiconductor"}, // { 5, 0xba, "Virtium Technology"}, // { 5, 0x3b, "Solid State System"}, // { 5, 0xbc, "Kian Tech LLC"}, // { 5, 0x3d, "Artimi"}, { 5, 0x3e, "PQI"}, // { 5, 0xbf, "Avago Technologies"}, // { 5, 0x40, "ADTechnology"}, { 5, 0xc1, "Sigma Designs"}, // { 5, 0xc2, "SiCortex"}, // { 5, 0x43, "Ventura Technology Group"}, // { 5, 0xc4, "eASIC"}, // { 5, 0x45, "M.H.S. SAS"}, { 5, 0x46, "MSI"}, // { 5, 0xc7, "Rapport"}, // { 5, 0xc8, "Makway International"}, // { 5, 0x49, "Broad Reach Engineering"}, // { 5, 0x4a, "Semiconductor Mfg Intl Corp"}, // { 5, 0xcb, "SiConnect"}, // { 5, 0x4c, "FCI USA"}, // { 5, 0xcd, "Validity Sensors"}, // { 5, 0xce, "Coney Technology"}, // { 5, 0x4f, "Spans Logic"}, // { 5, 0xd0, "Neterion"}, { 5, 0x51, "Qimonda"}, // { 5, 0x52, "New Japan Radio"}, // { 5, 0xd3, "Velogix"}, // { 5, 0x54, "Montalvo Systems"}, // { 5, 0xd5, "iVivity"}, { 5, 0xd6, "Walton Chaintech"}, { 5, 0x57, "AENEON"}, // { 5, 0x58, "Lorom Industrial"}, // { 5, 0xd9, "Radiospire Networks"}, // { 5, 0xda, "Sensio Technologies"}, // { 5, 0x5b, "Nethra Imaging"}, { 5, 0xdc, "Hexon"}, // { 5, 0x5d, "CompuStocx (CSX)"}, // { 5, 0x5e, "Methode Electronics"}, // { 5, 0xdf, "Connect One"}, // { 5, 0xe0, "Opulan Technologies"}, // { 5, 0x61, "Septentrio NV"}, { 5, 0x62, "Goldenmars"}, { 5, 0xe3, "Kreton"}, // { 5, 0x64, "Cochlear"}, // { 5, 0xe5, "Altair Semiconductor"}, // { 5, 0xe6, "NetEffect"}, // { 5, 0x67, "Spansion"}, // { 5, 0x68, "Taiwan Semiconductor Mfg"}, // { 5, 0xe9, "Emphany Systems"}, // { 5, 0xea, "ApaceWave Technologies"}, // { 5, 0x6b, "Mobilygen"}, // { 5, 0xec, "Tego"}, // { 5, 0x6d, "Cswitch"}, // { 5, 0x6e, "Haier (Beijing) IC Design"}, // { 5, 0xef, "MetaRAM"}, // { 5, 0x70, "Axel Electronics"}, // { 5, 0xf1, "Tilera"}, // { 5, 0xf2, "Aquantia"}, // { 5, 0x73, "Vivace Semiconductor"}, // { 5, 0xf4, "Redpine Signals"}, // { 5, 0x75, "Octalica"}, // { 5, 0x76, "InterDigital Communications"}, { 5, 0xf7, "Avant Technology"}, { 5, 0xf8, "Asrock"}, // { 5, 0x79, "Availink"}, // { 5, 0x7a, "Quartics"}, // { 5, 0xfb, "Element CXI"}, // { 5, 0x7c, "Innovaciones Microelectronicas"}, // { 5, 0xfd, "VeriSilicon Microelectronics"}, // { 5, 0xfe, "W5 Networks"}, // { 6, 0x01, "MOVEKING"}, // { 6, 0x02, "Mavrix Technology"}, // { 6, 0x83, "CellGuide"}, // { 6, 0x04, "Faraday Technology"}, // { 6, 0x85, "Diablo Technologies"}, // { 6, 0x86, "Jennic"}, // { 6, 0x07, "Octasic"}, { 6, 0x08, "Molex"}, // { 6, 0x89, "3Leaf Networks"}, // { 6, 0x8a, "Bright Micron Technology"}, // { 6, 0x0b, "Netxen"}, // { 6, 0x8c, "NextWave Broadband"}, // { 6, 0x0d, "DisplayLink"}, // { 6, 0x0e, "ZMOS Technology"}, // { 6, 0x8f, "Tec-Hill"}, // { 6, 0x10, "Multigig"}, // { 6, 0x91, "Amimon"}, // { 6, 0x92, "Euphonic Technologies"}, // { 6, 0x13, "BRN Phoenix"}, // { 6, 0x94, "InSilica"}, // { 6, 0x15, "Ember"}, { 6, 0x16, "Avexir"}, // { 6, 0x97, "Echelon"}, // { 6, 0x98, "Edgewater Computer Systems"}, // { 6, 0x19, "XMOS Semiconductor"}, // { 6, 0x1a, "GENUSION"}, { 6, 0x9b, "Memory Corp NV"}, // { 6, 0x1c, "SiliconBlue Technologies"}, // { 6, 0x9d, "Rambus"}, // { 6, 0x9e, "Andes Technology"}, // { 6, 0x1f, "Coronis Systems"}, // { 6, 0x20, "Achronix Semiconductor"}, // { 6, 0xa1, "Siano Mobile Silicon"}, // { 6, 0xa2, "Semtech"}, // { 6, 0x23, "Pixelworks"}, // { 6, 0xa4, "Gaisler Research AB"}, // { 6, 0x25, "Teranetics"}, // { 6, 0x26, "Toppan Printing"}, // { 6, 0xa7, "Kingxcon"}, { 6, 0xa8, "SiS"}, // { 6, 0x29, "I-O Data Device"}, // { 6, 0x2a, "NDS Americas"}, // { 6, 0xab, "Solomon Systech Limited"}, // { 6, 0x2c, "On Demand Microelectronics"}, // { 6, 0xad, "Amicus Wireless"}, // { 6, 0xae, "SMARDTV SNC"}, // { 6, 0x2f, "Comsys Communication"}, // { 6, 0xb0, "Movidia"}, // { 6, 0x31, "Javad GNSS"}, // { 6, 0x32, "Montage Technology Group"}, { 6, 0xb3, "Trident"}, { 6, 0x34, "Super Talent"}, // { 6, 0xb5, "Optichron"}, // { 6, 0xb6, "Future Waves UK"}, // { 6, 0x37, "SiBEAM"}, // { 6, 0x38, "Inicore,"}, // { 6, 0xb9, "Virident Systems"}, // { 6, 0xba, "M2000"}, // { 6, 0x3b, "ZeroG Wireless"}, { 6, 0xbc, "Gingle"}, // { 6, 0x3d, "Space Micro"}, // { 6, 0x3e, "Wilocity"}, // { 6, 0xbf, "Novafora, Ic."}, // { 6, 0x40, "iKoa"}, { 6, 0xc1, "ASint"}, { 6, 0xc2, "Ramtron"}, // { 6, 0x43, "Plato Networks"}, // { 6, 0xc4, "IPtronics AS"}, // { 6, 0x45, "Infinite-Memories"}, // { 6, 0x46, "Parade Technologies"}, // { 6, 0xc7, "Dune Networks"}, // { 6, 0xc8, "GigaDevice Semiconductor"}, // { 6, 0x49, "Modu"}, // { 6, 0x4a, "CEITEC"}, // { 6, 0xcb, "Northrop Grumman"}, // { 6, 0x4c, "XRONET"}, // { 6, 0xcd, "Sicon Semiconductor AB"}, // { 6, 0xce, "Atla Electronics"}, { 6, 0x4f, "TOPRAM"}, // { 6, 0xd0, "Silego Technology"}, { 6, 0x51, "Kinglife"}, // { 6, 0x52, "Ability Industries"}, // { 6, 0xd3, "Silicon Power Computer & Communications"}, // { 6, 0x54, "Augusta Technology"}, // { 6, 0xd5, "Nantronics Semiconductors"}, // { 6, 0xd6, "Hilscher Gesellschaft"}, // { 6, 0x57, "Quixant"}, // { 6, 0x58, "Percello"}, // { 6, 0xd9, "NextIO"}, // { 6, 0xda, "Scanimetrics"}, // { 6, 0x5b, "FS-Semi Company"}, // { 6, 0xdc, "Infinera"}, { 6, 0x5d, "SandForce"}, { 6, 0x5e, "Lexar Media"}, // { 6, 0xdf, "Teradyne"}, { 6, 0xe0, "Memory Exchange Corp."}, // { 6, 0x61, "Suzhou Smartek Electronics"}, { 6, 0x62, "Avantium"}, // { 6, 0xe3, "ATP Electronics"}, // { 6, 0x64, "Valens Semiconductor"}, // { 6, 0xe5, "Agate Logic"}, // { 6, 0xe6, "Netronome"}, // { 6, 0x67, "Zenverge"}, // { 6, 0x68, "N-trig"}, // { 6, 0xe9, "SanMax Technologies"}, // { 6, 0xea, "Contour Semiconductor"}, { 6, 0x6b, "TwinMOS"}, { 6, 0xec, "Silicon Systems"}, // { 6, 0x6d, "V-Color Technology"}, // { 6, 0x6e, "Certicom"}, // { 6, 0xef, "JSC ICC Milandr"}, // { 6, 0x70, "PhotoFast Global"}, { 6, 0xf1, "InnoDisk"}, { 6, 0xf2, "Muscle Power"}, // { 6, 0x73, "Energy Micro"}, // { 6, 0xf4, "Innofidei"}, // { 6, 0x75, "CopperGate Communications"}, // { 6, 0x76, "Holtek Semiconductor"}, // { 6, 0xf7, "Myson Century"}, // { 6, 0xf8, "FIDELIX"}, // { 6, 0x79, "Red Digital Cinema"}, // { 6, 0x7a, "Densbits Technology"}, // { 6, 0xfb, "Zempro"}, // { 6, 0x7c, "MoSys"}, // { 6, 0xfd, "Provigent"}, // { 6, 0xfe, "Triad Semiconductor"}, // { 8, 0x01, "Siklu Communication"}, // { 8, 0x02, "A Force Manufacturing"}, { 8, 0x83, "Strontium"}, // { 8, 0x04, "Abilis Systems"}, // { 8, 0x85, "Siglead"}, // { 8, 0x86, "Ubicom"}, // { 8, 0x07, "Unifosa"}, // { 8, 0x08, "Stretch"}, // { 8, 0x89, "Lantiq Deutschland"}, // { 8, 0x8a, "Visipro."}, { 8, 0x0b, "EKMemory"}, // { 8, 0x8c, "Microelectronics Institute ZTE"}, // { 8, 0x0d, "Cognovo"}, // { 8, 0x0e, "Carry Technology"}, { 8, 0x8f, "Nokia"}, { 8, 0x10, "King Tiger"}, // { 8, 0x91, "Sierra Wireless"}, { 8, 0x92, "HT Micron"}, { 8, 0x13, "Albatron"}, // { 8, 0x94, "Leica Geosystems AG"}, // { 8, 0x15, "BroadLight"}, // { 8, 0x16, "AEXEA"}, // { 8, 0x97, "ClariPhy Communications"}, // { 8, 0x98, "Green Plug"}, // { 8, 0x19, "Design Art Networks"}, // { 8, 0x1a, "Mach Xtreme Technology"}, // { 8, 0x9b, "ATO Solutions"}, // { 8, 0x1c, "Ramsta"}, // { 8, 0x9d, "Greenliant Systems"}, // { 8, 0x9e, "Teikon"}, // { 8, 0x1f, "Antec Hadron"}, // { 8, 0x20, "NavCom Technology"}, // { 8, 0xa1, "Shanghai Fudan Microelectronics"}, // { 8, 0xa2, "Calxeda"}, // { 8, 0x23, "JSC EDC Electronics"}, // { 8, 0xa4, "Kandit Technology"}, // { 8, 0x25, "Ramos Technology"}, // { 8, 0x26, "Goldenmars Technology"}, // { 8, 0xa7, "XeL Technology"}, // { 8, 0xa8, "Newzone"}, { 8, 0x29, "MercyPower"}, // { 8, 0x2a, "Nanjing Yihuo Technology."}, // { 8, 0xab, "Nethra Imaging"}, // { 8, 0x2c, "SiTel Semiconductor BV"}, // { 8, 0xad, "SolidGear"}, { 8, 0xae, "Topower"}, // { 8, 0x2f, "Wilocity"}, // { 8, 0xb0, "Profichip"}, // { 8, 0x31, "Gerad Technologies"}, { 8, 0x32, "Ritek"}, // { 8, 0xb3, "Gomos Technology Limited"}, { 8, 0x34, "Memoright"}, // { 8, 0xb5, "D-Broad"}, // { 8, 0xb6, "HiSilicon Technologies"}, // { 8, 0x37, "Syndiant ."}, // { 8, 0x38, "Enverv"}, // { 8, 0xb9, "Cognex"}, // { 8, 0xba, "Xinnova Technology"}, { 8, 0x3b, "Ultron"}, // { 8, 0xbc, "Concord Idea"}, // { 8, 0x3d, "AIM"}, // { 8, 0x3e, "Lifetime Memory Products"}, // { 8, 0xbf, "Ramsway"}, // { 8, 0x40, "Recore Systems B.V."}, // { 8, 0xc1, "Haotian Jinshibo Science Tech"}, // { 8, 0xc2, "Being Advanced Memory"}, // { 8, 0x43, "Adesto Technologies"}, // { 8, 0xc4, "Giantec Semiconductor"}, // { 8, 0x45, "HMD Electronics AG"}, // { 8, 0x46, "Gloway International (HK)"}, // { 8, 0xc7, "Kingcore"}, // { 8, 0xc8, "Anucell Technology Holding"}, // { 8, 0x49, "Accord Software & Systems Pvt."}, // { 8, 0x4a, "Active-Semi"}, // { 8, 0xcb, "Denso"}, // { 8, 0x4c, "TLSI"}, // { 8, 0xcd, "Shenzhen Daling Electronic"}, // { 8, 0xce, "Mustang"}, // { 8, 0x4f, "Orca Systems"}, // { 8, 0xd0, "Passif Semiconductor"}, // { 8, 0x51, "GigaDevice Semiconductor (Beijing)"}, // { 8, 0x52, "Memphis Electronic"}, // { 8, 0xd3, "Beckhoff Automation"}, // { 8, 0x54, "Harmony Semiconductor Corp"}, // { 8, 0xd5, "Air Computers SRL"}, { 8, 0xd6, "TMT Memory"}, { 9, 0xff, ""} }; memtest86+-5.01/README.build-process0000644000000000000000000000361512201317426015501 0ustar rootrootDuring memory testing memtest86 relocates itself in memory so it can test the memory it was previously running from. memtest86 is compiled as position mostly independent code. Some relocations records must be processed to achieve the affect of position independent code. A 16 bit loader is prepended to memtest86 so it can be loaded from a floppy, or from lilo. In restructuring the build process I had several goals. Maintainability and comprehsibility of the build process. Simplicity of the toolset. And the ability to build images bootable by both the legacy x86 bootloader, and images bootable by bootloaders that directly load static ELF images. With the ability to proecess relocation records, memtest.bin has been reduced in size from 84480 bytes to 49308 bytes. And now only requires one copy of memtest86. A reduction in size of 35K. And the build process can now ignore the size of memtest86. BIOS calls have been moved from setup.S to head.S making bootsect.S and setup.S exclusively for booting. memtest86 is built in three stages. In the first stage the relocatable object files are built as with any program. In the second stage the relocatable object files are linked together into memtest_shared, a shared library version of memtest86. In the third stage a raw memory image of memtest_shared is formed and linked into memtest.bin, and memtest. memtest.bin is the floppy/lilo bootable target. memtest is the ELF bootable target. Another major change is now data in the bss segment is also preserved when memtest86 is relocated, and memtest86 can be relocated to any address. The one thing to watch out for is pointers to data inside of memtest86. Except for constant pointers to static data there is not enough information to generate relocation records for pointers so they will not change when memtest86 is relocated, which might lead to nasty surpises. Eric Biederman memtest86+-5.01/error.c0000644000000000000000000003324512201317426013346 0ustar rootroot/* error.c - MemTest-86 Version 4.1 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "stddef.h" #include "stdint.h" #include "test.h" #include "config.h" #include "cpuid.h" #include "smp.h" #include "dmi.h" #include "controller.h" extern int dmi_err_cnts[MAX_DMI_MEMDEVS]; extern int beepmode; extern short dmi_initialized; extern struct cpu_ident cpu_id; extern struct barrier_s *barr; extern int test_ticks, nticks; extern struct tseq tseq[]; extern volatile int test; void poll_errors(); extern int num_cpus; static void update_err_counts(void); static void print_err_counts(void); static void common_err(); static int syn, chan, len=1; /* * Display data error message. Don't display duplicate errors. */ void error(ulong *adr, ulong good, ulong bad) { 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 * 0x4e0 for USB keyboard support. This often happens with Intel * 810, 815 and 820 chipsets. It is possible that we will skip * a real error but the odds are very low. */ if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) { return; } #endif /* A sporadic bug exists in test #6, with SMP enabled, that * reports false positives on < 65K-0.5MB range. I was * not able to solve this. After investigations, it seems * related to a BIOS issue similiar to the one solved by * USB_WAR, but for MP Table. */ /* Solved if (test == 6 && (ulong)adr <= 0x07FFFF && num_cpus > 1) { cprint(6,78,"-"); // Debug return; } */ common_err(adr, good, bad, xor, 0); spin_unlock(&barr->mutex); } /* * Display address error message. * Since this is strictly an address test, trying to create BadRAM * patterns does not make sense. Just report the error. */ 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); } /* * Display address error message. * Since this type of address error can also report data errors go * ahead and generate BadRAM patterns. */ 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) { if (beepmode){ beep(600); beep(1000); } if (v->pass && v->ecount == 0) { cprint(LINE_MSG, COL_MSG, " "); } ++(v->ecount); tseq[test].errors++; } static void print_err_counts(void) { int i; char *pp; if ((v->ecount > 4096) && (v->ecount % 256 != 0)) return; dprint(LINE_INFO, 72, 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 */ if ((v->printmode == PRINTMODE_ADDRESSES || v->printmode == PRINTMODE_PATTERNS) && v->msg_line < 24) { for(i=0, pp=(char *)((SCREEN_ADR+v->msg_line*160+1)); i<76; i++, pp+=2) { *pp = 0x47; } } } /* * Print an individual error */ void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type) { int i, j, n, x, flag=0; ulong page, offset; int patnchg; ulong mb; update_err_counts(); switch(v->printmode) { case PRINTMODE_SUMMARY: /* Don't do anything for a parity error. */ if (type == 3) { return; } /* Address error */ if (type == 1) { xor = good ^ bad; } /* Ecc correctable errors */ if (type == 2) { /* the bad value is the corrected flag */ if (bad) { v->erri.cor_err++; } page = (ulong)adr; offset = good; } else { page = page_of(adr); offset = (ulong)adr & 0xFFF; } /* Calc upper and lower error addresses */ if (v->erri.low_addr.page > page) { v->erri.low_addr.page = page; v->erri.low_addr.offset = offset; flag++; } else if (v->erri.low_addr.page == page && v->erri.low_addr.offset > offset) { v->erri.low_addr.offset = offset; v->erri.high_addr.offset = offset; flag++; } else if (v->erri.high_addr.page < page) { v->erri.high_addr.page = page; flag++; } if (v->erri.high_addr.page == page && v->erri.high_addr.offset < offset) { v->erri.high_addr.offset = offset; flag++; } /* Calc bits in error */ for (i=0, n=0; i<32; i++) { if (xor>>i & 1) { n++; } } v->erri.tbits += n; if (n > v->erri.max_bits) { v->erri.max_bits = n; flag++; } if (n < v->erri.min_bits) { v->erri.min_bits = n; flag++; } if (v->erri.ebits ^ xor) { flag++; } v->erri.ebits |= xor; /* Calc max contig errors */ len = 1; if ((ulong)adr == (ulong)v->erri.eadr+4 || (ulong)adr == (ulong)v->erri.eadr-4 ) { len++; } if (len > v->erri.maxl) { v->erri.maxl = len; flag++; } v->erri.eadr = (ulong)adr; if (v->erri.hdr_flag == 0) { clear_scroll(); cprint(LINE_HEADER+0, 1, "Error Confidence Value:"); cprint(LINE_HEADER+1, 1, " Lowest Error Address:"); cprint(LINE_HEADER+2, 1, " Highest Error Address:"); cprint(LINE_HEADER+3, 1, " Bits in Error Mask:"); 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:"); 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++; } if (flag) { /* Calc bits in error */ for (i=0, n=0; i<32; i++) { if (v->erri.ebits>>i & 1) { n++; } } page = v->erri.low_addr.page; offset = v->erri.low_addr.offset; mb = page >> 8; hprint(LINE_HEADER+1, 25, page); hprint2(LINE_HEADER+1, 33, offset, 3); cprint(LINE_HEADER+1, 36, " - . MB"); dprint(LINE_HEADER+1, 39, mb, 5, 0); dprint(LINE_HEADER+1, 45, ((page & 0xF)*10)/16, 1, 0); page = v->erri.high_addr.page; offset = v->erri.high_addr.offset; mb = page >> 8; hprint(LINE_HEADER+2, 25, page); hprint2(LINE_HEADER+2, 33, offset, 3); cprint(LINE_HEADER+2, 36, " - . MB"); dprint(LINE_HEADER+2, 39, mb, 5, 0); dprint(LINE_HEADER+2, 45, ((page & 0xF)*10)/16, 1, 0); hprint(LINE_HEADER+3, 25, v->erri.ebits); dprint(LINE_HEADER+4, 25, n, 2, 1); dprint(LINE_HEADER+4, 34, v->erri.min_bits, 2, 1); dprint(LINE_HEADER+4, 42, v->erri.max_bits, 2, 1); 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); dprint(LINE_HEADER+1+i, 68, tseq[i].errors, 8, 0); } } if (v->erri.cor_err) { dprint(LINE_HEADER+6, 25, v->erri.cor_err, 8, 1); } break; case PRINTMODE_ADDRESSES: /* Don't display duplicate errors */ if ((ulong)adr == (ulong)v->erri.eadr && xor == v->erri.exor) { return; } if (v->erri.hdr_flag == 0) { clear_scroll(); cprint(LINE_HEADER, 0, "Tst Pass Failing Address Good Bad Err-Bits Count CPU"); cprint(LINE_HEADER+1, 0, "--- ---- ----------------------- -------- -------- -------- ----- ----"); v->erri.hdr_flag++; } /* Check for keyboard input */ check_input(); scroll(); if ( type == 2 || type == 3) { page = (ulong)adr; offset = good; } else { page = page_of(adr); offset = ((unsigned long)adr) & 0xFFF; } mb = page >> 8; dprint(v->msg_line, 0, test+1, 3, 0); dprint(v->msg_line, 4, v->pass, 5, 0); hprint(v->msg_line, 11, page); hprint2(v->msg_line, 19, offset, 3); cprint(v->msg_line, 22, " - . MB"); dprint(v->msg_line, 25, mb, 5, 0); dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0); if (type == 3) { /* ECC error */ cprint(v->msg_line, 36, bad?"corrected ": "uncorrected "); hprint2(v->msg_line, 60, syn, 4); cprint(v->msg_line, 68, "ECC"); dprint(v->msg_line, 74, chan, 2, 0); } else if (type == 2) { cprint(v->msg_line, 36, "Parity error detected "); } else { hprint(v->msg_line, 36, good); 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; print_err_counts(); break; case PRINTMODE_PATTERNS: if (v->erri.hdr_flag == 0) { clear_scroll(); v->erri.hdr_flag++; } /* Do not do badram patterns from test 0 or 5 */ if (test == 0 || test == 5) { return; } /* Only do patterns for data errors */ if ( type != 0) { return; } /* Process the address in the pattern administration */ patnchg=insertaddress ((ulong) adr); if (patnchg) { printpatn(); } break; case PRINTMODE_NONE: if (v->erri.hdr_flag == 0) { clear_scroll(); v->erri.hdr_flag++; } break; } } /* * Print an ecc error */ void print_ecc_err(unsigned long page, unsigned long offset, int corrected, unsigned short syndrome, int channel) { ++(v->ecc_ecount); syn = syndrome; chan = channel; common_err((ulong *)page, offset, corrected, 0, 2); } #ifdef PARITY_MEM /* * Print a parity error message */ void parity_err( unsigned long edi, unsigned long esi) { unsigned long addr; if (test == 5) { addr = esi; } else { addr = edi; } common_err((ulong *)addr, addr & 0xFFF, 0, 0, 3); } #endif /* * Print the pattern array as a LILO boot option addressing BadRAM support. */ void printpatn (void) { int idx=0; int x; /* Check for keyboard input */ check_input(); if (v->numpatn == 0) return; scroll(); cprint (v->msg_line, 0, "badram="); x=7; for (idx = 0; idx < v->numpatn; idx++) { if (x > 80-22) { scroll(); x=7; } cprint (v->msg_line, x, "0x"); hprint (v->msg_line, x+2, v->patn[idx].adr ); cprint (v->msg_line, x+10, ",0x"); hprint (v->msg_line, x+13, v->patn[idx].mask); if (idx+1 < v->numpatn) cprint (v->msg_line, x+21, ","); x+=22; } } /* * Show progress by displaying elapsed time and update bar graphs */ short spin_idx[MAX_CPUS]; char spin[4] = {'|','/','-','\\'}; void do_tick(int me) { int i, j, pct; ulong h, l, n, t; extern int mstr_cpu; if (++spin_idx[me] > 3) { spin_idx[me] = 0; } cplace(8, 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) { print_err_counts(); } nticks++; v->total_ticks++; 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(2, COL_MID+9+v->tptr, "#"); v->tptr++; } 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(1, COL_MID+9+v->pptr, "#"); v->pptr++; } if (v->ecount && v->printmode == PRINTMODE_SUMMARY) { /* Compute confidence score */ pct = 0; /* If there are no errors within 1mb of start - end addresses */ h = v->pmap[v->msegs - 1].end - 0x100; if (v->erri.low_addr.page > 0x100 && v->erri.high_addr.page < h) { pct += 8; } /* Errors for only some tests */ if (v->pass) { for (i=0, n=0; tseq[i].msg != NULL; i++) { if (tseq[i].errors == 0) { n++; } } pct += n*3; } else { for (i=0, n=0; ierri.ebits & 0xf) n++; if (v->erri.ebits & 0xf0) n++; if (v->erri.ebits & 0xf00) n++; if (v->erri.ebits & 0xf000) n++; if (v->erri.ebits & 0xf0000) n++; if (v->erri.ebits & 0xf00000) n++; if (v->erri.ebits & 0xf000000) n++; if (v->erri.ebits & 0xf0000000) n++; pct += (8-n)*2; /* Adjust the score */ pct = pct*100/22; /* if (pct > 100) { pct = 100; } */ dprint(LINE_HEADER+0, 25, pct, 3, 1); } /* We can't do the elapsed time unless the rdtsc instruction * is supported */ if (cpu_id.fid.bits.rdtsc) { asm __volatile__( "rdtsc":"=a" (l),"=d" (h)); asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (l), "=d" (h) :"g" (v->startl), "g" (v->starth), "0" (l), "1" (h)); t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000; t += (l / v->clks_msec) / 1000; i = t % 60; j = i % 10; if(j != v->each_sec) { dprint(LINE_TIME, COL_TIME+9, i % 10, 1, 0); dprint(LINE_TIME, COL_TIME+8, 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); t /= 60; dprint(LINE_TIME, COL_TIME, t, 4, 0); if(v->check_temp > 0 && !(v->fail_safe & 4)) { coretemp(); } v->each_sec = j; } } /* Poll for ECC errors */ /* poll_errors(); */ } memtest86+-5.01/FAQ0000644000000000000000000003714312201317426012404 0ustar rootroot- What is memtest86+, what do I use it for? Memtest86+ is a utility designed to test whether your memory is in working order. It repeatedly writes an enormous amount of different patterns to all memory locations and reads them back again and verifies whether the result of the read is the same as what was written to memory. There can be a multitude of reasons for running memtest, but foremost of all is of course to test whether your memory modules might be bad. Whenever you suspect your modules to be bad because of system crashes, lockups or reboots it would be nice to know whether the modules are in working order. Memtest86+ is a utility which tries to answer that question for you. Another common use exists in the overclocking scene. When overclocking a system you are essentially pushing your system to the limits and at some point it will simply give way and break. Unfortunately there isn't a clear cut way of deciding whether a system is still working correctly. Because of the complexity of a computer a system which is pushed to the limits doesn't just break completely when it starts to fail, instead little errors start showing up in many different places in the system growing more frequent and widespread the more the system is pushed. Each one of these little errors can lead to a crash of your system but can also go unnoticed for days or weeks in a running system. The art so to speak of overclocking is thus to push the system as far as it can go without introducing any such errors. As memory is usually one of the first places these such errors start coming up a memory test is very useful. - How do I get it to run? There are several ways to use memtest, which are described below: + Run from floppydisk Memtest86+ is directly executable by any modern x86 compatible machine, by writing the bootable binary to a floppy disk one can boot from the disk to run memtest. Simply download the appropriate package, the Pre-Compiled Bootable Binary (.gz) package for Linux users and the Pre-Compiled package for Floppy (DOS - Win) for Windows users. For Windows, unzip the package into a directory like C:\memtest, insert a blank floppy into your a: disk drive and run the install.bat file. As the install prompts you, to use memtest directly, leave the disk in the drive and reboot your machine. For Linux, unpack the package into your home directory, insert a blank floppy into your floppy drive and execute 'dd if=~/memtest+-1.xx.bin.gz of=/dev/fd0 conv=osync' replacing 1.xx with the correct version number of the memtest86+ you downloaded. To run memtest immediately reboot your machine. Your machine should now boot from the disk, display the word Loading folowed by a series of periods and then show a screen much like the screenshots on the memtest86+ web page. The test is automatically started. If your machine simply boots back into Windows/Linux you will most likely have to configure your BIOS to attempt to boot from floppy disk on startup, refer to your computer's/mainboard's manual how to do this. When you are done testing simply remove the floppy and reset your computer, if ever you want to execure the test again simply reinsert the disk and reboot/start your computer. + Run from CD Memtest86+ is directly executable by any modern x86 compatible machine, by writing the iso to a CD one can boot from the CD to run memtest. Simply download the appropriate package, the Download - Pre-Compiled Bootable ISO (.gz) for Linux users and the Pre-Compiled Bootable ISO (.zip) for Windows users. For Windows, unzip the package into a directory like C:\memtest. You will now see a file called memtest86+-1.xx.iso in this directory. You will need to burn this file to a CD with a CD recording program. Do note however that you should not make a regular data CD on which you for instance write your text documents and holiday photographs. Instead the iso file is a so called image of a CD, it is a direct copy of a CD. Your CD recording program will most likely have a feature called burn image or something to that effect which you should use to burn the CD. For linux, unzip the package into your home directory. and execute 'cdrecord dev= ~/memtest86+-1.xx.iso' where you replace with the scsi address of your CD burner and replace 1.xx with the correct version number of the memtest86+ your downloaded. When the burning completed your drive will most likely have ejected the CD and you should have a bootable memtest86+ CD. To run the test directly reinsert the CD and reboot your machine. Your machine should now boot from the CD, display the word Loading folowed by a series of periods and then show a screen much like the screenshots on the memtest86+ web page. The test is automatically started. If your machine simply boots back into Windows/Linux you will most likely have to configure your BIOS to attempt to boot from CD-ROM drive on startup, refer to your computer's/mainboard's manual how to do this. When you are done testing simply remove the CD and reset your computer, if ever you want to execure the test again simply reinsert the CD and reboot/start your computer. + Run from USB Flash drive FIXME + Run from boot manager FIXME - How long does memtest86+ run? How do I stop it? Memtest86+ runs indefinately unless you stop it. It does however repeat the same tests over and over again. Memtest86+ contains a number of different tests which each take different approaches in trying to expose any errors in your memory. In the top right of your screen you can see the progress of each test in the lower of the two progress bars. The topmost progress bar shows the progress of a pass, each pass consists of all the tests in the memtest suite. Thus all tests are executed in one pass, so does that mean that no errors will show after the first pass if that pass didn't reveal any errors? Well no, there are several reasons why errors might only show up after a number of passes. Firstly as of this writing, the latest version of memtest also includes a test which uses random test patterns, each pass these patterns will of course be different. Secondly some types of errors simply don't show up until the system has been running for a while or are very critical on a certain timing condition, or other such conditions. To conclude, one successful pass of memtest will give you a pretty good idea that your memory is ok, only in rare cases will there be errors showing after the first pass. To be sure though simply have the test run overnight or even for a couple of days depending on the level of importance of the system. - How many errors are acceptable? No errors are acceptable. Even if there is just one error, something is amiss which can cause your system to crash. Of course what the cause of the errors is you will still have to determine. - What do I do when I get errors? Firstly, don't start drawing any conclusions. You only know that memtest86+ is giving your errors, not what the cause is. Unfortunately it is not a straightforward exercise to decisively test the memory in an actual system. This is because a computer is not just built up of some memory, but also includes many other elements such as a memory controller, cache, a cache controller, algorithmic and logic units, etc, all of which contribute to the machine. If there are faults in any of these other parts of the computer you will likely also see errors showing up in memtest. So what to do? First verify that the BIOS settings of your machine are correctly configured. Look up the memory timing settings applicable to the brand and type of memory modules you have and check they match your BIOS settings, correct them if they don't and run memtest again Ok, you have all the settings correctly set and you're still getting errors. Well of course a very likely cause are the memory modules and the logical course of action is to look into them further. If you are well stocked, have a few other machines at your disposal, or just want to spend the cash for some new modules the best way to test if the cause are your memory modules is just to replace them and test again. If you are less fortunate though there is still something you can do. If you have more then one module in your system, test them one by one, if one is consistently giving errors and another is consistently showing no errors it's a pretty good bet that the module giving the errors is simply defective. To exclude the possibility that a defective slot is throwing your results, use the same slot to test each different module. If each module by itself shows no errors, but when you place two or more modules into the machine at the same time you do get errors, you are most likely stuck with a compatibility issue and unfortunately there isn't a whole lot you can do about it. Be sure to check your computer/motherboard manual to see if the setup you are trying is allowed, some boards require special restrictions in the sizes of modules, the order of modules, the placement of double sided and single sides modules and more of such things. If you have only one module in your system, or all modules are giving errors, there are only very few options left. The only thing you can do really is to try the module(s) in another slot. Finally simply try out different orders of the memory modules, although your manual might not mention anything on the matter sometimes there simply exist timing or other issues which can be resolved by changing the order of your modules. And of course test each slot by putting a single module into that slot and running memtest on it. In the end if you still have not been able to localize the problem you will have to find a replacement module to establish whether the problem lies in your modules. See if you can borrow a module from someone else. When you have replaced the memory by new memory and the errors still persist, first check if you can rule out any compatibility issues or timing issues. If you are sure the memory should work in the system the cause of the errors must obviously lie someplace else in the system. The only way to find out where, is by trial and error really. Simply start replacing and/or removing parts of your computer one by one, running memtest each time you changed anything, until the errors are resolved. - I'm getting errors in test #x, what doest that mean? Interpreting memtest results is as scientific an endeavour as testing whether a person is a witch by the methods used in Monty Python's Holy Grail. In short, don't even start, it's not going to get you anywhere. Just interpret any error as you should any other and use the methods descibed in the previous question to determine the cause. - I'm getting errors in test #5 and/or #8 and have read a lot about it. Yes there are just about enough discussions on the topic to fill a book, but it all boils down to the answer given above. The only thing that can be said is that many a times, when memory latencies are incorrectly set in the BIOS you will experience errors in test #5 and #8. (Though #8 does not exist anymore as of version 1.40 and might be reinstated as a different test in a later version.) This does however NOT mean that errors in these tests are always the cause of incorrect settings, your memory might just as well be defective. - I'm getting errors in memtest on one machine, but not when I put the same memory in another, what does that mean? It can mean one of two things: - The machine that is giving the errors is defective. Errors don't just orginate from the memory module itself, but can also be caused by defects in the cpu, chipset, motherboard, PSU and even by timing issues introduced by any other component in the machine. - The machine giving the errors is imposing stricter timing than the other which the memory module simply can't cope with. If the module should work with the machine according to its specifications then it most likely is defective. - Which memory is tested? As much as possible of the system memory is tested. Unfortunately memtest86+ can usually not test all of the memory. The reason for this is that todays processors have become so complex that they require a small amount of memory to keep accounting data of the processor state. If memtest were to write over these areas the state of the processor becomes invalid and it's behaviour unpredictable. Alas it is also impossible to relocate these areas in the memory. This means that a small area of your memory can not be tested by memtest. If this part of the memory is defective you will know soon enough though as the processor, or parts of the processor simply won't work correctly if this part of your memory is defective. Do realise though that in very rare cases memtest will show no errors even though the module is defective, not because memtest can't detect the error, but because memtest can't test the area the error is located in. - When I select BIOS-ALL I get many errors / my machine crashes. This is normal. With todays computers this option should never be selected. See the previous question about the reason for the errors. - I want to use memtest on a multiboot CD, how do I do this? This is of course very dependent on which boot loader you use for your CD. Below is a description of how to set up a multiboot CD including memtest+ with isolinux, if you have experience with any other bootloader(s) please consider writing a small description of using memtest with that bootloader for the FAQ. -isolinux For general instructions on how to make a bootable CD with isolinux see the syslinux website and the manual. What you need to do to get memtest working is as follows. Download the Pre-Compiled Bootable Binary, the .gz if you are working under linux, the .zip if you are working under windows. Unpack the file from the package and rename it to an 8.3 filename with an extension other than .bin, renaming to memtest. (without an extension) is a good choice. Put the file somewhere in your CD directory structure, for example in images/memtest and edit your config file to include the following: label memtest kernel /images/memtest If you want to boot memtest automatically insert or change a line at the top to: default memtest If you want to display a prompt from which you can start memtest add or change the lines at the top to: (Change the timeout to suit your needs) prompt 1 timeout 200 - If memtest86+ shows no errors does that mean my memory is not defective? Of course no answers are definitive, no matter how good memtest86+ will eventually become there is always the possibility that a particular type of error will go unnoticed. As long as you are having no problems with the system it will be pretty safe to say that the modules are good. If you are having problems with the system however you will just have to check by trial and error, ie swapping the modules for new ones and/or testing with modules of a different brand/type. - When I run install.bat it doesn't write anything to floppy. You most likely have unpacked the memtest+-2.xx.floppy.zip file into a folder with a long pathname and/or containing + and - signs. It seems rawrite doesn't like that. Just move the files you unpacked to a directory like c:\memtest and execure it from there. memtest86+-5.01/cpuid.h0000644000000000000000000001276212201317426013327 0ustar rootroot/* * 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) extern struct cpu_ident cpu_id; 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); } /* Some CPUID calls want 'count' to be placed in ecx */ static inline void cpuid_count(unsigned int op, int count, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { *eax = op; *ecx = count; __cpuid(eax, ebx, ecx, edx); } /* Typedef for storing the Cache Information */ typedef union { unsigned char ch[48]; uint32_t uint[12]; 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; uint32_t fill5[8]; } 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 { uint32_t flat; struct { uint32_t :1; } bits; } cpuid_custom_features; /* Typedef for storing CPUID Feature flags */ typedef union { uint32_t uint32_array[3]; struct { uint32_t fpu:1; /* EDX feature flags, bit 0 */ uint32_t vme:1; uint32_t de:1; uint32_t pse:1; uint32_t rdtsc:1; uint32_t msr:1; uint32_t pae:1; uint32_t mce:1; uint32_t cx8:1; uint32_t apic:1; uint32_t bit10: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 bit20: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 bit30:1; uint32_t pbe:1; /* EDX feature flags, bit 31 */ uint32_t sse3:1; /* ECX feature flags, bit 0 */ uint32_t mulq:1; uint32_t bit2:1; uint32_t mon:1; uint32_t dscpl:1; uint32_t vmx:1; uint32_t smx:1; uint32_t eist:1; uint32_t tm2:1; uint32_t bits_9_31:23; uint32_t bits0_28:29; /* EDX extended feature flags, bit 0 */ uint32_t lm:1; /* Long Mode */ uint32_t bits_30_31:2; /* EDX extended feature flags, bit 32 */ } bits; } cpuid_feature_flags_t; /* An overall structure to cache all of the CPUID information */ struct cpu_ident { uint32_t max_cpuid; uint32_t max_xcpuid; uint32_t dts_pmp; 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; cpuid_custom_features custom; }; struct cpuid4_eax { uint32_t ctype:5; uint32_t level:3; uint32_t is_self_initializing:1; uint32_t is_fully_associative:1; uint32_t reserved:4; uint32_t num_threads_sharing:12; uint32_t num_cores_on_die:6; }; struct cpuid4_ebx { uint32_t coherency_line_size:12; uint32_t physical_line_partition:10; uint32_t ways_of_associativity:10; }; struct cpuid4_ecx { uint32_t number_of_sets:32; }; memtest86+-5.01/reloc.c0000644000000000000000000001707512201317426013324 0ustar rootroot/* reloc.c - MemTest-86 Version 3.3 * * Released under version 2 of the Gnu Public License. * By Eric Biederman */ #include "stddef.h" #include "stdint.h" #include "elf.h" #define __ELF_NATIVE_CLASS 32 #define ELF_MACHINE_NO_RELA 1 /* We use this macro to refer to ELF types independent of the native wordsize. `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ #define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) #define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) #define _ElfW_1(e,w,t) e##w##t /* We use this macro to refer to ELF types independent of the native wordsize. `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) #define assert(expr) ((void) 0) /* This #define produces dynamic linking inline functions for bootstrap relocation instead of general-purpose relocation. */ #define RTLD_BOOTSTRAP struct link_map { ElfW(Addr) l_addr; /* Current load address */ ElfW(Addr) ll_addr; /* Last load address */ ElfW(Dyn) *l_ld; /* Indexed pointers to dynamic section. [0,DT_NUM) are indexed by the processor-independent tags. [DT_NUM,DT_NUM+DT_PROCNUM) are indexed by the tag minus DT_LOPROC. [DT_NUM+DT_PROCNUM,DT_NUM+DT_PROCNUM+DT_EXTRANUM) are indexed by DT_EXTRATAGIDX(tagvalue) and [DT_NUM+DT_PROCNUM, DT_NUM+DT_PROCNUM+DT_EXTRANUM) are indexed by DT_EXTRATAGIDX(tagvalue) (see ). */ ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]; }; /* Return the link-time address of _DYNAMIC. Conveniently, this is the first element of the GOT. This must be inlined in a function which uses global data. */ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_dynamic (void) { register Elf32_Addr *got asm ("%ebx"); return *got; } /* Return the run-time load address of the shared object. */ static inline Elf32_Addr __attribute__ ((unused)) elf_machine_load_address (void) { Elf32_Addr addr; asm volatile ("leal _start@GOTOFF(%%ebx), %0\n" : "=r" (addr) : : "cc"); return addr; } /* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */ static inline void elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, const Elf32_Sym *sym, Elf32_Addr *const reloc_addr) { Elf32_Addr ls_addr, s_addr; Elf32_Addr value; if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE) { *reloc_addr += map->l_addr - map->ll_addr; return; } if (ELF32_R_TYPE(reloc->r_info) == R_386_NONE) { return; } value = sym->st_value; /* Every section except the undefined section has a base of map->l_addr */ ls_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->ll_addr; s_addr = sym->st_shndx == SHN_UNDEF ? 0 : map->l_addr; switch (ELF32_R_TYPE (reloc->r_info)) { case R_386_COPY: { /* Roll memcpy by hand as we don't have function calls yet. */ unsigned char *dest, *src; long i; dest = (unsigned char *)reloc_addr; src = (unsigned char *)(value + s_addr); for(i = 0; i < sym->st_size; i++) { dest[i] = src[i]; } } break; case R_386_GLOB_DAT: *reloc_addr = s_addr + value; break; case R_386_JMP_SLOT: *reloc_addr = s_addr + value; break; case R_386_32: if (map->ll_addr == 0) { *reloc_addr += value; } *reloc_addr += s_addr - ls_addr; break; case R_386_PC32: if (map->ll_addr == 0) { *reloc_addr += value - reloc->r_offset; } *reloc_addr += (s_addr - map->l_addr) - (ls_addr - map->ll_addr); break; default: assert (! "unexpected dynamic reloc type"); break; } } /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ static inline void __attribute__ ((unused)) elf_get_dynamic_info(ElfW(Dyn) *dyn, ElfW(Addr) l_addr, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM + DT_EXTRANUM]) { if (! dyn) return; while (dyn->d_tag != DT_NULL) { if (dyn->d_tag < DT_NUM) info[dyn->d_tag] = dyn; else if (dyn->d_tag >= DT_LOPROC && dyn->d_tag < DT_LOPROC + DT_PROCNUM) info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn; else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM) info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_PROCNUM ] = dyn; else assert (! "bad dynamic tag"); ++dyn; } if (info[DT_PLTGOT] != NULL) info[DT_PLTGOT]->d_un.d_ptr += l_addr; if (info[DT_STRTAB] != NULL) info[DT_STRTAB]->d_un.d_ptr += l_addr; if (info[DT_SYMTAB] != NULL) info[DT_SYMTAB]->d_un.d_ptr += l_addr; #if ! ELF_MACHINE_NO_RELA if (info[DT_RELA] != NULL) { assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela))); info[DT_RELA]->d_un.d_ptr += l_addr; } #endif #if ! ELF_MACHINE_NO_REL if (info[DT_REL] != NULL) { assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); info[DT_REL]->d_un.d_ptr += l_addr; } #endif if (info[DT_PLTREL] != NULL) { #if ELF_MACHINE_NO_RELA assert (info[DT_PLTREL]->d_un.d_val == DT_REL); #elif ELF_MACHINE_NO_REL assert (info[DT_PLTREL]->d_un.d_val == DT_RELA); #else assert (info[DT_PLTREL]->d_un.d_val == DT_REL || info[DT_PLTREL]->d_un.d_val == DT_RELA); #endif } if (info[DT_JMPREL] != NULL) info[DT_JMPREL]->d_un.d_ptr += l_addr; } /* Perform the relocations in MAP on the running program image as specified by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT relocations; they should be set up to call _dl_runtime_resolve, rather than fully resolved now. */ static inline void elf_dynamic_do_rel (struct link_map *map, ElfW(Addr) reladdr, ElfW(Addr) relsize) { const ElfW(Rel) *r = (const void *) reladdr; const ElfW(Rel) *end = (const void *) (reladdr + relsize); const ElfW(Sym) *const symtab = (const void *) map->l_info[DT_SYMTAB]->d_un.d_ptr; for (; r < end; ++r) { elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], (void *) (map->l_addr + r->r_offset)); } } void _dl_start(void) { static Elf32_Addr last_load_address = 0; struct link_map map; size_t cnt; /* Partly clean the `map' structure up. Don't use `memset' since it might nor be built in or inlined and we cannot make function calls at this point. */ for (cnt = 0; cnt < sizeof(map.l_info) / sizeof(map.l_info[0]); ++cnt) { map.l_info[cnt] = 0; } /* Get the last load address */ map.ll_addr = last_load_address; /* Figure out the run-time load address of the dynamic linker itself. */ last_load_address = map.l_addr = elf_machine_load_address(); /* Read our own dynamic section and fill in the info array. */ map.l_ld = (void *)map.l_addr + elf_machine_dynamic(); elf_get_dynamic_info (map.l_ld, map.l_addr - map.ll_addr, map.l_info); /* Relocate ourselves so we can do normal function calls and * data access using the global offset table. */ #if !ELF_MACHINE_NO_REL elf_dynamic_do_rel(&map, map.l_info[DT_REL]->d_un.d_ptr, map.l_info[DT_RELSZ]->d_un.d_val); if (map.l_info[DT_PLTREL]->d_un.d_val == DT_REL) { elf_dynamic_do_rel(&map, map.l_info[DT_JMPREL]->d_un.d_ptr, map.l_info[DT_PLTRELSZ]->d_un.d_val); } #endif #if !ELF_MACHINE_NO_RELA elf_dynamic_do_rela(&map, map.l_info[DT_RELA]->d_un.d_ptr, map.l_info[DT_RELASZ]->d_un.d_val); if (map.l_info[DT_PLTREL]->d_un.d_val == DT_RELA) { elf_dynamic_do_rela(&map, map.l_info[DT_JMPREL]->d_un.d_ptr, map.l_info[DT_PLTRELSZ]->d_un.d_val); } #endif /* Now life is sane; we can call functions and access global data. Set up to use the operating system facilities, and find out from the operating system's program loader where to find the program header table in core. Put the rest of _dl_start into a separate function, that way the compiler cannot put accesses to the GOT before ELF_DYNAMIC_RELOCATE. */ return; } memtest86+-5.01/stddef.h0000644000000000000000000000020112201317426013455 0ustar rootroot#ifndef I386_STDDEF_H #define I386_STDDEF_H #define NULL ((void *)0) typedef unsigned long size_t; #endif /* I386_STDDEF_H */ memtest86+-5.01/patn.c0000644000000000000000000000731312201317426013154 0ustar rootroot/* Pattern extension for memtest86 * * Generates patterns for the Linux kernel's BadRAM extension that avoids * allocation of faulty pages. * * Released under version 2 of the Gnu Public License. * * By Rick van Rein, vanrein@zonnet.nl * ---------------------------------------------------- * MemTest86+ V1.60 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ #include "test.h" /* * DEFAULT_MASK covers a longword, since that is the testing granularity. */ #define DEFAULT_MASK ((~0L) << 2) /* extern struct vars *v; */ /* What it does: * - Keep track of a number of BadRAM patterns in an array; * - Combine new faulty addresses with it whenever possible; * - Keep masks as selective as possible by minimising resulting faults; * - Print a new pattern only when the pattern array is changed. */ #define COMBINE_MASK(a,b,c,d) ((a & b & c & d) | (~a & b & ~c & d)) /* Combine two adr/mask pairs to one adr/mask pair. */ void combine (ulong adr1, ulong mask1, ulong adr2, ulong mask2, ulong *adr, ulong *mask) { *mask = COMBINE_MASK (adr1, mask1, adr2, mask2); *adr = adr1 | adr2; *adr &= *mask; // Normalise, no fundamental need for this } /* Count the number of addresses covered with a mask. */ ulong addresses (ulong mask) { ulong ctr=1; int i=32; while (i-- > 0) { if (! (mask & 1)) { ctr += ctr; } mask >>= 1; } return ctr; } /* Count how much more addresses would be covered by adr1/mask1 when combined * with adr2/mask2. */ ulong combicost (ulong adr1, ulong mask1, ulong adr2, ulong mask2) { ulong cost1=addresses (mask1); ulong tmp, mask; combine (adr1, mask1, adr2, mask2, &tmp, &mask); return addresses (mask) - cost1; } /* Find the cheapest array index to extend with the given adr/mask pair. * Return -1 if nothing below the given minimum cost can be found. */ int cheapindex (ulong adr1, ulong mask1, ulong mincost) { int i=v->numpatn; int idx=-1; while (i-- > 0) { ulong tmpcost=combicost(v->patn[i].adr, v->patn[i].mask, adr1, mask1); if (tmpcost < mincost) { mincost=tmpcost; idx=i; } } return idx; } /* Try to find a relocation index for idx if it costs nothing. * Return -1 if no such index exists. */ int relocateidx (int idx) { ulong adr =v->patn[idx].adr; ulong mask=v->patn[idx].mask; int new; v->patn[idx].adr ^= ~0L; // Never select idx new=cheapindex (adr, mask, 1+addresses (mask)); v->patn[idx].adr = adr; return new; } /* Relocate the given index idx only if free of charge. * This is useful to combine to `neighbouring' sections to integrate. * Inspired on the Buddy memalloc principle in the Linux kernel. */ void relocateiffree (int idx) { int newidx=relocateidx (idx); if (newidx>=0) { ulong cadr, cmask; combine (v->patn [newidx].adr, v->patn[newidx].mask, v->patn [ idx].adr, v->patn[ idx].mask, &cadr, &cmask); v->patn[newidx].adr =cadr; v->patn[newidx].mask=cmask; if (idx < --v->numpatn) { v->patn[idx].adr =v->patn[v->numpatn].adr; v->patn[idx].mask=v->patn[v->numpatn].mask; } relocateiffree (newidx); } } /* Insert a single faulty address in the pattern array. * Return 1 only if the array was changed. */ int insertaddress (ulong adr) { if (cheapindex (adr, DEFAULT_MASK, 1L) != -1) return 0; if (v->numpatn < BADRAM_MAXPATNS) { v->patn[v->numpatn].adr =adr; v->patn[v->numpatn].mask=DEFAULT_MASK; v->numpatn++; relocateiffree (v->numpatn-1); } else { int idx=cheapindex (adr, DEFAULT_MASK, ~0L); ulong cadr, cmask; combine (v->patn [idx].adr, v->patn[idx].mask, adr, DEFAULT_MASK, &cadr, &cmask); v->patn[idx].adr =cadr; v->patn[idx].mask=cmask; relocateiffree (idx); } return 1; } memtest86+-5.01/test.c0000644000000000000000000011075412201322630013166 0ustar rootroot/* test.c - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. * By Chris Brady * ---------------------------------------------------- * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * Thanks to Passmark for calculate_chunk() and various comments ! */ #include "test.h" #include "config.h" #include "stdint.h" #include "cpuid.h" #include "smp.h" #include extern struct cpu_ident cpu_id; 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(); static inline ulong roundup(ulong value, ulong mask) { return (value + mask) & ~mask; } // start / end - return values for range to test // me - this threads CPU number // j - index into v->map for current segment we are testing // align - number of bytes to align each block to void calculate_chunk(ulong** start, ulong** end, int me, int j, int makeMultipleOf) { ulong chunk; // If we are only running 1 CPU then test the whole block if (run_cpus == 1) { *start = v->map[j].start; *end = v->map[j].end; } else{ // Divide the current segment by the number of CPUs chunk = (ulong)v->map[j].end-(ulong)v->map[j].start; chunk /= run_cpus; // Round down to the nearest desired bitlength multiple chunk = (chunk + (makeMultipleOf-1)) & ~(makeMultipleOf-1); // Figure out chunk boundaries *start = (ulong*)((ulong)v->map[j].start+(chunk*me)); /* Set end addrs for the highest CPU num to the * end of the segment for rounding errors */ // Also rounds down to boundary if needed, may miss some ram but better than crashing or producing false errors. // This rounding probably will never happen as the segments should be in 4096 bytes pages if I understand correctly. if (me == mstr_cpu) { *end = (ulong*)(v->map[j].end); } else { *end = (ulong*)((ulong)(*start) + chunk); (*end)--; } } } /* * Memory address test, walking ones */ void addr_tst1(int me) { int i, j, k; volatile ulong *p, *pt, *end; ulong bad, mask, bank, p1; /* Test the global address bits */ for (p1=0, j=0; j<2; j++) { hprint(LINE_PAT, COL_PAT, p1); /* Set pattern in our lowest multiple of 0x20000 */ p = (ulong *)roundup((ulong)v->map[0].start, 0x1ffff); *p = p1; /* Now write pattern compliment */ p1 = ~p1; end = v->map[segs-1].end; for (i=0; i<100; i++) { mask = 4; do { pt = (ulong *)((ulong)p | mask); if (pt == p) { mask = mask << 1; continue; } if (pt >= end) { break; } *pt = p1; if ((bad = *p) != ~p1) { ad_err1((ulong *)p, (ulong *)mask, bad, ~p1); i = 1000; } mask = mask << 1; } while(mask); } do_tick(me); BAILR } /* Now check the address bits in each bank */ /* If we have more than 8mb of memory then the bank size must be */ /* bigger than 256k. If so use 1mb for the bank size. */ if (v->pmap[v->msegs - 1].end > (0x800000 >> 12)) { bank = 0x100000; } else { bank = 0x40000; } for (p1=0, k=0; k<2; k++) { hprint(LINE_PAT, COL_PAT, p1); for (j=0; jmap[j].start; /* Force start address to be a multiple of 256k */ p = (ulong *)roundup((ulong)p, bank - 1); end = v->map[j].end; /* Redundant checks for overflow */ while (p < end && p > v->map[j].start && p != 0) { *p = p1; p1 = ~p1; for (i=0; i<50; i++) { mask = 4; do { pt = (ulong *) ((ulong)p | mask); if (pt == p) { mask = mask << 1; continue; } if (pt >= end) { break; } *pt = p1; if ((bad = *p) != ~p1) { ad_err1((ulong *)p, (ulong *)mask, bad,~p1); i = 200; } mask = mask << 1; } while(mask); } if (p + bank > p) { p += bank; } else { p = end; } p1 = ~p1; } } do_tick(me); BAILR p1 = ~p1; } } /* * Memory address test, own address */ void addr_tst2(int me) { int j, done; ulong *p, *pe, *end, *start; cprint(LINE_PAT, COL_PAT, "address "); /* Write each address with it's own address */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { do_tick(me); BAILR /* Check for overflow */ if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p <= pe; p++) { * *p = (ulong)p; * } */ asm __volatile__ ( "jmp L91\n\t" ".p2align 4,,7\n\t" "L90:\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" (pe) ); p = pe + 1; } while (!done); } /* Each address should have its own address */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { do_tick(me); BAILR /* Check for overflow */ if (pe + SPINSZ > pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p <= pe; p++) { * if((bad = *p) != (ulong)p) { * ad_err2((ulong)p, bad); * } * } */ asm __volatile__ ( "jmp L95\n\t" ".p2align 4,,7\n\t" "L99:\n\t" "addl $4,%%edi\n\t" "L95:\n\t" "movl (%%edi),%%ecx\n\t" "cmpl %%edi,%%ecx\n\t" "jne L97\n\t" "L96:\n\t" "cmpl %%edx,%%edi\n\t" "jb L99\n\t" "jmp L98\n\t" "L97:\n\t" "pushl %%edx\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" "call ad_err2\n\t" "popl %%edi\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" "jmp L96\n\t" "L98:\n\t" : : "D" (p), "d" (pe) : "ecx" ); p = pe + 1; } while (!done); } } /* * Test all of memory using a "half moving inversions" algorithm using random * numbers and their complment as the data pattern. Since we are not able to * produce random numbers in reverse order testing is only done in the forward * direction. */ void movinvr(int me) { int i, j, done, seed1, seed2; ulong *p; ulong *pe; ulong *start,*end; ulong xorVal; //ulong num, bad; /* Initialize memory with initial sequence of random numbers. */ if (cpu_id.fid.bits.rdtsc) { asm __volatile__ ("rdtsc":"=a" (seed1),"=d" (seed2)); } else { seed1 = 521288629 + v->pass; seed2 = 362436069 - v->pass; } /* Display the current seed */ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, seed1); rand_seed(seed1, seed2, me); for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code */ /* for (; p <= pe; p++) { *p = rand(me); } */ 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" "cmpl %%ebx,%%edi\n\t" "jb L201\n\t" : : "D" (p), "b" (pe), "c" (me) : "eax" ); p = pe + 1; } while (!done); } /* Do moving inversions test. Check for initial pattern and then * write the complement for each memory location. */ for (i=0; i<2; i++) { rand_seed(seed1, seed2, me); for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code */ /*for (; p <= pe; p++) { num = rand(me); if (i) { num = ~num; } if ((bad=*p) != num) { error((ulong*)p, num, bad); } *p = ~num; }*/ if (i) { xorVal = 0xffffffff; } else { xorVal = 0; } asm __volatile__ ( "pushl %%ebp\n\t" // Skip first increment "jmp L26\n\t" ".p2align 4,,7\n\t" // increment 4 bytes (32-bits) "L27:\n\t" "addl $4,%%edi\n\t" // Check this byte "L26:\n\t" // Get next random number, pass in me(edx), random value returned in num(eax) // num = rand(me); // cdecl call maintains all registers except eax, ecx, and edx // We maintain edx with a push and pop here using it also as an input // we don't need the current eax value and want it to change to the return value // we overwrite ecx shortly after this discarding its current value "pushl %%edx\n\t" // Push function inputs onto stack "call rand\n\t" "popl %%edx\n\t" // Remove function inputs from stack // XOR the random number with xorVal(ebx), which is either 0xffffffff or 0 depending on the outer loop // if (i) { num = ~num; } "xorl %%ebx,%%eax\n\t" // Move the current value of the current position p(edi) into bad(ecx) // (bad=*p) "movl (%%edi),%%ecx\n\t" // Compare bad(ecx) to num(eax) "cmpl %%eax,%%ecx\n\t" // If not equal jump the error case "jne L23\n\t" // Set a new value or not num(eax) at the current position p(edi) // *p = ~num; "L25:\n\t" "movl $0xffffffff,%%ebp\n\t" "xorl %%ebp,%%eax\n\t" "movl %%eax,(%%edi)\n\t" // Loop until current position p(edi) equals the end position pe(esi) "cmpl %%esi,%%edi\n\t" "jb L27\n\t" "jmp L24\n" // Error case "L23:\n\t" // Must manually maintain eax, ecx, and edx as part of cdecl call convention "pushl %%edx\n\t" "pushl %%ecx\n\t" // Next three pushes are functions input "pushl %%eax\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" // Remove function inputs from stack and restore register values "popl %%eax\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" "jmp L25\n" "L24:\n\t" "popl %%ebp\n\t" :: "D" (p), "S" (pe), "b" (xorVal), "d" (me) : "eax", "ecx" ); p = pe + 1; } while (!done); } } } /* * 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, int me) { int i, j, done; ulong *p, *pe, len, *start, *end; /* Display the current pattern */ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } len = pe - p + 1; if (p == pe ) { break; } //Original C code replaced with hand tuned assembly code // seems broken /*for (; p <= pe; p++) { *p = p1; }*/ asm __volatile__ ( "rep\n\t" \ "stosl\n\t" : : "c" (len), "D" (p), "a" (p1) ); 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. */ for (i=0; i pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } // Original C code replaced with hand tuned assembly code // seems broken /*for (; p <= pe; p++) { if ((bad=*p) != p1) { error((ulong*)p, p1, bad); } *p = p2; }*/ 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" \ "cmpl %%edx,%%edi\n\t" \ "jb L0\n\t" \ "jmp L4\n" \ "L3:\n\t" \ "pushl %%edx\n\t" \ "pushl %%ebx\n\t" \ "pushl %%ecx\n\t" \ "pushl %%eax\n\t" \ "pushl %%edi\n\t" \ "call error\n\t" \ "popl %%edi\n\t" \ "popl %%eax\n\t" \ "popl %%ecx\n\t" \ "popl %%ebx\n\t" \ "popl %%edx\n\t" \ "jmp L5\n" \ "L4:\n\t" \ :: "a" (p1), "D" (p), "d" (pe), "b" (p2) : "ecx" ); p = pe + 1; } while (!done); } for (j=segs-1; j>=0; j--) { calculate_chunk(&start, &end, me, j, 4); pe = end; p = end; done = 0; do { do_tick(me); BAILR /* Check for underflow */ if (pe - SPINSZ < pe && pe != 0) { pe -= SPINSZ; } else { pe = start; done++; } /* Since we are using unsigned addresses a * redundent check is required */ if (pe < start || pe > end) { pe = start; done++; } if (p == pe ) { break; } //Original C code replaced with hand tuned assembly code // seems broken /*do { if ((bad=*p) != p2) { error((ulong*)p, p2, bad); } *p = p1; } while (--p >= pe);*/ asm __volatile__ ( "jmp L9\n\t" ".p2align 4,,7\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 L11\n\t" "jmp L7\n\t" "L6:\n\t" "pushl %%edx\n\t" "pushl %%eax\n\t" "pushl %%ecx\n\t" "pushl %%ebx\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "popl %%ebx\n\t" "popl %%ecx\n\t" "popl %%eax\n\t" "popl %%edx\n\t" "jmp L10\n" "L7:\n\t" :: "a" (p1), "D" (p), "d" (pe), "b" (p2) : "ecx" ); p = pe - 1; } while (!done); } } } void movinv32(int iter, ulong p1, ulong lb, ulong hb, int sval, int off,int me) { int i, j, k=0, n=0, done; ulong *p, *pe, *start, *end, pat = 0, p3; p3 = sval << 31; /* Display the current pattern */ if (mstr_cpu == me) hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Do a SPINSZ section of memory */ /* Original C code replaced with hand tuned assembly code * while (p <= pe) { * *p = pat; * if (++k >= 32) { * pat = lb; * k = 0; * } else { * pat = pat << 1; * pat |= sval; * } * p++; * } */ asm __volatile__ ( "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) ); 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. */ for (i=0; i pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * 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; * } else { * pat = pat << 1; * pat |= sval; * } * } */ asm __volatile__ ( "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) ); p = pe + 1; } while (!done); } 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--) { calculate_chunk(&start, &end, me, j, 64); p = end; pe = end; done = 0; do { do_tick(me); BAILR /* Check for underflow */ 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++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * 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; * } else { * pat = pat >> 1; * pat |= p3; * } * }; */ asm __volatile__ ( "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) ); p = pe - 1; } while (!done); } } } /* * Test all of memory using modulo X access pattern. */ void modtst(int offset, int iter, ulong p1, ulong p2, int me) { int j, k, l, done; ulong *p; ulong *pe; ulong *start, *end; /* Display the current pattern */ 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 pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p <= pe; p += MOD_SZ) { * *p = p1; * } */ asm __volatile__ ( "jmp L60\n\t" \ ".p2align 4,,7\n\t" \ "L60:\n\t" \ "movl %%eax,(%%edi)\n\t" \ "addl $80,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ "jb L60\n\t" \ : "=D" (p) : "D" (p), "d" (pe), "a" (p1) ); } while (!done); } /* Write the rest of memory "iter" times with the pattern complement */ for (l=0; l pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p <= pe; p++) { * if (k != offset) { * *p = p2; * } * if (++k > MOD_SZ-1) { * k = 0; * } * } */ asm __volatile__ ( "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" \ "movl %%eax,(%%edi)\n\t" \ "L52:\n\t" \ "incl %%ebx\n\t" \ "cmpl $19,%%ebx\n\t" \ "jle L53\n\t" \ "xorl %%ebx,%%ebx\n\t" \ "L53:\n\t" \ "cmpl %%edx,%%edi\n\t" \ "jb L54\n\t" \ : "=b" (k) : "D" (p), "d" (pe), "a" (p2), "b" (k), "c" (offset) ); p = pe + 1; } while (!done); } } /* Now check every nth location */ for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } /* Original C code replaced with hand tuned assembly code * for (; p <= pe; p += MOD_SZ) { * if ((bad=*p) != p1) { * error((ulong*)p, p1, bad); * } * } */ asm __volatile__ ( "jmp L70\n\t" \ ".p2align 4,,7\n\t" \ "L70:\n\t" \ "movl (%%edi),%%ecx\n\t" \ "cmpl %%eax,%%ecx\n\t" \ "jne L71\n\t" \ "L72:\n\t" \ "addl $80,%%edi\n\t" \ "cmpl %%edx,%%edi\n\t" \ "jb L70\n\t" \ "jmp L73\n\t" \ "L71:\n\t" \ "pushl %%edx\n\t" "pushl %%ecx\n\t" "pushl %%eax\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "popl %%eax\n\t" "popl %%ecx\n\t" "popl %%edx\n\t" "jmp L72\n" "L73:\n\t" \ : "=D" (p) : "D" (p), "d" (pe), "a" (p1) : "ecx" ); } while (!done); } } /* * Test memory using block moves * Adapted from Robert Redelmeier's burnBX test */ void block_move(int iter, int me) { int i, j, done; ulong len; ulong *p, *pe, pp; ulong *start, *end; cprint(LINE_PAT, COL_PAT-2, " "); /* Initialize memory with the initial pattern. */ for (j=0; j pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } len = ((ulong)pe - (ulong)p) / 64; //len++; asm __volatile__ ( "jmp L100\n\t" ".p2align 4,,7\n\t" "L100:\n\t" // First loop eax is 0x00000001, edx is 0xfffffffe "movl %%eax, %%edx\n\t" "notl %%edx\n\t" // Set a block of 64-bytes // First loop DWORDS are "movl %%eax,0(%%edi)\n\t" // 0x00000001 "movl %%eax,4(%%edi)\n\t" // 0x00000001 "movl %%eax,8(%%edi)\n\t" // 0x00000001 "movl %%eax,12(%%edi)\n\t" // 0x00000001 "movl %%edx,16(%%edi)\n\t" // 0xfffffffe "movl %%edx,20(%%edi)\n\t" // 0xfffffffe "movl %%eax,24(%%edi)\n\t" // 0x00000001 "movl %%eax,28(%%edi)\n\t" // 0x00000001 "movl %%eax,32(%%edi)\n\t" // 0x00000001 "movl %%eax,36(%%edi)\n\t" // 0x00000001 "movl %%edx,40(%%edi)\n\t" // 0xfffffffe "movl %%edx,44(%%edi)\n\t" // 0xfffffffe "movl %%eax,48(%%edi)\n\t" // 0x00000001 "movl %%eax,52(%%edi)\n\t" // 0x00000001 "movl %%edx,56(%%edi)\n\t" // 0xfffffffe "movl %%edx,60(%%edi)\n\t" // 0xfffffffe // rotate left with carry, // second loop eax is 0x00000002 // second loop edx is (~eax) 0xfffffffd "rcll $1, %%eax\n\t" // Move current position forward 64-bytes (to start of next block) "leal 64(%%edi), %%edi\n\t" // Loop until end "decl %%ecx\n\t" "jnz L100\n\t" : "=D" (p) : "D" (p), "c" (len), "a" (1) : "edx" ); } 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 pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } pp = (ulong)p + (((ulong)pe - (ulong)p) / 2); // Mid-point of this block len = ((ulong)pe - (ulong)p) / 8; // Half the size of this block in DWORDS for(i=0; i pe && pe != 0) { pe += SPINSZ; } else { pe = end; } if (pe >= end) { pe = end; done++; } if (p == pe ) { break; } pe-=2; /* the last dwords to test are pe[0] and pe[1] */ asm __volatile__ ( "jmp L120\n\t" ".p2align 4,,7\n\t" "L124:\n\t" "addl $8,%%edi\n\t" // Next QWORD "L120:\n\t" // Compare adjacent DWORDS "movl (%%edi),%%ecx\n\t" "cmpl 4(%%edi),%%ecx\n\t" "jnz L121\n\t" // Print error if they don't match // Loop until end of block "L122:\n\t" "cmpl %%edx,%%edi\n\t" "jb L124\n" "jmp L123\n\t" "L121:\n\t" // eax not used so we don't need to save it as per cdecl // ecx is used but not restored, however we don't need it's value anymore after this point "pushl %%edx\n\t" "pushl 4(%%edi)\n\t" "pushl %%ecx\n\t" "pushl %%edi\n\t" "call error\n\t" "popl %%edi\n\t" "addl $8,%%esp\n\t" "popl %%edx\n\t" "jmp L122\n" "L123:\n\t" : "=D" (p) : "D" (p), "d" (pe) : "ecx" ); } while (!done); } } /* * Test memory for bit fade, fill memory with pattern. */ void bit_fade_fill(ulong p1, int me) { int j, done; ulong *p, *pe; ulong *start,*end; /* Display the current pattern */ hprint(LINE_PAT, COL_PAT, p1); /* Initialize memory with the initial pattern. */ for (j=0; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { do_tick(me); BAILR /* 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++; } 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; jmap[j].start; end = v->map[j].end; pe = (ulong *)start; p = start; done = 0; do { do_tick(me); BAILR /* 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++; } p = pe + 1; } while (!done); } } /* Sleep for N seconds */ void sleep(long n, int flag, int me, int sms) { ulong sh, sl, l, h, t, ip=0; /* save the starting time */ asm __volatile__( "rdtsc":"=a" (sl),"=d" (sh)); /* loop for n seconds */ while (1) { asm __volatile__( "rep ; nop\n\t" "rdtsc":"=a" (l),"=d" (h)); asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (l), "=d" (h) :"g" (sl), "g" (sh), "0" (l), "1" (h)); if (sms != 0) { t = h * ((unsigned)0xffffffff / v->clks_msec); t += (l / v->clks_msec); } else { t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000; t += (l / v->clks_msec) / 1000; } /* Is the time up? */ if (t >= n) { break; } /* Only display elapsed time if flag is set */ if (flag == 0) { continue; } if (t != ip) { do_tick(me); BAILR ip = t; } } } /* Beep function */ void beep(unsigned int frequency) { unsigned int count = 1193180 / frequency; // Switch on the speaker outb_p(inb_p(0x61)|3, 0x61); // Set command for counter 2, 2 byte write outb_p(0xB6, 0x43); // Select desired Hz outb_p(count & 0xff, 0x42); outb((count >> 8) & 0xff, 0x42); // Block for 100 microseconds sleep(100, 0, 0, 1); // Switch off the speaker outb(inb_p(0x61)&0xFC, 0x61); } memtest86+-5.01/screen_buffer.h0000644000000000000000000000115712201317426015027 0ustar rootroot/* --*- C -*-- * * By Jani Averbach, Jaa@iki.fi, 2001 * * Released under version 2 of the Gnu Public License. * */ #ifndef SCREEN_BUFFER_H_1D10F83B_INCLUDED #define SCREEN_BUFFER_H_1D10F83B_INCLUDED #include "config.h" char get_scrn_buf(const int y, const int x); void set_scrn_buf(const int y, const int x, const char val); void clear_screen_buf(void); void tty_print_region(const int pi_top,const int pi_left, const int pi_bottom,const int pi_right); void tty_print_line(int y, int x, const char *text); void tty_print_screen(void); void print_error(char *pstr); #endif /* SCREEN_BUFFER_H_1D10F83B_INCLUDED */ memtest86+-5.01/controller.h0000644000000000000000000000073012201317426014376 0ustar rootroot#ifndef MEMTEST_CONTROLLER_H #define MEMTEST_CONTROLLER_H struct pci_memory_controller { unsigned vendor; unsigned device; char *name; char *ram_type; int tested; void (*poll_fsb)(void); void (*poll_timings)(void); void (*setup_ecc)(void); void (*poll_errors)(void); }; void find_controller(void); void poll_errors(void); void set_ecc_polling(int val); void coretemp(void); extern struct pci_memory_controller controllers[]; #endif /* MEMTEST_CONTROLLER_H */ memtest86+-5.01/build-number.txt0000644000000000000000000000000212201317426015160 0ustar rootroot7 memtest86+-5.01/spd.c0000644000000000000000000003462112201317426013002 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #include "test.h" #include "io.h" #include "pci.h" #include "msr.h" #include "spd.h" #include "screen_buffer.h" #include "jedec_id.h" #define NULL 0 #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_raw[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; } static void piix4_get_smb(void) { unsigned long x; int result; result = pci_conf_read(0, smbdev, smbfun, 0x08, 1, &x); if(x < 0x40){ // SB600/700 result = pci_conf_read(0, smbdev, smbfun, 0x90, 2, &x); if (result == 0) smbusbase = (unsigned short) x & 0xFFFE; } else { // SB800 sb800_get_smb(); } } void sb800_get_smb(void) { int lbyte, hbyte; __outb(AMD_SMBUS_BASE_REG + 1, AMD_INDEX_IO_PORT); lbyte = __inb(AMD_DATA_IO_PORT); __outb(AMD_SMBUS_BASE_REG, AMD_INDEX_IO_PORT); hbyte = __inb(AMD_DATA_IO_PORT); smbusbase = lbyte; smbusbase <<= 8; smbusbase += hbyte; smbusbase &= 0xFFE0; if (smbusbase == 0xFFE0) { smbusbase = 0; } } 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_raw[0] = ich5_smb_read_byte(0x50 + dimmadr, 0); if (spd_raw[0] == 0xff) return -1; // no spd here for (x = 1; x < 256; x++) { spd_raw[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_raw[0] = us15w_smb_read_byte(0x50 + dimmadr, 0); if (spd_raw[0] == 0xff) return -1; // no spd here for (x = 1; x < 256; x++) { spd_raw[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[] = { // Intel SMBUS {0x8086, 0x9C22, "Intel HSW-ULT", ich5_get_smb, ich5_read_spd}, {0x8086, 0x8C22, "Intel HSW", ich5_get_smb, ich5_read_spd}, {0x8086, 0x1E22, "Intel Z77", ich5_get_smb, ich5_read_spd}, {0x8086, 0x1C22, "Intel P67", ich5_get_smb, ich5_read_spd}, {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}, // AMD SMBUS {0x1002, 0x4385, "AMD SB600/700", piix4_get_smb, ich5_read_spd}, {0x1022, 0x780B, "AMD SB800/900", sb800_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 get_spd_spec(void) { int index; int h, i, j, z; int k = 0; int module_size; int curcol; int temp_nbd; int tck; index = find_smb_controller(); if (index == -1) { // Unknown SMBUS Controller, exit return; } smbcontrollers[index].get_adr(); cprint(LINE_SPD-2, 0, "Memory SPD Informations"); cprint(LINE_SPD-1, 0, "--------------------------"); for (j = 0; j < 8; j++) { if (smbcontrollers[index].read_spd(j) == 0) { curcol = 1; if(spd_raw[2] == 0x0b){ // We are here if DDR3 present // First print slot#, module capacity cprint(LINE_SPD+k, curcol, " - Slot :"); dprint(LINE_SPD+k, curcol+8, k, 1, 0); module_size = get_ddr3_module_size(spd_raw[4] & 0xF, spd_raw[8] & 0x7, spd_raw[7] & 0x7, spd_raw[7] >> 3); temp_nbd = getnum(module_size); curcol += 12; dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd; cprint(LINE_SPD+k, curcol, " MB"); curcol += 4; // If XMP is supported, check Tck in XMP reg if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A && spd_raw[12]) { tck = spd_raw[186]; } else { tck = spd_raw[12]; } // Then module jedec speed switch(tck) { default: cprint(LINE_SPD+k, curcol, "DDR3-????"); break; case 20: cprint(LINE_SPD+k, curcol, "DDR3-800"); curcol--; break; case 15: cprint(LINE_SPD+k, curcol, "DDR3-1066"); break; case 12: cprint(LINE_SPD+k, curcol, "DDR3-1333"); break; case 10: cprint(LINE_SPD+k, curcol, "DDR3-1600"); break; case 9: cprint(LINE_SPD+k, curcol, "DDR3-1866"); break; case 8: cprint(LINE_SPD+k, curcol, "DDR3-2133"); break; case 7: cprint(LINE_SPD+k, curcol, "DDR3-2400"); break; case 6: cprint(LINE_SPD+k, curcol, "DDR3-2533"); break; case 5: cprint(LINE_SPD+k, curcol, "DDR3-2666"); break; } curcol += 10; if((spd_raw[8] >> 3) == 1) { cprint(LINE_SPD+k, curcol, "ECC"); curcol += 4; } // Then print module infos (manufacturer & part number) spd_raw[117] &= 0x0F; // Parity odd or even for (i = 0; jep106[i].cont_code < 9; i++) { if (spd_raw[117] == jep106[i].cont_code && spd_raw[118] == jep106[i].hex_byte) { // We are here if a Jedec manufacturer is detected cprint(LINE_SPD+k, curcol, "-"); curcol += 2; cprint(LINE_SPD+k, curcol, jep106[i].name); for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } curcol++; // Display module serial number for (h = 128; h < 146; h++) { cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h])); curcol++; } // Detect Week and Year of Manufacturing (Think to upgrade after 2015 !!!) if(curcol <= 72 && spd_raw[120] > 3 && spd_raw[120] < 16 && spd_raw[121] < 55) { cprint(LINE_SPD+k, curcol, "(W"); dprint(LINE_SPD+k, curcol+2, spd_raw[121], 2, 0); if(spd_raw[121] < 10) { cprint(LINE_SPD+k, curcol+2, "0"); } cprint(LINE_SPD+k, curcol+4, "'"); dprint(LINE_SPD+k, curcol+5, spd_raw[120], 2, 0); if(spd_raw[120] < 10) { cprint(LINE_SPD+k, curcol+5, "0"); } cprint(LINE_SPD+k, curcol+7, ")"); curcol += 9; } // Detect XMP Memory if(spd_raw[176] == 0x0C && spd_raw[177] == 0x4A) { cprint(LINE_SPD+k, curcol, "*XMP*"); } } } } // We enter this function if DDR2 is detected if(spd_raw[2] == 0x08){ // First print slot#, module capacity cprint(LINE_SPD+k, curcol, " - Slot :"); dprint(LINE_SPD+k, curcol+8, k, 1, 0); module_size = get_ddr2_module_size(spd_raw[31], spd_raw[5]); temp_nbd = getnum(module_size); curcol += 12; dprint(LINE_SPD+k, curcol, module_size, temp_nbd, 0); curcol += temp_nbd; cprint(LINE_SPD+k, curcol, " MB"); curcol += 4; // Then module jedec speed float ddr2_speed, byte1, byte2; byte1 = (spd_raw[9] >> 4) * 10; byte2 = spd_raw[9] & 0xF; ddr2_speed = 1 / (byte1 + byte2) * 10000 * 2; temp_nbd = getnum(ddr2_speed); cprint(LINE_SPD+k, curcol, "DDR2-"); curcol += 5; dprint(LINE_SPD+k, curcol, ddr2_speed, temp_nbd, 0); curcol += temp_nbd; if((spd_raw[11] >> 1) == 1) { cprint(LINE_SPD+k, curcol+1, "ECC"); curcol += 4; } // Then print module infos (manufacturer & part number) int ccode = 0; for(i = 64; i < 72; i++) { if(spd_raw[i] == 0x7F) { ccode++; } } curcol++; for (i = 0; jep106[i].cont_code < 9; i++) { if (ccode == jep106[i].cont_code && spd_raw[64+ccode] == jep106[i].hex_byte) { // We are here if a Jedec manufacturer is detected cprint(LINE_SPD+k, curcol, "-"); curcol += 2; cprint(LINE_SPD+k, curcol, jep106[i].name); for(z = 0; jep106[i].name[z] != '\0'; z++) { curcol++; } curcol++; // Display module serial number for (h = 73; h < 91; h++) { cprint(LINE_SPD+k, curcol, convert_hex_to_char(spd_raw[h])); curcol++; } } } } k++; } } } 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_raw[i], 2); } flag = 0; while(!flag) { if (get_key()) flag++; } wait_keyup(); } } pop2down(); } int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks) { int module_size; switch(sdram_capacity) { case 0: module_size = 256; break; case 1: module_size = 512; break; default: case 2: module_size = 1024; break; case 3: module_size = 2048; break; case 4: module_size = 4096; break; case 5: module_size = 8192; break; case 6: module_size = 16384; break; } module_size /= 8; switch(prim_bus_width) { case 0: module_size *= 8; break; case 1: module_size *= 16; break; case 2: module_size *= 32; break; case 3: module_size *= 64; break; } switch(sdram_width) { case 0: module_size /= 4; break; case 1: module_size /= 8; break; case 2: module_size /= 16; break; case 3: module_size /= 32; break; } module_size *= (ranks + 1); return module_size; } int get_ddr2_module_size(int rank_density_byte, int rank_num_byte) { int module_size; switch(rank_density_byte) { case 1: module_size = 1024; break; case 2: module_size = 2048; break; case 4: module_size = 4096; break; case 8: module_size = 8192; break; case 16: module_size = 16384; break; case 32: module_size = 128; break; case 64: module_size = 256; break; default: case 128: module_size = 512; break; } module_size *= (rank_num_byte & 7) + 1; return module_size; } struct ascii_map { unsigned hex_code; char *name; }; char* convert_hex_to_char(unsigned hex_org) { static char buf[2] = " "; if (hex_org >= 0x20 && hex_org < 0x80) { buf[0] = hex_org; } else { //buf[0] = '\0'; buf[0] = ' '; } return buf; }memtest86+-5.01/README.background0000644000000000000000000002117312201317426015044 0ustar rootroot 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 Sub: Memtest86-SMP memtest86+-5.01/dmi.c0000644000000000000000000002300212201317426012754 0ustar rootroot/* 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+ V4.00 - Added compliance with SMBIOS Spec V2.6.1 */ #include "test.h" #include #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 system_map { struct tstruct_header header; uint8_t manufacturer; uint8_t productname; uint8_t version; uint8_t serialnumber; uint8_t uuidbytes[16]; uint8_t wut; } __attribute__((packed)); struct cpu_map { struct tstruct_header header; uint8_t cpu_socket; uint8_t cpu_type; uint8_t cpu_family; uint8_t cpu_manufacturer; uint32_t cpu_id; uint8_t cpu_version; uint8_t cpu_voltage; uint16_t ext_clock; uint16_t max_speed; uint16_t cur_speed; uint8_t cpu_status; uint8_t cpu_upgrade; uint16_t l1_handle; uint16_t l2_handle; uint16_t l3_handle; uint8_t cpu_serial; uint8_t cpu_asset_tag; uint8_t cpu_part_number; uint8_t core_count; uint8_t core_enabled; uint8_t thread_count; uint16_t cpu_specs; uint16_t cpu_family_2; } __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", "????", "DRAM", "EDRAM", "VRAM", "SRAM", "RAM", "ROM", "FLASH", "EEPROM", "FEPROM", "EPROM", "CDRAM", "3DRAM", "SDRAM", "SGRAM", "RDRAM", "DDR", "DDR2", "DDR2 FB", "RSVD", "RSVD","RSVD","DDR3","FBD2" }; struct mem_dev * mem_devs[MAX_DMI_MEMDEVS]; int mem_devs_count=0; struct md_map * md_maps[MAX_DMI_MEMDEVS]; struct system_map * dmi_system_info; struct cpu_map * dmi_cpu_info; int md_maps_count=0; int dmi_err_cnts[MAX_DMI_MEMDEVS]; short dmi_initialized=0; 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 open_dmi(void){ char *dmi, *dmi_search_start, *dmi_start; int found=0; struct dmi_eps *eps; char *table_start; int tstruct_count=0; dmi_search_start = (char *)DMI_SEARCH_START; //find anchor 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; // Need fix (SMBIOS/DDR3) if (header->type == 20 || header->type == 1) md_maps[md_maps_count++] = (struct md_map *)dmi; // MB_SPEC if (header->type == 2) { dmi_system_info = (struct system_map *)dmi; } // CPU_SPEC if (header->type == 4) { dmi_cpu_info = (struct cpu_map *)dmi; } dmi+=header->length; while( ! (*dmi == 0 && *(dmi+1) == 0 ) ) dmi++; dmi+=2; if (++tstruct_count > eps->numstructs) return -1; } return 0; } void init_dmi(void){ int i; for(i=0; i < MAX_DMI_MEMDEVS; i++) dmi_err_cnts[i]=0; open_dmi(); dmi_initialized=1; } void print_dmi_startup_info(void) { char *string1; char *string2; char *string3; int dmicol = 78; int slenght; int sl1, sl2, sl3; if(!dmi_initialized) { init_dmi(); } string1 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->manufacturer); sl1 = strlen(string1); string2 = get_tstruct_string(&dmi_system_info->header,dmi_system_info->productname); sl2 = strlen(string2); string3 = get_tstruct_string(&dmi_cpu_info->header,dmi_cpu_info->cpu_socket); sl3 = strlen(string3); slenght = sl1 + sl2; if(sl3 > 2) { slenght += sl3 + 4; } else { slenght++; } if(sl1 && sl2) { //dmicol -= slenght; // right align dmicol = 39 - slenght/2; // center align cprint(LINE_DMI, dmicol, string1); dmicol += sl1 + 1; cprint(LINE_DMI, dmicol, string2); dmicol += sl2 + 1; if(sl3 > 2){ cprint(LINE_DMI, dmicol, "("); dmicol++; cprint(LINE_DMI, dmicol, string3); dmicol += sl3; cprint(LINE_DMI, dmicol, ")"); } } } void print_dmi_info(void){ int i,j,page; char * string=0; if(!dmi_initialized) init_dmi(); 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"); cprint(POP2_Y+4, POP2_X+4, "--------------------------------------------------------------"); for(i=8*(page-1); iheader), 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+44, form_factors[mem_devs[i]->form]); //print mappings int mapped=0,of=0; cprint(yof+1, POP2_X+6,"mapped to: "); for(j=0; jheader.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>>22, 4); of += 4; hprint3(yof+1, POP2_X+17+of, md_maps[j]->start<<10, 8); of += 8; cprint(yof+1, POP2_X+17+of, "-"); of++; hprint3(yof+1, POP2_X+17+of, md_maps[j]->end>>22, 4); of += 4; hprint3(yof+1, POP2_X+17+of, ((md_maps[j]->end+1)<<10) - 1, 8); of += 8; if(md_maps[j]->end == 0) { hprint3(yof+1, POP2_X+17+of-8,0,8); } } if (!mapped) { cprint(yof+1, POP2_X+17, "No mapping (Interleaved Device)"); } } wait_keyup(); while (get_key() == 0); } } //return 1 if the list of bad memory devices changes, 0 otherwise, -1 if no mapped int add_dmi_err(ulong adr){ int i,j,found=-1; if(!dmi_initialized) init_dmi(); 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) continue; if (dmi_err_cnts[j]){ found=0; }else{ found = dmi_err_cnts[j] = 1; } } } return found; } void print_dmi_err(void){ int i,count,of; char *string; scroll(); cprint(v->msg_line, 0,"Bad Memory Devices: "); of=20; for ( i=count=0; i < MAX_DMI_MEMDEVS; i++){ if (!dmi_err_cnts[i]) continue; struct mem_dev *md = mem_devs[i]; if(count++){ cprint(v->msg_line, of, ", "); of+=2; } string=get_tstruct_string((struct tstruct_header *)md,md->dev_locator); if (strlen(string) + of > 80){ scroll(); of=7; } cprint(v->msg_line, of, string); of += strlen(string); } } memtest86+-5.01/mt86+_loader.asm0000644000000000000000000001440612201432014014737 0ustar rootroot; A loader for www.memtest.org images, by Eric Auer 2003. ; This assumes that the image starts with the boot sector, ; which has the size of setup.S in sectors in a byte at offset ; 1f1h (497). Further, I assume setup.S directly after the boot ; sector and the actual memtest head.S after setup.S ... ; This version is derived from memtestL loader, which loads ; memtest.bin from a separate file. This version is meant to ; be used like (DOS / Unix variants): ; copy /b memteste.bin + memtest.bin memtest.exe ; cat memteste.bin memtest.bin > memtest.exe ; The good thing is that you get a single file which can be ; compressed, for example with http://upx.sf.net/ (UPX). %define fullsize (150024 + buffer - exeh) ; 150024 is the size of memtest86+ V5.01, adjust as needed! %define stacksize 2048 %define stackpara ((stacksize + 15) / 16) ; the trick is that NASM believes the header would be part ; of the loaded image, so we "org 20h bytes too early" to fix: org 0e0h ; NASM thinks after header we have 100h ; which is what we want it to think. exeh: db "MZ" dw fullsize % 512 ; how much to load from dw (fullsize + 511) / 512 ; .exe to RAM dw 0 ; no relocations used dw 2 ; header size is 2 * 16 bytes dw stackpara ; minimum heap is 128 * 16 bytes, for stack dw stackpara ; we do not need more heap either dw (fullsize + 15) / 16 ; SS is after file ; segment offsets are relative to PSPseg+10h ; initial DS and ES point to PSPseg, and file ; except headers is loaded to PSPseg+10h. dw stacksize-4 ; initial SP value dw 0 ; no checksum dw 100h ; initial IP dw -10h ; initial CS relative to PSPseg+10h dw 0 ; no relocation table, "offset 0 in file" dw 0 ; this is not an overlay db "MEMT" ; padding to a multiple of 16 bytes ; loaded part begins here (set CS so that IP is 100h here) start: ; entry point ; if you use obj + linker, use "..start:" mov ah, 01h mov bh, 00h mov cx, 2000h int 10h mov ax,cs ; *** mov ds,ax ; *** mov es,ax ; *** ; test if we have 386 or better: pushf ; save flags xor ax,ax push ax popf ; try to clear all bits pushf pop ax and ax,0f000h cmp ax,0f000h jz noinst1 ; 4 msb stuck to 1: 808x or 80186 mov ax,0f000h push ax popf ; try to set 4 msb pushf pop ax test ax,0f000h jz noinst1 ; 4 msb stuck to 0: 80286 popf ; restore flags jmp short found386 noinst1: popf ; restore flags mov dx,need386 jmp generror found386: ; now test if the system is in real mode: smsw ax ; MSW is the low half of CR0 ; (smsw is not priv'd, unlike mov eax,cr0) test al,1 ; if the PE (protected mode) flag on? %ifndef DEBUG ; ignore findings in debug mode jnz foundprotected %endif jmp foundreal foundprotected: mov dx,noreal jmp generror ; ------------ need386 db "Sorry, you need at least a 386 CPU to use Memtest86+." db 13,10,"$" noreal db "You cannot run Memtest86+ if the system already is in" db " protected mode.",13,10,"$" ; ------------ generror: ; generic error exit push cs pop ds push cs pop es mov ah,9 int 21h mov ax,4c01h int 21h ; ------------ foundreal: mov cx,buffer+15 shr cx,4 ; buffer offset in paragraphs mov ax,cs add ax,cx ; buffer offset in paragraphs ; now AX is the buffer segment mov [cs:bufsetup+2],ax ; far pointer to boot sector now mov cx,20h ; size of boot sector in paragraphs add [cs:bufsetup+2],cx ; far pointer to setup now movzx eax,ax shl eax,4 ; linear buffer offset mov [cs:buflinear],eax findpoint: ; now patch the loader! mov al,[buffer+1f1h] ; size of setup.S in sectors ; should be 4 ... inc al ; the boot sector itself movzx eax,al shl eax,9 ; log 2 of sector size add [cs:buflinear],eax ; linear address of head.S now mov ax,[buffer+251h] ; should be jmp far dword (ofs, seg) cmp ax,0ea66h jz foundpatch patchbug: ; could not patch the jump mov dx,nopatch jmp generror gdtbug: mov dx,nogdt jmp generror foundpatch: mov eax,[cs:buflinear] mov [buffer+253h],eax ; patch the protected mode entry jump ; (offset only - segment selector unchanged: flat linear CS) findgdt: mov eax,[cs:buffer+20ch] ; should be lgdt offset and eax,00ffffffh cmp eax,0016010fh ; lgdt ... jnz gdtbug mov ax,[cs:buffer+20fh] ; GDTR contents pointer mov bx,ax mov eax,[cs:buffer+200h+bx+2] ; GDT linear offset and eax,1ffh ; assume GDT in first sector of setup.S ; *** WARNING: this is needed because setup.S contains ; *** HARDCODED offset of setup.S on linear 90200h, which ; *** is 90000h + bootsect.S ... flaw in Memtest86! mov cx,[cs:bufsetup+2] ; setup.S segment movzx ecx,cx shl ecx,4 ; linear setup.S address add eax,ecx ; fixed GDT linear offset mov [cs:buffer+200h+bx+2],eax ; patch it ;mov dx,trying ;mov ah,9 ;int 21h ;xor ax,ax ;int 16h ; wait for a keypress from the user mov ax,[cs:bufsetup+2] ; setup segment mov ds,ax ; set nice data segments for setup.S ... mov es,ax xor ax,ax mov fs,ax mov gs,ax cli lss sp,[cs:newstack] ; stack in first 64k now! movzx esp,sp ; ensure 16bit stack pointer ; Memtest86 head.S assumes that it can just turn SS to ; linear. This would put the stack at 0:200h or so for us ; if we fail to move the stack around ... %ifdef DEBUG mov ebp,[cs:buflinear] ; will show up in debugging logs mov esi,[cs:bufsetup] ; will show up in debugging logs %endif jmp far [cs:bufsetup] ; setup.S will enable the A20 (ignoring HIMEM, just using ; the classic 8042 programming trick) and turn on protected ; mode. Then it will jump to head.S, which luckily can run ; from any offset inside the linear 4 GB CS ... ; ------------ buflinear dd 0 ; linear address of head.S entry point bufsetup dw 0,0 ; far pointer to setup.S entry point newstack dw 03fch,0 ; beware, stack will overwrite IDT. ; ------------ nopatch db "jmp far dword not found at setup.S offset 37h,",13,10 db "(file offset 237h is not 66h, 0eah)",13,10 db "please adjust and recompile memtestl...",13,10,"$" nogdt db "lgdt [...] not found at setup.S offset 0ch,",13,10 db "(file offset 20ch is not 0fh, 01h, 16h)",13,10 db "please adjust and recompile memtestl...",13,10,"$" trying db "Now trying to start Memtest86...",13,10 db "You have to reboot to leave Memtest86 again.",13,10 db "Press a key to go on.",13,10,"$" ; ------------ align 16 buffer: ; a label pointing to where in the file memtest.bin will be. memtest86+-5.01/main.c0000644000000000000000000007524312201317426013145 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * ------------------------------------------------ * 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 "cpuid.h" #include "smp.h" #include "config.h" #undef TEST_TIMES #define DEFTESTS 9 #define FIRST_DIVISER 3 /* The main stack is allocated during boot time. The stack size should * preferably be a multiple of page size(4Kbytes) */ extern struct cpu_ident cpu_id; extern char toupper(char c); extern int isxdigit(char c); extern void reboot(); extern void bzero(); extern void smp_set_ordinal(int me, int ord); extern int smp_my_ord_num(int me); extern int smp_ord_to_cpu(int me); extern void get_cpuid(); extern void initialise_cpus(); 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); extern struct barrier_s *barr; extern int num_cpus; extern int act_cpus; 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 cpu); int do_test(int ord); struct tseq tseq[] = { {1, -1, 0, 6, 0, "[Address test, walking ones, no cache] "}, {1, -1, 1, 6, 0, "[Address test, own address Sequential] "}, {1, 32, 2, 6, 0, "[Address test, own address Parallel] "}, {1, 32, 3, 6, 0, "[Moving inversions, 1s & 0s Parallel] "}, {1, 32, 5, 3, 0, "[Moving inversions, 8 bit pattern] "}, {1, 32, 6, 30, 0, "[Moving inversions, random pattern] "}, {1, 32, 7, 81, 0, "[Block move] "}, {1, 1, 8, 3, 0, "[Moving inversions, 32 bit pattern] "}, {1, 32, 9, 48, 0, "[Random number sequence] "}, {1, 32, 10, 6, 0, "[Modulo 20, Random pattern] "}, {1, 1, 11, 240, 0, "[Bit fade test, 2 patterns] "}, {1, 0, 0, 0, 0, NULL} }; volatile int mstr_cpu; volatile int run_cpus; volatile int cpu_ord=0; int maxcpus=MAX_CPUS; volatile short cpu_sel; volatile short cpu_mode; char cpu_mask[MAX_CPUS]; long bin_mask=0xffffffff; short onepass; volatile short btflag = 0; volatile int test; short restart_flag; bool reloc_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 int bail; int nticks; int test_ticks; volatile int segs; static int ltest; static int pass_flag = 0; volatile short start_seq = 0; static int c_iter; ulong high_test_adr; 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 */ /* Find the next selected test to run */ void next_test() { test++; while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) { test++; } if (tseq[test].cpu_sel == 0) { /* We hit the end of the list so we completed a pass */ pass_flag++; /* Find the next test to run, start searching from 0 */ test = 0; while (tseq[test].sel == 0 && tseq[test].cpu_sel != 0) { test++; } } } /* Set default values for all parameters */ void set_defaults() { int i; if (start_seq == 2) { /* This is a restart so we reset everything */ onepass = 0; i = 0; while (tseq[i].cpu_sel) { tseq[i].sel = 1; i++; } test = 0; if (tseq[0].sel == 0) { next_test(); } } ltest = -1; win_next = 0; window = 0; bail = 0; cpu_mode = CPM_ALL; cpu_sel = 0; v->printmode=PRINTMODE_ADDRESSES; v->numpatn=0; v->plim_lower = 0; v->plim_upper = v->pmap[v->msegs-1].end; v->pass = 0; v->msg_line = 0; v->ecount = 0; v->ecc_ecount = 0; v->msg_line = LINE_SCROLL-1; v->scroll_start = v->msg_line * 160; v->erri.low_addr.page = 0x7fffffff; v->erri.low_addr.offset = 0xfff; v->erri.high_addr.page = 0; v->erri.high_addr.offset = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.maxl = 0; v->erri.cor_err = 0; v->erri.ebits = 0; v->erri.hdr_flag = 0; v->erri.tbits = 0; for (i=0; tseq[i].msg != NULL; i++) { tseq[i].errors = 0; } restart_flag = 0; tseq[10].sel = 0; } /* Boot trace function */ short tidx = 25; void btrace(int me, int line, char *msg, int wait, long v1, long v2) { int y, x; /* Is tracing turned on? */ if (btflag == 0) return; spin_lock(&barr->mutex); y = tidx%13; x = tidx/13*40; cplace(y+11, x+1, ' '); if (++tidx > 25) { tidx = 0; } y = tidx%13; x = tidx/13*40; cplace(y+11, x+1, '>'); dprint(y+11, x+2, me, 2, 0); dprint(y+11, x+5, line, 4, 0); cprint(y+11, x+10, msg); hprint(y+11, x+22, v1); hprint(y+11, x+31, v2); if (wait) { wait_keyup(); } spin_unlock(&barr->mutex); } /* 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); /* CPU 0, Copy memtest86+ code */ if (cpu == 0) { memmove((void *)addr, &_start, _end - _start); } /* Wait for the copy */ barrier(); /* 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); /* Jump to the start address */ goto *ja; } /* 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" ); } void reloc_internal(int cpu) { /* clear variables */ reloc_pending = FALSE; run_at(LOW_TEST_ADR, cpu); } void reloc(void) { bail++; reloc_pending = TRUE; } /* 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 parse_command_line(void) { long simple_strtoul(char *cmd, char *ptr, int base); char *cp, dummy; int i, j, k; if (cmdline_parsed) return; /* Fill in the cpu mask array with the default */ for (i=0; ipmap[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 { /* APs only, Register the APs */ btrace(my_cpu_num, __LINE__, "AP_Start ", 0, my_cpu_num, cpu_ord); smp_ap_booted(my_cpu_num); /* Asign a sequential CPU ordinal to each active cpu */ spin_lock(&barr->mutex); my_cpu_ord = cpu_ord++; smp_set_ordinal(my_cpu_num, my_cpu_ord); spin_unlock(&barr->mutex); btrace(my_cpu_num, __LINE__, "AP_Done ", 0, my_cpu_num, my_cpu_ord); } } else { /* Unlock after a relocation */ spin_unlock(&barr->mutex); /* Get the CPU ordinal since it is lost during relocation */ my_cpu_ord = smp_my_ord_num(my_cpu_num); btrace(my_cpu_num, __LINE__, "Reloc_Done",0,my_cpu_num,my_cpu_ord); } /* A barrier to insure that all of the CPUs are done with startup */ barrier(); btrace(my_cpu_num, __LINE__, "1st Barr ", 1, my_cpu_num, my_cpu_ord); /* Setup Memory Management and measure memory speed, we do it here * because we need all of the available CPUs */ if (start_seq < 2) { /* Enable floating point processing */ if (cpu_id.fid.bits.fpu) __asm__ __volatile__ ( "movl %%cr0, %%eax\n\t" "andl $0x7, %%eax\n\t" "movl %%eax, %%cr0\n\t" : : : "ax" ); if (cpu_id.fid.bits.sse) __asm__ __volatile__ ( "movl %%cr4, %%eax\n\t" "orl $0x00000200, %%eax\n\t" "movl %%eax, %%cr4\n\t" : : : "ax" ); btrace(my_cpu_num, __LINE__, "Mem Mgmnt ", 1, cpu_id.fid.bits.pae, cpu_id.fid.bits.lm); /* Setup memory management modes */ /* If we have PAE, turn it on */ if (cpu_id.fid.bits.pae == 1) { __asm__ __volatile__( "movl %%cr4, %%eax\n\t" "orl $0x00000020, %%eax\n\t" "movl %%eax, %%cr4\n\t" : : : "ax" ); cprint(LINE_TITLE+1, COL_MODE, "(PAE Mode)"); } /* If this is a 64 CPU enable long mode */ if (cpu_id.fid.bits.lm == 1) { __asm__ __volatile__( "movl $0xc0000080, %%ecx\n\t" "rdmsr\n\t" "orl $0x00000100, %%eax\n\t" "wrmsr\n\t" : : : "ax", "cx" ); cprint(LINE_TITLE+1, COL_MODE, "(X64 Mode)"); } /* Get the memory Speed with all CPUs */ get_mem_speed(my_cpu_num, num_cpus); } /* 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. */ btrace(my_cpu_num, __LINE__, "Start Done", 1, 0, 0); start_seq = 2; /* Loop through all tests */ while (1) { /* If the restart flag is set all initial params */ if (restart_flag) { set_defaults(); continue; } /* Skip single CPU tests if we are using only one CPU */ if (tseq[test].cpu_sel == -1 && (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 + WIN_SZ)) { /* Main scheduling barrier */ cprint(8, my_cpu_num+7, "W"); btrace(my_cpu_num, __LINE__, "Sched_Barr", 1,window,win_next); barrier(); /* Don't go over the 8TB PAE limit */ if (win_next > MAX_MEM) { break; } /* For the bit fade test, #11, we cannot relocate so bump the * window to 1 */ if (tseq[test].pat == 11 && window == 0) { window = 1; } /* Relocate if required */ if (window != 0 && (ulong)&_start != LOW_TEST_ADR) { btrace(my_cpu_num, __LINE__, "Sched_RelL", 1,0,0); run_at(LOW_TEST_ADR, my_cpu_num); } if (window == 0 && v->plim_lower >= win0_start) { window++; } if (window == 0 && (ulong)&_start == LOW_TEST_ADR) { btrace(my_cpu_num, __LINE__, "Sched_RelH", 1,0,0); run_at(high_test_adr, my_cpu_num); } /* Decide which CPU(s) to use */ btrace(my_cpu_num, __LINE__, "Sched_CPU0",1,cpu_sel, tseq[test].cpu_sel); run = 1; switch(cpu_mode) { case CPM_RROBIN: case CPM_SEQ: /* Select a single CPU */ if (my_cpu_ord == 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_ord == 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_ord >= tseq[test].cpu_sel) { run = 0; } /* Set the master CPU to the highest CPU number * that has been selected */ if (act_cpus < tseq[test].cpu_sel) { mstr_cpu = act_cpus-1; run_cpus = act_cpus; } else { mstr_cpu = tseq[test].cpu_sel-1; run_cpus = tseq[test].cpu_sel; } } } btrace(my_cpu_num, __LINE__, "Sched_CPU1",1,run_cpus,run); barrier(); dprint(9, 7, run_cpus, 2, 0); /* Setup a sub barrier for only the selected CPUs */ if (my_cpu_ord == 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, my_cpu_num+7, "-"); btrace(my_cpu_num, __LINE__, "Sched_Win0",1,window,win_next); /* Do we need to exit */ if(reloc_pending) { reloc_internal(my_cpu_num); } if (my_cpu_ord == mstr_cpu) { switch (window) { /* Special case for relocation */ case 0: winx.start = 0; winx.end = win1_end; window++; break; /* Special case for first segment */ case 1: winx.start = win0_start; winx.end = WIN_SZ; win_next += WIN_SZ; window++; break; /* For all other windows */ default: winx.start = win_next; win_next += WIN_SZ; winx.end = win_next; } btrace(my_cpu_num,__LINE__,"Sched_Win1",1,winx.start, winx.end); /* Find the memory areas to test */ segs = compute_segments(winx, my_cpu_num); } s_barrier(); btrace(my_cpu_num,__LINE__,"Sched_Win2",1,segs, v->map[0].pbase_addr); 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) { /* Either there is no PAE or we are at the PAE limit */ break; } btrace(my_cpu_num, __LINE__, "Strt_Test ",1,my_cpu_num, my_cpu_ord); do_test(my_cpu_ord); btrace(my_cpu_num, __LINE__, "End_Test ",1,my_cpu_num, my_cpu_ord); paging_off(); } /* End of window loop */ s_barrier(); btrace(my_cpu_num, __LINE__, "End_Win ",1,test, window); /* 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_ord != 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 >= act_cpus) { cpu_sel = 0; } next_test(); break; case CPM_SEQ: if (++cpu_sel >= act_cpus) { cpu_sel = 0; next_test(); } break; case CPM_ALL: if (tseq[test].cpu_sel == -1) { /* Do the same test for each CPU */ if (++cpu_sel >= act_cpus) { cpu_sel = 0; next_test(); } else { continue; } } else { next_test(); } } //???? btrace(my_cpu_num, __LINE__, "Next_CPU ",1,cpu_sel,test); /* If this was the last test then we finished a pass */ if (pass_flag) { pass_flag = 0; v->pass++; dprint(LINE_INFO, 49, v->pass, 5, 0); find_ticks_for_pass(); ltest = -1; if (v->ecount == 0) { /* If onepass is enabled and we did not get any errors * reboot to exit the test */ if (onepass) { reboot(); } if (!btflag) cprint(LINE_MSG, COL_MSG-8, "** Pass complete, no errors, press Esc to exit **"); if(BEEP_END_NO_ERROR) { beep(1000); beep(2000); beep(1000); beep(2000); } } } bail=0; } /* End test loop */ } void test_setup() { static int ltest = -1; /* See if a specific test has been selected */ if (v->testsel >= 0) { test = v->testsel; } /* Only do the setup if this is a new test */ if (test == ltest) { return; } 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/FIRST_DIVISER; } else { c_iter = tseq[test].iter; } /* 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, tseq[test].pat, 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_ord) { int i=0, j=0; static int bitf_sleep; unsigned long p0=0, p1=0, p2=0; if (my_ord == 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); /* Good 'ol Legacy USB_WAR */ if (v->map[0].start < (ulong*)0x500) { v->map[0].start = (ulong*)0x500; } cprint(LINE_PAT, COL_MID+25, " R"); } else { cprint(LINE_PAT, COL_MID+25, " "); } /* 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); } switch(tseq[test].pat) { /* Do the testing according to the selected pattern */ case 0: /* Address test, walking ones (test #0) */ /* Run with cache turned off */ set_cache(0); addr_tst1(my_ord); set_cache(1); BAILOUT; break; case 1: case 2: /* Address test, own address (test #1, 2) */ addr_tst2(my_ord); BAILOUT; break; case 3: case 4: /* Moving inversions, all ones and zeros (tests #3, 4) */ p1 = 0; p2 = ~p1; s_barrier(); movinv1(c_iter,p1,p2,my_ord); BAILOUT; /* Switch patterns */ s_barrier(); movinv1(c_iter,p2,p1,my_ord); BAILOUT; break; 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; s_barrier(); movinv1(c_iter,p1,p2, my_ord); BAILOUT; /* Switch patterns */ s_barrier(); movinv1(c_iter,p2,p1, my_ord); BAILOUT } break; case 6: /* Random Data (test #6) */ /* Seed the random number generator */ if (my_ord == mstr_cpu) { if (cpu_id.fid.bits.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_ord == mstr_cpu) { sp1 = rand(0); sp2 = ~p1; } s_barrier(); movinv1(2,sp1,sp2, my_ord); BAILOUT; } break; case 7: /* Block move (test #7) */ block_move(c_iter, my_ord); BAILOUT; break; case 8: /* Moving inversions, 32 bit shifting pattern (test #8) */ for (i=0, p1=1; p1; p1=p1<<1, i++) { s_barrier(); movinv32(c_iter,p1, 1, 0x80000000, 0, i, my_ord); BAILOUT s_barrier(); movinv32(c_iter,~p1, 0xfffffffe, 0x7fffffff, 1, i, my_ord); BAILOUT } break; case 9: /* Random Data Sequence (test #9) */ for (i=0; i < c_iter; i++) { s_barrier(); movinvr(my_ord); BAILOUT; } break; case 10: /* Modulo 20 check, Random pattern (test #10) */ for (j=0; j>1) { p1 = p0 | (p0<<8) | (p0<<16) | (p0<<24); for (i=0; i 1) { twin.start = wnxt; wnxt += WIN_SZ; twin.end = wnxt; } /* Find the memory areas I am going to test */ sg = compute_segments(twin, -1); 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 /= act_cpus; break; case 7: case 8: len /= act_cpus; break; } } ch += (len + SPINSZ -1)/SPINSZ; } } return(ch); } /* Compute the total number of ticks per pass */ void find_ticks_for_pass(void) { int i; v->pptr = 0; v->pass_ticks = 0; v->total_ticks = 0; cprint(1, COL_MID+8, " "); i = 0; while (tseq[i].cpu_sel != 0) { /* Skip tests 2 and 4 if we are using 1 cpu */ if (act_cpus == 1 && (i == 2 || i == 4)) { i++; continue; } v->pass_ticks += find_ticks_for_test(i); i++; } } static int find_ticks_for_test(int tst) { int ticks=0, c, ch; if (tseq[tst].sel == 0) { return(0); } /* Determine the number of chunks for this test */ ch = find_chunks(tst); /* Set the number of iterations. We only do 1/2 of the iterations */ /* on the first pass */ if (v->pass == 0) { c = tseq[tst].iter/FIRST_DIVISER; } else { c = tseq[tst].iter; } 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/act_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; } if (cpu_mode == CPM_SEQ || tseq[tst].cpu_sel == -1) { ticks *= act_cpus; } if (tseq[tst].pat == 7 || tseq[tst].pat == 11) { return ticks; } return ticks*ch; } static int compute_segments(struct pmap win, int me) { unsigned long wstart, wend; int i, sg; /* Compute the window I am testing memory in */ 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) { wstart = v->plim_lower; } if (wend > v->plim_upper) { wend = v->plim_upper; } if (wstart >= wend) { return(0); } /* List the segments being tested */ for (i=0; i< v->msegs; i++) { unsigned long start, end; start = v->pmap[i].start; end = v->pmap[i].end; if (start <= wstart) { start = wstart; } if (end >= wend) { end = wend; } #if 0 cprint(LINE_SCROLL+(2*i), 0, " ("); hprint(LINE_SCROLL+(2*i), 2, start); cprint(LINE_SCROLL+(2*i), 10, ", "); hprint(LINE_SCROLL+(2*i), 12, end); cprint(LINE_SCROLL+(2*i), 20, ") "); cprint(LINE_SCROLL+(2*i), 22, "r("); hprint(LINE_SCROLL+(2*i), 24, wstart); cprint(LINE_SCROLL+(2*i), 32, ", "); hprint(LINE_SCROLL+(2*i), 34, wend); cprint(LINE_SCROLL+(2*i), 42, ") "); cprint(LINE_SCROLL+(2*i), 44, "p("); hprint(LINE_SCROLL+(2*i), 46, v->plim_lower); cprint(LINE_SCROLL+(2*i), 54, ", "); hprint(LINE_SCROLL+(2*i), 56, v->plim_upper); cprint(LINE_SCROLL+(2*i), 64, ") "); cprint(LINE_SCROLL+(2*i+1), 0, "w("); hprint(LINE_SCROLL+(2*i+1), 2, win.start); cprint(LINE_SCROLL+(2*i+1), 10, ", "); hprint(LINE_SCROLL+(2*i+1), 12, win.end); cprint(LINE_SCROLL+(2*i+1), 20, ") "); cprint(LINE_SCROLL+(2*i+1), 22, "m("); hprint(LINE_SCROLL+(2*i+1), 24, v->pmap[i].start); cprint(LINE_SCROLL+(2*i+1), 32, ", "); hprint(LINE_SCROLL+(2*i+1), 34, v->pmap[i].end); cprint(LINE_SCROLL+(2*i+1), 42, ") "); cprint(LINE_SCROLL+(2*i+1), 44, "i="); hprint(LINE_SCROLL+(2*i+1), 46, i); cprint(LINE_SCROLL+(2*i+2), 0, " " " "); cprint(LINE_SCROLL+(2*i+3), 0, " " " "); #endif if ((start < end) && (start < wend) && (end > wstart)) { 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, ", sg="); hprint(LINE_SCROLL+(2*i+1), 59, sg); #endif sg++; } } return (sg); } memtest86+-5.01/init.c0000644000000000000000000007002212201322323013142 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * ------------------------------------------------ * init.c - MemTest-86 Version 3.6 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "stdin.h" #include "stddef.h" #include "test.h" #include "defs.h" #include "config.h" #include "cpuid.h" #include "smp.h" #include "io.h" #include "spd.h" #include "pci.h" #include "controller.h" extern struct tseq tseq[]; extern short memsz_mode; extern int num_cpus; extern int act_cpus; extern int found_cpus; unsigned long imc_type = 0; extern int maxcpus; extern char cpu_mask[]; extern void initialise_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); static void cpu_type(void); static int cpuspeed(void); static void get_cache_size(); static void cpu_cache_speed(); void get_cpuid(); int beepmode; extern short dmi_initialized; extern int dmi_err_cnts[MAX_DMI_MEMDEVS]; /* Failsafe function */ /* msec: number of ms to wait - scs: scancode expected to stop */ /* bits: 0 = extended detection - 1: SMP - 2: Temp Check */ /* 3: MP SMP - 4-7: RSVD */ void failsafe(int msec, int scs) { int i; ulong sh, sl, l, h, t; unsigned char c; volatile char *pp; for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) { *pp = 0x1E; } for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<3; i++, pp+=2) { *pp = 0x9E; } for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(55*2)+1); i<3; i++, pp+=2) { *pp = 0x9E; } cprint(18, 18, "==> Press F1 to enter Fail-Safe Mode <=="); if(v->fail_safe & 2) { cprint(19, 15, "==> Press F2 to force Multi-Threading (SMP) <=="); } /* save the starting time */ asm __volatile__( "rdtsc":"=a" (sl),"=d" (sh)); /* loop for n seconds */ while (1) { asm __volatile__( "rdtsc":"=a" (l),"=d" (h)); asm __volatile__ ( "subl %2,%0\n\t" "sbbl %3,%1" :"=a" (l), "=d" (h) :"g" (sl), "g" (sh), "0" (l), "1" (h)); t = h * ((unsigned)0xffffffff / v->clks_msec); t += (l / v->clks_msec); /* Is the time up? */ if (t >= msec) { break; } /* Is expected Scan code pressed? */ c = get_key(); c &= 0x7f; /* F1 */ if(c == scs) { v->fail_safe |= 1; break; } /* F2 */ if(c == scs+1) { v->fail_safe ^= 2; break; } /* F3 */ if(c == scs+2) { if(v->fail_safe & 2) { v->fail_safe ^= 2; } v->fail_safe |= 8; break; } } cprint(18, 18, " "); cprint(19, 15, " "); for(i=0, pp=(char *)(SCREEN_ADR+(18*160)+(18*2)+1); i<40; i++, pp+=2) { *pp = 0x17; } } static void display_init(void) { int i; volatile char *pp; /* Set HW cursor out of screen boundaries */ __outb(0x0F, 0x03D4); __outb(0xFF, 0x03D5); __outb(0x0E, 0x03D4); __outb(0xFF, 0x03D5); serial_echo_init(); serial_echo_print("INE_SCROLL;24r"); /* Set scroll area row 7-23 */ serial_echo_print(""); /* Clear Screen */ serial_echo_print(""); serial_echo_print(""); serial_echo_print(""); /* Clear screen & set background to blue */ for(i=0, pp=(char *)(SCREEN_ADR); i<80*24; i++) { *pp++ = ' '; *pp++ = 0x17; } /* Make the name background green */ for(i=0, pp=(char *)(SCREEN_ADR+1); itest_pages); 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; v->erri.low_addr.page = 0x7fffffff; v->erri.low_addr.offset = 0xfff; v->erri.high_addr.page = 0; v->erri.high_addr.offset = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.min_bits = 32; v->erri.max_bits = 0; v->erri.maxl = 0; v->erri.cor_err = 0; v->erri.ebits = 0; v->erri.hdr_flag = 0; v->erri.tbits = 0; 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; } } } /* setup beep mode */ beepmode = BEEP_MODE; /* Get the cpu and cache information */ get_cpuid(); /* setup pci */ pci_init(); get_cache_size(); cpu_type(); cpu_cache_speed(); /* Check fail safe */ failsafe(5000, 0x3B); /* Initalize SMP */ initialise_cpus(); for (i = 0; i fail_safe & 3) == 2) { cprint(LINE_CPU,9, "(SMP: Disabled)"); cprint(LINE_RAM,9, "Running..."); } // dprint(10, 5, found_cpus, 2, 0); /* Find Memory Specs */ if(v->fail_safe & 1) { cprint(LINE_CPU, COL_SPEC, " **** FAIL SAFE **** FAIL SAFE **** "); cprint(LINE_RAM, COL_SPEC, " No detection, same reliability "); } else { find_controller(); get_spd_spec(); if(num_cpus <= 16 && !(v->fail_safe & 4)) { coretemp(); } } if(v->check_temp > 0 && !(v->fail_safe & 4)) { cprint(LINE_CPU, 26, "| CPU Temp"); cprint(LINE_CPU+1, 26, "| C"); } beep(600); beep(1000); /* 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 = 64; } if (l2_cache == 0) { l1_cache = 512; } v->printmode=PRINTMODE_ADDRESSES; v->numpatn=0; } /* Get cache sizes for most AMD and Intel CPUs, exceptions for old CPUs are * handled in CPU detection */ void get_cache_size() { int i, j, n, size; unsigned int v[4]; unsigned char *dp = (unsigned char *)v; struct cpuid4_eax *eax = (struct cpuid4_eax *)&v[0]; struct cpuid4_ebx *ebx = (struct cpuid4_ebx *)&v[1]; struct cpuid4_ecx *ecx = (struct cpuid4_ecx *)&v[2]; 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 */ l1_cache = 0; l2_cache = 0; l3_cache = 0; /* Use CPUID(4) if it is available */ if (cpu_id.max_cpuid > 3) { /* figure out how many cache leaves */ n = -1; do { ++n; /* Do cpuid(4) loop to find out num_cache_leaves */ cpuid_count(4, n, &v[0], &v[1], &v[2], &v[3]); } while ((eax->ctype) != 0); /* loop through all of the leaves */ for (i=0; ictype == 1 || eax->ctype == 3) { /* Compute the cache size */ size = (ecx->number_of_sets + 1) * (ebx->coherency_line_size + 1) * (ebx->physical_line_partition + 1) * (ebx->ways_of_associativity + 1); size /= 1024; switch (eax->level) { case 1: l1_cache += size; break; case 2: l2_cache += size; break; case 3: l3_cache += size; break; } } } return; } /* No CPUID(4) so we use the older CPUID(2) method */ /* Get number of times to iterate */ cpuid(2, &v[0], &v[1], &v[2], &v[3]); n = v[0] & 0xff; for (i=0 ; ifail_safe |= 4; } // Atom Clover Trail if(cpu_id.vers.bits.extendedModel == 4) { imc_type = 0x0007; } // HSW-ULT break; case 0x6: if(cpu_id.vers.bits.extendedModel == 3) { imc_type = 0x0009; // Atom Cedar Trail v->fail_safe |= 4; // Disable Core temp } break; case 0xA: switch(cpu_id.vers.bits.extendedModel) { case 0x1: imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHME) break; case 0x2: imc_type = 0x0004; // Core 2nd Gen (SNB) break; case 0x3: imc_type = 0x0006; // Core 3nd Gen (IVB) break; } break; case 0xC: switch(cpu_id.vers.bits.extendedModel) { case 0x1: if(cpu_id.vers.bits.stepping > 9) { imc_type = 0x0008; } // Atom PineView v->fail_safe |= 4; // Disable Core temp break; case 0x2: imc_type = 0x0002; // Core i7 1st Gen 32 nm (WMR) break; case 0x3: imc_type = 0x0007; // Core 4nd Gen (HSW) break; } break; case 0xD: imc_type = 0x0005; // SNB-E break; case 0xE: imc_type = 0x0001; // Core i7 1st Gen 45 nm (NHM) break; } if(imc_type) { tsc_invariable = 1; } return; } } void smp_default_mode(void) { int i, result; char *cpupsn = cpu_id.brand_id.char_array; char *disabledcpu[] = { "Opteron", "Xeon", "Genuine Intel" }; for(i = 0; i < 3; i++) { result = strstr(cpupsn , disabledcpu[i]); if(result != -1) { v->fail_safe |= 0b10; } } // For 5.01 release, SMP disabled by defualt by config.h toggle if(CONSERVATIVE_SMP) { v->fail_safe |= 0b10; } } /* * Find CPU type */ void cpu_type(void) { /* If we can get a brand string use it, and we are done */ if (cpu_id.max_xcpuid >= 0x80000004) { cprint(0, COL_MID, cpu_id.brand_id.char_array); //If we have a brand string, maybe we have an IMC. Check that. detect_imc(); smp_default_mode(); return; } /* 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.vers.bits.family) { case 4: switch(cpu_id.vers.bits.model) { case 3: cprint(0, COL_MID, "AMD 486DX2"); break; case 7: cprint(0, COL_MID, "AMD 486DX2-WB"); break; case 8: cprint(0, COL_MID, "AMD 486DX4"); break; case 9: cprint(0, COL_MID, "AMD 486DX4-WB"); break; case 14: cprint(0, COL_MID, "AMD 5x86-WT"); break; case 15: 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.vers.bits.model) { case 0: case 1: case 2: case 3: cprint(0, COL_MID, "AMD K5"); l1_cache = 8; break; case 6: case 7: cprint(0, COL_MID, "AMD K6"); break; case 8: cprint(0, COL_MID, "AMD K6-2"); break; case 9: cprint(0, COL_MID, "AMD K6-III"); break; case 13: cprint(0, COL_MID, "AMD K6-III+"); break; } break; case 6: switch(cpu_id.vers.bits.model) { case 1: cprint(0, COL_MID, "AMD Athlon (0.25)"); break; case 2: case 4: cprint(0, COL_MID, "AMD Athlon (0.18)"); break; case 6: if (l2_cache == 64) { cprint(0, COL_MID, "AMD Duron (0.18)"); } else { cprint(0, COL_MID, "Athlon XP (0.18)"); } break; case 8: case 10: if (l2_cache == 64) { cprint(0, COL_MID, "AMD Duron (0.13)"); } else { cprint(0, COL_MID, "Athlon XP (0.13)"); } break; case 3: case 7: cprint(0, COL_MID, "AMD Duron"); /* Duron stepping 0 CPUID for L2 is broken */ /* (AMD errata T13)*/ if (cpu_id.vers.bits.stepping == 0) { /* stepping 0 */ /* Hard code the right L2 size */ l2_cache = 64; } else { } 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.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.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.vers.bits.family == 4) { switch(cpu_id.vers.bits.model) { case 0: case 1: cprint(0, COL_MID, "Intel 486DX"); break; case 2: cprint(0, COL_MID, "Intel 486SX"); break; case 3: cprint(0, COL_MID, "Intel 486DX2"); break; case 4: cprint(0, COL_MID, "Intel 486SL"); break; case 5: cprint(0, COL_MID, "Intel 486SX2"); break; case 7: cprint(0, COL_MID, "Intel 486DX2-WB"); break; case 8: cprint(0, COL_MID, "Intel 486DX4"); break; case 9: cprint(0, COL_MID, "Intel 486DX4-WB"); break; } /* Since we can't get CPU speed or cache info return */ return; } switch(cpu_id.vers.bits.family) { case 5: switch(cpu_id.vers.bits.model) { case 0: case 1: case 2: case 3: case 7: cprint(0, COL_MID, "Pentium"); if (l1_cache == 0) { l1_cache = 8; } break; case 4: case 8: cprint(0, COL_MID, "Pentium-MMX"); if (l1_cache == 0) { l1_cache = 16; } break; } break; case 6: switch(cpu_id.vers.bits.model) { case 0: case 1: cprint(0, COL_MID, "Pentium Pro"); break; case 3: case 4: cprint(0, COL_MID, "Pentium II"); break; case 5: if (l2_cache == 0) { cprint(0, COL_MID, "Celeron"); } else { cprint(0, COL_MID, "Pentium II"); } break; case 6: if (l2_cache == 128) { cprint(0, COL_MID, "Celeron"); } else { cprint(0, COL_MID, "Pentium II"); } } break; case 7: case 8: case 11: if (l2_cache == 128) { cprint(0, COL_MID, "Celeron"); } else { cprint(0, COL_MID, "Pentium III"); } break; case 9: if (l2_cache == 512) { cprint(0, COL_MID, "Celeron M (0.13)"); } else { cprint(0, COL_MID, "Pentium M (0.13)"); } 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(0, COL_MID, "Celeron M (0.09)"); } else { cprint(0, COL_MID, "Pentium M (0.09)"); } break; case 14: cprint(0, COL_MID, "Intel Core"); break; case 15: 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.vers.bits.model) { case 0: case 1: case 2: if (l2_cache == 128) { cprint(0, COL_MID, "Celeron"); } else { cprint(0, COL_MID, "Pentium 4"); } break; case 3: case 4: if (l2_cache == 256) { cprint(0, COL_MID, "Celeron (0.09)"); } else { cprint(0, COL_MID, "Pentium 4 (0.09)"); } break; case 6: cprint(0, COL_MID, "Pentium D (65nm)"); break; default: cprint(0, COL_MID, "Unknown Intel"); break; break; } } break; /* VIA/Cyrix/Centaur Processors with CPUID */ case 'C': 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(0, COL_MID, "Centaur 5x86"); break; case 6: // VIA C3 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; } } } else { /* CyrixInstead */ switch(cpu_id.vers.bits.family) { case 5: switch(cpu_id.vers.bits.model) { case 0: cprint(0, COL_MID, "Cyrix 6x86MX/MII"); break; case 4: cprint(0, COL_MID, "Cyrix GXm"); break; } return; case 6: // VIA C3 switch(cpu_id.vers.bits.model) { case 6: cprint(0, COL_MID, "Cyrix III"); break; case 7: if (cpu_id.vers.bits.stepping < 8) { cprint(0, COL_MID, "VIA C3 Samuel2"); } else { cprint(0, COL_MID, "VIA C3 Ezra-T"); } break; case 8: cprint(0, COL_MID, "VIA C3 Ezra-T"); break; case 9: cprint(0, COL_MID, "VIA C3 Nehemiah"); break; } // L1 = L2 = 64 KB from Cyrix III to Nehemiah l1_cache = 64; l2_cache = 64; break; } } break; /* Unknown processor */ default: /* Make a guess at the family */ switch(cpu_id.vers.bits.family) { case 5: cprint(0, COL_MID, "586"); case 6: 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 = 4; ulong speed; /* Print CPU speed */ if ((speed = cpuspeed()) > 0) { if (speed < 999499) { speed += 50; /* for rounding */ 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(1, off, " MHz"); dprint(1, off, speed/1000, 5, 0); } extclock = speed; } /* Print out L1 cache info */ /* 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(2, 0, "L1 Cache: K "); dprint(2, 11, l1_cache, 3, 0); if ((speed=memspeed(STEST_ADDR, (l1_cache/2)*1024, 200))) { cprint(2, 16, " MB/s"); dprint(2, 16, speed, 6, 0); } } /* Print out L2 cache info */ /* We measure the L2 cache speed by using a block size that is */ /* the size of the L1 cache. We have to fudge if the L1 */ /* cache is bigger than the L2 */ if (l2_cache) { 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(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 "); aprint(4, 10, l3_cache/4); //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; /* 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 + l1_cache) * 4; /* 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; } speed = memspeed(STEST_ADDR, i * 1024, 100); cprint(5, 16, " MB/s"); dprint(5, 16, speed, 6, 0); } /* #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 (cpu_id.fid.bits.rdtsc == 0 ) { return(-1); } /* Setup timer */ outb((inb(0x61) & ~0x02) | 0x01, 0x61); outb(0xb0, 0x43); outb(TICKS & 0xff, 0x42); outb(TICKS >> 8, 0x42); asm __volatile__ ("rdtsc":"=a" (stlow),"=d" (sthigh)); loops = 0; do { loops++; } while ((inb(0x61) & 0x20) == 0); asm __volatile__ ( "rdtsc\n\t" \ "subl stlow,%%eax\n\t" \ "sbbl sthigh,%%edx\n\t" \ :"=a" (end_low), "=d" (end_high) ); /* Make sure we have a credible result */ if (loops < 4 || end_low < 50000) { return(-1); } v->clks_msec = end_low/50; if (tsc_invariable) end_low = correct_tsc(end_low); return(v->clks_msec); } /* Measure cache speed by copying a block of memory. */ /* Returned value is kbytes/second */ ulong memspeed(ulong src, ulong len, int iter) { int i; ulong dst, wlen; ulong st_low, st_high; ulong end_low, end_high; ulong cal_low, cal_high; if (cpu_id.fid.bits.rdtsc == 0 ) { return(-1); } if (len == 0) return(-2); dst = src + len; wlen = len / 4; /* Length is bytes */ /* Calibrate the overhead with a zero word copy */ asm __volatile__ ("rdtsc":"=a" (st_low),"=d" (st_high)); for (i=0; iclks_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.fid.bits.eist) { 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; } memtest86+-5.01/makeiso.sh0000755000000000000000000000227712201317565014045 0ustar rootroot#!/bin/sh # check to see if the correct tools are installed for X in wc genisoimage do if [ "$(which $X)" = "" ]; then echo "makeiso.sh error: $X is not in your path." >&2 exit 1 elif [ ! -x $(which $X) ]; then echo "makeiso.sh error: $X is not executable." >&2 exit 1 fi done #check to see if memtest.bin is present if [ ! -w memtest.bin ]; then echo "makeiso.sh error: cannot find memtest.bin, did you compile it?" >&2 exit 1 fi # enlarge the size of memtest.bin SIZE=$(wc -c memtest.bin | awk '{print $1}') FILL=$((1474560 - $SIZE)) dd if=/dev/zero of=fill.tmp bs=$FILL count=1 cat memtest.bin fill.tmp > memtest.img rm -f fill.tmp echo "Generating iso image ..." mkdir "cd" mkdir "cd/boot" mv memtest.img cd/boot cd cd # Create the cd.README echo -e "There is nothing to do here\r\r\nMemtest86+ is located on the bootsector of this CD\r\r\n" > README.TXT echo -e "Just boot from this CD and Memtest86+ will launch" >> README.TXT genisoimage -A "MKISOFS 1.1.2" -p "Memtest86+ 5.01" -publisher "Samuel D. " -b boot/memtest.img -c boot/boot.catalog -V "MT501" -o memtest.iso . mv memtest.iso ../mt501.iso cd .. rm -rf cd echo "Done! Memtest86+ 5.01 ISO is mt501.iso" memtest86+-5.01/io.h0000644000000000000000000000660412201317426012630 0ustar rootroot#ifndef _ASM_IO_H #define _ASM_IO_H /* * This file contains the definitions for the x86 IO instructions * inb/inw/inl/outb/outw/outl and the "string versions" of the same * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" * versions of the single-IO instructions (inb_p/inw_p/..). * * This file is not meant to be obfuscating: it's just complicated * to (a) handle it all in a way that makes gcc able to optimize it * as well as possible and (b) trying to avoid writing the same thing * over and over again with slight variations and possibly making a * mistake somewhere. */ #ifdef SLOW_IO_BY_JUMPING #define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") #else #define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") #endif #ifdef REALLY_SLOW_IO #define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } #else #define SLOW_DOWN_IO __SLOW_DOWN_IO #endif /* * Talk about misusing macros.. */ #define __OUT1(s,x) \ extern inline void __out##s(unsigned x value, unsigned short port) { #define __OUT2(s,s1,s2) \ __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" #define __OUT(s,s1,x) \ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \ __OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \ __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \ __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; } #define __IN1(s) \ extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v; #define __IN2(s,s1,s2) \ __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" #define __IN(s,s1,i...) \ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \ __IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \ __IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \ __IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; } #define __OUTS(s) \ extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ { __asm__ __volatile__ ("cld ; rep ; outs" #s \ : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } #define RETURN_TYPE unsigned char /* __IN(b,"b","0" (0)) */ __IN(b,"") #undef RETURN_TYPE #define RETURN_TYPE unsigned short /* __IN(w,"w","0" (0)) */ __IN(w,"") #undef RETURN_TYPE #define RETURN_TYPE unsigned int __IN(l,"") #undef RETURN_TYPE __OUT(b,"b",char) __OUT(w,"w",short) __OUT(l,,int) __OUTS(b) __OUTS(w) __OUTS(l) /* * Note that due to the way __builtin_constant_p() works, you * - can't use it inside a inline function (it will never be true) * - you don't have to worry about side effects within the __builtin.. */ #define outb(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outbc((val),(port)) : \ __outb((val),(port))) #define inb(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inbc(port) : \ __inb(port)) #define outw(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outwc((val),(port)) : \ __outw((val),(port))) #define inw(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inwc(port) : \ __inw(port)) #define outl(val,port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __outlc((val),(port)) : \ __outl((val),(port))) #define inl(port) \ ((__builtin_constant_p((port)) && (port) < 256) ? \ __inlc(port) : \ __inl(port)) #endif memtest86+-5.01/elf.h0000644000000000000000000005666512201317426013003 0ustar rootroot#ifndef ELF_H #define ELF_H #define EI_NIDENT 16 /* Size of e_ident array. */ /* Values for e_type. */ #define ET_NONE 0 /* No file type */ #define ET_REL 1 /* Relocatable file */ #define ET_EXEC 2 /* Executable file */ #define ET_DYN 3 /* Shared object file */ #define ET_CORE 4 /* Core file */ /* Values for e_machine (architecute). */ #define EM_NONE 0 /* No machine */ #define EM_M32 1 /* AT&T WE 32100 */ #define EM_SPARC 2 /* SUN SPARC */ #define EM_386 3 /* Intel 80386+ */ #define EM_68K 4 /* Motorola m68k family */ #define EM_88K 5 /* Motorola m88k family */ #define EM_486 6 /* Perhaps disused */ #define EM_860 7 /* Intel 80860 */ #define EM_MIPS 8 /* MIPS R3000 big-endian */ #define EM_S370 9 /* IBM System/370 */ #define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ #define EM_PARISC 15 /* HPPA */ #define EM_VPP500 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ #define EM_960 19 /* Intel 80960 */ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* PowerPC 64-bit */ #define EM_S390 22 /* IBM S390 */ #define EM_V800 36 /* NEC V800 series */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH-32 */ #define EM_RCE 39 /* Motorola RCE */ #define EM_ARM 40 /* ARM */ #define EM_FAKE_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Hitachi SH */ #define EM_SPARCV9 43 /* SPARC v9 64-bit */ #define EM_TRICORE 44 /* Siemens Tricore */ #define EM_ARC 45 /* Argonaut RISC Core */ #define EM_H8_300 46 /* Hitachi H8/300 */ #define EM_H8_300H 47 /* Hitachi H8/300H */ #define EM_H8S 48 /* Hitachi H8S */ #define EM_H8_500 49 /* Hitachi H8/500 */ #define EM_IA_64 50 /* Intel Merced */ #define EM_MIPS_X 51 /* Stanford MIPS-X */ #define EM_COLDFIRE 52 /* Motorola Coldfire */ #define EM_68HC12 53 /* Motorola M68HC12 */ #define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ #define EM_PCP 55 /* Siemens PCP */ #define EM_NCPU 56 /* Sony nCPU embeeded RISC */ #define EM_NDR1 57 /* Denso NDR1 microprocessor */ #define EM_STARCORE 58 /* Motorola Start*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ #define EM_ST100 60 /* STMicroelectronic ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ #define EM_X86_64 62 /* AMD x86-64 architecture */ #define EM_PDSP 63 /* Sony DSP Processor */ #define EM_FX66 66 /* Siemens FX66 microcontroller */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ #define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ #define EM_SVX 73 /* Silicon Graphics SVx */ #define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */ #define EM_VAX 75 /* Digital VAX */ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ #define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ #define EM_HUANY 81 /* Harvard University machine-independent object files */ #define EM_PRISM 82 /* SiTera Prism */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ #define EM_FR30 84 /* Fujitsu FR30 */ #define EM_D10V 85 /* Mitsubishi D10V */ #define EM_D30V 86 /* Mitsubishi D30V */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Mitsubishi M32R */ #define EM_MN10300 89 /* Matsushita MN10300 */ #define EM_MN10200 90 /* Matsushita MN10200 */ #define EM_PJ 91 /* picoJava */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ #define EM_NUM 95 /* Values for p_type. */ #define PT_NULL 0 /* Unused entry. */ #define PT_LOAD 1 /* Loadable segment. */ #define PT_DYNAMIC 2 /* Dynamic linking information segment. */ #define PT_INTERP 3 /* Pathname of interpreter. */ #define PT_NOTE 4 /* Auxiliary information. */ #define PT_SHLIB 5 /* Reserved (not used). */ #define PT_PHDR 6 /* Location of program header itself. */ /* Values for p_flags. */ #define PF_X 0x1 /* Executable. */ #define PF_W 0x2 /* Writable. */ #define PF_R 0x4 /* Readable. */ #define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */ #define EI_MAG0 0 #define ELFMAG0 0x7f #define EI_MAG1 1 #define ELFMAG1 'E' #define EI_MAG2 2 #define ELFMAG2 'L' #define EI_MAG3 3 #define ELFMAG3 'F' #define ELFMAG "\177ELF" #define EI_CLASS 4 /* File class byte index */ #define ELFCLASSNONE 0 /* Invalid class */ #define ELFCLASS32 1 /* 32-bit objects */ #define ELFCLASS64 2 /* 64-bit objects */ #define EI_DATA 5 /* Data encodeing byte index */ #define ELFDATANONE 0 /* Invalid data encoding */ #define ELFDATA2LSB 1 /* 2's complement little endian */ #define ELFDATA2MSB 2 /* 2's complement big endian */ #define EI_VERSION 6 /* File version byte index */ /* Value must be EV_CURRENT */ #define EV_NONE 0 /* Invalid ELF Version */ #define EV_CURRENT 1 /* Current version */ #define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */ #ifndef ASSEMBLY #include "stdint.h" /* * ELF definitions common to all 32-bit architectures. */ typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef uint16_t Elf32_Section; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Size; typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Half; typedef uint64_t Elf64_Off; typedef uint16_t Elf64_Section; typedef int32_t Elf64_Sword; typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Size; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; /* * ELF header. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf32_Half e_type; /* File type. */ Elf32_Half e_machine; /* Machine architecture. */ Elf32_Word e_version; /* ELF format version. */ Elf32_Addr e_entry; /* Entry point. */ Elf32_Off e_phoff; /* Program header file offset. */ Elf32_Off e_shoff; /* Section header file offset. */ Elf32_Word e_flags; /* Architecture-specific flags. */ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ Elf32_Half e_phentsize; /* Size of program header entry. */ Elf32_Half e_phnum; /* Number of program header entries. */ Elf32_Half e_shentsize; /* Size of section header entry. */ Elf32_Half e_shnum; /* Number of section header entries. */ Elf32_Half e_shstrndx; /* Section name strings section. */ } Elf32_Ehdr; typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf64_Half e_type; /* File type. */ Elf64_Half e_machine; /* Machine architecture. */ Elf64_Word e_version; /* ELF format version. */ Elf64_Addr e_entry; /* Entry point. */ Elf64_Off e_phoff; /* Program header file offset. */ Elf64_Off e_shoff; /* Section header file offset. */ Elf64_Word e_flags; /* Architecture-specific flags. */ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ Elf64_Half e_phentsize; /* Size of program header entry. */ Elf64_Half e_phnum; /* Number of program header entries. */ Elf64_Half e_shentsize; /* Size of section header entry. */ Elf64_Half e_shnum; /* Number of section header entries. */ Elf64_Half e_shstrndx; /* Section name strings section. */ } Elf64_Ehdr; /* * Program header. */ typedef struct { Elf32_Word p_type; /* Entry type. */ Elf32_Off p_offset; /* File offset of contents. */ Elf32_Addr p_vaddr; /* Virtual address (not used). */ Elf32_Addr p_paddr; /* Physical address. */ Elf32_Size p_filesz; /* Size of contents in file. */ Elf32_Size p_memsz; /* Size of contents in memory. */ Elf32_Word p_flags; /* Access permission flags. */ Elf32_Size p_align; /* Alignment in memory and file. */ } Elf32_Phdr; typedef struct { Elf64_Word p_type; /* Entry type. */ Elf64_Word p_flags; /* Access permission flags. */ Elf64_Off p_offset; /* File offset of contents. */ Elf64_Addr p_vaddr; /* Virtual address (not used). */ Elf64_Addr p_paddr; /* Physical address. */ Elf64_Size p_filesz; /* Size of contents in file. */ Elf64_Size p_memsz; /* Size of contents in memory. */ Elf64_Size p_align; /* Alignment in memory and file. */ } Elf64_Phdr; /* Dynamic section entry. */ typedef struct { Elf32_Sword d_tag; /* Dynamic entry type */ union { Elf32_Word d_val; /* Integer value */ Elf32_Addr d_ptr; /* Address value */ } d_un; } Elf32_Dyn; typedef struct { Elf64_Sxword d_tag; /* Dynamic entry type */ union { Elf64_Xword d_val; /* Integer value */ Elf64_Addr d_ptr; /* Address value */ } d_un; } Elf64_Dyn; /* Legal values for d_tag (dynamic entry type). */ #define DT_NULL 0 /* Marks end of dynamic section */ #define DT_NEEDED 1 /* Name of needed library */ #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ #define DT_PLTGOT 3 /* Processor defined value */ #define DT_HASH 4 /* Address of symbol hash table */ #define DT_STRTAB 5 /* Address of string table */ #define DT_SYMTAB 6 /* Address of symbol table */ #define DT_RELA 7 /* Address of Rela relocs */ #define DT_RELASZ 8 /* Total size of Rela relocs */ #define DT_RELAENT 9 /* Size of one Rela reloc */ #define DT_STRSZ 10 /* Size of string table */ #define DT_SYMENT 11 /* Size of one symbol table entry */ #define DT_INIT 12 /* Address of init function */ #define DT_FINI 13 /* Address of termination function */ #define DT_SONAME 14 /* Name of shared object */ #define DT_RPATH 15 /* Library search path (deprecated) */ #define DT_SYMBOLIC 16 /* Start symbol search here */ #define DT_REL 17 /* Address of Rel relocs */ #define DT_RELSZ 18 /* Total size of Rel relocs */ #define DT_RELENT 19 /* Size of one Rel reloc */ #define DT_PLTREL 20 /* Type of reloc in PLT */ #define DT_DEBUG 21 /* For debugging; unspecified */ #define DT_TEXTREL 22 /* Reloc might modify .text */ #define DT_JMPREL 23 /* Address of PLT relocs */ #define DT_BIND_NOW 24 /* Process relocations of object */ #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ #define DT_RUNPATH 29 /* Library search path */ #define DT_FLAGS 30 /* Flags for the object being loaded */ #define DT_ENCODING 32 /* Start of encoded range */ #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ #define DT_NUM 34 /* Number used */ #define DT_LOOS 0x6000000d /* Start of OS-specific */ #define DT_HIOS 0x6ffff000 /* End of OS-specific */ #define DT_LOPROC 0x70000000 /* Start of processor-specific */ #define DT_HIPROC 0x7fffffff /* End of processor-specific */ #define DT_PROCNUM 0x32 /* Most used by any processor */ /* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's approach. */ #define DT_VALRNGLO 0x6ffffd00 #define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ #define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ #define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ #define DT_CHECKSUM 0x6ffffdf8 #define DT_PLTPADSZ 0x6ffffdf9 #define DT_MOVEENT 0x6ffffdfa #define DT_MOVESZ 0x6ffffdfb #define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting the following DT_* entry. */ #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ #define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ #define DT_VALRNGHI 0x6ffffdff #define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ #define DT_VALNUM 12 /* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the Dyn.d_un.d_ptr field of the Elf*_Dyn structure. If any adjustment is made to the ELF object after it has been built these entries will need to be adjusted. */ #define DT_ADDRRNGLO 0x6ffffe00 #define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ #define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ #define DT_CONFIG 0x6ffffefa /* Configuration information. */ #define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ #define DT_AUDIT 0x6ffffefc /* Object auditing. */ #define DT_PLTPAD 0x6ffffefd /* PLT padding. */ #define DT_MOVETAB 0x6ffffefe /* Move table. */ #define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ #define DT_ADDRRNGHI 0x6ffffeff #define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ #define DT_ADDRNUM 10 /* The versioning entry types. The next are defined as part of the GNU extension. */ #define DT_VERSYM 0x6ffffff0 #define DT_RELACOUNT 0x6ffffff9 #define DT_RELCOUNT 0x6ffffffa /* These were chosen by Sun. */ #define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ #define DT_VERDEF 0x6ffffffc /* Address of version definition table */ #define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ #define DT_VERNEED 0x6ffffffe /* Address of table with needed versions */ #define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define DT_VERSIONTAGNUM 16 /* Sun added these machine-independent extensions in the "processor-specific" range. Be compatible. */ #define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ #define DT_FILTER 0x7fffffff /* Shared object to get values from */ #define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) #define DT_EXTRANUM 3 /* Values of `d_un.d_val' in the DT_FLAGS entry. */ #define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ #define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ #define DF_TEXTREL 0x00000004 /* Object contains text relocations */ #define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ #define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ /* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry in the dynamic section. */ #define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ #define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ #define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ #define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ #define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ #define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ #define DF_1_TRANS 0x00000200 #define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ #define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ #define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ #define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ #define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ #define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ #define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ /* Flags for the feature selection in DT_FEATURE_1. */ #define DTF_1_PARINIT 0x00000001 #define DTF_1_CONFEXP 0x00000002 /* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ #define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ #define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not generally available. */ /* Special section indices. */ #define SHN_UNDEF 0 /* Undefined section */ #define SHN_LORESERVE 0xff00 /* Start of reserved indices */ #define SHN_LOPROC 0xff00 /* Start of processor-specific */ #define SHN_HIPROC 0xff1f /* End of processor-specific */ #define SHN_LOOS 0xff20 /* Start of OS-specific */ #define SHN_HIOS 0xff3f /* End of OS-specific */ #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ #define SHN_COMMON 0xfff2 /* Associated symbol is common */ #define SHN_XINDEX 0xffff /* Index is in extra table. */ #define SHN_HIRESERVE 0xffff /* End of reserved indices */ /* Legal values for sh_type (section type). */ #define SHT_NULL 0 /* Section header table entry unused */ #define SHT_PROGBITS 1 /* Program data */ #define SHT_SYMTAB 2 /* Symbol table */ #define SHT_STRTAB 3 /* String table */ #define SHT_RELA 4 /* Relocation entries with addends */ #define SHT_HASH 5 /* Symbol hash table */ #define SHT_DYNAMIC 6 /* Dynamic linking information */ #define SHT_NOTE 7 /* Notes */ #define SHT_NOBITS 8 /* Program space with no data (bss) */ #define SHT_REL 9 /* Relocation entries, no addends */ #define SHT_SHLIB 10 /* Reserved */ #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ #define SHT_INIT_ARRAY 14 /* Array of constructors */ #define SHT_FINI_ARRAY 15 /* Array of destructors */ #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ #define SHT_GROUP 17 /* Section group */ #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ #define SHT_NUM 19 /* Number of defined types. */ #define SHT_LOOS 0x60000000 /* Start OS-specific */ #define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ #define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ #define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_COMDAT 0x6ffffffb #define SHT_SUNW_syminfo 0x6ffffffc #define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ #define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ #define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ #define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ #define SHT_HIOS 0x6fffffff /* End OS-specific type */ #define SHT_LOPROC 0x70000000 /* Start of processor-specific */ #define SHT_HIPROC 0x7fffffff /* End of processor-specific */ #define SHT_LOUSER 0x80000000 /* Start of application-specific */ #define SHT_HIUSER 0x8fffffff /* End of application-specific */ /* Legal values for sh_flags (section flags). */ #define SHF_WRITE (1 << 0) /* Writable */ #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ #define SHF_EXECINSTR (1 << 2) /* Executable */ #define SHF_MERGE (1 << 4) /* Might be merged */ #define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ #define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ #define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ #define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling required */ #define SHF_GROUP (1 << 9) /* Section is member of a group. */ #define SHF_TLS (1 << 10) /* Section hold thread-local data. */ #define SHF_MASKOS 0x0ff00000 /* OS-specific. */ #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ /* Section group handling. */ #define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ /* Symbol table entry. */ typedef struct { Elf32_Word st_name; /* Symbol name (string tbl index) */ Elf32_Addr st_value; /* Symbol value */ Elf32_Word st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf32_Section st_shndx; /* Section index */ } Elf32_Sym; typedef struct { Elf64_Word st_name; /* Symbol name (string tbl index) */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* Symbol visibility */ Elf64_Section st_shndx; /* Section index */ Elf64_Addr st_value; /* Symbol value */ Elf64_Xword st_size; /* Symbol size */ } Elf64_Sym; /* Relocation table entry without addend (in section of type SHT_REL). */ typedef struct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ } Elf32_Rel; /* I have seen two different definitions of the Elf64_Rel and Elf64_Rela structures, so we'll leave them out until Novell (or whoever) gets their act together. */ /* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ typedef struct { Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ } Elf64_Rel; /* Relocation table entry with addend (in section of type SHT_RELA). */ typedef struct { Elf32_Addr r_offset; /* Address */ Elf32_Word r_info; /* Relocation type and symbol index */ Elf32_Sword r_addend; /* Addend */ } Elf32_Rela; typedef struct { Elf64_Addr r_offset; /* Address */ Elf64_Xword r_info; /* Relocation type and symbol index */ Elf64_Sxword r_addend; /* Addend */ } Elf64_Rela; /* How to extract and insert information held in the r_info field. */ #define ELF32_R_SYM(val) ((val) >> 8) #define ELF32_R_TYPE(val) ((val) & 0xff) #define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) #define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff) #define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) /* Intel 80386 specific definitions. */ /* i386 relocs. */ #define R_386_NONE 0 /* No reloc */ #define R_386_32 1 /* Direct 32 bit */ #define R_386_PC32 2 /* PC relative 32 bit */ #define R_386_GOT32 3 /* 32 bit GOT entry */ #define R_386_PLT32 4 /* 32 bit PLT address */ #define R_386_COPY 5 /* Copy symbol at runtime */ #define R_386_GLOB_DAT 6 /* Create GOT entry */ #define R_386_JMP_SLOT 7 /* Create PLT entry */ #define R_386_RELATIVE 8 /* Adjust by program base */ #define R_386_GOTOFF 9 /* 32 bit offset to GOT */ #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ #define R_386_32PLT 11 #define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ #define R_386_TLS_IE 15 /* Address of GOT entry for static TLS block offset */ #define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block offset */ #define R_386_TLS_LE 17 /* Offset relative to static TLS block */ #define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of general dynamic thread local data */ #define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of local dynamic thread local data in LE code */ #define R_386_16 20 #define R_386_PC16 21 #define R_386_8 22 #define R_386_PC8 23 #define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic thread local data */ #define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ #define R_386_TLS_GD_CALL 26 /* Relocation for call to __tls_get_addr() */ #define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ #define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic thread local data in LE code */ #define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ #define R_386_TLS_LDM_CALL 30 /* Relocation for call to __tls_get_addr() in LDM code */ #define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ #define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ #define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS block offset */ #define R_386_TLS_LE_32 34 /* Negated offset relative to static TLS block */ #define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ #define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ #define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ /* Keep this the last entry. */ #define R_386_NUM 38 #endif /* ASSEMBLY */ #endif /* ELF_H */ memtest86+-5.01/major_version0000644000000000000000000000000512201317426014635 0ustar rootroot4.99 memtest86+-5.01/make_buildnum.sh0000755000000000000000000000146712201317426015225 0ustar rootroot#!sh # FILE: make_buildnum.sh version="`sed 's/^ *//' major_version`" old="`sed 's/^ *//' build.number` +1" echo $old | bc > build.number.temp mv build.number.temp build.number #versin.. echo "$version`sed 's/^ *//' build.number` - `date`" > version.number #header echo "#ifndef BUILD_NUMBER_STR" > build_number.h echo "#define BUILD_NUMBER_STR \"`sed 's/^ *//' build.number`\"" >> build_number.h echo "#endif" >> build_number.h echo "#ifndef VERSION_STR" >> build_number.h echo "#define VERSION_STR \"$version`sed 's/^ *//' build.number` - `date`\"" >> build_number.h echo "#endif" >> build_number.h echo "#ifndef VERSION_STR_SHORT" >> build_number.h echo "#define VERSION_STR_SHORT \"$version`sed 's/^ *//' build.number`\"" >> build_number.h echo "#endif" >> build_number.h memtest86+-5.01/stdin.h0000644000000000000000000000245412201317426013341 0ustar rootroot#ifndef I386_STDINT_H #define I386_STDINT_H /* Exact integral types */ typedef unsigned char uint8_t; typedef signed char int8_t; typedef unsigned short uint16_t; typedef signed short int16_t; typedef unsigned int uint32_t; typedef signed int int32_t; typedef unsigned long long uint64_t; typedef signed long long int64_t; /* Small types */ typedef unsigned char uint_least8_t; typedef signed char int_least8_t; typedef unsigned short uint_least16_t; typedef signed short int_least16_t; typedef unsigned int uint_least32_t; typedef signed int int_least32_t; typedef unsigned long long uint_least64_t; typedef signed long long int_least64_t; /* Fast Types */ typedef unsigned char uint_fast8_t; typedef signed char int_fast8_t; typedef unsigned int uint_fast16_t; typedef signed int int_fast16_t; typedef unsigned int uint_fast32_t; typedef signed int int_fast32_t; typedef unsigned long long uint_fast64_t; typedef signed long long int_fast64_t; /* Types for `void *' pointers. */ typedef int intptr_t; typedef unsigned int uintptr_t; /* Largest integral types */ typedef long long int intmax_t; typedef unsigned long long uintmax_t; #endif /* I386_STDINT_H */memtest86+-5.01/memtest.bin.lds0000644000000000000000000000034712201317426014777 0ustar rootrootOUTPUT_FORMAT("binary") OUTPUT_ARCH("i386") ENTRY(_main); SECTIONS { . = 0; .bootsect : { *(.bootsect) } .setup : { *(.setup) } .memtest : { _start = . ; *(.data) _end = . ; } _syssize = (_end - _start + 15) >> 4; } memtest86+-5.01/memtest.lds0000644000000000000000000000020312201317426014217 0ustar rootrootOUTPUT_FORMAT("elf32-i386"); OUTPUT_ARCH(i386); ENTRY(_start); SECTIONS { . = 0x10000; _start = . ; .data : { *(.data) } } memtest86+-5.01/msr.h0000644000000000000000000000765212201317426013026 0ustar rootroot#ifndef __ASM_MSR_H #define __ASM_MSR_H /* * Access to machine-specific registers (available on 586 and better only) * Note: the rd* operations modify the parameters directly (without using * pointer indirection), this allows gcc to optimize better */ #define __FIXUP_ALIGN ".align 8" #define __FIXUP_WORD ".quad" #define EFAULT 14 /* Bad address */ #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \ : "c" (msr) : "edi") /* #define rdmsr_safe(msr,val1,val2) ({\ int _rc; \ __asm__ __volatile__( \ "1: rdmsr\n2:\n" \ ".section .fixup,\"ax\"\n" \ "3: movl %5,%2\n; jmp 2b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " "__FIXUP_ALIGN"\n" \ ".previous\n" \ : "=a" (val1), "=d" (val2), "=&r" (_rc) \ : "c" (msr), "2" (0), "i" (-EFAULT)); \ _rc; }) */ #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : /* no outputs */ \ : "c" (msr), "a" (val1), "d" (val2)) #define rdtsc(low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) #define rdtscl(low) \ __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) #define write_tsc(val1,val2) wrmsr(0x10, val1, val2) #define rdpmc(counter,low,high) \ __asm__ __volatile__("rdpmc" \ : "=a" (low), "=d" (high) \ : "c" (counter)) /* symbolic names for some interesting MSRs */ /* Intel defined MSRs. */ #define MSR_IA32_P5_MC_ADDR 0 #define MSR_IA32_P5_MC_TYPE 1 #define MSR_IA32_PLATFORM_ID 0x17 #define MSR_IA32_EBL_CR_POWERON 0x2a #define MSR_IA32_APICBASE 0x1b #define MSR_IA32_APICBASE_BSP (1<<8) #define MSR_IA32_APICBASE_ENABLE (1<<11) #define MSR_IA32_APICBASE_BASE (0xfffff<<12) #define MSR_IA32_UCODE_WRITE 0x79 #define MSR_IA32_UCODE_REV 0x8b #define MSR_IA32_BBL_CR_CTL 0x119 #define MSR_IA32_MCG_CAP 0x179 #define MSR_IA32_MCG_STATUS 0x17a #define MSR_IA32_MCG_CTL 0x17b #define MSR_IA32_THERM_CONTROL 0x19a #define MSR_IA32_THERM_INTERRUPT 0x19b #define MSR_IA32_THERM_STATUS 0x19c #define MSR_IA32_MISC_ENABLE 0x1a0 #define MSR_IA32_TEMPERATURE_TARGET 0x1a2 #define MSR_IA32_DEBUGCTLMSR 0x1d9 #define MSR_IA32_LASTBRANCHFROMIP 0x1db #define MSR_IA32_LASTBRANCHTOIP 0x1dc #define MSR_IA32_LASTINTFROMIP 0x1dd #define MSR_IA32_LASTINTTOIP 0x1de #define MSR_IA32_MC0_CTL 0x400 #define MSR_IA32_MC0_STATUS 0x401 #define MSR_IA32_MC0_ADDR 0x402 #define MSR_IA32_MC0_MISC 0x403 #define MSR_P6_PERFCTR0 0xc1 #define MSR_P6_PERFCTR1 0xc2 #define MSR_P6_EVNTSEL0 0x186 #define MSR_P6_EVNTSEL1 0x187 #define MSR_IA32_PERF_STATUS 0x198 #define MSR_IA32_PERF_CTL 0x199 /* AMD Defined MSRs */ #define MSR_K6_EFER 0xC0000080 #define MSR_K6_STAR 0xC0000081 #define MSR_K6_WHCR 0xC0000082 #define MSR_K6_UWCCR 0xC0000085 #define MSR_K6_EPMR 0xC0000086 #define MSR_K6_PSOR 0xC0000087 #define MSR_K6_PFIR 0xC0000088 #define MSR_K7_EVNTSEL0 0xC0010000 #define MSR_K7_PERFCTR0 0xC0010004 #define MSR_K7_HWCR 0xC0010015 #define MSR_K7_CLK_CTL 0xC001001b #define MSR_K7_FID_VID_CTL 0xC0010041 #define MSR_K7_VID_STATUS 0xC0010042 /* Centaur-Hauls/IDT defined MSRs. */ #define MSR_IDT_FCR1 0x107 #define MSR_IDT_FCR2 0x108 #define MSR_IDT_FCR3 0x109 #define MSR_IDT_FCR4 0x10a #define MSR_IDT_MCR0 0x110 #define MSR_IDT_MCR1 0x111 #define MSR_IDT_MCR2 0x112 #define MSR_IDT_MCR3 0x113 #define MSR_IDT_MCR4 0x114 #define MSR_IDT_MCR5 0x115 #define MSR_IDT_MCR6 0x116 #define MSR_IDT_MCR7 0x117 #define MSR_IDT_MCR_CTRL 0x120 /* VIA Cyrix defined MSRs*/ #define MSR_VIA_FCR 0x1107 #define MSR_VIA_LONGHAUL 0x110a #define MSR_VIA_BCR2 0x1147 /* Transmeta defined MSRs */ #define MSR_TMTA_LONGRUN_CTRL 0x80868010 #define MSR_TMTA_LONGRUN_FLAGS 0x80868011 #define MSR_TMTA_LRTI_READOUT 0x80868018 #define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a #endif /* __ASM_MSR_H */ memtest86+-5.01/makedos.sh0000755000000000000000000000043212201317426014023 0ustar rootroot#!/bin/bash if [ -f memtest.bin ] then CSIZE="$(awk 'NR==16' mt86+_loader.asm | awk '{print $2}')"; NSIZE="$(ls -l memtest.bin | awk '{print $5}')"; sed "s/$CSIZE/$NSIZE/" mt86+_loader.asm > mt86+_loader.asm.new; mv mt86+_loader.asm.new mt86+_loader.asm; nasm mt86+_loader.asm; fi memtest86+-5.01/README0000644000000000000000000010700412201317426012724 0ustar rootroot ==================== = MemTest-86 v4.0 = = 28 Mar, 2011 = = Chris Brady = ==================== Table of Contents ================= 1) Introduction 2) Licensing 3) Installation 4) Serial Port Console 5) Online Commands 6) Memory Sizing 7) Error Display 8) Trouble-shooting Memory Errors 9) Execution Time 10) Memory Testing Philosophy 11) Memtest86 Test Algorithms 12) Individual Test Descriptions 13) Problem Reporting - Contact Information 14) Known Problems 15) Planned Features List 16) Change Log 17) Acknowledgments 1) Introduction =============== Memtest86 is thorough, stand alone memory test for Intel/AMD x86 architecture systems. BIOS based memory tests are only a quick check and often miss failures that are detected by Memtest86. For updates go to the Memtest86 web page: http://www.memtest86.com 2) Licensing ============ Memtest86 is released under the terms of the Gnu Public License (GPL). Other than the provisions of the GPL there are no restrictions for use, private or commercial. See: http://www.gnu.org/licenses/gpl.html for details. 3) Linux Installation ============================ Memtest86 is a stand alone program and can be loaded from either a disk partition or from a floppy disk. To build Memtest86: 1) Review the Makefile and adjust options as needed. 2) Type "make" This creates a file named "memtest.bin" which is a bootable image. This image file may be copied to a floppy disk or may be loaded from a disk partition via Lilo or Grub image from a hard disk partition. To create a Memtest86 bootdisk 1) Insert a blank write enabled floppy disk. 2) As root, Type "make install" To boot from a disk partition via Grub 1) Copy the image file to a permanent location (ie. /boot/memtest.bin). 2) Add an entry in the Grub config file (/boot/grub/menu.lst) to boot memtest86. Only the title and kernel fields need to be specified. The following is a sample Grub entry for booting memtest86: title Memtest86 kernel (hd0,0)/memtest.bin To boot from a disk partition via Lilo 1) Copy the image file to a permanent location (ie. /boot/memtest.bin). 2) Add an entry in the lilo config file (usually /etc/lilo.conf) to boot memtest86. Only the image and label fields need to be specified. The following is a sample Lilo entry for booting memtest86: image = /boot/memtest.bin label = memtest86 3) As root, type "lilo" If you encounter build problems a binary image has been included (precomp.bin). To create a boot-disk with this pre-built image do the following: 1) Insert a blank write enabled floppy disk. 2) Type "make install-precomp" 4) Serial Console ================= Memtest86 can be used on PC's equipped with a serial port for the console. By default serial port console support is not enabled since it slows down testing. To enable change the SERIAL_CONSOLE_DEFAULT define in config.h from a zero to a one. The serial console baud rate may also be set in config.h with the SERIAL_BAUD_RATE define. The other serial port settings are no parity, 8 data bits, 1 stop bit. All of the features used by memtest86 are accessible via the serial console. However, the screen sometimes is garbled when the online commands are used. 5) Online Commands ================== Memtest86 has a limited number of online commands. Online commands provide control over caching, test selection, address range and error scrolling. A help bar is displayed at the bottom of the screen listing the available on-line commands. Command Description ESC Exits the test and does a warm restart via the BIOS. c Enters test configuration menu Menu options are: 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 set and the scroll region is full. CR Clear scroll lock (Enables error message scrolling) 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 is reporting of individual errors. In BadRAM Patterns mode patterns are created for use with the Linux BadRAM feature. This slick feature allows Linux to avoid bad memory pages. Details about the BadRAM feature can be found at: http://home.zonnet.nl/vanrein/badram The error summary mode displays the following information: Error Confidence Value: A value that indicates the validity of the errors being reported with larger values indicating greater validity. There is a high probability that all errors reported are valid regardless of this value. However, when this value exceeds 100 it is nearly impossible that the reported errors will be invalid. Lowest Error Address: The lowest address that where an error has been reported. Highest Error Address: The highest address that where an error has been reported. Bits in Error Mask: A mask of all bits that have been in error (hexadecimal). Bits in Error: Total bit in error for all error instances and the min, max and average bit in error of each individual occurrence. Max Contiguous Errors: The maximum of contiguous addresses with errors. ECC Correctable Errors: The number of errors that have been corrected by ECC hardware. Test Errors: On the right hand side of the screen the number of errors for each test are displayed. For individual errors the following information is displayed when a memory error is detected. An error message is only displayed for errors with a different address or failing bit pattern. All displayed values are in hexadecimal. Tst: Test number 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 is a bitmask for that address. These patterns state that faults have occurred in addresses that equal F on all "1" bits in M. Such a pattern may capture more errors that actually exist, but at least all the errors are captured. These patterns have been designed to capture regular patterns of errors caused by the hardware structure in a terse syntax. The BadRAM patterns are `grown' increment-ally rather than `designed' from an overview of all errors. The number of pairs is constrained to five for a number of practical reasons. As a result, handcrafting patterns from the output in address printing mode may, in exceptional cases, yield better results. 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 the motherboard. It is impossible for the test to determine what causes the failure to occur. Most failures will be due to a problem with memory. When it is not, the only option is to replace parts until the failure is corrected. Once a memory error has been detected, determining the failing module is not a clear cut procedure. With the large number of motherboard vendors and possible combinations of simm slots it would be difficult if not impossible to assemble complete information about how a particular error would map to a failing memory module. However, there are steps that may be taken to determine the failing module. Here are three techniques that you may wish to use: 1) Removing modules This is simplest method for isolating a failing modules, but may only be employed when one or more modules can be removed from the system. By selectively removing modules from the system and then running the test you will be able to find the bad module(s). Be sure to note exactly which modules are in the system when the test passes and when the test fails. 2) Rotating modules When none of the modules can be removed then you may wish to rotate modules to find the failing one. This technique can only be used if there are three or more modules in the system. Change the location of two modules at a time. For example put the module from slot 1 into slot 2 and put the module from slot 2 in slot 1. Run the test and if either the failing bit or address changes then you know that the failing module is one of the ones just moved. By using several combinations of module movement you should be able to determine which module is failing. 3) Replacing modules If you are unable to use either of the previous techniques then you are left to selective replacement of modules to find the failure. 4) Avoiding allocation The printing mode for BadRAM patterns is intended to construct boot time parameters for a Linux kernel that is compiled with BadRAM support. This work-around makes it possible for Linux to reliably run on defective RAM. For more information on BadRAM support for Linux, sail to http://home.zonnet.nl/vanrein/badram Sometimes memory errors show up due to component incompatibility. A memory module may work fine in one system and not in another. This is not uncommon and is a source of confusion. The components are not necessarily bad but certain combinations may need to be avoided. I am often asked about the reliability of errors reported by Mestest86. In the vast majority of cases errors reported by the test are valid. There are some systems that cause Memtest86 to be confused about the size of memory and it will try to test non-existent memory. This will cause a large number of consecutive addresses to be reported as bad and generally there will be many bits in error. If you have a relatively small number of failing addresses and only one or two bits in error you can be certain that the errors are valid. Also intermittent errors are always valid. All valid memory errors should be corrected. It is possible that a particular error will never show up in normal operation. However, operating with marginal memory is risky and can result in data loss and even disk corruption. You can be sure that Murphy will get you if you know about a memory error and ignore it. 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. 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 indefinitely. The pass counter increments each time that all of the selected tests have been run. Generally a single pass is sufficient to catch all but the most obscure errors. However, for complete confidence when intermittent errors are suspected testing for a longer period is advised. 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 of memory architecture or how errors can best be detected. This works fine for hard memory failures but does little to find intermittent errors. BIOS based memory tests are useless for finding intermittent memory errors. Memory chips consist of a large array of tightly packed memory cells, one for each bit of data. The vast majority of the intermittent failures are a result of interaction between these memory cells. Often writing a memory cell can cause one of the adjacent cells to be written with the same data. An effective memory test attempts to test for this condition. Therefore, an ideal strategy for testing memory would be the following: 1) write a cell with a zero 2) write all of the adjacent cells with a one, one or more times 3) check that the first cell still has a zero It should be obvious that this strategy requires an exact knowledge of how the memory cells are laid out on the chip. In addition there is a never ending number of possible chip layouts for different chip types and manufacturers making this strategy impractical. However, there are testing algorithms that can approximate this ideal strategy. 11) Memtest86 Test Algorithms ============================= Memtest86 uses two algorithms that provide a reasonable approximation of the ideal test strategy above. The first of these strategies is called moving inversions. The moving inversion test works as follows: 1) Fill memory with a pattern 2) Starting at the lowest address 2a check that the pattern has not changed 2b write the patterns complement 2c increment the address repeat 2a - 2c 3) Starting at the highest address 3a check that the pattern has not changed 3b write the patterns complement 3c decrement the address repeat 3a - 3c This algorithm is a good approximation of an ideal memory test but there are some limitations. Most high density chips today store data 4 to 16 bits wide. With chips that are more than one bit wide it is impossible to selectively read or write just one bit. This means that we cannot guarantee that all adjacent cells have been tested for interaction. In this case the best we can do is to use some patterns to insure that all adjacent cells have at least been written with all possible one and zero combinations. It can also be seen that caching, buffering and out of order execution will interfere with the moving inversions algorithm and make less effective. It is possible to turn off cache but the memory buffering in new high performance chips can not be disabled. To address this limitation a new algorithm I call Modulo-X was created. This algorithm is not affected by cache or buffering. The algorithm works as follows: 1) For starting offsets of 0 - 20 do 1a write every 20th location with a pattern 1b write all other locations with the patterns complement repeat 1b one or more times 1c check every 20th location for the pattern This algorithm accomplishes nearly the same level of adjacency testing as moving inversions but is not affected by caching or buffering. Since separate write passes (1a, 1b) and the read pass (1c) are done for all of memory we can be assured that all of the buffers and cache have been flushed between passes. The selection of 20 as the stride size was somewhat arbitrary. Larger strides may be more effective but would take longer to execute. The choice of 20 seemed to be a reasonable compromise between speed and thoroughness. 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 algorithm, data pattern and caching. The execution order for these tests were arranged so that errors will be detected as rapidly as possible. A description of each of the test sections follows: Test 0 [Address test, walking ones, no cache] Tests all address bits in all memory banks by using a walking ones address pattern. Errors from this test are not used to calculate BadRAM patterns. 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. This test is done sequentially with each available CPU. 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 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 5 [Moving inversions, 8 bit pat] This is the same as test 4 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 6 [Moving inversions, random pattern] Test 6 uses the same algorithm as test 4 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. The random number sequence is different with each pass so multiple passes increase effectiveness. 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 of memory are moved around using the movsl instruction. After the moves are completed the data patterns are checked. Because the data is checked only after the memory moves are completed it is not possible to know where the error occurred. The addresses reported are only for where the bad pattern was found. Since the moves are constrained to a 8MB segment of memory the failing address will always be lest than 8MB away from the reported address. Errors from this test are not used to calculate BadRAM patterns. 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 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 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 11 [Bit fade test, 2 patterns] The bit fade test initializes all of memory with a pattern and then sleeps for 5 minutes. Then memory is examined to see if any memory bits have changed. All ones and all zero patterns are used. 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 respond to ANY Memtest86 emails. Bug reports and suggestions are welcome but will typically not be responded to. *** NOTE: *** The Keyword MEM86 must appear in the subject of all emails or the message will be automaticly deleted before it gets to me. This thanks to spam and viruses! Problems/Bugs: Before submitting a problem report please check the Known Problems section to see if this problem has already been reported. Be sure to include the version number and also any details that may be relevant. Chris Brady, Email: bugs@memtest86.com With some PC's Memtest86 will just die with no hints as to what went wrong. Without any details it is impossible to fix these failures. Fixing these problems will require debugging on your part. There is no point in reporting these failures unless you have a Linux system and would be willing to debug the failure. Enhancements: If you would like to request an enhancement please see if is already on the Planned Features List before sending your request. All requests will be considered, but not all can be implemented. If you are be interested in contributing code please contact me so that the integration can be co-ordinated. Chris Brady, Email: enhance@memtest86.com Questions: Unfortunately, I do not have time to respond to any questions or provide assistance with troubleshooting problems. Please read the Troubleshooting and Known Problems sections for assistance with problems. These sections have the answers for the questions that I have answers to. If there is not an answer for your problem in these sections it is probably not something I can help you with. 15) Known Problems ================== Sometimes when booting from a floppy disk the following messages scroll up on the screen: X:8000 AX:0212 BX:8600 CX:0201 DX:0000 This the BIOS reporting floppy disk read errors. Either re-write or toss the floppy disk. 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 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 or bug but is listed here due to the many questions I get about this issue. Changes in the compiler and loader have caused problems with Memtest86 resulting in both build failures and errors in execution. A 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. - 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). Additions and corrections for CPU detection. Support for memory module information reporting. Misc bug fixes. Enhancements in v3.3 (12/Jan/2007) Added support for additional chipsets. (from Memtest86+ v1.60) Changed Modulo 20 test (#8) to use a more effective random pattern rather than simple ones and zeros. Fixed a bug that prevented testing of low memory. Added an advanced menu option to display SPD info (only for selected chipsets). Updated CPU detection for new CPUs and corrected some bugs. Reworked online command text for better clarity. Added a fix to correct a Badram pattern bug. Enhancements in v3.2 (11/Nov/2004) Added two new, highly effective tests that use random number patterns (tests 4 and 6). Reworked the online commands: - Changed wording for better clarity - Dropped Cache Mode menu Updated CPU detection for newer AMD, Intel and Cyrix CPUs. Reworked test sequence: - Dropped ineffective non cached tests (Numbers 7-11) - Changed cache mode to "cached" for test 2 - Fixed bug that did not allow some tests to be skipped - Added bailout for Bit fade test Error reports are highlighted in red to provide a more vivid error indication. Added support for a large number of additional chipsets. (from Memtest86+ v1.30) Added an advanced setup feature that with new chiset allows memory timings to be altered from inside Memtest86. (from Memtest86+ v1.30) Enhancements in v3.1 (11/Mar/2004) Added processor detection for newer AMD processors. Added new "Bit Fade" extended test. Fixed a compile time bug with gcc version 3.x. E7500 memory controller ECC support Added support for 16bit ECC syndromes Option to keep the serial port baud rate of the boot loader Enhancements in v3.0 (22/May/2002) Provided by Eric Biederman Testing of more than 2gb of memory is at last fixed (tested with 6Gb) The infrastructure is to poll ecc error reporting chipset regisets, and the support has been done for some chipsets. Uses dynamic relocation information records to make itself PIC instead of requiring 2 copies of memtest86 in the binary. The serial console code does not do redundant writes to the serial port Very little slow down at 9600 baud. You can press ^l or just l to get a screen refresh, when you are connecting and UN-connecting a serial cable. Net-booting is working again Linux-BIOS support (To get the memory size) Many bug-fixes and code cleanup. Enhancements in v2.9 (29/Feb/2002) The memory sizing code has been completely rewritten. By default Memtest86 gets a memory map from the BIOS that is now used to find available memory. A new online configuration option provides three choices for how memory will be sized, including the old "probe" method. The default mode generally will not test all of memory, but should be more stable. See the "Memory Sizing" section for details. Testing of more than 2gb of memory should now work. A number of bugs were found and corrected that prevented testing above 2gb. Testing with more than 2gb has been limited and there could be problems with a full 4gb of memory. 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 effectiveness but progress reports will be less frequent. Minor bug fixes. Enhancements in v2.8 (18/Oct/2001) Eric Biederman reworked the build process making it far simpler and also 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 for Athlon/Duron CPU's. By default the serial console is disabled since this was slowing down testing. Added CPU detection for Pentium 4. Enhancements in v2.7 (12/Jul/2001) Expanded workaround for errors caused by BIOS USB keyboard support to include test #5. Re-worked L1 / L2 cache detection code to provide clearer reporting. Fixed an obvious bug in the computation of cache and memory speeds. Changed on-line menu to stay in the menu between option selections. Fixed bugs in the test restart and redraw code. Adjusted code size to fix compilation problems with RedHat 7.1. Misc updates to the documentation. Enhancements in v2.6 (25/May/2001) Added workaround for errors caused by BIOS USB keyboard support. Fixed problems with reporting of 1 GHZ + processor speeds. Fixed Duron cache detection. Added screen buffer so that menus will work correctly from a serial console. The Memtest86 image is now built in ELF format. Enhancements in v2.5 (14/Dec/00) Enhanced CPU and cache detection to correctly identify Duron CPU and K6-III 1MB cache. Added code to report cache-able memory size. Added limited support for parity memory. Support was added to allow use of on-line commands from a serial port. Dropped option for changing refresh rates. This was not useful and did not work on newer motherboards. Improved fatal exception reporting to include a register and stack dump. The pass number is now displayed in the error report. Fixed a bug that crashed the test when selecting one of the extended tests. Enhancements in v2.4 The error report format was reworked for better clarity and now includes a decimal address in megabytes. A new memory move test was added (from Robert Redelmeier's CPU-Burn) The test sequence and iterations were modified. Fixed scrolling problems with the BadRAM patterns. Enhancements in v2.3 A progress meter was added to replace the spinner and dots. Measurement and reporting of memory and cache performance was added. Support for creating BadRAM patterns was added. All of the test routines were rewritten in assembler to improve both test performance and speed. The screen layout was reworked to hopefully be more readable. An error summary option was added to the online commands. Enhancements in v2.2 Added two new address tests Added an on-line command for setting test address range Optimized test code for faster execution (-O3, -funroll-loops and -fomit-frame-pointer) Added and elapsed time counter. Adjusted menu options for better consistency Enhancements in v2.1 Fixed a bug in the CPU detection that caused the test to hang or crash with some 486 and Cryrix CPU's Added CPU detection for Cyrix CPU's Extended and improved CPU detection for Intel and AMD CPU's Added a compile time option (BIOS_MEMSZ) for obtaining the last memory address from the BIOS. This should fix problems with memory sizing on certain motherboards. This option is not enabled by default. It may be enabled be default in a future release. Enhancements in v2.0 Added new Modulo-20 test algorithm. Added a 32 bit shifting pattern to the moving inversions algorithm. Created test sections to specify algorithm, pattern and caching. Improved test progress indicators. Created popup menus for configuration. Added menu for test selection. Added CPU and cache identification. Added a "bail out" feature to quit the current test when it does not fit the test selection parameters. Re-arranged the screen layout and colors. Created local include files for I/O and serial interface definitions rather than using the sometimes incompatible system include files. Broke up the "C" source code into four separate source modules. Enhancements in v1.5 Some additional changes were made to fix obscure memory sizing problems. The 4 bit wide data pattern was increased to 8 bits since 8 bit wide memory chips are becoming more common. A new test algorithm was added to improve detection of data pattern sensitive errors. Enhancements in v1.4 Changes to the memory sizing code to avoid problems with some motherboards where memtest would find more memory than actually exists. Added support for a console serial port. (thanks to Doug Sisk) On-line commands are now available for configuring Memtest86 on the fly (see On-line Commands). Enhancements in v1.3 Scrolling of memory errors is now provided. Previously, only one screen of error information was displayed. Memtest86 can now be booted from any disk via lilo. Testing of up to 4gb of memory has been fixed is now enabled by default. This capability was clearly broken in v1.2a and should work correctly now but has not been fully tested (4gb PC's are a bit rare). The maximum memory size supported by the motherboard is now being calculated correctly. In previous versions there were cases where not all of memory would be tested and the maximum memory size supported was incorrect. For some types of failures the good and bad values were reported to be same with an Xor value of 0. This has been fixed by retaining the data read from memory and not re-reading the bad data in the error reporting routine. APM (advanced power management) is now disabled by Memtest86. This keeps the screen from blanking while the test is running. Problems with enabling & disabling cache on some motherboards have been corrected. 17) Acknowledgments =================== Memtest86 was developed by Chris Brady with the resources and assistance listed below: - The initial versions of the source files bootsect.S, setup.S, head.S and build.c are from the Linux 1.2.1 kernel and have been heavily modified. - Doug Sisk provided code to support a console connected via a serial port. - Code to create BadRAM patterns was provided by Rick van Rein. - Tests 5 and 8 are based on Robert Redelmeier's burnBX test. - Screen buffer code was provided by Jani Averbach. - Eric Biederman provided all of the feature content for version 3.0 plus many bugfixes and significant code cleanup. - Major enhancements to hardware detection and reporting in version 3.2, 3.3 pnd 3.4 rovided by Samuel Demeulemeester (from Memtest86+ v1.11, v1.60 and v1.70). memtest86+-5.01/memtest_shared.lds0000644000000000000000000000163212201317426015554 0ustar rootrootOUTPUT_FORMAT("elf32-i386"); OUTPUT_ARCH(i386); ENTRY(startup_32); SECTIONS { . = 0; .text : { _start = .; *(.text) *(.text.*) *(.plt) _etext = . ; } = 0x9090 .rodata : { *(.rodata) *(.rodata.*) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynamic : { *(.dynamic) } .rel.text : { *(.rel.text .rel.text.*) } .rel.rodata : { *(.rel.rodata .rel.rodata.*) } .rel.data : { *(.rel.data .rel.data.*) } .rel.got : { *(.rel.got .rel.got.*) } .rel.plt : { *(.rel.plt .rel.plt.*) } . = ALIGN(4); .data : { _data = .; *(.data) *(.data.*) } .got : { *(.got.plt) *(.got) _edata = . ; } . = ALIGN(4); .bss : { _bss = .; *(.dynbss) *(.bss) *(.bss.*) *(COMMON) /* _end must be at least 256 byte aligned */ . = ALIGN(256); _end = .; } /DISCARD/ : { *(*) } } memtest86+-5.01/spd.h0000644000000000000000000000100012201317426012770 0ustar rootroot/* * MemTest86+ V5.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ #define AMD_INDEX_IO_PORT 0xCD6 #define AMD_DATA_IO_PORT 0xCD7 #define AMD_SMBUS_BASE_REG 0x2C void get_spd_spec(void); int get_ddr2_module_size(int rank_density_byte, int rank_num_byte); int get_ddr3_module_size(int sdram_capacity, int prim_bus_width, int sdram_width, int ranks); char* convert_hex_to_char(unsigned hex_org); void sb800_get_smb(void); memtest86+-5.01/Makefile0000644000000000000000000000407612201317426013511 0ustar rootroot# Makefile for MemTest86+ # # Author: Chris Brady # Created: January 1, 1996 # # Path for the floppy disk device # FDISK=/dev/fd0 AS=as -32 CC=gcc 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 cpuid.o linuxbios.o pci.o memsize.o spd.o error.o dmi.o controller.o \ smp.o vmem.o random.o all: clean memtest.bin memtest scp memtest.bin root@192.168.0.12:/srv/tftp/mt86plus # Link it statically once so I know I don't have undefined # symbols and then link it dynamically so I have full # relocation information memtest_shared: $(OBJS) memtest_shared.lds Makefile $(LD) --warn-constructors --warn-common -static -T memtest_shared.lds \ -o $@ $(OBJS) && \ $(LD) -shared -Bsymbolic -T memtest_shared.lds -o $@ $(OBJS) memtest_shared.bin: memtest_shared objcopy -O binary $< memtest_shared.bin 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 reloc.o: reloc.c $(CC) -c $(CFLAGS) -fno-strict-aliasing reloc.c test.o: 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 # rule for build number generation build_number: sh make_buildnum.sh clean: rm -f *.o *.s *.iso memtest.bin memtest memtest_shared \ memtest_shared.bin memtest.iso iso: make all ./makeiso.sh install: all dd $(FDISK) bs=8192 install-precomp: dd $(FDISK) bs=8192 dos: all cat mt86+_loader memtest.bin > memtest.exe memtest86+-5.01/controller.c0000644000000000000000000031536412201317426014405 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org */ //#include "defs.h" #include "config.h" //#include "test.h" #include "pci.h" #include "controller.h" #include "spd.h" #include "test.h" #include "stdint.h" #include "cpuid.h" #include "msr.h" #include "dmi.h" int col, col2; int nhm_bus = 0x3F; extern ulong extclock; extern unsigned long imc_type; extern struct cpu_ident cpu_id; /* #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ : "=a" (val1), "=d" (val2) \ : "c" (msr) : "edi") #define wrmsr(msr,val1,val2) \ __asm__ __volatile__("wrmsr" \ : \ : "c" (msr), "a" (val1), "d" (val2) : "edi") */ /* 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, }; void coretemp(void) { unsigned int msrl, msrh; unsigned int tjunc, tabs, tnow; unsigned long rtcr; double amd_raw_temp; // Only enable coretemp if IMC is known if(imc_type == 0) { return; } tnow = 0; // Intel CPU if(cpu_id.vend_id.char_array[0] == 'G' && cpu_id.max_cpuid >= 6) { if(cpu_id.dts_pmp & 1){ rdmsr(MSR_IA32_THERM_STATUS, msrl, msrh); tabs = ((msrl >> 16) & 0x7F); rdmsr(MSR_IA32_TEMPERATURE_TARGET, msrl, msrh); tjunc = ((msrl >> 16) & 0x7F); if(tjunc < 50 || tjunc > 125) { tjunc = 90; } // assume Tjunc = 90C if boggus value received. tnow = tjunc - tabs; dprint(LINE_CPU+1, 30, v->check_temp, 3, 0); v->check_temp = tnow; } return; } // AMD CPU if(cpu_id.vend_id.char_array[0] == 'A' && cpu_id.vers.bits.extendedFamily > 0) { pci_conf_read(0, 24, 3, 0xA4, 4, &rtcr); amd_raw_temp = ((rtcr >> 21) & 0x7FF); v->check_temp = (int)(amd_raw_temp / 8); dprint(LINE_CPU+1, 30, v->check_temp, 3, 0); } } void print_cpu_line(float dram_freq, float fsb_freq, int ram_type) { int cur_col = COL_SPEC; cprint(LINE_CPU, cur_col, "RAM: "); cur_col += 5; dprint(LINE_CPU, cur_col, dram_freq, 4, 1); cur_col += 4; cprint(LINE_CPU, cur_col, "MHz ("); cur_col += 5; switch(ram_type) { default: case 1: cprint(LINE_CPU, cur_col, "DDR-"); cur_col += 4; break; case 2: cprint(LINE_CPU, cur_col, "DDR2-"); cur_col += 5; break; case 3: cprint(LINE_CPU, cur_col, "DDR3-"); cur_col += 5; break; } if(dram_freq < 500) { dprint(LINE_CPU, cur_col, dram_freq*2, 3, 0); cur_col += 3; } else { dprint(LINE_CPU, cur_col, dram_freq*2, 4, 0); cur_col += 4; } cprint(LINE_CPU, cur_col, ")"); cur_col++; if(fsb_freq > 10) { cprint(LINE_CPU, cur_col, " - BCLK: "); cur_col += 9; dprint(LINE_CPU, cur_col, fsb_freq, 3, 0); } } void print_ram_line(float cas, int rcd, int rp, int ras, int chan) { int cur_col = COL_SPEC; cprint(LINE_RAM, cur_col, "Timings: CAS "); cur_col += 13; // CAS Latency (tCAS) if (cas == 1.5) { cprint(LINE_RAM, cur_col, "1.5"); cur_col += 3; } else if (cas == 2.5) { cprint(LINE_RAM, cur_col, "2.5"); cur_col += 3; } else if (cas < 10) { dprint(LINE_RAM, cur_col, cas, 1, 0); cur_col += 1; } else { dprint(LINE_RAM, cur_col, cas, 2, 0); cur_col += 2; } cprint(LINE_RAM, cur_col, "-"); cur_col += 1; // RAS-To-CAS (tRCD) if (rcd < 10) { dprint(LINE_RAM, cur_col, rcd, 1, 0); cur_col += 1; } else { dprint(LINE_RAM, cur_col, rcd, 2, 0); cur_col += 2; } cprint(LINE_RAM, cur_col, "-"); cur_col += 1; // RAS Precharge (tRP) if (rp < 10) { dprint(LINE_RAM, cur_col, rp, 1, 0); cur_col += 1; } else { dprint(LINE_RAM, cur_col, rp, 2, 0); cur_col += 2; } cprint(LINE_RAM, cur_col, "-"); cur_col += 1; // RAS Active to precharge (tRAS) if (ras < 10) { dprint(LINE_RAM, cur_col, ras, 1, 0); cur_col += 1; } else { dprint(LINE_RAM, cur_col, ras, 2, 0); cur_col += 2; } switch(chan) { case 0: break; case 1: cprint(LINE_RAM, cur_col, " @ 64-bit Mode"); break; case 2: cprint(LINE_RAM, cur_col, " @ 128-bit Mode"); break; case 3: cprint(LINE_RAM, cur_col, " @ 192-bit Mode"); break; case 4: cprint(LINE_RAM, cur_col, " @ 256-bit Mode"); break; } } static void poll_fsb_nothing(void) { char *name; /* Print the controller name */ name = controllers[ctrl.index].name; cprint(LINE_CPU, COL_SPEC, "Chipset: "); cprint(LINE_CPU, COL_SPEC+9, name); return; } static void poll_timings_nothing(void) { char *ram_type; /* Print the controller name */ ram_type = controllers[ctrl.index].ram_type; cprint(LINE_RAM, COL_SPEC, "RAM Type: "); cprint(LINE_RAM, COL_SPEC+10, ram_type); 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_wmr(void) { ulong dev0; // Activate MMR I/O pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); if (!(dev0 & 0x1)) { pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1); } } static void setup_nhm(void) { static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; unsigned long did, vid, mc_control, mc_ssrcontrol; int i; //Nehalem supports Scrubbing */ ctrl.cap = ECC_SCRUB; ctrl.mode = ECC_NONE; /* First, locate the PCI bus where the MCH is located */ for(i = 0; i < sizeof(possible_nhm_bus); i++) { pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid); pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did); vid &= 0xFFFF; did &= 0xFF00; if(vid == 0x8086 && did >= 0x2C00) { nhm_bus = possible_nhm_bus[i]; } } /* Now, we have the last IMC bus number in nhm_bus */ /* Check for ECC & Scrub */ pci_conf_read(nhm_bus, 3, 0, 0x4C, 2, &mc_control); if((mc_control >> 4) & 1) { ctrl.mode = ECC_CORRECT; pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); if(mc_ssrcontrol & 3) { ctrl.mode = ECC_SCRUB; } } } static void setup_nhm32(void) { static float possible_nhm_bus[] = {0xFF, 0x7F, 0x3F}; unsigned long did, vid, mc_control, mc_ssrcontrol; int i; //Nehalem supports Scrubbing */ ctrl.cap = ECC_SCRUB; ctrl.mode = ECC_NONE; /* First, locate the PCI bus where the MCH is located */ for(i = 0; i < sizeof(possible_nhm_bus); i++) { pci_conf_read( possible_nhm_bus[i], 3, 4, 0x00, 2, &vid); pci_conf_read( possible_nhm_bus[i], 3, 4, 0x02, 2, &did); vid &= 0xFFFF; did &= 0xFF00; if(vid == 0x8086 && did >= 0x2C00) { nhm_bus = possible_nhm_bus[i]; } } /* Now, we have the last IMC bus number in nhm_bus */ /* Check for ECC & Scrub */ pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); if((mc_control >> 1) & 1) { ctrl.mode = ECC_CORRECT; pci_conf_read(nhm_bus, 3, 2, 0x48, 2, &mc_ssrcontrol); if(mc_ssrcontrol & 1) { ctrl.mode = ECC_SCRUB; } } } 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.vers.bits.extendedModel >= 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 setup_k10(void) { static const int ddim[] = { ECC_NONE, ECC_CORRECT, ECC_CHIPKILL, ECC_CHIPKILL }; unsigned long nbxcfg; unsigned int mcgsrl; unsigned int mcgsth; unsigned long mcanb; unsigned long dramcl; ulong msr_low, msr_high; // 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 ((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 ); /* Enable ECS */ rdmsr(0xC001001F, msr_low, msr_high); wrmsr(0xC001001F, msr_low, (msr_high | 0x4000)); rdmsr(0xC001001F, msr_low, msr_high); } static void setup_apu(void) { ulong msr_low, msr_high; /* Enable ECS */ rdmsr(0xC001001F, msr_low, msr_high); wrmsr(0xC001001F, msr_low, (msr_high | 0x4000)); rdmsr(0xC001001F, msr_low, msr_high); } /* 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_E5400(void) { unsigned long mcs; /* Read the hardware capabilities */ pci_conf_read(ctrl.bus, 16, 1, 0x40, 4, &mcs); /* Fill in the correct memory capabilities */ ctrl.mode = 0; ctrl.cap = ECC_SCRUB; /* Checking and correcting enabled */ if (((mcs >> 5) & 1) == 1) { ctrl.mode |= ECC_CORRECT; } /* scrub enabled */ if (((mcs >> 7) & 1) == 1) { ctrl.mode |= __ECC_SCRUB; } } 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 setup_p35(void) { // Activate MMR I/O ulong dev0, capid0; pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); if (!(dev0 & 0x1)) { pci_conf_write( 0, 0, 0, 0x48, 1, dev0 | 1); } // ECC Checking (No poll on X38/48 for now) pci_conf_read( 0, 0, 0, 0xE4, 4, &capid0); if ((capid0 >> 8) & 1) { ctrl.cap = ECC_NONE; } else { ctrl.cap = ECC_CORRECT; } ctrl.mode = ECC_NONE; /* ulong toto; pci_conf_write(0, 31, 3, 0x40, 1, 0x1); pci_conf_read(0, 31, 3, 0x0, 4, &toto); hprint(11,0,toto); pci_conf_read(0, 31, 3, 0x10, 4, &toto); hprint(11,10,toto) ; pci_conf_read(0, 31, 3, 0x20, 4, &toto); hprint(11,20,toto) ; pci_conf_read(0, 28, 0, 0x0, 4, &toto); hprint(11,30,toto); pci_conf_read(0, 31, 0, 0x0, 4, &toto); hprint(11,40,toto) ; pci_conf_read(0, 31, 1, 0x0, 4, &toto); hprint(11,50,toto) ; pci_conf_read(0, 31, 2, 0x0, 4, &toto); hprint(11,60,toto) ; */ } /* 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's 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 float p4model1ratios[] = {16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15}; static float getP4PMmultiplier(void) { //unsigned int msr_lo, msr_hi; int msr_lo, msr_hi; float coef; /* Find multiplier (by MSR) */ if (cpu_id.vers.bits.family == 6) { if(cpu_id.fid.bits.eist & 1) { rdmsr(0x198, msr_lo, msr_hi); coef = ((msr_lo) >> 8) & 0x1F; if ((msr_lo >> 14) & 0x1) { coef += 0.5f; } // Atom Fix if(coef == 6) { coef = ((msr_hi) >> 8) & 0x1F; if ((msr_hi >> 14) & 0x1) { coef += 0.5f; } } } else { rdmsr(0x2A, msr_lo, msr_hi); coef = (msr_lo >> 22) & 0x1F; } } else { if (cpu_id.vers.bits.model < 2) { rdmsr(0x2A, msr_lo, msr_hi); coef = (msr_lo >> 8) & 0xF; coef = p4model1ratios[(int)coef]; } else { rdmsr(0x2C, msr_lo, msr_hi); coef = (msr_lo >> 24) & 0x1F; } } return coef; } static float getNHMmultiplier(void) { unsigned int msr_lo, msr_hi; float coef; /* Find multiplier (by MSR) */ /* First, check if Flexible Ratio is Enabled */ rdmsr(0x194, msr_lo, msr_hi); if((msr_lo >> 16) & 1){ coef = (msr_lo >> 8) & 0xFF; } else { rdmsr(0xCE, msr_lo, msr_hi); coef = (msr_lo >> 8) & 0xFF; } return coef; } static float getSNBmultiplier(void) { unsigned int msr_lo, msr_hi; float coef; rdmsr(0xCE, msr_lo, msr_hi); coef = (msr_lo >> 8) & 0xFF; return coef; } static void poll_fsb_ct(void) { unsigned long mcr, mdr; double dramratio, dramclock, fsb; float coef = getP4PMmultiplier(); /* Build the MCR Message*/ mcr = (0x10 << 24); // 10h = Read - 11h = Write mcr += (0x01 << 16); // DRAM Registers located on port 01h mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h mcr &= 0xFFFFFFF0; // bit 03:00 RSVD /* Send Message to GMCH */ pci_conf_write(0, 0, 0, 0xD0, 4, mcr); /* Read Answer from Sideband bus */ pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); /* Get RAM ratio */ switch (mdr & 0x3) { default: case 0: dramratio = 3.0f; break; case 1: dramratio = 4.0f; break; case 2: dramratio = 5.0f; break; case 3: dramratio = 6.0f; break; } // Compute FSB & RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print'em all. Whoa ! print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_amd64(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long fid, temp2; unsigned long dramchr; float clockratio; double dramclock; unsigned int dummy[3]; int ram_type; float coef = 10; cpuid(0x80000007, &dummy[0], &dummy[1], &dummy[2], &dummy[3]); /* First, got the FID by MSR */ /* First look if Cool 'n Quiet is supported to choose the best msr */ if (((dummy[3] >> 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.vers.bits.extendedModel >= 4) { /* K8 0FH */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr & 0x7); clockratio = coef; ram_type = 2; 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; ram_type = 1; 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_cpu_line(dramclock, (extclock / 1000 / coef), ram_type); } static void poll_fsb_k10(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long temp2; unsigned long dramchr; unsigned long mainPllId; double dramclock; ulong offset = 0; int ram_type = 2; /* First, we need the clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); temp2 = (dramchr & 0x7); switch (temp2) { case 0x7: temp2++; case 0x6: temp2++; case 0x5: temp2++; case 0x4: temp2++; default: temp2 += 3; } /* Compute the final DRAM Clock */ if (((cpu_id.vers.bits.extendedModel >> 4) & 0xFF) == 1) { dramclock = ((temp2 * 200) / 3.0) + 0.25; } else { unsigned long target; unsigned long dx; unsigned divisor; target = temp2 * 400; /* Get the FID by MSR */ rdmsr(0xc0010071, mcgsrl, mcgsth); pci_conf_read(0, 24, 3, 0xD4, 4, &mainPllId); if ( mainPllId & 0x40 ) mainPllId &= 0x3F; else mainPllId = 8; /* FID for 1600 */ mcgsth = (mcgsth >> 17) & 0x3F; if ( mcgsth ) { if ( mainPllId > mcgsth ) mainPllId = mcgsth; } dx = (mainPllId + 8) * 1200; for ( divisor = 3; divisor < 100; divisor++ ) if ( (dx / divisor) <= target ) break; pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); // If Channel A not enabled, switch to channel B if(((dramchr>>14) & 0x1)) { offset = 0x100; pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr); } //DDR2 or DDR3 if ((dramchr >> 8)&1) { ram_type = 3; } else { ram_type = 2;; } dramclock = ((dx / divisor) / 6.0) + 0.25; } /* ...and print */ print_cpu_line(dramclock, 0, ram_type); } static void poll_fsb_k12(void) { unsigned long temp2; unsigned long dramchr; double dramratio, dramclock, fsb, did; unsigned int mcgsrl,mcgsth, fid, did_raw; // Get current FID & DID rdmsr(0xc0010071, mcgsrl, mcgsth); did_raw = mcgsrl & 0xF; fid = (mcgsrl >> 4) & 0xF; switch(did_raw) { default: case 0x0: did = 1.0f; break; case 0x1: did = 1.5f; break; case 0x2: did = 2.0f; break; case 0x3: did = 3.0f; break; case 0x4: did = 4.0f; break; case 0x5: did = 6.0f; break; case 0x6: did = 8.0f; break; case 0x7: did = 12.0f; break; case 0x8: did = 16.0f; break; } fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / did)); /* Finaly, we need the clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); if(((dramchr >> 14) & 0x1) == 1) { pci_conf_read(0, 24, 2, 0x194, 4, &dramchr); } temp2 = (dramchr & 0x1F); switch (temp2) { default: case 0x06: dramratio = 4.0f; break; case 0x0A: dramratio = 16.0f / 3.0f; break; case 0x0E: dramratio = 20.0f / 3.0f; break; case 0x12: dramratio = 8.0f; break; case 0x16: dramratio = 28.0f / 3.0f; break; } dramclock = fsb * dramratio; /* print */ print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_k16(void) { unsigned long dramchr; double dramratio, dramclock, fsb; // FIXME: Unable to find a real way to detect multiplier. fsb = 100.0f; /* Clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); switch (dramchr & 0x1F) { default: case 0x04: /* 333 */ dramratio = 10.0f / 3.0f; break; case 0x06: /* 400 */ dramratio = 4.0f; break; case 0x0A: /* 533 */ dramratio = 16.0f / 3.0f; break; case 0x0E: /* 667 */ dramratio = 20.0f / 3.0f; break; case 0x12: /* 800 */ dramratio = 8.0f; break; case 0x16: /* 933 */ dramratio = 28.0f / 3.0f; break; case 0x19: /* 1050 */ dramratio = 21.0f / 2.0f; break; case 0x1A: /* 1066 */ dramratio = 32.0f / 3.0f; break; } dramclock = fsb * dramratio; /* print */ print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_k15(void) { unsigned long temp2; unsigned long dramchr; double dramratio, dramclock, fsb; unsigned int mcgsrl,mcgsth, fid, did; // Get current FID & DID rdmsr(0xc0010071, mcgsrl, mcgsth); fid = mcgsrl & 0x3F; did = (mcgsrl >> 6) & 0x7; fsb = ((extclock / 1000.0f) / ((fid + 16.0f) / (2^did)) / 2); /* Finaly, we need the clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); if(((dramchr >> 14) & 0x1) == 1) { pci_conf_read(0, 24, 2, 0x194, 4, &dramchr); } temp2 = (dramchr & 0x1F); switch (temp2) { case 0x04: dramratio = 10.0f / 3.0f; break; default: case 0x06: dramratio = 4.0f; break; case 0x0A: dramratio = 16.0f / 3.0f; break; case 0x0E: dramratio = 20.0f / 3.0f; break; case 0x12: dramratio = 8.0f; break; case 0x16: dramratio = 28.0f / 3.0f; break; case 0x1A: dramratio = 32.0f / 3.0f; break; case 0x1F: dramratio = 36.0f / 3.0f; break; } dramclock = fsb * dramratio; /* print */ print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_k14(void) { unsigned long dramchr; double dramratio, dramclock, fsb; // FIXME: Unable to find a real way to detect multiplier. fsb = 100.0f; /* Clock ratio */ pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); switch (dramchr & 0x1F) { default: case 0x06: dramratio = 4.0f; break; case 0x0A: dramratio = 16.0f / 3.0f; break; case 0x0E: dramratio = 20.0f / 3.0f; break; case 0x12: dramratio = 8.0f; break; } dramclock = fsb * dramratio; /* print */ print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_i925(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, mchcfg2, dev0, drc, idetect; float coef = getP4PMmultiplier(); long *ptr; int ddr_type; 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; } ddr_type = 1; } else { // We are in DDR2 Mode ddr_type = 2; 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_cpu_line(dramclock, fsb, ddr_type); } static void poll_fsb_i945(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0; float 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 print_cpu_line(dramclock, fsb, 2); } static void poll_fsb_i945gme(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float 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 = 400; break; default: case 1: fsb_mch = 533; break; case 2: fsb_mch = 667; break; } switch (fsb_mch) { case 400: switch ((mchcfg >> 4)&7) { case 2: dramratio = 1.0f; break; case 3: dramratio = 4.0f/3.0f; break; case 4: dramratio = 5.0f/3.0f; break; } break; default: case 533: switch ((mchcfg >> 4)&7) { case 2: dramratio = 3.0f/4.0f; break; case 3: dramratio = 1.0f; break; case 4: dramratio = 5.0f/4.0f; break; } break; case 667: switch ((mchcfg >> 4)&7) { case 2: dramratio = 3.0f/5.0f; break; case 3: dramratio = 4.0f/5.0f; break; case 4: dramratio = 1.0f; break; } break; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio * 2; print_cpu_line(dramclock, fsb, 2); } static void poll_fsb_i975(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float 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_cpu_line(dramclock, fsb, 2); } static void poll_fsb_i965(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float coef = getP4PMmultiplier(); long *ptr; /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 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; case 4: fsb_mch = 1333; break; case 6: fsb_mch = 1600; 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 = 5.0f/4.0f; break; case 2: dramratio = 5.0f/3.0f; break; case 3: dramratio = 2.0f; break; case 4: dramratio = 8.0f/3.0f; break; case 5: dramratio = 10.0f/3.0f; break; } break; case 1066: switch ((mchcfg >> 4)&7) { case 1: dramratio = 1.0f; break; case 2: dramratio = 5.0f/4.0f; break; case 3: dramratio = 3.0f/2.0f; break; case 4: dramratio = 2.0f; break; case 5: dramratio = 5.0f/2.0f; break; } break; case 1333: switch ((mchcfg >> 4)&7) { case 2: dramratio = 1.0f; break; case 3: dramratio = 6.0f/5.0f; break; case 4: dramratio = 8.0f/5.0f; break; case 5: dramratio = 2.0f; break; } break; case 1600: switch ((mchcfg >> 4)&7) { case 3: dramratio = 1.0f; break; case 4: dramratio = 4.0f/3.0f; break; case 5: dramratio = 3.0f/2.0f; break; case 6: dramratio = 2.0f; break; } break; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 2); } static void poll_fsb_p35(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch, Device_ID, Memory_Check, c0ckectrl, offset; float coef = getP4PMmultiplier(); long *ptr; int ram_type; pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID); Device_ID &= 0xFFFF; /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); 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; case 4: fsb_mch = 1333; break; case 6: fsb_mch = 1600; 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 = 5.0f/4.0f; break; case 2: dramratio = 5.0f/3.0f; break; case 3: dramratio = 2.0; break; case 4: dramratio = 8.0f/3.0f; break; case 5: dramratio = 10.0f/3.0f; break; } break; case 1066: switch ((mchcfg >> 4)&7) { case 1: dramratio = 1.0f; break; case 2: dramratio = 5.0f/4.0f; break; case 3: dramratio = 3.0f/2.0f; break; case 4: dramratio = 2.0f; break; case 5: dramratio = 5.0f/2.0f; break; } break; case 1333: switch ((mchcfg >> 4)&7) { case 2: dramratio = 1.0f; break; case 3: dramratio = 6.0f/5.0f; break; case 4: dramratio = 8.0f/5.0f; break; case 5: dramratio = 2.0f; break; } break; case 1600: switch ((mchcfg >> 4)&7) { case 3: dramratio = 1.0f; break; case 4: dramratio = 4.0f/3.0f; break; case 5: dramratio = 3.0f/2.0f; break; case 6: dramratio = 2.0f; break; } break; } // On P45, check 1A8 if(Device_ID > 0x2E00 && imc_type != 8) { ptr = (long*)(dev0+offset+0x1A8); Memory_Check = *ptr & 0xFFFFFFFF; Memory_Check >>= 2; Memory_Check &= 1; Memory_Check = !Memory_Check; } else if (imc_type == 8) { ptr = (long*)(dev0+offset+0x224); Memory_Check = *ptr & 0xFFFFFFFF; Memory_Check &= 1; Memory_Check = !Memory_Check; } else { ptr = (long*)(dev0+offset+0x1E8); Memory_Check = *ptr & 0xFFFFFFFF; } //Determine DDR-II or DDR-III if (Memory_Check & 1) { ram_type = 2; } else { ram_type = 3; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, ram_type); } static void poll_fsb_im965(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, dev0, fsb_mch; float coef = getP4PMmultiplier(); long *ptr; /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0xC00); mchcfg = *ptr & 0xFFFF; dramratio = 1; switch (mchcfg & 7) { case 1: fsb_mch = 533; break; default: case 2: fsb_mch = 800; break; case 3: fsb_mch = 667; break; case 6: fsb_mch = 1066; break; } switch (fsb_mch) { case 533: switch ((mchcfg >> 4)&7) { case 1: dramratio = 5.0f/4.0f; break; case 2: dramratio = 3.0f/2.0f; break; case 3: dramratio = 2.0f; break; } break; case 667: switch ((mchcfg >> 4)&7) { case 1: dramratio = 1.0f; break; case 2: dramratio = 6.0f/5.0f; break; case 3: dramratio = 8.0f/5.0f; break; case 4: dramratio = 2.0f; break; case 5: dramratio = 12.0f/5.0f; break; } break; default: case 800: switch ((mchcfg >> 4)&7) { case 1: dramratio = 5.0f/6.0f; break; case 2: dramratio = 1.0f; break; case 3: dramratio = 4.0f/3.0f; break; case 4: dramratio = 5.0f/3.0f; break; case 5: dramratio = 2.0f; break; } break; case 1066: switch ((mchcfg >> 4)&7) { case 5: dramratio = 3.0f/2.0f; break; case 6: dramratio = 2.0f; break; } break; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 2); } static void poll_fsb_5400(void) { double dramclock, dramratio, fsb; unsigned long ambase_low, ambase_high, ddrfrq; float coef = getP4PMmultiplier(); /* Find dramratio */ pci_conf_read( 0, 16, 0, 0x48, 4, &ambase_low); ambase_low &= 0xFFFE0000; pci_conf_read( 0, 16, 0, 0x4C, 4, &ambase_high); ambase_high &= 0xFF; pci_conf_read( 0, 16, 1, 0x56, 1, &ddrfrq); ddrfrq &= 7; dramratio = 1; switch (ddrfrq) { case 0: case 1: case 4: dramratio = 1.0; break; case 2: dramratio = 5.0f/4.0f; break; case 3: case 7: dramratio = 4.0f/5.0f; break; } // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 2); } static void poll_fsb_nf4ie(void) { double dramclock, dramratio, fsb; float mratio, nratio; unsigned long reg74, reg60; float 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_cpu_line(dramclock, fsb, 2); } static void poll_fsb_i875(void) { double dramclock, dramratio, fsb; unsigned long mchcfg, smfs; float 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_cpu_line(dramclock, fsb, 2); } static void poll_fsb_p4(void) { ulong fsb, idetect; float coef = getP4PMmultiplier(); char *name; int col,temp; fsb = ((extclock /1000) / coef); /* For synchro only chipsets */ pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); if (idetect == 0x2540 || idetect == 0x254C) { print_cpu_line(fsb, fsb, 1); } else { /* Print the controller name */ col = COL_SPEC; cprint(LINE_CPU, col, "Chipset: "); col += 9; /* Print the controller name */ name = controllers[ctrl.index].name; cprint(LINE_CPU, col, name); /* Now figure out how much I just printed */ temp = 20; while(name[temp - 20] != '\0') { col++; temp++; } if(temp < 36){ cprint(LINE_CPU, col +1, "- FSB : "); col += 9; dprint(LINE_CPU, col, fsb, 3,0); col += 3; } } } static void poll_fsb_i855(void) { double dramclock, dramratio, fsb ; unsigned int msr_lo, msr_hi; ulong mchcfg, idetect; int coef; pci_conf_read( 0, 0, 0, 0x02, 2, &idetect); /* Find multiplier (by MSR) */ /* Is it a Pentium M ? */ if (cpu_id.vers.bits.family == 6) { rdmsr(0x2A, msr_lo, msr_hi); coef = (msr_lo >> 22) & 0x1F; } else { rdmsr(0x2C, msr_lo, msr_hi); coef = (msr_lo >> 24) & 0x1F; } fsb = ((extclock /1000) / coef); /* 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_cpu_line(dramclock, fsb, 1); } static void poll_fsb_amd32(void) { unsigned int mcgsrl; unsigned int mcgsth; unsigned long temp; double dramclock; double coef2; int col; char *name; /* 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; /* Print the controller name */ col = COL_SPEC; cprint(LINE_CPU, col, "Chipset: "); col += 9; /* Print the controller name */ name = controllers[ctrl.index].name; cprint(LINE_CPU, col, name); /* Now figure out how much I just printed */ temp = 20; while(name[temp - 20] != '\0') { col++; temp++; } if(temp < 36){ cprint(LINE_CPU, col +1, "- FSB : "); col += 9; dprint(LINE_CPU, col, dramclock, 3,0); col += 3; } } 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 */ print_cpu_line(dramclock, fsb, 1); } static void poll_fsb_us15w(void) { double dramclock, dramratio, fsb; unsigned long msr; /* Find dramratio */ /* D0 MsgRd, 05 Zunit, 03 MSR */ pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0050300 ); pci_conf_read(0, 0, 0, 0xD4, 4, &msr ); fsb = ( msr >> 3 ) & 1; dramratio = 0.5; // Compute RAM Frequency if (( msr >> 3 ) & 1) { fsb = 533; } else { fsb = 400; } /* switch (( msr >> 0 ) & 7) { case 0: gfx = 100; break; case 1: gfx = 133; break; case 2: gfx = 150; break; case 3: gfx = 178; break; case 4: gfx = 200; break; case 5: gfx = 266; break; default: gfx = 0; break; } */ dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 1); } static void poll_fsb_nhm(void) { double dramclock, dramratio, fsb; unsigned long mc_dimm_clk_ratio; float coef = getNHMmultiplier(); //unsigned long qpi_pll_status; //float qpi_speed; fsb = ((extclock /1000) / coef); /* Print QPI Speed (if ECC not supported) */ /* if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 10) { pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status); qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2; cprint(LINE_CPU+5, col +1, "/ QPI : "); col += 9; dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); col += 1; cprint(LINE_CPU+5, col, "."); col += 1; qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; dprint(LINE_CPU+5, col, qpi_speed, 1,0); col += 1; cprint(LINE_CPU+5, col +1, "GT/s"); col += 5; } */ /* Get the clock ratio */ pci_conf_read(nhm_bus, 3, 4, 0x54, 2, &mc_dimm_clk_ratio); dramratio = (mc_dimm_clk_ratio & 0x1F); // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio / 2; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_nhm32(void) { double dramclock, dramratio, fsb; unsigned long mc_dimm_clk_ratio; float coef = getNHMmultiplier(); //unsigned long qpi_pll_status; //float qpi_speed; fsb = ((extclock /1000) / coef); /* Print QPI Speed (if ECC not supported) */ /* if(ctrl.mode == ECC_NONE && cpu_id.vers.bits.model == 12) { pci_conf_read(nhm_bus, 2, 1, 0x50, 2, &qpi_pll_status); qpi_speed = (qpi_pll_status & 0x7F) * ((extclock / 1000) / coef) * 2; cprint(LINE_CPU+5, col +1, "/ QPI : "); col += 9; dprint(LINE_CPU+5, col, qpi_speed/1000, 1,0); col += 1; cprint(LINE_CPU+5, col, "."); col += 1; qpi_speed = ((qpi_speed / 1000) - (int)(qpi_speed / 1000)) * 10; dprint(LINE_CPU+5, col, qpi_speed, 1,0); col += 1; cprint(LINE_CPU+5, col +1, "GT/s"); col += 5; } */ /* Get the clock ratio */ pci_conf_read(nhm_bus, 3, 4, 0x50, 2, &mc_dimm_clk_ratio); dramratio = (mc_dimm_clk_ratio & 0x1F); // Compute RAM Frequency fsb = ((extclock / 1000) / coef); dramclock = fsb * dramratio / 2; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_wmr(void) { double dramclock, dramratio, fsb; unsigned long dev0; float coef = getNHMmultiplier(); long *ptr; fsb = ((extclock / 1000) / coef); /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x2C20); dramratio = 1; /* Get the clock ratio */ dramratio = 0.25 * (float)(*ptr & 0x1F); // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_snb(void) { double dramclock, dramratio, fsb; unsigned long dev0; float coef = getSNBmultiplier(); long *ptr; fsb = ((extclock / 1000) / coef); /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x5E04); dramratio = 1; /* Get the clock ratio */ dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f); // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_ivb(void) { double dramclock, dramratio, fsb; unsigned long dev0, mchcfg; float coef = getSNBmultiplier(); long *ptr; fsb = ((extclock / 1000) / coef); /* Find dramratio */ pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x5E04); mchcfg = *ptr & 0xFFFF; dramratio = 1; /* Get the clock ratio */ switch((mchcfg >> 8) & 0x01) { case 0x0: dramratio = (float)(*ptr & 0x1F) * (133.34f / 100.0f); break; case 0x1: dramratio = (float)(*ptr & 0x1F) * (100.0f / 100.0f); break; } // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } static void poll_fsb_snbe(void) { double dramclock, dramratio, fsb; unsigned long dev0; float coef = getSNBmultiplier(); fsb = ((extclock / 1000) / coef); /* Find dramratio */ pci_conf_read( 0xFF, 10, 1, 0x98, 4, &dev0); dev0 &= 0xFFFFFFFF; dramratio = 1; /* Get the clock ratio */ dramratio = (float)(dev0 & 0x3F) * (66.67f / 100.0f); // Compute RAM Frequency dramclock = fsb * dramratio; // Print DRAM Freq print_cpu_line(dramclock, fsb, 3); } /* ------------------ Here the code for Timings detection ------------------ */ /* ------------------------------------------------------------------------- */ static void poll_timings_nf4ie(void) { ulong regd0, reg8c, reg9c, reg80; int cas, rcd, rp, ras, chan; //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; if (reg80 & 0x3) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_i875(void) { ulong dev6, dev62; ulong temp; float cas; int rcd, rp, ras, chan; long *ptr, *ptr2; pci_conf_read( 0, 6, 0, 0x40, 4, &dev62); ptr2=(long*)(dev6+0x68); /* Read the MMR Base Address & Define the pointer */ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); /* 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 64 or 128 bits mode if (((*ptr2 >> 21)&3) > 0) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_i925(void) { // Thanks for CDH optis float cas; int rcd,rp,ras,chan; 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; // CAS Latency (tCAS) temp = ((drt >> 8)& 0x3); if ((drc & 3) == 2){ // Timings DDR-II if (temp == 0x0) { cas = 5; } else if (temp == 0x1) { cas = 4; } else if (temp == 0x2) { cas = 3; } else { cas = 6; } } else { // Timings DDR-I if (temp == 0x0) { cas = 3; } else if (temp == 0x1) { cas = 2.5f;} else { cas = 2; } } // RAS-To-CAS (tRCD) rcd = ((drt >> 4)& 0x3)+2; // RAS Precharge (tRP) rp = (drt&0x3)+2; // RAS Active to precharge (tRAS) // If Lakeport, than change tRAS computation (Thanks to CDH, again) if (idetect > 0x2700) ras = ((drt >> 19)& 0x1F); else ras = ((drt >> 20)& 0x0F); temp = (dcc&0x3); if (temp == 1) { chan = 2; } else if (temp == 2) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_i965(void) { // Thanks for CDH optis ulong dev0, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register; long *ptr; int rcd,rp,ras,chan; float cas; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x29C); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x250); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x258); Read_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) cas = ((ODT_Control_Register >> 17)& 7) + 3.0f; // RAS-To-CAS (tRCD) rcd = (Read_Register >> 16) & 0xF; // RAS Precharge (tRP) rp = (ACT_Register >> 13) & 0xF; // RAS Active to precharge (tRAS) ras = (Precharge_Register >> 11) & 0x1F; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_im965(void) { // Thanks for CDH optis ulong dev0, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register; long *ptr; int rcd,rp,ras,chan; float cas; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x1200); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x1300); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x100); ptr = (long*)(dev0+offset+0x121C); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x1214); Precharge_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) cas = ((ODT_Control_Register >> 23)& 7) + 3.0f; // RAS-To-CAS (tRCD) rcd = ((Precharge_Register >> 5)& 7) + 2.0f; // RAS Precharge (tRP) rp = (Precharge_Register & 7) + 2.0f; // RAS Active to precharge (tRAS) ras = (Precharge_Register >> 21) & 0x1F; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_p35(void) { // Thanks for CDH optis float cas; int rcd, rp, ras, chan; ulong dev0, Device_ID, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register; long *ptr; pci_conf_read( 0, 0, 0, 0x02, 2, &Device_ID); Device_ID &= 0xFFFF; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x265); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x25D); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x258); Read_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) if(Device_ID > 0x2E00 && imc_type != 8) { cas = ((ODT_Control_Register >> 8)& 0x3F) - 6.0f; } else { cas = ((ODT_Control_Register >> 8)& 0x3F) - 9.0f; } // RAS-To-CAS (tRCD) rcd = (Read_Register >> 17) & 0xF; // RAS Precharge (tRP) rp = (ACT_Register >> 13) & 0xF; // RAS Active to precharge (tRAS) ras = Precharge_Register & 0x3F; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_wmr(void) { float cas; int rcd, rp, ras, chan; ulong dev0, c0ckectrl, c1ckectrl, offset; ulong ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, MRC_Register; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; ptr = (long*)(dev0+0x260); c0ckectrl = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+0x660); c1ckectrl = *ptr & 0xFFFFFFFF; // If DIMM 0 not populated, check DIMM 1 ((c0ckectrl) >> 20 & 0xF)?(offset = 0):(offset = 0x400); ptr = (long*)(dev0+offset+0x265); ODT_Control_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x25D); Precharge_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x252); ACT_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x258); Read_Register = *ptr & 0xFFFFFFFF; ptr = (long*)(dev0+offset+0x240); MRC_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) if(MRC_Register & 0xF) { cas = (MRC_Register & 0xF) + 3.0f; } else { cas = ((ODT_Control_Register >> 8)& 0x3F) - 5.0f; } // RAS-To-CAS (tRCD) rcd = (Read_Register >> 17) & 0xF; // RAS Precharge (tRP) rp = (ACT_Register >> 13) & 0xF; // RAS Active to precharge (tRAS) ras = Precharge_Register & 0x3F; if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_snb(void) { float cas; int rcd, rp, ras, chan; ulong dev0, offset; ulong IMC_Register, MCMain0_Register, MCMain1_Register; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; offset = 0x0000; ptr = (long*)(dev0+offset+0x4000); IMC_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) cas = (float)((IMC_Register >> 8) & 0x0F); // RAS-To-CAS (tRCD) rcd = IMC_Register & 0x0F; // RAS Precharge (tRP) rp = (IMC_Register >> 4) & 0x0F; // RAS Active to precharge (tRAS) ras = (IMC_Register >> 16) & 0xFF; // Channels ptr = (long*)(dev0+offset+0x5004); MCMain0_Register = *ptr & 0xFFFF; ptr = (long*)(dev0+offset+0x5008); MCMain1_Register = *ptr & 0xFFFF; if(MCMain0_Register == 0 || MCMain1_Register == 0) { chan = 1; } else { chan = 2; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_hsw(void) { float cas; int rcd, rp, ras, chan; ulong dev0, offset = 0; ulong IMC_Register, MCMain0_Register, MCMain1_Register; long *ptr; //Now, read MMR Base Address pci_conf_read( 0, 0, 0, 0x48, 4, &dev0); dev0 &= 0xFFFFC000; // Channels ptr = (long*)(dev0+offset+0x5004); MCMain0_Register = *ptr & 0xFFFF; ptr = (long*)(dev0+offset+0x5008); MCMain1_Register = *ptr & 0xFFFF; if(MCMain0_Register && MCMain1_Register) { chan = 2; } else { chan = 1; } if(MCMain0_Register) { offset = 0x0000; } else { offset = 0x0400; } // CAS Latency (tCAS) ptr = (long*)(dev0+offset+0x4014); IMC_Register = *ptr & 0xFFFFFFFF; cas = (float)(IMC_Register & 0x1F); ptr = (long*)(dev0+offset+0x4000); IMC_Register = *ptr & 0xFFFFFFFF; // RAS-To-CAS (tRCD) rcd = IMC_Register & 0x1F; // RAS Precharge (tRP) rp = (IMC_Register >> 5) & 0x1F; // RAS Active to precharge (tRAS) ras = (IMC_Register >> 10) & 0x3F; print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_snbe(void) { float cas; int rcd, rp, ras; int nb_channel = 0, current_channel = 0; ulong temp, IMC_Register; long *ptr; //Read Channel #1 pci_conf_read(0xFF, 16, 2, 0x80, 4, &temp); temp &= 0x3F; if(temp != 0xB) { current_channel = 0; nb_channel++; } //Read Channel #2 pci_conf_read(0xFF, 16, 3, 0x80, 4, &temp); temp &= 0x3F; if(temp != 0xB) { current_channel = 1; nb_channel++; } //Read Channel #3 pci_conf_read(0xFF, 16, 6, 0x80, 4, &temp); temp &= 0x3F; if(temp != 0xB) { current_channel = 4; nb_channel++; } //Read Channel #4 pci_conf_read(0xFF, 16, 7, 0x80, 4, &temp); temp &= 0x3F; if(temp != 0xB) { current_channel = 5; nb_channel++; } pci_conf_read(0, 5, 0, 0x84, 4, &temp); ptr = (long*)((temp & 0xFC000000) + (MAKE_PCIE_ADDRESS(0xFF,16,current_channel) | 0x200)); IMC_Register = *ptr & 0xFFFFFFFF; // CAS Latency (tCAS) cas = (float)((IMC_Register >> 9) & 0x1F); // RAS-To-CAS (tRCD) rcd = IMC_Register & 0x1F; // RAS Precharge (tRP) rp = (IMC_Register >> 5) & 0x0F; // RAS Active to precharge (tRAS) ras = (IMC_Register >> 19) & 0x3F; print_ram_line(cas, rcd, rp, ras, nb_channel); } static void poll_timings_5400(void) { // Thanks for CDH optis ulong ambase, mtr1, mtr2, offset, mca; long *ptr; float cas; int rcd, rp, ras, chan; //Hard-coded Ambase value (should not be realocated by software when using Memtest86+ ambase = 0xFE000000; offset = mtr1 = mtr2 = 0; // Will loop until a valid populated channel is found // Bug : DIMM 0 must be populated or it will fall in an endless loop while(((mtr2 & 0xF) < 3) || ((mtr2 & 0xF) > 6)) { ptr = (long*)(ambase+0x378+offset); mtr1 = *ptr & 0xFFFFFFFF; ptr = (long*)(ambase+0x37C+offset); mtr2 = *ptr & 0xFFFFFFFF; offset += 0x8000; } pci_conf_read( 0, 16, 1, 0x58, 4, &mca); //This chipset only supports FB-DIMM (Removed => too long) //cprint(LINE_CPU+5, col +1, "- Type : FBD"); // Now, detect timings // CAS Latency (tCAS) cas = mtr2 & 0xF; // RAS-To-CAS (tRCD) rcd = 6 - ((mtr1 >> 10) & 3); // RAS Precharge (tRP) rp = 6 - ((mtr1 >> 8) & 3); // RAS Active to precharge (tRAS) ras = 16 - (3 * ((mtr1 >> 29) & 3)) + ((mtr1 >> 12) & 3); if(((mtr1 >> 12) & 3) == 3 && ((mtr1 >> 29) & 3) == 2) { ras = 9; } if ((mca >> 14) & 1) { chan = 1; } else { chan = 2; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_E7520(void) { ulong drt, ddrcsr; float cas; int rcd, rp, ras, chan; 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; if ((ddrcsr & 0xF) >= 0xC) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_i855(void) { ulong drt, temp; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 0, 0x78, 4, &drt); /* Now, we could print some additionnals timings infos) */ cprint(LINE_CPU+6, col2 +1, "/ CAS : "); col2 += 9; // CAS Latency (tCAS) temp = ((drt >> 4)&0x1); if (temp == 0x0) { cas = 2.5; } else { cas = 2; } // RAS-To-CAS (tRCD) temp = ((drt >> 2)& 0x1); if (temp == 0x0) { rcd = 3; } else { rcd = 2; } // RAS Precharge (tRP) temp = (drt&0x1); if (temp == 0x0) { rp = 3 ; } else { rp = 2; } // RAS Active to precharge (tRAS) temp = 7-((drt >> 9)& 0x3); if (temp == 0x0) { ras = 7; } if (temp == 0x1) { ras = 6; } if (temp == 0x2) { ras = 5; } print_ram_line(cas, rcd, rp, ras, 1); } static void poll_timings_E750x(void) { ulong drt, drc, temp; float cas; int rcd, rp, ras, chan; 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; } if (((drc >> 22)&1) == 1) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_i852(void) { ulong drt, temp; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 1, 0x60, 4, &drt); /* Now, we could print some additionnals timings infos) */ cprint(LINE_CPU+6, col2 +1, "/ CAS : "); col2 += 9; // CAS Latency (tCAS) temp = ((drt >> 5)&0x1); if (temp == 0x0) { cas = 2.5; } else { cas = 2; } // RAS-To-CAS (tRCD) temp = ((drt >> 2)& 0x3); if (temp == 0x0) { rcd = 4; } if (temp == 0x1) { rcd = 3; } else { rcd = 2; } // RAS Precharge (tRP) temp = (drt&0x3); if (temp == 0x0) { rp = 4; } if (temp == 0x1) { rp = 3; } else { rp = 2; } // RAS Active to precharge (tRAS) temp = ((drt >> 9)& 0x3); if (temp == 0x0) { ras = 8; } if (temp == 0x1) { ras = 7; } if (temp == 0x2) { ras = 6; } if (temp == 0x3) { ras = 5; } print_ram_line(cas, rcd, rp, ras, 1); } static void poll_timings_amd64(void) { ulong dramtlr, dramclr; int temp, chan; float tcas; int trcd, trp, tras ; pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); pci_conf_read(0, 24, 2, 0x90, 4, &dramclr); if (cpu_id.vers.bits.extendedModel >= 4) { /* NEW K8 0Fh Family 90 nm (DDR2) */ // CAS Latency (tCAS) tcas = (dramtlr & 0x7) + 1; // RAS-To-CAS (tRCD) trcd = ((dramtlr >> 4) & 0x3) + 3; // RAS Precharge (tRP) trp = ((dramtlr >> 8) & 0x3) + 3; // RAS Active to precharge (tRAS) tras = ((dramtlr >> 12) & 0xF) + 3; // Print 64 or 128 bits mode if ((dramclr >> 11)&1) { chan = 2; } else { chan = 1; } } else { /* OLD K8 (DDR1) */ // CAS Latency (tCAS) temp = (dramtlr & 0x7); if (temp == 0x1) { tcas = 2; } if (temp == 0x2) { tcas = 3; } if (temp == 0x5) { tcas = 2.5; } // RAS-To-CAS (tRCD) trcd = ((dramtlr >> 12) & 0x7); // RAS Precharge (tRP) trp = ((dramtlr >> 24) & 0x7); // RAS Active to precharge (tRAS) tras = ((dramtlr >> 20) & 0xF); // Print 64 or 128 bits mode if (((dramclr >> 16)&1) == 1) { chan = 2; } else { chan = 1; } } print_ram_line(tcas, trcd, trp, tras, chan); } static void poll_timings_k10(void) { ulong dramtlr, dramclr, dramchr, dramchrb; ulong offset = 0; int cas, rcd, rp, ras, chan; pci_conf_read(0, 24, 2, 0x94, 4, &dramchr); pci_conf_read(0, 24, 2, 0x194, 4, &dramchrb); if(((dramchr>>14) & 0x1) || ((dramchr>>14) & 0x1)) { chan = 1; } else { chan = 2; } // If Channel A not enabled, switch to channel B if(((dramchr>>14) & 0x1)) { offset = 0x100; pci_conf_read(0, 24, 2, 0x94+offset, 4, &dramchr); } pci_conf_read(0, 24, 2, 0x88+offset, 4, &dramtlr); pci_conf_read(0, 24, 2, 0x110, 4, &dramclr); // CAS Latency (tCAS) if(((dramchr >> 8)&1) || ((dramchr & 0x7) == 0x4)){ // DDR3 or DDR2-1066 cas = (dramtlr & 0xF) + 4; rcd = ((dramtlr >> 4) & 0x7) + 5; rp = ((dramtlr >> 7) & 0x7) + 5; ras = ((dramtlr >> 12) & 0xF) + 15; } else { // DDR2-800 or less cas = (dramtlr & 0xF) + 1; rcd = ((dramtlr >> 4) & 0x3) + 3; rp = ((dramtlr >> 8) & 0x3) + 3; ras = ((dramtlr >> 12) & 0xF) + 3; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_k12(void) { ulong dramt0, dramlow, dimma, dimmb; int cas, rcd, rp, ras, chan = 0; pci_conf_read(0, 24, 2, 0x94, 4, &dimma); pci_conf_read(0, 24, 2, 0x194, 4, &dimmb); if(((dimma >> 14) & 0x1) == 0) { chan++; pci_conf_read(0, 24, 2, 0x88, 4, &dramlow); pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040); pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0); } if(((dimmb >> 14) & 0x1) == 0) { chan++; pci_conf_read(0, 24, 2, 0x188, 4, &dramlow); pci_conf_write(0, 24, 2, 0x1F0, 4, 0x00000040); pci_conf_read(0, 24, 2, 0x1F4, 4, &dramt0); } cas = (dramlow & 0xF) + 4; rcd = (dramt0 & 0xF) + 5; rp = ((dramt0 >> 8) & 0xF) + 5; ras = ((dramt0 >> 16) & 0x1F) + 15; print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_k14(void) { ulong dramt0, dramlow; int cas, rcd, rp, ras; pci_conf_read(0, 24, 2, 0x88, 4, &dramlow); pci_conf_write(0, 24, 2, 0xF0, 4, 0x00000040); pci_conf_read(0, 24, 2, 0xF4, 4, &dramt0); cas = (dramlow & 0xF) + 4; rcd = (dramt0 & 0xF) + 5; rp = ((dramt0 >> 8) & 0xF) + 5; ras = ((dramt0 >> 16) & 0x1F) + 15; print_ram_line(cas, rcd, rp, ras, 1); } static void poll_timings_k15(void) { ulong dramp1, dramp2, dimma, dimmb; int cas, rcd, rp, ras, chan = 0; pci_conf_read(0, 24, 2, 0x94, 4, &dimma); pci_conf_read(0, 24, 2, 0x194, 4, &dimmb); if(((dimma>>14) & 0x1) || ((dimmb>>14) & 0x1)) { chan = 1; } else { chan = 2; } pci_conf_read(0, 24, 2, 0x200, 4, &dramp1); pci_conf_read(0, 24, 2, 0x204, 4, &dramp2); cas = dramp1 & 0x1F; rcd = (dramp1 >> 8) & 0x1F; rp = (dramp1 >> 16) & 0x1F; ras = (dramp1 >> 24) & 0x3F; print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_k16(void) { ulong dramt0, dramt1; int cas, rcd, rp, rc, ras; pci_conf_read(0, 24, 2, 0x200, 4, &dramt0); pci_conf_read(0, 24, 2, 0x204, 4, &dramt1); cas = (dramt0 & 0x1F); rcd = ((dramt0 >> 8) & 0x1F); rp = ((dramt0 >> 16) & 0x1F); ras = ((dramt0 >> 24) & 0x3F); rc = (dramt1 & 0x3F); print_ram_line(cas, rcd, rp, ras, 1); } static void poll_timings_EP80579(void) { ulong drt1, drt2; float cas; int rcd, rp, ras; pci_conf_read( 0, 0, 0, 0x78, 4, &drt1); pci_conf_read( 0, 0, 0, 0x64, 4, &drt2); cas = ((drt1 >> 3) & 0x7) + 3; rcd = ((drt1 >> 9) & 0x7) + 3; rp = ((drt1 >> 6) & 0x7) + 3; ras = ((drt2 >> 28) & 0xF) + 8; print_ram_line(cas, rcd, rp, ras, 0); } static void poll_timings_nf2(void) { ulong dramtlr, dramtlr2, dramtlr3, temp; ulong dimm1p, dimm2p, dimm3p; float cas; int rcd, rp, ras, chan; 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); // CAS Latency (tCAS) temp = ((dramtlr2 >> 4) & 0x7); if (temp == 0x2) { cas = 2; } if (temp == 0x3) { cas = 3; } if (temp == 0x6) { cas = 2.5; } // RAS-To-CAS (tRCD) rcd = ((dramtlr >> 20) & 0xF); // RAS Precharge (tRP) rp = ((dramtlr >> 28) & 0xF); // RAS Active to precharge (tRAS) ras = ((dramtlr >> 15) & 0xF); // 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 ) { chan = 2; } else { chan = 1; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_us15w(void) { // Thanks for CDH optis ulong dtr; float cas; int rcd, rp; /* Find dramratio */ /* D0 MsgRd, 01 Dunit, 01 DTR */ pci_conf_write(0, 0, 0, 0xD0, 4, 0xD0010100 ); pci_conf_read(0, 0, 0, 0xD4, 4, &dtr ); // CAS Latency (tCAS) cas = ((dtr >> 4) & 0x3) + 3; // RAS-To-CAS (tRCD) rcd = ((dtr >> 2) & 0x3) + 3; // RAS Precharge (tRP) rp = ((dtr >> 0) & 0x3) + 3; print_ram_line(cas, rcd, rp, 9, 1); } static void poll_timings_nhm(void) { ulong mc_channel_bank_timing, mc_control, mc_channel_mrs_value; float cas; int rcd, rp, ras, chan; int fvc_bn = 4; /* Find which channels are populated */ pci_conf_read(nhm_bus, 3, 0, 0x48, 2, &mc_control); mc_control = (mc_control >> 8) & 0x7; /* Get the first valid channel */ if(mc_control & 1) { fvc_bn = 4; } else if(mc_control & 2) { fvc_bn = 5; } else if(mc_control & 4) { fvc_bn = 6; } // Now, detect timings // CAS Latency (tCAS) / RAS-To-CAS (tRCD) / RAS Precharge (tRP) / RAS Active to precharge (tRAS) pci_conf_read(nhm_bus, fvc_bn, 0, 0x88, 4, &mc_channel_bank_timing); pci_conf_read(nhm_bus, fvc_bn, 0, 0x70, 4, &mc_channel_mrs_value); cas = ((mc_channel_mrs_value >> 4) & 0xF ) + 4.0f; rcd = (mc_channel_bank_timing >> 9) & 0xF; ras = (mc_channel_bank_timing >> 4) & 0x1F; rp = mc_channel_bank_timing & 0xF; // Print 1, 2 or 3 Channels if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) { chan = 1; } else if (mc_control == 7) { chan = 3; } else { chan = 2; } print_ram_line(cas, rcd, rp, ras, chan); } static void poll_timings_ct(void) { unsigned long mcr,mdr; float cas; int rcd, rp, ras; /* Build the MCR Message*/ mcr = (0x10 << 24); // 10h = Read - 11h = Write mcr += (0x01 << 16); // DRAM Registers located on port 01h mcr += (0x01 << 8); // DRP = 00h, DTR0 = 01h, DTR1 = 02h, DTR2 = 03h mcr &= 0xFFFFFFF0; // bit 03:00 RSVD /* Send Message to GMCH */ pci_conf_write(0, 0, 0, 0xD0, 4, mcr); /* Read Answer from Sideband bus */ pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); // CAS Latency (tCAS) cas = ((mdr >> 12)& 0x7) + 5.0f; // RAS-To-CAS (tRCD) rcd = ((mdr >> 8)& 0x7) + 5; // RAS Precharge (tRP) rp = ((mdr >> 4)& 0x7) + 5; // RAS is in DTR1. Read Again. mcr = 0x10010200; // Quick Mode ! Awesome ! pci_conf_write(0, 0, 0, 0xD0, 4, mcr); pci_conf_read(0, 0, 0, 0xD4, 4, &mdr); // RAS Active to precharge (tRAS) ras = (mdr >> 20) & 0xF; // Print print_ram_line(cas, rcd, rp, ras, 1); } /* ------------------ Let's continue ------------------ */ /* ---------------------------------------------------- */ 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","SDRAM PC-100", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd751, poll_nothing }, { 0x1022, 0x700c, "AMD 762","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing }, { 0x1022, 0x700e, "AMD 761","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_amd76x, poll_nothing }, /* SiS */ { 0x1039, 0x0600, "SiS 600","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0620, "SiS 620","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x5600, "SiS 5600","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0645, "SiS 645","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0646, "SiS 645DX","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0630, "SiS 630","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0650, "SiS 650","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0651, "SiS 651","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0730, "SiS 730","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0735, "SiS 735","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0740, "SiS 740","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0745, "SiS 745","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0748, "SiS 748","DDR-SDRAM", 0, poll_fsb_amd32, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0655, "SiS 655","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0656, "SiS 656","DDR/DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0648, "SiS 648","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0649, "SiS 649","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0661, "SiS 661","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0671, "SiS 671","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1039, 0x0672, "SiS 672","DDR2-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, /* ALi */ { 0x10b9, 0x1531, "ALi Aladdin 4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x10b9, 0x1541, "ALi Aladdin 5","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x10b9, 0x1644, "ALi Aladdin M1644","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, /* ATi */ { 0x1002, 0x5830, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1002, 0x5831, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1002, 0x5832, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1002, 0x5833, "ATi Radeon 9100 IGP","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1002, 0x5954, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1002, 0x5A41, "ATi Xpress 200","DDR-SDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_nothing, poll_nothing }, /* nVidia */ { 0x10de, 0x01A4, "nVidia nForce","DDR-SDRAM", 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, 0x0071, "nForce4 SLI","", 0, poll_fsb_nf4ie, poll_timings_nf4ie, setup_nothing, poll_nothing }, /* VIA */ { 0x1106, 0x0305, "VIA KT133/KT133A","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0391, "VIA KX133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0501, "VIA MVP4","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0585, "VIA VP/VPX","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0595, "VIA VP2","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0597, "VIA VP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0598, "VIA MVP3","EDO/SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0691, "VIA Apollo Pro 133(A)","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0693, "VIA Apollo Pro+","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0601, "VIA PLE133","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3099, "VIA KT266(A)/KT333","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3189, "VIA KT400(A)/600","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0269, "VIA KT880","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3205, "VIA KM400","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3116, "VIA KM266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3156, "VIA KN266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3123, "VIA CLE266","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x0198, "VIA PT800","DDR-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x1106, 0x3258, "VIA PT880","DDR2-SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, /* Serverworks */ { 0x1166, 0x0008, "CNB20HE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing }, { 0x1166, 0x0009, "CNB20LE","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_cnb20, poll_nothing }, /* Intel */ { 0x8086, 0x1130, "Intel i815","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x122d, "Intel i430FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x1235, "Intel i430MX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x1237, "Intel i440FX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x1250, "Intel i430HX","EDO DRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x1A21, "Intel i840","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i840, poll_nothing }, { 0x8086, 0x1A30, "Intel i845","SDR/DDR", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing }, { 0x8086, 0x2560, "Intel i845E/G/PE/GE","", 0, poll_fsb_p4, poll_timings_nothing, setup_i845, poll_nothing }, { 0x8086, 0x2500, "Intel i820","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i820, poll_nothing }, { 0x8086, 0x2530, "Intel i850","RDRAM", 0, poll_fsb_p4, poll_timings_nothing, setup_i850, poll_nothing }, { 0x8086, 0x2531, "Intel i860","RDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i860, poll_nothing }, { 0x8086, 0x7030, "Intel i430VX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7100, "Intel i430TX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7120, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7122, "Intel i810","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7124, "Intel i810E","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7180, "Intel i440[LE]X","SDRAM",0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7190, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x7192, "Intel i440BX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x71A0, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing }, { 0x8086, 0x71A2, "Intel i440GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_i440gx, poll_nothing }, { 0x8086, 0x84C5, "Intel i450GX","SDRAM", 0, poll_fsb_nothing, poll_timings_nothing, setup_nothing, poll_nothing }, { 0x8086, 0x2540, "Intel E7500","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing }, { 0x8086, 0x254C, "Intel E7501","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E750x, setup_iE7xxx, poll_nothing }, { 0x8086, 0x255d, "Intel E7205","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing }, { 0x8086, 0x3592, "Intel E7320","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing }, { 0x8086, 0x2588, "Intel E7221","DDR-SDRAM",0, poll_fsb_i925, poll_timings_i925, setup_i925, poll_nothing }, { 0x8086, 0x3590, "Intel E7520","DDR-SDRAM",0, poll_fsb_p4, poll_timings_E7520, setup_iE7520, poll_nothing }, { 0x8086, 0x2600, "Intel E8500","DDR-SDRAM",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_nothing }, { 0x8086, 0x2550, "Intel E7505","DDR-SDRAM",0, poll_fsb_p4, poll_timings_nothing, setup_iE7xxx, poll_nothing }, { 0x8086, 0x3580, "Intel i852P/i855G","", 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_nothing }, { 0x8086, 0x2770, "Intel i945P/G","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing }, { 0x8086, 0x27A0, "Intel i945GM/PM","", 0, poll_fsb_i945, poll_timings_i925, setup_i925, poll_nothing }, { 0x8086, 0x27AC, "Intel i945GME","", 0, poll_fsb_i945gme, 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, 0x2970, "Intel i946PL/GZ","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, { 0x8086, 0x2990, "Intel Q963/Q965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, { 0x8086, 0x29A0, "Intel P965/G965","", 0, poll_fsb_i965, poll_timings_i965, setup_p35, poll_nothing}, { 0x8086, 0x2A00, "Intel GM965/GL960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, { 0x8086, 0x2A10, "Intel GME965/GLE960","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, { 0x8086, 0x2A40, "Intel PM/GM45/47","", 0, poll_fsb_im965, poll_timings_im965, setup_p35, poll_nothing}, { 0x8086, 0x29B0, "Intel Q35","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x29C0, "Intel P35/G33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x29D0, "Intel Q33","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x29E0, "Intel X38/X48","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x29F0, "Intel 3200/3210","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x2E10, "Intel Q45/Q43","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x2E20, "Intel P45/G45","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x2E30, "Intel G41","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0x8086, 0x4001, "Intel 5400A","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x4003, "Intel 5400B","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x25D8, "Intel 5000P","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x25D4, "Intel 5000V","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x25C0, "Intel 5000X","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x25D0, "Intel 5000Z","", 0, poll_fsb_5400, poll_timings_5400, setup_E5400, poll_nothing}, { 0x8086, 0x5020, "Intel EP80579","", 0, poll_fsb_p4, poll_timings_EP80579, setup_nothing, poll_nothing }, { 0x8086, 0x8100, "Intel US15W","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing}, { 0x8086, 0x8101, "Intel UL11L/US15L","", 0, poll_fsb_us15w, poll_timings_us15w, setup_nothing, poll_nothing}, /* INTEL IMC (Integrated Memory Controllers) */ { 0xFFFF, 0x0001, "Core IMC","", 0, poll_fsb_nhm, poll_timings_nhm, setup_nhm, poll_nothing}, { 0xFFFF, 0x0002, "Core IMC","", 0, poll_fsb_nhm32, poll_timings_nhm, setup_nhm32, poll_nothing}, { 0xFFFF, 0x0003, "Core IMC","", 0, poll_fsb_wmr, poll_timings_wmr, setup_wmr, poll_nothing}, { 0xFFFF, 0x0004, "SNB IMC","", 0, poll_fsb_snb, poll_timings_snb, setup_wmr, poll_nothing}, { 0xFFFF, 0x0005, "SNB-E IMC","", 0, poll_fsb_snbe, poll_timings_snbe, setup_wmr, poll_nothing}, { 0xFFFF, 0x0006, "IVB IMC","", 0, poll_fsb_ivb, poll_timings_snb, setup_wmr, poll_nothing}, { 0xFFFF, 0x0007, "HSW IMC","", 0, poll_fsb_ivb, poll_timings_hsw, setup_wmr, poll_nothing}, { 0xFFFF, 0x0008, "PineView IMC","", 0, poll_fsb_p35, poll_timings_p35, setup_p35, poll_nothing}, { 0xFFFF, 0x0009, "CedarTrail IMC","", 0, poll_fsb_ct, poll_timings_ct, setup_nothing, poll_nothing}, /* AMD IMC (Integrated Memory Controllers) */ { 0xFFFF, 0x0100, "AMD K8 IMC","", 0, poll_fsb_amd64, poll_timings_amd64, setup_amd64, poll_nothing }, { 0xFFFF, 0x0101, "AMD K10 IMC","", 0, poll_fsb_k10, poll_timings_k10, setup_k10, poll_nothing }, { 0xFFFF, 0x0102, "AMD K12 IMC","", 0, poll_fsb_k12, poll_timings_k12, setup_apu, poll_nothing }, { 0xFFFF, 0x0103, "AMD K14 IMC","", 0, poll_fsb_k14, poll_timings_k14, setup_apu, poll_nothing }, { 0xFFFF, 0x0104, "AMD K15 IMC","", 0, poll_fsb_k15, poll_timings_k15, setup_apu, poll_nothing }, { 0xFFFF, 0x0105, "AMD K16 IMC","", 0, poll_fsb_k16, poll_timings_k16, setup_apu, poll_nothing } }; static void print_memory_controller(void) { /* Print memory controller info */ if (ctrl.index == 0) { return; } /* Now print the memory controller capabilities */ /* cprint(LINE_CPU+5, col, " "); col++; if (ctrl.cap == ECC_UNKNOWN) { return; } if (ctrl.cap & __ECC_DETECT) { int on; on = ctrl.mode & __ECC_DETECT; cprint(LINE_CPU+5, col, "(ECC : "); cprint(LINE_CPU+5, 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+5, col, " / "); if (ctrl.cap & __ECC_CHIPKILL) { cprint(LINE_CPU+5, col +3, on?"Correct -":""); on?(col += 12):(col +=3); } else { cprint(LINE_CPU+5, 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+5, col, " Chipkill : "); cprint(LINE_CPU+5, 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+5, col, " Scrub"); cprint(LINE_CPU+5, col +6, on?"+ ":"- "); col += 7; } if (ctrl.cap & __ECC_UNEXPECTED) { int on; on = ctrl.mode & __ECC_UNEXPECTED; cprint(LINE_CPU+5, col, "Unknown"); cprint(LINE_CPU+5, col +7, on?"+ ":"- "); col += 9; } */ /* Print advanced caracteristics */ col2 = 0; controllers[ctrl.index].poll_fsb(); controllers[ctrl.index].poll_timings(); } void find_controller(void) { unsigned long vendor; unsigned long device; 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); // Detect IMC by CPUID if(imc_type) { vendor = 0xFFFF; device = imc_type; } if(v->fail_safe & 1) { vendor = 0xFFFF; device = 0xFFFF; } //hprint(11,0,vendor); hprint(11,10,device); ctrl.index = 0; if (result == 0 || imc_type) { for(i = 1; i < sizeof(controllers)/sizeof(controllers[0]); i++) { if ((controllers[i].vendor == vendor) && (controllers[i].device == device)) { ctrl.index = i; break; } } } 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(); if(imc_type) { print_dmi_startup_info(); } } 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"); } } */ memtest86+-5.01/head.S0000644000000000000000000004376512201317426013106 0ustar rootroot/* * linux/boot/head.S * Copyright (C) 1991, 1992 Linus Torvalds */ /* * head.S contains the 32-bit startup code. * * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for MemTest-86. * Setup the memory management for flat non-paged linear addressing. * 17 May 2004 : Added X86_PWRCAP for AMD64 (Memtest86+ - Samuel D.) */ .text #define __ASSEMBLY__ #include "defs.h" #include "config.h" #include "test.h" .code32 .globl startup_32 startup_32: cld cli /* Ensure I have a boot_stack pointer */ testl %esp, %esp jnz 0f movl $(LOW_TEST_ADR + _GLOBAL_OFFSET_TABLE_), %esp leal boot_stack_top@GOTOFF(%esp), %esp 0: /* Load the GOT pointer */ call 0f 0: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx /* Pick the appropriate boot_stack address */ leal boot_stack_top@GOTOFF(%ebx), %esp /* Reload all of the segment registers */ leal gdt@GOTOFF(%ebx), %eax movl %eax, 2 + gdt_descr@GOTOFF(%ebx) lgdt gdt_descr@GOTOFF(%ebx) leal flush@GOTOFF(%ebx), %eax pushl $KERNEL_CS pushl %eax lret flush: movl $KERNEL_DS, %eax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* * Zero BSS */ 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: /* * Setup an exception handler */ leal idt@GOTOFF(%ebx), %edi leal vec0@GOTOFF(%ebx), %edx movl $(KERNEL_CS << 16),%eax movw %dx, %ax /* selector = 0x0010 = cs */ movw $0x8E00, %dx /* interrupt gate - dpl=0, present */ movl %eax, (%edi) movl %edx, 4(%edi) addl $8, %edi leal vec1@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec2@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec3@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec4@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec5@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec6@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec7@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec8@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec9@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec10@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec11@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec12@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec13@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec14@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec15@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec16@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec17@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec18@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi leal vec19@GOTOFF(%ebx),%edx movl $(KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi /* Now that it is initialized load the interrupt descriptor table */ leal idt@GOTOFF(%ebx), %eax movl %eax, 2 + idt_descr@GOTOFF(%ebx) lidt idt_descr@GOTOFF(%ebx) leal _dl_start@GOTOFF(%ebx), %eax call *%eax /* Never forget to initialize the FPU ... Never ! */ finit call test_start /* In case we return simulate an exception */ pushfl pushl %cs call 0f 0: pushl $0 /* error code */ pushl $257 /* vector */ jmp int_hand vec0: pushl $0 /* error code */ pushl $0 /* vector */ jmp int_hand vec1: pushl $0 /* error code */ pushl $1 /* vector */ jmp int_hand vec2: pushl $0 /* error code */ pushl $2 /* vector */ jmp int_hand vec3: pushl $0 /* error code */ pushl $3 /* vector */ jmp int_hand vec4: pushl $0 /* error code */ pushl $4 /* vector */ jmp int_hand vec5: pushl $0 /* error code */ pushl $5 /* vector */ jmp int_hand vec6: pushl $0 /* error code */ pushl $6 /* vector */ jmp int_hand vec7: pushl $0 /* error code */ pushl $7 /* vector */ jmp int_hand vec8: /* error code */ pushl $8 /* vector */ jmp int_hand vec9: pushl $0 /* error code */ pushl $9 /* vector */ jmp int_hand vec10: /* error code */ pushl $10 /* vector */ jmp int_hand vec11: /* error code */ pushl $11 /* vector */ jmp int_hand vec12: /* error code */ pushl $12 /* vector */ jmp int_hand vec13: /* error code */ pushl $13 /* vector */ jmp int_hand vec14: /* error code */ pushl $14 /* vector */ jmp int_hand vec15: pushl $0 /* error code */ pushl $15 /* vector */ jmp int_hand vec16: pushl $0 /* error code */ pushl $16 /* vector */ jmp int_hand vec17: /* error code */ pushl $17 /* vector */ jmp int_hand vec18: pushl $0 /* error code */ pushl $18 /* vector */ jmp int_hand vec19: pushl $0 /* error code */ pushl $19 /* vector */ jmp int_hand int_hand: pushl %eax pushl %ebx pushl %ecx pushl %edx pushl %edi pushl %esi pushl %ebp /* original boot_stack pointer */ leal 48(%esp), %eax pushl %eax pushl %ds pushl %ss pushl %esp /* pointer to trap regs struct on the boot_stack */ call inter addl $8, %esp popl %ebp popl %esi popl %edi popl %edx popl %ecx popl %ebx popl %eax iret /* * The interrupt descriptor table has room for 32 idt's */ .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 /* NULL descriptor */ .quad 0x0000000000000000 /* not used */ .quad 0x00cf9b000000ffff /* 0x10 main 4gb code at 0x000000 */ .quad 0x00cf93000000ffff /* 0x18 main 4gb data at 0x000000 */ .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .byte 0x00, 0x9b # code read/exec/accessed .byte 0x00, 0x00 # granularity = bytes .word 0xFFFF # 16bit 64KB - (0x10000*1 = 64KB) .word 0 # base address = SETUPSEG .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 # Page Directory Tables: # There are 4 tables, the first two map the first 2 GB of memory. The last two are used with # PAE to map # the rest of memory in 2 GB segments. The last two tables are changed in vmem.c to map each segment. # We use 2 MB pages so only the Page Directory Table is used (no page tables). .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 # Legacy Mode Page Directory Pointer Table: # 4 Entries, pointing to the Page Directory Tables .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 # Long Mode Page Directory Pointer Table: # 4 Entries, pointing to the Page Directory Tables .balign 4096 lpdp: .long pd0 + 3 .long 0 .long pd1 + 3 .long 0 .long pd2 + 3 .long 0 .long pd3 + 3 .long 0 # The long mode level 4 page map table .balign 4096 .globl pml4 pml4: .long lpdp + 3 .long 0 .previous #define RSTART startup_32 .globl query_pcbios query_pcbios: /* Save the caller save registers */ pushl %ebx pushl %esi pushl %edi pushl %ebp call 1f 1: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* Compute the reloc address */ leal RSTART@GOTOFF(%ebx), %esi /* Fixup real code pointer */ movl %esi, %eax shrl $4, %eax movw %ax, 2 + realptr@GOTOFF(%ebx) /* Fixup protected code pointer */ leal prot@GOTOFF(%ebx), %eax movl %eax, protptr@GOTOFF(%ebx) /* Compute the gdt fixup */ 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 /* Fixup the gdt */ andl $0x0000ffff, REAL_CS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_CS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_CS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_CS + 4 + gdt@GOTOFF(%ebx) andl $0x0000ffff, REAL_DS + 0 + gdt@GOTOFF(%ebx) orl %eax, REAL_DS + 0 + gdt@GOTOFF(%ebx) andl $0x00ffff00, REAL_DS + 4 + gdt@GOTOFF(%ebx) orl %ecx, REAL_DS + 4 + gdt@GOTOFF(%ebx) /* Fixup the gdt_descr */ leal gdt@GOTOFF(%ebx), %eax movl %eax, 2 + gdt_descr@GOTOFF(%ebx) lidt idt_real@GOTOFF(%ebx) /* Don't disable the a20 line */ /* Load 16bit data segments, to ensure the segment limits are set */ movl $REAL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %ss movl %eax, %fs movl %eax, %gs /* Compute the boot_stack base */ leal boot_stack@GOTOFF(%ebx), %ecx /* Compute the address of meminfo */ leal mem_info@GOTOFF(%ebx), %edi /* switch to 16bit mode */ ljmp $REAL_CS, $1f - RSTART 1: .code16 /* Disable Paging and protected mode */ /* clear the PG & PE bits of CR0 */ movl %cr0,%eax andl $~((1 << 31)|(1<<0)),%eax movl %eax,%cr0 /* make intersegment jmp to flush the processor pipeline * and reload %cs:%eip (to clear upper 16 bits of %eip). */ ljmp *(realptr - RSTART) real: /* we are in real mode now * set up the real mode segment registers : %ds, %ss, %es, %gs, %fs */ movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss /* Adjust the boot_stack pointer */ movl %ecx, %eax shrl $4, %eax movw %ax, %ss subl %ecx, %esp /* Save my base pointer */ pushl %ebx /* Setup %ds to point to my data area */ shrl $4, %edi movl %edi, %ds /* Enable interrupts or BIOS's go crazy */ sti # Get memory size (extended mem, kB) #define SMAP 0x534d4150 xorl %eax, %eax movl %eax, (E88) movl %eax, (E801) movl %eax, (E820NR) # 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 [E820MAP]. # This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm meme820: xorl %ebx, %ebx # continuation counter movw $E820MAP, %di # point into the whitelist # so we can have the bios # directly write into it. jmpe820: movl $0x0000e820, %eax # e820, upper word zeroed movl $SMAP, %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 $SMAP, %eax # check the return is `SMAP' 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 (E820NR), %al # up to 32 entries cmpb $E820MAX, %al jnl bail820 incb (E820NR) movw %di, %ax addw $E820ENTRY_SIZE, %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, (E801) # store extended memory size andl $0xffff, %ecx # clear sign extend addl %ecx, (E801) # 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, (E88) #ifdef APM_OFF # 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: #endif /* O.k. the BIOS query is done switch back to protected mode */ cli /* Restore my saved variables */ popl %ebx /* Get an convinient %ds */ movw %cs, %ax movw %ax, %ds /* Load the global descriptor table */ addr32 lgdt gdt_descr - RSTART /* Turn on protected mode */ /* Set the PE bit in CR0 */ movl %cr0,%eax orl $(1<<0),%eax movl %eax,%cr0 /* flush the prefetch queue, and relaod %cs:%eip */ data32 ljmp *(protptr - RSTART) prot: .code32 /* Reload other segment registers */ movl $KERNEL_DS, %eax movl %eax, %ds movl %eax, %es movl %eax, %fs movl %eax, %gs movl %eax, %ss /* Adjust the boot_stack pointer */ leal boot_stack@GOTOFF(%ebx), %eax addl %eax, %esp /* Restore the caller saved registers */ popl %ebp popl %edi popl %esi popl %ebx movl $1, %eax ret realptr: .word real - RSTART .word 0x0000 protptr: .long 0 .long KERNEL_CS idt_real: .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 .previous .data .balign 16 .globl mem_info mem_info: . = . + MEMINFO_SIZE .previous .bss .balign 16 boot_stack: .globl boot_stack . = . + 4096 boot_stack_top: .globl boot_stack_top .previous memtest86+-5.01/test.h0000644000000000000000000001673412201317426013205 0ustar rootroot/* test.h - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #ifndef _TEST_H_ #define _TEST_H_ #define E88 0x00 #define E801 0x04 #define E820NR 0x08 /* # entries in E820MAP */ #define E820MAP 0x0c /* our map */ #define E820MAX 127 /* number of entries in E820MAP */ #define E820ENTRY_SIZE 20 #define MEMINFO_SIZE (E820MAP + E820MAX * E820ENTRY_SIZE) #ifndef __ASSEMBLY__ #define E820_RAM 1 #define E820_RESERVED 2 #define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ #define E820_NVS 4 struct e820entry { unsigned long long addr; /* start of memory segment */ unsigned long long size; /* size of memory segment */ unsigned long type; /* type of memory segment */ }; struct mem_info_t { unsigned long e88_mem_k; /* 0x00 */ unsigned long e801_mem_k; /* 0x04 */ unsigned long e820_nr; /* 0x08 */ struct e820entry e820[E820MAX]; /* 0x0c */ /* 0x28c */ }; typedef unsigned long ulong; #define STACKSIZE (8*1024) #define MAX_MEM 0x7FF00000 /* 8 TB */ #define WIN_SZ 0x80000 /* 2 GB */ #define UNMAP_SZ (0x100000-WIN_SZ) /* Size of umappped first segment */ #define SPINSZ 0x4000000 /* 256 MB */ #define MOD_SZ 20 #define BAILOUT if (bail) return(1); #define BAILR if (bail) return; #define RES_START 0xa0000 #define RES_END 0x100000 #define SCREEN_ADR 0xb8000 #define SCREEN_END_ADR (SCREEN_ADR + 80*25*2) #define DMI_SEARCH_START 0x0000F000 #define DMI_SEARCH_LENGTH 0x000F0FFF #define MAX_DMI_MEMDEVS 16 #define TITLE_WIDTH 28 #define LINE_TITLE 0 #define LINE_TST 3 #define LINE_RANGE 4 #define LINE_PAT 5 #define LINE_TIME 5 #define LINE_STATUS 8 #define LINE_INFO 9 #define LINE_HEADER 12 #define LINE_SCROLL 14 #define LINE_SPD 14 #define LINE_MSG 22 #define LINE_CPU 7 #define LINE_RAM 8 #define LINE_DMI 23 #define COL_INF1 15 #define COL_INF2 32 #define COL_INF3 51 #define COL_INF4 70 #define COL_MODE 15 #define COL_MID 30 #define COL_PAT 41 #define BAR_SIZE (78-COL_MID-9) #define COL_MSG 23 #define COL_TIME 67 #define COL_SPEC 41 #define POP_W 34 #define POP_H 15 #define POP_X 11 #define POP_Y 8 #define POP2_W 74 #define POP2_H 21 #define POP2_X 3 #define POP2_Y 2 /* CPU mode types */ #define CPM_ALL 1 #define CPM_RROBIN 2 #define CPM_SEQ 3 /* memspeed operations */ #define MS_COPY 1 #define MS_WRITE 2 #define MS_READ 3 #define SZ_MODE_BIOS 1 #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 strstr(char *str1, char *str2); int strlen(char *string); int query_linuxbios(void); int query_pcbios(void); int insertaddress(ulong); void printpatn(void); 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 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, 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 init(void); struct eregs; void inter(struct eregs *trap_regs); void set_cache(int val); void check_input(void); void footer(void); void scroll(void); void clear_scroll(void); void popup(void); void popdown(void); void popclear(void); void pop2up(void); void pop2down(void); void pop2clear(void); void get_config(void); void get_menu(void); void get_printmode(void); void addr_tst1(int cpu); void addr_tst2(int cpu); int getnum(ulong val); void sleep(long sec, int flag, int cpu, int sms); 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, unsigned short syndrome, int channel); void mem_size(void); void adj_mem(void); ulong getval(int x, int y, int result_shift); int get_key(void); int ascii_to_keycode(int in); void wait_keyup(void); void print_hdr(void); void restart(void); void parity_err(ulong edi, ulong esi); void start_config(void); void clear_screen(void); void paging_off(void); void show_spd(void); int map_page(unsigned long page); void *mapping(unsigned long page_address); void *emapping(unsigned long page_address); int isdigit(char c); 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); void beep(unsigned int frequency); #define PRINTMODE_SUMMARY 0 #define PRINTMODE_ADDRESSES 1 #define PRINTMODE_PATTERNS 2 #define PRINTMODE_NONE 3 #define BADRAM_MAXPATNS 10 struct pair { ulong adr; ulong mask; }; static inline void cache_off(void) { asm( "push %eax\n\t" "movl %cr0,%eax\n\t" "orl $0x40000000,%eax\n\t" /* Set CD */ "movl %eax,%cr0\n\t" "wbinvd\n\t" "pop %eax\n\t"); } static inline void cache_on(void) { asm( "push %eax\n\t" "movl %cr0,%eax\n\t" "andl $0x9fffffff,%eax\n\t" /* Clear CD and NW */ "movl %eax,%cr0\n\t" "pop %eax\n\t"); } struct mmap { ulong pbase_addr; ulong *start; ulong *end; }; struct pmap { ulong start; ulong end; }; struct tseq { short sel; short cpu_sel; short pat; short iter; short errors; char *msg; }; struct xadr { ulong page; ulong offset; }; struct err_info { struct xadr low_addr; struct xadr high_addr; unsigned long ebits; long tbits; short min_bits; short max_bits; unsigned long maxl; unsigned long eadr; unsigned long exor; unsigned long cor_err; short hdr_flag; }; #define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ #define MAX_MEM_SEGMENTS E820MAX /* Define common variables accross relocations of memtest86 */ struct vars { int pass; int msg_line; int ecount; int ecc_ecount; int msegs; int testsel; int scroll_start; int pass_ticks; int total_ticks; int pptr; int tptr; struct err_info erri; struct pmap pmap[MAX_MEM_SEGMENTS]; volatile struct mmap map[MAX_MEM_SEGMENTS]; ulong plim_lower; ulong plim_upper; ulong clks_msec; ulong starth; ulong startl; ulong snaph; ulong snapl; int printmode; int numpatn; struct pair patn [BADRAM_MAXPATNS]; ulong test_pages; ulong selected_pages; ulong reserved_pages; int check_temp; int fail_safe; int each_sec; int beepmode; }; #define FIRMWARE_UNKNOWN 0 #define FIRMWARE_PCBIOS 1 #define FIRMWARE_LINUXBIOS 2 extern struct vars * const v; extern unsigned char _start[], _end[], startup_32[]; extern unsigned char _size, _pages; extern struct mem_info_t mem_info; #endif /* __ASSEMBLY__ */ #endif /* _TEST_H_ */ memtest86+-5.01/vmem.c0000644000000000000000000000653512201317426013163 0ustar rootroot/* vmem.c - MemTest-86 * * Virtual memory handling (PAE) * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "stdint.h" #include "test.h" #include "cpuid.h" extern struct cpu_ident cpu_id; static unsigned long mapped_win = 1; void paging_off(void) { if (!cpu_id.fid.bits.pae) return; __asm__ __volatile__ ( /* Disable paging */ "movl %%cr0, %%eax\n\t" "andl $0x7FFFFFFF, %%eax\n\t" "movl %%eax, %%cr0\n\t" : : : "ax" ); } static void paging_on(void *pdp) { if (!cpu_id.fid.bits.pae) return; __asm__ __volatile__( /* Load the page table address */ "movl %0, %%cr3\n\t" /* Enable paging */ "movl %%cr0, %%eax\n\t" "orl $0x80000000, %%eax\n\t" "movl %%eax, %%cr0\n\t" : : "r" (pdp) : "ax" ); } static void paging_on_lm(void *pml) { if (!cpu_id.fid.bits.pae) return; __asm__ __volatile__( /* Load the page table address */ "movl %0, %%cr3\n\t" /* Enable paging */ "movl %%cr0, %%eax\n\t" "orl $0x80000000, %%eax\n\t" "movl %%eax, %%cr0\n\t" : : "r" (pml) : "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 unsigned char pml4[]; extern struct pde pd2[]; unsigned long win = page >> 19; /* Less than 2 GB so no mapping is required */ if (win == 0) { return 0; } if (cpu_id.fid.bits.pae == 0) { /* Fail, we don't have PAE */ return -1; } if (cpu_id.fid.bits.lm == 0 && (page > 0x1000000)) { /* Fail, we want an address that is out of bounds (> 64GB) * for PAE and no long mode (ie. 32 bit CPU). */ 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 (cpu_id.fid.bits.lm == 1) { paging_on_lm(pml4); } else { 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 than 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; } memtest86+-5.01/build.number0000644000000000000000000000000412201317426014345 0ustar rootroot617 memtest86+-5.01/stdint.h0000644000000000000000000000264612201317426013530 0ustar rootroot#ifndef I386_STDINT_H #define I386_STDINT_H /* Exact integral types */ typedef unsigned char uint8_t; typedef signed char int8_t; typedef unsigned short uint16_t; typedef signed short int16_t; typedef unsigned int uint32_t; typedef signed int int32_t; typedef unsigned long long uint64_t; typedef signed long long int64_t; /* Small types */ typedef unsigned char uint_least8_t; typedef signed char int_least8_t; typedef unsigned short uint_least16_t; typedef signed short int_least16_t; typedef unsigned int uint_least32_t; typedef signed int int_least32_t; typedef unsigned long long uint_least64_t; typedef signed long long int_least64_t; /* Fast Types */ typedef unsigned char uint_fast8_t; typedef signed char int_fast8_t; typedef unsigned int uint_fast16_t; typedef signed int int_fast16_t; typedef unsigned int uint_fast32_t; typedef signed int int_fast32_t; typedef unsigned long long uint_fast64_t; typedef signed long long int_fast64_t; /* Types for `void *' pointers. */ typedef int intptr_t; typedef unsigned int uintptr_t; /* Largest integral types */ 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 */ memtest86+-5.01/defs.h0000644000000000000000000000173712201317426013144 0ustar rootroot/* defs.h - MemTest-86 Version 3.3 * assembler/compiler definitions * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #define SETUPSECS 4 /* Number of setup sectors */ /* * Caution!! There is magic in the build process. Read * README.build-process before you change anything. * Unlike earlier versions all of the settings are in defs.h * so the build process should be more robust. */ #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 */ #define SETUPSEG (INITSEG+0x20) /* Segment adrs for relocated setup */ #define TSTLOAD 0x1000 /* Segment adrs for load of test */ #define KERNEL_CS 0x10 /* 32 bit segment adrs for code */ #define KERNEL_DS 0x18 /* 32 bit segment adrs for data */ #define REAL_CS 0x20 /* 16 bit segment adrs for code */ #define REAL_DS 0x28 /* 16 bit segment adrs for data */ memtest86+-5.01/changelog0000644000000000000000000000206612201317426013720 0ustar rootrootMemtest86+ V5.01 changelog ---------------------------- - Added support for up to 2 TB of RAM on X64 CPUs - Added experimental SMT support up to 32 cores - Added complete detection for memory controllers. - Added Motherboard Manufacturer & Model reporting - Added CPU temperature reporting - Added enhanced Fail Safe Mode (Press F1 at startup) - Added support for Intel "Sandy Bridge-E" CPUs - Added support for Intel "Ivy Bridge" CPUs - Added preliminary support for Intel "Haswell" CPUs - Added preliminary support for Intel "Haswell-ULT" CPUs - Added support for AMD "Kabini" (K16) CPUs - Added support for AMD "Bulldozer" CPUs - Added support for AMD "Trinity" CPUs - Added support for AMD E-/C-/G-/Z- "Bobcat" CPUs - Added support for Intel Atom "Pineview" CPUs - Added support for Intel Atom "Cedar Trail" CPUs - Added SPD detection on most AMD Chipsets - Enforced Coreboot support - Optimized run time for faster memory error detection - Rewriten lots of memory timings detection code - Corrected bugs, bugs and more bugs memtest86+-5.01/config.h0000644000000000000000000000314012201322177013455 0ustar rootroot/* * MemTest86+ V5 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.canardpc.com - http://www.memtest.org * ------------------------------------------------ * config.h - MemTest-86 Version 3.3 * * Compile time configuration options * * Released under version 2 of the Gnu Public License. * By Chris Brady */ /* CONSERVATIVE_SMP - If set to 0, SMP will be enabled by default */ /* Might be enabled in future revision after extensive testing */ /* In all cases, SMP is disabled by defaut on server platform */ #define CONSERVATIVE_SMP 1 /* BEEP_MODE - Beep on error. Default off, Change to 1 to enable */ #define BEEP_MODE 0 /* BEEP_END_NO_ERROR - Beep at end of each pass without error. Default off, Change to 1 to enable */ #define BEEP_END_NO_ERROR 0 /* PARITY_MEM - Enables support for reporting memory parity errors */ /* Experimental, normally enabled */ #define PARITY_MEM /* SERIAL_CONSOLE_DEFAULT - The default state of the serial console. */ /* This is normally off since it slows down testing. Change to a 1 */ /* to enable. */ #define SERIAL_CONSOLE_DEFAULT 0 /* 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 */ /* #define SCRN_DEBUG */ /* APM - Turns off APM at boot time to avoid blanking the screen */ /* Normally enabled */ #define APM_OFF /* USB_WAR - Enables a workaround for errors caused by BIOS USB keyboard */ /* and mouse support*/ /* Normally enabled */ #define USB_WAR memtest86+-5.01/config.c0000644000000000000000000002770412201317426013465 0ustar rootroot/* config.c - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. * By Chris Brady * ---------------------------------------------------- * MemTest86+ V5.00 Specific code (GPL V2.0) * By Samuel DEMEULEMEESTER, sdemeule@memtest.org * http://www.x86-secret.com - http://www.memtest.org */ #include "test.h" #include "screen_buffer.h" #include "dmi.h" extern int bail, beepmode; extern struct tseq tseq[]; extern short e820_nr; void performance(); extern volatile short cpu_mode; extern volatile int test; extern void find_chunks(); extern volatile short start_seq; extern short restart_flag; extern short onepass; extern short btflag; extern void get_list(int x, int y, int len, char *buf); char save[2][POP_H][POP_W]; char save2[2][POP2_H][POP2_W]; void get_config() { int flag = 0, sflag = 0, i, j, k, n, m, prt = 0; int reprint_screen = 0; char cp[64]; ulong page; popup(); wait_keyup(); while(!flag) { 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) Error Report Mode"); cprint(POP_Y+6, POP_X+6, "(4) Core Selection"); cprint(POP_Y+7, POP_X+6, "(5) Refresh Screen"); cprint(POP_Y+8, POP_X+6, "(6) Display DMI Data"); cprint(POP_Y+9, POP_X+6, "(7) Display SPD Data"); cprint(POP_Y+11, POP_X+6, "(0) Continue"); /* Wait for key release */ /* Fooey! This nuts'es up the serial input. */ sflag = 0; switch(get_key()) { case 2: /* 1 - Test Selection */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Selection:"); 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) Enter Test List"); cprint(POP_Y+7, POP_X+6, "(0) Cancel"); if (v->testsel < 0) { cprint(POP_Y+3, POP_X+5, ">"); } else { cprint(POP_Y+5, POP_X+5, ">"); } wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Default - All tests */ i = 0; while (tseq[i].cpu_sel) { tseq[i].sel = 1; i++; } find_ticks_for_pass(); sflag++; break; case 3: /* Skip test */ bail++; sflag++; break; case 4: /* Select test */ popclear(); cprint(POP_Y+1, POP_X+3, "Test Selection:"); cprint(POP_Y+4, POP_X+5, "Test Number [1-11]: "); n = getval(POP_Y+4, POP_X+24, 0) - 1; if (n <= 11) { /* Deselect all tests */ i = 0; while (tseq[i].cpu_sel) { tseq[i].sel = 0; i++; } /* Now set the selection */ tseq[n].sel = 1; v->pass = -1; test = n; find_ticks_for_pass(); sflag++; bail++; } break; case 5: /* Enter a test list */ popclear(); cprint(POP_Y+1, POP_X+3, "Enter a comma separated list"); cprint(POP_Y+2, POP_X+3, "of tests to execute:"); cprint(POP_Y+5, POP_X+5, "List: "); /* Deselect all tests */ k = 0; while (tseq[k].cpu_sel) { tseq[k].sel = 0; k++; } /* Get the list */ for (i=0; i<64; i++) cp[i] = 0; get_list(POP_Y+5, POP_X+10, 64, cp); /* Now enable all of the tests in the * list */ i = j = m = 0; while (1) { if (isdigit(cp[i])) { n = cp[i]-'0'; j = j*10 + n; i++; if (cp[i] == ',' || cp[i] == 0){ if (j < k) { tseq[j].sel = 1; m++; } if (cp[i] == 0) break; j = 0; i++; } } } /* If we didn't select at least one * test turn them all back on */ if (m == 0) { k = 0; while (tseq[k].cpu_sel) { tseq[k].sel = 1; k++; } } v->pass = -1; test = n; find_ticks_for_pass(); sflag++; bail++; break; case 11: case 57: sflag++; break; } } popclear(); break; case 3: /* 2 - Address Range */ popclear(); cprint(POP_Y+1, POP_X+2, "Test Address Range:"); cprint(POP_Y+3, POP_X+6, "(1) Set Lower Limit"); cprint(POP_Y+4, POP_X+6, "(2) Set Upper Limit"); cprint(POP_Y+5, POP_X+6, "(3) Test All Memory"); cprint(POP_Y+6, POP_X+6, "(0) Cancel"); wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Lower Limit */ popclear(); cprint(POP_Y+2, POP_X+4, "Lower Limit: "); cprint(POP_Y+4, POP_X+4, "Current: "); aprint(POP_Y+4, POP_X+13, v->plim_lower); cprint(POP_Y+6, POP_X+4, "New: "); page = getval(POP_Y+6, POP_X+9, 12); if (page + 1 <= v->plim_upper) { v->plim_lower = page; test--; bail++; } adj_mem(); find_chunks(); find_ticks_for_pass(); sflag++; break; case 3: /* Upper Limit */ popclear(); cprint(POP_Y+2, POP_X+4, "Upper Limit: "); cprint(POP_Y+4, POP_X+4, "Current: "); aprint(POP_Y+4, POP_X+13, v->plim_upper); cprint(POP_Y+6, POP_X+4, "New: "); page = getval(POP_Y+6, POP_X+9, 12); if (page - 1 >= v->plim_lower) { v->plim_upper = page; bail++; test--; } adj_mem(); find_chunks(); find_ticks_for_pass(); sflag++; break; case 4: /* All of memory */ v->plim_lower = 0; v->plim_upper = v->pmap[v->msegs - 1].end; test--; bail++; adj_mem(); find_chunks(); find_ticks_for_pass(); sflag++; break; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } popclear(); break; case 4: /* Error Mode */ popclear(); cprint(POP_Y+1, POP_X+2, "Printing Mode:"); cprint(POP_Y+3, POP_X+6, "(1) Error Summary"); cprint(POP_Y+4, POP_X+6, "(2) Individual Errors"); cprint(POP_Y+5, POP_X+6, "(3) BadRAM Patterns"); cprint(POP_Y+6, POP_X+6, "(4) Error Counts Only"); cprint(POP_Y+7, POP_X+6, "(5) Beep on Error"); cprint(POP_Y+8, POP_X+6, "(0) Cancel"); cprint(POP_Y+3+v->printmode, POP_X+5, ">"); if (beepmode) { cprint(POP_Y+7, POP_X+5, ">"); } wait_keyup(); while (!sflag) { switch(get_key()) { case 2: /* Error Summary */ v->printmode=PRINTMODE_SUMMARY; v->erri.eadr = 0; v->erri.hdr_flag = 0; sflag++; break; case 3: /* Separate Addresses */ v->printmode=PRINTMODE_ADDRESSES; v->erri.eadr = 0; v->erri.hdr_flag = 0; v->msg_line = LINE_SCROLL-1; sflag++; break; case 4: /* BadRAM Patterns */ v->printmode=PRINTMODE_PATTERNS; v->erri.hdr_flag = 0; sflag++; prt++; break; case 5: /* Error Counts Only */ v->printmode=PRINTMODE_NONE; v->erri.hdr_flag = 0; sflag++; break; case 6: /* Set Beep On Error mode */ beepmode = !beepmode; sflag++; break; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } popclear(); break; case 5: /* CPU Mode */ reprint_screen = 1; popclear(); 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 (RRb)"); cprint(POP_Y+5, POP_X+6, "(3) Sequential (Seq)"); 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: if (cpu_mode != CPM_ALL) bail++; cpu_mode = CPM_ALL; sflag++; popdown(); cprint(9,34,"All"); popup(); break; case 3: if (cpu_mode != CPM_RROBIN) bail++; cpu_mode = CPM_RROBIN; sflag++; popdown(); cprint(9,34,"RRb"); popup(); break; case 4: if (cpu_mode != CPM_SEQ) bail++; cpu_mode = CPM_SEQ; sflag++; popdown(); cprint(9,34,"Seq"); popup(); break; case 11: case 57: /* 0/CR - Continue */ sflag++; break; } } popclear(); break; case 6: reprint_screen = 1; flag++; break; case 7: /* Display DMI Memory Info */ pop2up(); print_dmi_info(); pop2down(); break; case 8: /* Display SPD Data */ popdown(); show_spd(); popup(); sflag++; break; case 11: case 57: case 28: /* 0/CR/SP - Continue */ flag++; break; } } popdown(); if (prt) { printpatn(); } if (reprint_screen){ tty_print_screen(); } } void popup() { int i, j; char *pp; for (i=POP_Y; iselected_pages = 0; for (i=0; i< v->msegs; i++) { /* Segment inside limits ? */ if (v->pmap[i].start >= v->plim_lower && v->pmap[i].end <= v->plim_upper) { v->selected_pages += (v->pmap[i].end - v->pmap[i].start); continue; } /* Segment starts below limit? */ if (v->pmap[i].start < v->plim_lower) { /* Also ends below limit? */ if (v->pmap[i].end < v->plim_lower) { continue; } /* Ends past upper limit? */ if (v->pmap[i].end > v->plim_upper) { v->selected_pages += v->plim_upper - v->plim_lower; } else { /* Straddles lower limit */ v->selected_pages += (v->pmap[i].end - v->plim_lower); } continue; } /* Segment ends above limit? */ if (v->pmap[i].end > v->plim_upper) { /* Also starts above limit? */ if (v->pmap[i].start > v->plim_upper) { continue; } /* Straddles upper limit */ v->selected_pages += (v->plim_upper - v->pmap[i].start); } } } memtest86+-5.01/setup.S0000644000000000000000000000665112201317426013336 0ustar rootroot/* * setup.s is responsible for getting the system data from the BIOS, * and putting them into the appropriate places in system memory. * both setup.s and system has been loaded by the bootblock. * * 1-Jan-96 Modified by Chris Brady for use as a boot/loader for memtest-86. */ #define __ASSEMBLY__ #include "defs.h" .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 # 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 movb $0xD1, %al # command write outb %al, $0x64 call empty_8042 movb $0xDF, %al # A20 on outb %al, $0x60 call empty_8042 /* * Note that the short jump isn't strictly needed, althought there are * reasons why it might be a good idea. It won't hurt in any case. */ movw $0x0001, %ax # protected mode (PE) bit lmsw %ax # This is it# jmp flush_instr flush_instr: movw $KERNEL_DS, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss movw %ax, %fs movw %ax, %gs data32 ljmp $KERNEL_CS, $(TSTLOAD <<4) # jmp offset 2000 of segment 0x10 (cs) /* * This routine checks that the keyboard command queue is empty * (after emptying the output buffers) * * No timeout is used - if this hangs there is something wrong with * the machine, and we probably couldn't proceed anyway. */ 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 inb $0x60, %al # read it jmp empty_8042 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 # 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" /* Pad setup to the proper size */ .org (SETUPSECS*512) memtest86+-5.01/lib.c0000644000000000000000000005735012201317426012766 0ustar rootroot/* lib.c - MemTest-86 Version 3.4 * * Released under version 2 of the Gnu Public License. * By Chris Brady */ #include "io.h" #include "serial.h" #include "test.h" #include "config.h" #include "screen_buffer.h" #include "stdint.h" #include "cpuid.h" #include "smp.h" int slock = 0, lsr = 0; short serial_cons = SERIAL_CONSOLE_DEFAULT; #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; int keycode; }; inline void reboot(void) { /* tell the BIOS to do a cold start */ *((unsigned short *)0x472) = 0x0; while(1) { outb(0xFE, 0x64); outb(0x02, 0xcf9); /* reset that doesn't rely on the keyboard controller */ outb(0x04, 0xcf9); outb(0x0E, 0xcf9); } } int strlen(char * string){ int i=0; while(*string++){i++;}; return i; } int strstr(char *haystack, char * needle) { int i=0,j=0; int here=0; while(1){ if(needle[i]==haystack[j]) { if(here==0) here=j; i++;j++; if(i>=strlen(needle)) { return here; } if(j>=strlen(haystack)) { return -1; } } else { j++;i=0;here=0; } } } int memcmp(const void *s1, const void *s2, ulong count) { const unsigned char *src1 = s1, *src2 = s2; int i; for(i = 0; i < count; i++) { if (src1[i] != src2[i]) { return (int)src1[i] - (int)src2[i]; } } 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; char *d = (char *)dest, *s = (char *)src; /* If src == dest do nothing */ if (dest < src) { for(i = 0; i < n; i++) { d[i] = s[i]; } } else if (dest > src) { for(i = n -1; i >= 0; i--) { d[i] = s[i]; } } 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 */ void scroll(void) { int i, j; char *s, tmp; /* Only scroll if at the bottom of the screen */ if (v->msg_line < 23) { v->msg_line++; } else { /* If scroll lock is on, loop till it is cleared */ while (slock) { check_input(); } for (i=LINE_SCROLL; i<23; i++) { s = (char *)(SCREEN_ADR + ((i+1) * 160)); for (j=0; j<160; j+=2, s+=2) { *(s-160) = *s; tmp = get_scrn_buf(i+1, j/2); set_scrn_buf(i, j/2, tmp); } } /* Clear the newly opened line */ s = (char *)(SCREEN_ADR + (23 * 160)); for (j=0; j<80; j++) { *s = ' '; set_scrn_buf(23, j, ' '); s += 2; } tty_print_region(LINE_SCROLL, 0, 23, 79); } } /* * Clear scroll region */ void clear_scroll(void) { int i; char *s; s = (char*)(SCREEN_ADR+LINE_HEADER*160); for(i=0; i<80*(24-LINE_HEADER); i++) { *s++ = ' '; *s++ = 0x17; } } /* * 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) { register int i; char *dptr; dptr = (char *)(SCREEN_ADR + (160*y) + (2*x)); for (i=0; text[i]; i++) { *dptr = text[i]; dptr += 2; } tty_print_line(y, x, text); } void itoa(char s[], int n) { int i, sign; if((sign = n) < 0) n = -n; i=0; do { s[i++] = n % 10 + '0'; } while ((n /= 10) > 0); if(sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } void reverse(char s[]) { int c, i, j; for(j = 0; s[j] != 0; j++) ; for(i=0, j = j - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; 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 */ void aprint(int y, int x, ulong page) { /* page is in multiples of 4K */ if ((page << 2) < 9999) { dprint(y, x, page << 2, 4, 0); cprint(y, x+4, "K"); } else if ((page >>8) < 9999) { dprint(y, x, (page + (1 << 7)) >> 8, 4, 0); cprint(y, x+4, "M"); } else if ((page >>18) < 9999) { dprint(y, x, (page + (1 << 17)) >> 18, 4, 0); cprint(y, x+4, "G"); } else { dprint(y, x, (page + (1 << 27)) >> 28, 4, 0); cprint(y, x+4, "T"); } } /* * Print a decimal number on screen */ void dprint(int y, int x, ulong val, int len, int right) { ulong j, k; int i, flag=0; char buf[18]; if (val > 999999999 || len > 9) { return; } for(i=0, j=1; i0; j/=10) { k = val/j; if (k > 9) { j *= 100; continue; } if (flag || k || j == 1) { buf[i++] = k + '0'; flag++; } else { buf[i++] = ' '; } val -= k * j; } } else { for(i=0; i 9) { j *= 100; len++; continue; } if (k == 0 && flag == 0) { continue; } buf[i++] = k + '0'; val -= k * j; } else { if (flag == 0 && i < len-1) { buf[i++] = '0'; } else { buf[i++] = ' '; } } flag++; } } buf[i] = 0; cprint(y,x,buf); } /* * Print a hex number on screen at least digits long */ void hprint2(int y,int x, unsigned long val, int digits) { unsigned long j; int i, idx, flag = 0; char buf[18]; for (i=0, idx=0; i<8; i++) { j = val >> (28 - (4 * i)); j &= 0xf; if (j < 10) { if (flag || j || i == 7) { buf[idx++] = j + '0'; flag++; } else { buf[idx++] = '0'; } } else { buf[idx++] = j + 'a' - 10; flag++; } } if (digits > 8) { digits = 8; } if (flag > digits) { digits = flag; } buf[idx] = 0; cprint(y,x,buf + (idx - digits)); } /* * Print a hex number on screen exactly digits long */ void hprint3(int y,int x, unsigned long val, int digits) { unsigned long j; int i, idx, flag = 0; char buf[18]; for (i=0, idx=0; i> 20; dprint(y, x, j, 4, 0); cprint(y, x+4, "m"); j = (val & 0xffc00) >> 10; dprint(y, x+5, j, 4, 0); cprint(y, x+9, "k"); j = val & 0x3ff; dprint(y, x+10, j, 4, 0); } char *codes[] = { " Divide", " Debug", " NMI", " Brkpnt", "Overflow", " Bound", " Inv_Op", " No_Math", "Double_Fault", "Seg_Over", " Inv_TSS", " Seg_NP", "Stack_Fault", "Gen_Prot", "Page_Fault", " Resvd", " FPE", "Alignment", " Mch_Chk", "SIMD FPE" }; struct eregs { ulong ss; ulong ds; ulong esp; ulong ebp; ulong esi; ulong edi; ulong edx; ulong ecx; ulong ebx; ulong eax; ulong vect; ulong code; ulong eip; ulong cs; ulong eflag; }; /* Handle an interrupt */ void inter(struct eregs *trap_regs) { 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) { __asm__("movl %%cr2,%0":"=r" (address)); } #ifdef PARITY_MEM /* Check for a parity error */ if (trap_regs->vect == 2) { parity_err(trap_regs->edi, trap_regs->esi); return; } #endif /* clear scrolling region */ pp=(unsigned char *)(SCREEN_ADR+(2*80*(LINE_SCROLL-2))); for(i=0; i<2*80*(24-LINE_SCROLL-2); i++, pp+=2) { *pp = ' '; } line = LINE_SCROLL-2; 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]); } else { hprint(line+2, 7, trap_regs->vect); } cprint(line+3, 0, " PC: "); hprint(line+3, 7, trap_regs->eip); cprint(line+4, 0, " CS: "); hprint(line+4, 7, trap_regs->cs); cprint(line+5, 0, "Eflag: "); 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: "); hprint(line+7, 7, address); } cprint(line+2, 20, "eax: "); hprint(line+2, 25, trap_regs->eax); cprint(line+3, 20, "ebx: "); hprint(line+3, 25, trap_regs->ebx); cprint(line+4, 20, "ecx: "); hprint(line+4, 25, trap_regs->ecx); cprint(line+5, 20, "edx: "); hprint(line+5, 25, trap_regs->edx); cprint(line+6, 20, "edi: "); hprint(line+6, 25, trap_regs->edi); cprint(line+7, 20, "esi: "); hprint(line+7, 25, trap_regs->esi); cprint(line+8, 20, "ebp: "); hprint(line+8, 25, trap_regs->ebp); cprint(line+9, 20, "esp: "); hprint(line+9, 25, trap_regs->esp); cprint(line+1, 38, "Stack:"); for (i=0; i<10; i++) { hprint(line+2+i, 38, trap_regs->esp+(4*i)); hprint(line+2+i, 47, *(ulong*)(trap_regs->esp+(4*i))); hprint(line+2+i, 57, trap_regs->esp+(4*(i+10))); hprint(line+2+i, 66, *(ulong*)(trap_regs->esp+(4*(i+10)))); } cprint(line+11, 0, "CS:EIP: "); pp = (unsigned char *)trap_regs->eip; for(i = 0; i < 9; i++) { hprint2(line+11, 8+(3*i), pp[i], 2); } while(1) { check_input(); } } void set_cache(int val) { switch(val) { case 0: cache_off(); break; case 1: cache_on(); break; } } int get_key() { int c; c = inb(0x64); if ((c & 1) == 0) { if (serial_cons) { int comstat; comstat = serial_echo_inb(UART_LSR); if (comstat & UART_LSR_DR) { c = serial_echo_inb(UART_RX); /* Pressing '.' has same effect as 'c' on a keyboard. Oct 056 Dec 46 Hex 2E Ascii . */ return (ascii_to_keycode(c)); } } return(0); } c = inb(0x60); return((c)); } void check_input(void) { unsigned char c; if ((c = get_key())) { switch(c & 0x7f) { case 1: /* "ESC" key was pressed, bail out. */ cprint(LINE_RANGE, COL_MID+23, "Halting... "); reboot(); break; case 46: /* c - Configure */ get_config(); break; case 28: /* CR - clear scroll lock */ slock = 0; footer(); break; case 57: /* SP - set scroll lock */ slock = 1; footer(); break; case 0x26: /* ^L/L - redraw the display */ tty_print_screen(); break; } } } void footer() { cprint(24, 0, "(ESC)exit (c)configuration (SP)scroll_lock (CR)scroll_unlock"); if (slock) { cprint(24, 74, "Locked"); } else { cprint(24, 74, " "); } } ulong getval(int x, int y, int result_shift) { unsigned long val; int done; int c; int i, n; int base; int shift; char buf[16]; for(i = 0; i < sizeof(buf)/sizeof(buf[0]); i++ ) { buf[i] = ' '; } buf[sizeof(buf)/sizeof(buf[0]) -1] = '\0'; wait_keyup(); done = 0; n = 0; base = 10; while(!done) { /* Read a new character and process it */ c = get_key(); switch(c) { case 0x26: /* ^L/L - redraw the display */ tty_print_screen(); break; case 0x1c: /* CR */ /* If something has been entered we are done */ if(n) done = 1; break; case 0x19: /* p */ buf[n] = 'p'; break; case 0x22: /* g */ buf[n] = 'g'; break; case 0x32: /* m */ buf[n] = 'm'; break; case 0x25: /* k */ buf[n] = 'k'; break; case 0x2d: /* x */ /* Only allow 'x' after an initial 0 */ if (n == 1 && (buf[0] == '0')) { buf[n] = 'x'; } break; case 0x0e: /* BS */ if (n > 0) { n -= 1; buf[n] = ' '; } break; /* Don't allow entering a number not in our current base */ case 0x0B: if (base >= 1) buf[n] = '0'; break; case 0x02: if (base >= 2) buf[n] = '1'; break; case 0x03: if (base >= 3) buf[n] = '2'; break; case 0x04: if (base >= 4) buf[n] = '3'; break; case 0x05: if (base >= 5) buf[n] = '4'; break; case 0x06: if (base >= 6) buf[n] = '5'; break; case 0x07: if (base >= 7) buf[n] = '6'; break; case 0x08: if (base >= 8) buf[n] = '7'; break; case 0x09: if (base >= 9) buf[n] = '8'; break; case 0x0A: if (base >= 10) buf[n] = '9'; break; case 0x1e: if (base >= 11) buf[n] = 'a'; break; case 0x30: if (base >= 12) buf[n] = 'b'; break; case 0x2e: if (base >= 13) buf[n] = 'c'; break; case 0x20: if (base >= 14) buf[n] = 'd'; break; case 0x12: if (base >= 15) buf[n] = 'e'; break; case 0x21: if (base >= 16) buf[n] = 'f'; break; default: break; } /* Don't allow anything to be entered after a suffix */ if (n > 0 && ( (buf[n-1] == 'p') || (buf[n-1] == 'g') || (buf[n-1] == 'm') || (buf[n-1] == 'k'))) { buf[n] = ' '; } /* If we have entered a character increment n */ if (buf[n] != ' ') { n++; } buf[n] = ' '; /* Print the current number */ cprint(x, y, buf); /* Find the base we are entering numbers in */ base = 10; if ((buf[0] == '0') && (buf[1] == 'x')) { base = 16; } else if (buf[0] == '0') { base = 8; } } /* Compute our current shift */ shift = 0; switch(buf[n-1]) { case 'g': /* gig */ shift = 30; break; case 'm': /* meg */ shift = 20; break; case 'p': /* page */ shift = 12; break; case 'k': /* kilo */ shift = 10; break; } shift -= result_shift; /* Compute our current value */ val = simple_strtoul(buf, 0, base); if (shift > 0) { if (shift >= 32) { val = 0xffffffff; } else { val <<= shift; } } else { if (-shift >= 32) { val = 0; } else { val >>= -shift; } } return val; } void ttyprint(int y, int x, const char *p) { static char sx[3]; static char sy[3]; sx[0]='\0'; sy[0]='\0'; x++; y++; itoa(sx, x); itoa(sy, y); serial_echo_print("["); serial_echo_print(sy); serial_echo_print(";"); serial_echo_print(sx); serial_echo_print("H"); serial_echo_print(p); } void serial_echo_init(void) { 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); hi = serial_echo_inb(UART_DLM); lo = serial_echo_inb(UART_DLL); serial_echo_outb(comstat, UART_LCR); /* now do hardwired init */ 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 */ comstat = serial_echo_inb(UART_LSR); /* COM? LSR */ comstat = serial_echo_inb(UART_RX); /* COM? RBR */ serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */ clear_screen_buf(); return; } /* * Get_number of digits */ int getnum(ulong val) { int len = 0; int i = 1; while(i <= val) { len++; i *= 10; } return len; } void serial_echo_print(const char *p) { if (!serial_cons) { return; } /* Now, do each character */ while (*p) { WAIT_FOR_XMITR; /* Send the character out. */ serial_echo_outb(*p, UART_TX); if(*p==10) { WAIT_FOR_XMITR; serial_echo_outb(13, UART_TX); } p++; } } /* Except for multi-character key sequences this mapping * table is complete. So it should not need to be updated * when new keys are searched for. However the key handling * should really be turned around and only in get_key should * we worry about the exact keycode that was pressed. Everywhere * else we should switch on the character... */ struct ascii_map_str ser_map[] = /*ascii keycode ascii keycode*/ { /* Special cases come first so I can leave * their ``normal'' mapping in the table, * without it being activated. */ { 27, 0x01}, /* ^[/ESC -> ESC */ { 127, 0x0e}, /* DEL -> BS */ { 8, 0x0e}, /* ^H/BS -> BS */ { 10, 0x1c}, /* ^L/NL -> CR */ { 13, 0x1c}, /* ^M/CR -> CR */ { 9, 0x0f}, /* ^I/TAB -> TAB */ { 19, 0x39}, /* ^S -> SP */ { 17, 28}, /* ^Q -> CR */ { ' ', 0x39}, /* SP -> SP */ { 'a', 0x1e}, { 'A', 0x1e}, { 1, 0x1e}, /* ^A -> A */ { 'b', 0x30}, { 'B', 0x30}, { 2, 0x30}, /* ^B -> B */ { 'c', 0x2e}, { 'C', 0x2e}, { 3, 0x2e}, /* ^C -> C */ { 'd', 0x20}, { 'D', 0x20}, { 4, 0x20}, /* ^D -> D */ { 'e', 0x12}, { 'E', 0x12}, { 5, 0x12}, /* ^E -> E */ { 'f', 0x21}, { 'F', 0x21}, { 6, 0x21}, /* ^F -> F */ { 'g', 0x22}, { 'G', 0x22}, { 7, 0x22}, /* ^G -> G */ { 'h', 0x23}, { 'H', 0x23}, { 8, 0x23}, /* ^H -> H */ { 'i', 0x17}, { 'I', 0x17}, { 9, 0x17}, /* ^I -> I */ { 'j', 0x24}, { 'J', 0x24}, { 10, 0x24}, /* ^J -> J */ { 'k', 0x25}, { 'K', 0x25}, { 11, 0x25}, /* ^K -> K */ { 'l', 0x26}, { 'L', 0x26}, { 12, 0x26}, /* ^L -> L */ { 'm', 0x32}, { 'M', 0x32}, { 13, 0x32}, /* ^M -> M */ { 'n', 0x31}, { 'N', 0x31}, { 14, 0x31}, /* ^N -> N */ { 'o', 0x18}, { 'O', 0x18}, { 15, 0x18}, /* ^O -> O */ { 'p', 0x19}, { 'P', 0x19}, { 16, 0x19}, /* ^P -> P */ { 'q', 0x10}, { 'Q', 0x10}, { 17, 0x10}, /* ^Q -> Q */ { 'r', 0x13}, { 'R', 0x13}, { 18, 0x13}, /* ^R -> R */ { 's', 0x1f}, { 'S', 0x1f}, { 19, 0x1f}, /* ^S -> S */ { 't', 0x14}, { 'T', 0x14}, { 20, 0x14}, /* ^T -> T */ { 'u', 0x16}, { 'U', 0x16}, { 21, 0x16}, /* ^U -> U */ { 'v', 0x2f}, { 'V', 0x2f}, { 22, 0x2f}, /* ^V -> V */ { 'w', 0x11}, { 'W', 0x11}, { 23, 0x11}, /* ^W -> W */ { 'x', 0x2d}, { 'X', 0x2d}, { 24, 0x2d}, /* ^X -> X */ { 'y', 0x15}, { 'Y', 0x15}, { 25, 0x15}, /* ^Y -> Y */ { 'z', 0x2c}, { 'Z', 0x2c}, { 26, 0x2c}, /* ^Z -> Z */ { '-', 0x0c}, { '_', 0x0c}, { 31, 0x0c}, /* ^_ -> _ */ { '=', 0x0c}, { '+', 0x0c}, { '[', 0x1a}, { '{', 0x1a}, { 27, 0x1a}, /* ^[ -> [ */ { ']', 0x1b}, { '}', 0x1b}, { 29, 0x1b}, /* ^] -> ] */ { ';', 0x27}, { ':', 0x27}, { '\'', 0x28}, { '"', 0x28}, { '`', 0x29}, { '~', 0x29}, { '\\', 0x2b}, { '|', 0x2b}, { 28, 0x2b}, /* ^\ -> \ */ { ',', 0x33}, { '<', 0x33}, { '.', 0x34}, { '>', 0x34}, { '/', 0x35}, { '?', 0x35}, { '1', 0x02}, { '!', 0x02}, { '2', 0x03}, { '@', 0x03}, { '3', 0x04}, { '#', 0x04}, { '4', 0x05}, { '$', 0x05}, { '5', 0x06}, { '%', 0x06}, { '6', 0x07}, { '^', 0x07}, { 30, 0x07}, /* ^^ -> 6 */ { '7', 0x08}, { '&', 0x08}, { '8', 0x09}, { '*', 0x09}, { '9', 0x0a}, { '(', 0x0a}, { '0', 0x0b}, { ')', 0x0b}, { 0, 0} }; /* * Given an ascii character, return the keycode * * Uses ser_map definition above. * * It would be more efficient to use an array of 255 characters * and directly index into it. */ int ascii_to_keycode (int in) { struct ascii_map_str *p; for (p = ser_map; p->ascii; p++) { if (in ==p->ascii) return p->keycode; } return 0; } /* * Call this when you want to wait for the user to lift the * finger off of a key. It is a noop if you are using a * serial console. */ void wait_keyup( void ) { /* Check to see if someone lifted the keyboard key */ while (1) { if ((get_key() & 0x80) != 0) { return; } /* Trying to simulate waiting for a key release with * the serial port is to nasty to let live. * In particular some menus don't even display until * you release the key that caused to to get there. * With the serial port this results in double pressing * or something worse for just about every key. */ if (serial_cons) { return; } } } /* * Handles "console=" 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; } /* Get a comma seperated list of numbers */ void get_list(int x, int y, int len, char *buf) { int c, n = 0; len--; wait_keyup(); while(1) { /* Read a new character and process it */ c = get_key(); switch(c) { case 0x1c: /* CR */ /* If something has been entered we are done */ if(n) { buf[n] = 0; return; } break; case 0x0e: /* BS */ if (n > 0) { n -= 1; buf[n] = ' '; } break; case 0x0B: buf[n++] = '0'; break; case 0x02: buf[n++] = '1'; break; case 0x03: buf[n++] = '2'; break; case 0x04: buf[n++] = '3'; break; case 0x05: buf[n++] = '4'; break; case 0x06: buf[n++] = '5'; break; case 0x07: buf[n++] = '6'; break; case 0x08: buf[n++] = '7'; break; case 0x09: buf[n++] = '8'; break; case 0x0a: buf[n++] = '9'; break; case 0x33: buf[n++] = ','; break; } cprint(x, y, buf); if (n >= len) { buf[n] = 0; return; } } }memtest86+-5.01/smp.h0000644000000000000000000002055012201317426013014 0ustar rootroot/* ********************************************************** * Copyright 2002 VMware, Inc. All rights reserved. -- VMware Confidential * **********************************************************/ #ifndef _SMP_H_ #define _SMP_H_ #include "stdint.h" #include "defs.h" #define MAX_CPUS 32 #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_wait(spinlock_t *lck) { if (cpu_id.fid.bits.mon) { /* Use monitor/mwait for a low power, low contention spin */ asm volatile( "movl $0,%%ecx\n\t" "movl %%ecx, %%edx\n\t" "1:\n\t" "movl %%edi,%%eax\n\t" "monitor\n\t" "cmpb $0,(%%edi)\n\t" "jne 2f\n\t" "movl %%ecx, %%eax\n\t" "mwait\n\t" "jmp 1b\n" "2:" : : "D" (lck): "%eax", "%ecx", "%edx" ); } else { /* No monitor/mwait so just spin with a lot of nop's */ 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" ); } } static inline void spin_lock(spinlock_t *lck) { if (cpu_id.fid.bits.mon) { /* Use monitor/mwait for a low power, low contention spin */ asm volatile( "\n1:\t" " ; lock;decb (%%edi)\n\t" "jns 3f\n" "movl $0,%%ecx\n\t" "movl %%ecx, %%edx\n\t" "2:\t" "movl %%edi,%%eax\n\t" "monitor\n\t" "movl %%ecx, %%eax\n\t" "mwait\n\t" "cmpb $0,(%%edi)\n\t" "jle 2b\n\t" "jmp 1b\n" "3:\n\t" : : "D" (lck): "%eax", "%ecx", "%edx" ); } else { /* No monitor/mwait so just spin with a lot of nop's */ int inc = 0x400; 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" (lck->slock) : "c" (inc) : "memory" ); } } static inline void spin_unlock(spinlock_t *lock) { asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory"); } #endif /* _SMP_H_ */ memtest86+-5.01/mt86+_loader0000644000000000000000000000142012201432025014152 0ustar rootrootMZ'$MEMT Ȏ؎1PX%=tPXtDu|Sorry, you need at least a 386 CPU to use Memtest86+. $You cannot run Memtest86+ if the system already is in protected mode. $ !L!. .ff.f}ff .f}A=ft .f}fC.ff%f=u..ff%.fff.f.؎1.&f..jmp far dword not found at setup.S offset 37h, (file offset 237h is not 66h, 0eah) please adjust and recompile memtestl... $lgdt [...] not found at setup.S offset 0ch, (file offset 20ch is not 0fh, 01h, 16h) please adjust and recompile memtestl... $Now trying to start Memtest86... You have to reboot to leave Memtest86 again. Press a key to go on. $memtest86+-5.01/dmi.h0000644000000000000000000000023712201317426012766 0ustar rootroot#ifndef __DMI_H__ #define __DMI_H__ int add_dmi_err(ulong adr); void print_dmi_err(void); void print_dmi_info(void); void print_dmi_startup_info(void); #endif memtest86+-5.01/pci.h0000644000000000000000000001027212201317426012770 0ustar rootroot#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); #define MAKE_PCIE_ADDRESS(bus, device, function) (((bus) & 0xFF)<<20) | (((device) & 0x1F)<<15) | (((function) & 0x7)<<12) /* * 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 */ memtest86+-5.01/serial.h0000644000000000000000000001416512201317426013501 0ustar rootroot/* * include/linux/serial.h * * Copyright (C) 1992, 1994 by Theodore Ts'o. * * Redistribution of this file is permitted under the terms of the GNU * Public License (GPL) * * These are the UART port assignments, expressed as offsets from the base * register. These assignments should hold for any serial port based on * a 8250, 16450, or 16550(A). */ #ifndef _LINUX_SERIAL_REG_H #define _LINUX_SERIAL_REG_H #define UART_RX 0 /* In: Receive buffer (DLAB=0) */ #define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ #define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ #define UART_DLM 1 /* Out: Divisor Latch High (DLAB=1) */ #define UART_IER 1 /* Out: Interrupt Enable Register */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_EFR 2 /* I/O: Extended Features Register */ /* (DLAB=1, 16C660 only) */ #define UART_LCR 3 /* Out: Line Control Register */ #define UART_MCR 4 /* Out: Modem Control Register */ #define UART_LSR 5 /* In: Line Status Register */ #define UART_MSR 6 /* In: Modem Status Register */ #define UART_SCR 7 /* I/O: Scratch Register */ /* * These are the definitions for the FIFO Control Register * (16650 only) */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ #define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ #define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ #define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ #define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ /* 16650 redefinitions */ #define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ #define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ #define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ #define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ #define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ #define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ #define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ #define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ /* * These are the definitions for the Line Control Register * * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. */ #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ #define UART_LCR_SBC 0x40 /* Set break control */ #define UART_LCR_SPAR 0x20 /* Stick parity (?) */ #define UART_LCR_EPAR 0x10 /* Even parity select */ #define UART_LCR_PARITY 0x08 /* Parity Enable */ #define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ #define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ #define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ #define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ #define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ /* * These are the definitions for the Line Status Register */ #define UART_LSR_TEMT 0x40 /* Transmitter empty */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ #define UART_LSR_BI 0x10 /* Break interrupt indicator */ #define UART_LSR_FE 0x08 /* Frame error indicator */ #define UART_LSR_PE 0x04 /* Parity error indicator */ #define UART_LSR_OE 0x02 /* Overrun error indicator */ #define UART_LSR_DR 0x01 /* Receiver data ready */ /* * These are the definitions for the Interrupt Identification Register */ #define UART_IIR_NO_INT 0x01 /* No interrupts pending */ #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ #define UART_IIR_MSI 0x00 /* Modem status interrupt */ #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ /* * These are the definitions for the Interrupt Enable Register */ #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ /* * These are the definitions for the Modem Control Register */ #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ #define UART_MCR_OUT2 0x08 /* Out2 complement */ #define UART_MCR_OUT1 0x04 /* Out1 complement */ #define UART_MCR_RTS 0x02 /* RTS complement */ #define UART_MCR_DTR 0x01 /* DTR complement */ /* * These are the definitions for the Modem Status Register */ #define UART_MSR_DCD 0x80 /* Data Carrier Detect */ #define UART_MSR_RI 0x40 /* Ring Indicator */ #define UART_MSR_DSR 0x20 /* Data Set Ready */ #define UART_MSR_CTS 0x10 /* Clear to Send */ #define UART_MSR_DDCD 0x08 /* Delta DCD */ #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ #define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ /* * These are the definitions for the Extended Features Register * (StarTech 16C660 only, when DLAB=1) */ #define UART_EFR_CTS 0x80 /* CTS flow control */ #define UART_EFR_RTS 0x40 /* RTS flow control */ #define UART_EFR_SCD 0x20 /* Special character detect */ #define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ /* * the low four bits control software flow control */ #include "io.h" #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 \ do { \ lsr = serial_echo_inb(UART_LSR); \ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY) #if 0 static inline void serial_echo(int ch) { int lsr; WAIT_FOR_XMITR; serial_echo_outb(ch, UART_TX); } static inline void serial_debug(int ch) { serial_echo(ch); serial_echo('\r'); serial_echo('\n'); } #endif #endif /* _LINUX_SERIAL_REG_H */ memtest86+-5.01/random.c0000644000000000000000000000204712201317426013471 0ustar rootroot/******************************************************************/ /* 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 "stdint.h" #include "cpuid.h" #include "smp.h" /* 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]; unsigned long rand (int cpu) { static unsigned int a = 18000, b = 30903; int me; 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); return ((SEED_X[me]<<16) + (SEED_Y[me]&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; } memtest86+-5.01/extra.h0000644000000000000000000000154112201317426013337 0ustar rootroot// This is the extra stuff added to the memtest+ from memtest.org // Code from Eric Nelson and Wee /* extra.c * * Released under version 2 of the Gnu Public License. * */ #ifndef MEMTEST_EXTRA_H #define MEMTEST_EXTRA_H void change_timing(int cas, int rcd, int rp, int ras); void find_memctr(void); void disclaimer(void); void get_option(void); void get_menu(void); void a64_parameter(void); int get_cas(void); void change_timing_i852(int cas, int rcd, int rp, int ras); void change_timing_i925(int cas, int rcd, int rp, int ras); void change_timing_i875(int cas, int rcd, int rp, int ras); void change_timing_nf2(int cas, int rcd, int rp, int ras); void change_timing_amd64(int cas, int rcd, int rp, int ras); void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr); void __delay(ulong loops); #endif /* MEMTEST_EXTRA_H */ memtest86+-5.01/extra.c0000644000000000000000000006150212201317426013335 0ustar rootroot// This is the extra stuff added to the memtest+ from memtest.org // Code from Eric Nelson and Wee // (Checked without vendor-specific optimization before adding) /* extra.c - * * Released under version 2 of the Gnu Public License. * */ #include "test.h" #include "screen_buffer.h" #include "pci.h" #include "extra.h" static int ctrl = -1; struct memory_controller { unsigned vendor; unsigned device; int worked; void (*change_timing)(int cas, int rcd, int rp, int ras); }; static struct memory_controller mem_ctr[] = { /* AMD 64*/ { 0x1022, 0x1100, 1, change_timing_amd64}, //AMD64 hypertransport link /* nVidia */ { 0x10de, 0x01E0, 0, change_timing_nf2}, // nforce2 /* Intel */ { 0x8086, 0x2570, 0, change_timing_i875}, //Intel i848/i865 { 0x8086, 0x2578, 0, change_timing_i875}, //Intel i875P { 0x8086, 0x2580, 0, change_timing_i925}, //Intel i915P/G { 0x8086, 0x2584, 0, change_timing_i925}, //Intel i925X { 0x8086, 0x2770, 0, change_timing_i925}, //Intel Lakeport { 0x8086, 0x3580, 0, change_timing_i852}, //Intel i852GM - i855GM/GME (But not i855PM) }; struct drc { unsigned t_rwt; unsigned t_wrt; unsigned t_ref; unsigned t_en2t; unsigned t_rwqb; unsigned t_rct; unsigned t_rrd; unsigned t_wr; }; static struct drc a64; void find_memctr(void) // Basically copy from the find_controller function { unsigned long vendor; unsigned long device; unsigned long a64; int i= 0; int result; result = pci_conf_read(0, 0, 0, PCI_VENDOR_ID, 2, &vendor); result = pci_conf_read(0, 0, 0, PCI_DEVICE_ID, 2, &device); pci_conf_read(0, 24, 0, 0x00, 4, &a64); if( a64 == 0x11001022) { ctrl = 0; return; } if (result == 0) { for(i = 1; i < sizeof(mem_ctr)/sizeof(mem_ctr[0]); i++) { if ((mem_ctr[i].vendor == vendor) && (mem_ctr[i].device == device)) { ctrl = i; return; } } } ctrl = -1; } void a64_parameter(void) { ulong dramtlr; if ( 0 == pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr) ) { a64.t_rct = 7 + ((dramtlr>>4) & 0x0F); a64.t_rrd = 0 + ((dramtlr>>16) & 0x7); a64.t_wr = 2 + ((dramtlr>>28) & 0x1); } if ( 0 == pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr) ) { a64.t_rwt = 1 + ((dramtlr>>4) & 0x07); a64.t_wrt = 1 + (dramtlr & 0x1); a64.t_ref = 1 + ((dramtlr>>11) & 0x3); } if ( 0 == pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr) ) { a64.t_en2t = 1 + ((dramtlr>>28) & 0x1); a64.t_rwqb = 2 << ((dramtlr>>14) & 0x3); } } void change_timing(int cas, int rcd, int rp, int ras) { find_memctr(); if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) { return; } mem_ctr[ctrl].change_timing(cas, rcd, rp, ras); restart(); } void amd64_option() { int rwt=0, wrt=0, ref=0, en2t=0, rct=0, rrd=0, rwqb=0, wr = 0, flag=0; if ((ctrl == -1) || ( ctrl > sizeof(mem_ctr)/sizeof(mem_ctr[0]))) { return; } if (mem_ctr[ctrl].worked) { a64_parameter(); cprint(POP_Y+1, POP_X+4, "AMD64 options"); cprint(POP_Y+3, POP_X+4, "(1) Rd-Wr Delay : "); dprint(POP_Y+3, POP_X+24, a64.t_rwt, 2, 0); cprint(POP_Y+4, POP_X+4, "(2) Wr-Rd Delay : "); dprint(POP_Y+4, POP_X+24, a64.t_wrt, 2, 0); cprint(POP_Y+5, POP_X+4, "(3) Rd/Wr Bypass : "); dprint(POP_Y+5, POP_X+24, a64.t_rwqb, 2, 0); cprint(POP_Y+6, POP_X+4, "(4) Refresh Rate : "); switch ( a64.t_ref) { case 1 : cprint(POP_Y+6, POP_X+23, "15.6us"); break; case 2 : cprint(POP_Y+6, POP_X+23, " 7.8us"); break; case 3 : cprint(POP_Y+6, POP_X+23, " 3.9us"); break; } cprint(POP_Y+7, POP_X+4, "(5) Command Rate :"); dprint(POP_Y+7, POP_X+24, a64.t_en2t, 2, 0); cprint(POP_Y+7, POP_X+26, "T "); cprint(POP_Y+8, POP_X+4, "(6) Row Cycle Time: "); dprint(POP_Y+8, POP_X+24, a64.t_rct, 2, 0); cprint(POP_Y+9, POP_X+4, "(7) RAS-RAS Delay : "); dprint(POP_Y+9, POP_X+24, a64.t_rrd, 2, 0); cprint(POP_Y+10, POP_X+4, "(8) Write Recovery: "); dprint(POP_Y+10, POP_X+24, a64.t_wr, 2, 0); cprint(POP_Y+11, POP_X+4,"(0) Cancel "); while(!flag) { switch(get_key()) { case 2: popclear(); // read-to-write delay cprint(POP_Y+3, POP_X+4, "Rd-Wr delay "); cprint(POP_Y+4, POP_X+4, " (2 - 6 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rwt, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); rwt = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 3: popclear(); // read-to-write delay cprint(POP_Y+3, POP_X+4, "Wr-Rd delay "); cprint(POP_Y+4, POP_X+4, " (1 - 2 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_wrt, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); wrt = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 4: popclear(); // Read write queue bypass count cprint(POP_Y+3, POP_X+4, "Rd/Wr bypass "); cprint(POP_Y+4, POP_X+4, " (2, 4 or 8 )"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rwqb, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); rwqb = getval(POP_Y+7, POP_X+11, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 5: popclear(); // refresh rate cprint(POP_Y+3, POP_X+4, "Refresh rate "); cprint(POP_Y+4, POP_X+4, "Current: "); switch ( a64.t_ref){ case 1 : cprint(POP_Y+4, POP_X+14, "15.6us"); break; case 2 : cprint(POP_Y+4, POP_X+14, "7.8us "); break; case 3 : cprint(POP_Y+4, POP_X+14, "3.9us "); break; } cprint(POP_Y+6, POP_X+4, "New: "); cprint(POP_Y+7, POP_X+4, "(1) 15.6us"); cprint(POP_Y+8, POP_X+4, "(2) 7.8us "); cprint(POP_Y+9, POP_X+4, "(3) 3.9us "); ref = getval(POP_Y+6, POP_X+11, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 6: popclear(); //Enable 2T command and addressing cprint(POP_Y+3, POP_X+4, "Command rate:"); cprint(POP_Y+5, POP_X+4, "(1) 1T "); //only supoprted by CG revision and later cprint(POP_Y+6, POP_X+4, "(2) 2T "); en2t = getval(POP_Y+3, POP_X+22, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 7: popclear(); //Row cycle time cprint(POP_Y+3, POP_X+4, "Row cycle time: "); cprint(POP_Y+4, POP_X+4, " (7 - 20 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rct, 4, 0); cprint(POP_Y+7, POP_X+4, "New: "); rct = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 8: popclear(); //Active-to-Active RAS Delay cprint(POP_Y+3, POP_X+4, "RAS-RAS Delay: "); cprint(POP_Y+4, POP_X+4, " (2 - 4 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_rrd, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); rrd = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 9: popclear(); //Active-to-Active RAS Delay cprint(POP_Y+3, POP_X+4, "Write Recovery: "); cprint(POP_Y+4, POP_X+4, " (2 - 3 cycles)"); cprint(POP_Y+5, POP_X+4, "Current: "); dprint(POP_Y+5, POP_X+14, a64.t_wr, 2, 0); cprint(POP_Y+7, POP_X+4, "New: "); wr = getval(POP_Y+7, POP_X+12, 0); amd64_tweak(rwt, wrt, ref,en2t, rct, rrd, rwqb, wr); break; case 11: case 57: flag++; /* 0/CR - Cancel */ break; } } } } void get_option() { int cas =0, rp=0, rcd=0, ras=0, sflag = 0 ; while(!sflag) { switch(get_key()) { case 2: popclear(); cas = get_cas(); popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras = getval(POP_Y+3, POP_X+15, 0); popclear(); change_timing(cas, rcd, rp, ras); break; case 3: popclear(); cas = get_cas(); change_timing(cas, 0, 0, 0); sflag++; break; case 4: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd =getval(POP_Y+3, POP_X+15, 0); change_timing(0, rcd, 0, 0); sflag++; break; case 5: popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, rp, 0); sflag++; break; case 6: popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, 0, ras); sflag++; break; case 7: popclear(); amd64_option(); sflag++; popclear(); break; case 8: break; case 11: case 57: sflag++; /* 0/CR - Cancel */ break; } } } void get_option_1() { int rp=0, rcd=0, ras=0, sflag = 0 ; while(!sflag) { switch(get_key()) { case 2: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp = getval(POP_Y+3, POP_X+15, 0); popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras = getval(POP_Y+3, POP_X+15, 0); popclear(); change_timing(0, rcd, rp, ras); break; case 3: popclear(); cprint(POP_Y+3, POP_X+8, "tRCD: "); rcd =getval(POP_Y+3, POP_X+15, 0); change_timing(0, rcd, 0, 0); break; case 4: popclear(); cprint(POP_Y+3, POP_X+8, "tRP: "); rp =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, rp, 0); break; case 5: popclear(); cprint(POP_Y+3, POP_X+8, "tRAS: "); ras =getval(POP_Y+3, POP_X+15, 0); change_timing(0, 0, 0, ras); break; case 6: popclear(); amd64_option(); sflag++; popclear(); break; case 7: break; case 11: case 57: sflag++; /* 0/CR - Cancel */ break; } } } void get_menu(void) { int menu ; find_memctr(); switch(ctrl) { case 0: menu = 2; break; case 1: case 2: case 3: case 4: menu = 0; break; case 5: menu = 1; break; case 6: menu = 0; break; default: menu = -1; break; } if (menu == -1) { popclear(); } else if (menu == 0) { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tCAS "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRCD "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRP "); cprint(POP_Y+7, POP_X+5, "(5) Modify tRAS "); cprint(POP_Y+8, POP_X+5, "(0) Cancel"); wait_keyup(); get_option(); } else if (menu == 1) { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); cprint(POP_Y+7, POP_X+5, "(0) Cancel"); wait_keyup(); get_option(); } else // AMD64 special menu { cprint(POP_Y+1, POP_X+2, "Modify Timing:"); cprint(POP_Y+3, POP_X+5, "(1) Modify All "); cprint(POP_Y+4, POP_X+5, "(2) Modify tRCD "); cprint(POP_Y+5, POP_X+5, "(3) Modify tRP "); cprint(POP_Y+6, POP_X+5, "(4) Modify tRAS "); cprint(POP_Y+7, POP_X+5, "(5) AMD64 Options"); cprint(POP_Y+8, POP_X+5, "(0) Cancel"); wait_keyup(); get_option_1(); } } int get_cas(void) { int i852=0, cas=0; ulong drc, ddr; long *ptr; switch(ctrl) { case 0: ddr = 1; break; case 1: case 2: case 3: ddr = 1; break; case 4: pci_conf_read( 0, 0, 0, 0x44, 4, &ddr); ddr &= 0xFFFFC000; ptr=(long*)(ddr+0x120); drc = *ptr; if ((drc & 3) == 2) ddr = 2; else ddr = 1; break; case 5: ddr = 2; break; case 6: ddr = 1; i852 = 1; break; default: ddr = 1; } if (ddr == 1) { cprint(POP_Y+3, POP_X+8, "tCAS: "); cprint(POP_Y+5, POP_X+8, "(1) CAS 2.5 "); cprint(POP_Y+6, POP_X+8, "(2) CAS 2 "); if(!i852) { cprint(POP_Y+7, POP_X+8, "(3) CAS 3 "); } cas = getval(POP_Y+3, POP_X+15, 0); } else if (ddr == 2) { cprint(POP_Y+3, POP_X+8, "tCAS: "); cprint(POP_Y+5, POP_X+8, "(1) CAS 4 "); cprint(POP_Y+6, POP_X+8, "(2) CAS 3 "); cprint(POP_Y+7, POP_X+8, "(3) CAS 5 "); cas = getval(POP_Y+3, POP_X+15, 0); } else { cas = -1; } popclear(); return (cas); } ///////////////////////////////////////////////////////// // here we go for the exciting timing change part... // ///////////////////////////////////////////////////////// void change_timing_i852(int cas, int rcd, int rp, int ras) { ulong dramtlr; ulong int1, int2; pci_conf_read(0, 0, 1, 0x60, 4, &dramtlr); // CAS Latency (tCAS) int1 = dramtlr & 0xFF9F; if (cas == 2) { int2 = int1 ^ 0x20; } else if (cas == 1) { int2 = int1; } else { int2 = dramtlr; } // RAS-To-CAS (tRCD) int1 = int2 & 0xFFF3; if (rcd == 2) { int2 = int1 ^ 0x8; } else if (rcd == 3) { int2 = int1 ^ 0x4; } else if (rcd == 4) { int2 = int1; } // else { int2 = int2; } // RAS Precharge (tRP) int1 = int2 & 0xFFFC; if (rp == 2) { int2 = int1 ^ 0x2; } else if (rp == 3) { int2 = int1 ^ 0x1; } else if (rp == 4) { int2 = int1; } // else { int2 = int2; } // RAS Active to precharge (tRAS) int1 = int2 & 0xF9FF; if (ras == 5) { int2 = int1 ^ 0x0600; } else if (ras == 6) { int2 = int1 ^ 0x0400; } else if (ras == 7) { int2 = int1 ^ 0x0200; } else if (ras == 8) { int2 = int1; } // else { int2 = int2; } pci_conf_write(0, 0, 1, 0x60, 4, int2); __delay(500); } void change_timing_i925(int cas, int rcd, int rp, int ras) { ulong int1, dev0, temp; long *ptr; //read MMRBAR pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x114); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0x70; if (rcd == 2) { temp = int1 ^ 0x70; } else if (rcd == 3) { temp = int1 ^ 0x60; } else if (rcd == 4) { temp = int1 ^ 0x50; } else if (rcd == 5) { temp = int1 ^ 0x40; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x7; if (rp == 2) { temp = int1 ^ 0x7; } else if (rp == 3) { temp = int1 ^ 0x6; } else if (rp == 4) { temp = int1 ^ 0x5; } else if (rp == 5) { temp = int1 ^ 0x4; } // else { temp = temp;} if (mem_ctr[ctrl].device == 0x2770 ) // Lakeport? { // RAS Active to precharge (tRAS) int1 = temp | 0xF80000; // bits 23:19 if (ras == 4) { temp = int1 ^ 0xD80000; } else if (ras == 5) { temp = int1 ^ 0xD00000; } else if (ras == 6) { temp = int1 ^ 0xC80000; } else if (ras == 7) { temp = int1 ^ 0xC00000; } else if (ras == 8) { temp = int1 ^ 0xB80000; } else if (ras == 9) { temp = int1 ^ 0xB00000; } else if (ras == 10) { temp = int1 ^ 0xA80000; } else if (ras == 11) { temp = int1 ^ 0xA00000; } else if (ras == 12) { temp = int1 ^ 0x980000; } else if (ras == 13) { temp = int1 ^ 0x900000; } else if (ras == 14) { temp = int1 ^ 0x880000; } else if (ras == 15) { temp = int1 ^ 0x800000; } // else { temp = temp;} } else { // RAS Active to precharge (tRAS) int1 = temp | 0xF00000; // bits 23:20 if (ras == 4) { temp = int1 ^ 0xB00000; } else if (ras == 5) { temp = int1 ^ 0xA00000; } else if (ras == 6) { temp = int1 ^ 0x900000; } else if (ras == 7) { temp = int1 ^ 0x800000; } else if (ras == 8) { temp = int1 ^ 0x700000; } else if (ras == 9) { temp = int1 ^ 0x600000; } else if (ras == 10) { temp = int1 ^ 0x500000; } else if (ras == 11) { temp = int1 ^ 0x400000; } else if (ras == 12) { temp = int1 ^ 0x300000; } else if (ras == 13) { temp = int1 ^ 0x200000; } else if (ras == 14) { temp = int1 ^ 0x100000; } else if (ras == 15) { temp = int1 ^ 0x000000; } // else { temp = temp;} } // CAS Latency (tCAS) int1 = temp | 0x0300; if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x100; } else if (cas == 3) { temp = int1 ^ 0x300; } // else { temp = temp;} *ptr = temp; __delay(500); return; } void change_timing_Lakeport(int cas, int rcd, int rp, int ras) { ulong int1, dev0, temp; long *ptr; //read MMRBAR pci_conf_read( 0, 0, 0, 0x44, 4, &dev0); dev0 &= 0xFFFFC000; ptr=(long*)(dev0+0x114); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0x70; if (rcd == 2) { temp = int1 ^ 0x70; } else if (rcd == 3) { temp = int1 ^ 0x60; } else if (rcd == 4) { temp = int1 ^ 0x50; } else if (rcd == 5) { temp = int1 ^ 0x40; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x7; if (rp == 2) { temp = int1 ^ 0x7; } else if (rp == 3) { temp = int1 ^ 0x6; } else if (rp == 4) { temp = int1 ^ 0x5; } else if (rp == 5) { temp = int1 ^ 0x4; } // else { temp = temp;} // CAS Latency (tCAS) int1 = temp | 0x0300; if (cas == 1) { temp = int1 ^ 0x200; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x100; } else if (cas == 3) { temp = int1 ^ 0x300; } // else { temp = temp;} *ptr = temp; __delay(500); return; } void change_timing_i875(int cas, int rcd, int rp, int ras){ ulong int1, dev6, temp; long *ptr; /* Read the MMR Base Address & Define the pointer from the BAR6 overflow register */ pci_conf_read( 0, 6, 0, 0x10, 4, &dev6); ptr=(long*)(dev6+0x60); temp = *ptr; // RAS-To-CAS (tRCD) int1 = temp | 0xC; if (rcd == 2) { temp = int1 ^ 0x4; } else if (rcd == 3) { temp = int1 ^ 0x8; } else if (rcd == 4) { temp = int1 ^ 0xC; } else if (rcd == 5) { temp = int1 ^ 0xC; } // else { temp = temp;} //RAS precharge (tRP) int1 = temp | 0x3; if (rp == 2) { temp = int1 ^ 0x1; } else if (rp == 3) { temp = int1 ^ 0x2; } else if (rp == 4) { temp = int1 ^ 0x3; } else if (rp == 5) { temp = int1 ^ 0x3; } // else { temp = temp;} // RAS Active to precharge (tRAS) int1 = temp | 0x380; if (ras == 5) { temp = int1 ^ 0x100; } else if (ras == 6) { temp = int1 ^ 0x180; } else if (ras == 7) { temp = int1 ^ 0x200; } else if (ras == 8) { temp = int1 ^ 0x280; } else if (ras == 9) { temp = int1 ^ 0x300; } else if (ras == 10) { temp = int1 ^ 0x380; } // else { temp = temp;} // CAS Latency (tCAS) int1 = temp | 0x60; if (cas == 1) { temp = int1 ^ 0x60; } // cas 2.5 else if (cas == 2) { temp = int1 ^ 0x40; } else if (cas == 3) { temp = int1 ^ 0x20; } // else { temp = temp; } *ptr = temp; __delay(500); return; } void change_timing_nf2(int cas, int rcd, int rp, int ras) { ulong dramtlr, dramtlr2; ulong int1, int2; pci_conf_read(0, 0, 1, 0x90, 4, &dramtlr); pci_conf_read(0, 0, 1, 0xA0, 4, &dramtlr2); // CAS Latency (tCAS) int1 = dramtlr2 | 0x0070; if (cas == 1) { int2 = int1 ^ 0x10; } // cas = 2.5 else if (cas == 2) { int2 = int1 ^ 0x50; } else if (cas == 3) { int2 = int1 ^ 0x40; } else { int2 = dramtlr2; } pci_conf_write(0, 0, 1, 0xA0, 4, int2); // RAS-To-CAS (tRCD) int1 = dramtlr | 0x700000; if (rcd == 2) { int2 = int1 ^ 0x500000; } else if (rcd == 3) { int2 = int1 ^ 0x400000; } else if (rcd == 4) { int2 = int1 ^ 0x300000; } else if (rcd == 5) { int2 = int1 ^ 0x200000; } else if (rcd == 6) { int2 = int1 ^ 0x100000; } else { int2 = dramtlr;} // RAS Precharge (tRP) int1 = int2 | 0x70000000; if (rp == 2) { int2 = int1 ^ 0x50000000; } else if (rp == 3) { int2 = int1 ^ 0x40000000; } else if (rp == 4) { int2 = int1 ^ 0x30000000; } else if (rp == 5) { int2 = int1 ^ 0x20000000; } else if (rp == 6) { int2 = int1 ^ 0x10000000; } // else { int2 = int2;} // RAS Active to precharge (tRAS) int1 = int2 | 0x78000; if (ras == 4) { int2 = int1 ^ 0x58000; } else if (ras == 5) { int2 = int1 ^ 0x50000; } else if (ras == 6) { int2 = int1 ^ 0x48000; } else if (ras == 7) { int2 = int1 ^ 0x40000; } else if (ras == 8) { int2 = int1 ^ 0x38000; } else if (ras == 9) { int2 = int1 ^ 0x30000; } else if (ras == 10) { int2 = int1 ^ 0x28000; } else if (ras == 11) { int2 = int1 ^ 0x20000; } else if (ras == 12) { int2 = int1 ^ 0x18000; } else if (ras == 13) { int2 = int1 ^ 0x10000; } else if (ras == 14) { int2 = int1 ^ 0x08000; } // else { int2 = int2;} pci_conf_write(0, 0, 1, 0x90, 4, int2); __delay(500); } void change_timing_amd64(int cas, int rcd, int rp, int ras) { ulong dramtlr; ulong int1= 0x0; pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); // RAS-To-CAS (tRCD) int1 = dramtlr | 0x7000; if (rcd == 2) { dramtlr = int1 ^ 0x5000; } else if (rcd == 3) { dramtlr = int1 ^ 0x4000; } else if (rcd == 4) { dramtlr = int1 ^ 0x3000; } else if (rcd == 5) { dramtlr = int1 ^ 0x2000; } else if (rcd == 6) { dramtlr = int1 ^ 0x1000; } else if (rcd == 1) { dramtlr = int1 ^ 0x6000; } // else { dramtlr = dramtlr;} //RAS precharge (tRP) int1 = dramtlr | 0x7000000; if (rp == 2) { dramtlr = int1 ^ 0x5000000; } else if (rp == 3) { dramtlr = int1 ^ 0x4000000; } else if (rp == 1) { dramtlr = int1 ^ 0x6000000; } else if (rp == 4) { dramtlr = int1 ^ 0x3000000; } else if (rp == 5) { dramtlr = int1 ^ 0x2000000; } else if (rp == 6) { dramtlr = int1 ^ 0x1000000; } // else { dramtlr = dramtlr;} // RAS Active to precharge (tRAS) int1 = dramtlr | 0xF00000; if (ras == 5) { dramtlr = int1 ^ 0xA00000; } else if (ras == 6) { dramtlr = int1 ^ 0x900000; } else if (ras == 7) { dramtlr = int1 ^ 0x800000; } else if (ras == 8) { dramtlr = int1 ^ 0x700000; } else if (ras == 9) { dramtlr = int1 ^ 0x600000; } else if (ras == 10) { dramtlr = int1 ^ 0x500000; } else if (ras == 11) { dramtlr = int1 ^ 0x400000; } else if (ras == 12) { dramtlr = int1 ^ 0x300000; } else if (ras == 13) { dramtlr = int1 ^ 0x200000; } else if (ras == 14) { dramtlr = int1 ^ 0x100000; } // else { dramtlr = dramtlr;} // CAS Latency (tCAS) int1 = dramtlr | 0x7; // some changes will cause the system hang, tried Draminit to no avail if (cas == 1) { dramtlr = int1 ^ 0x2; } // cas 2.5 else if (cas == 2) { dramtlr = int1 ^ 0x6; } else if (cas == 3) { dramtlr = int1 ^ 0x5; } else if (cas == 4) { dramtlr = int1 ^ 0x7; } //cas 1.5 on a64 // else { dramtlr = dramtlr; } // pci_conf_read(0, 24, 2, 0x90, 4, &dramcr);// use dram init pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); __delay(500); //////////////////////////////////////////////////////////////// // trying using the draminit, but do not work } // copy from lib.c code to add delay to chipset timing modification void __delay(ulong loops) { int d0; __asm__ __volatile__( "\tjmp 1f\n" ".align 16\n" "1:\tjmp 2f\n" ".align 16\n" "2:\tdecl %0\n\tjns 2b" :"=&a" (d0) :"0" (loops)); } void amd64_tweak(int rwt, int wrt, int ref, int en2t, int rct, int rrd, int rwqb, int wr) { ulong dramtlr; ulong int1= 0x0; pci_conf_read(0, 24, 2, 0x88, 4, &dramtlr); // Row Cycle time int1 = dramtlr | 0xF0; if (rct == 7 ) { dramtlr = int1 ^ 0xF0; } else if (rct == 8 ) { dramtlr = int1 ^ 0xE0; } else if (rct == 9 ) { dramtlr = int1 ^ 0xD0; } else if (rct == 10) { dramtlr = int1 ^ 0xC0; } else if (rct == 11) { dramtlr = int1 ^ 0xB0; } else if (rct == 12) { dramtlr = int1 ^ 0xA0; } else if (rct == 13) { dramtlr = int1 ^ 0x90; } else if (rct == 14) { dramtlr = int1 ^ 0x80; } else if (rct == 15) { dramtlr = int1 ^ 0x70; } else if (rct == 16) { dramtlr = int1 ^ 0x60; } else if (rct == 17) { dramtlr = int1 ^ 0x50; } else if (rct == 18) { dramtlr = int1 ^ 0x40; } else if (rct == 19) { dramtlr = int1 ^ 0x30; } else if (rct == 20) { dramtlr = int1 ^ 0x20; } // else { dramtlr = dramtlr;} //Active-avtive ras-ras delay int1 = dramtlr | 0x70000; if (rrd == 2) { dramtlr = int1 ^ 0x50000; } // 2 bus clocks else if (rrd == 3) { dramtlr = int1 ^ 0x40000; } // 3 bus clocks else if (rrd == 4) { dramtlr = int1 ^ 0x30000; } // 4 bus clocks // else { dramtlr = dramtlr;} //Write recovery time int1 = dramtlr | 0x10000000; if (wr == 2) { dramtlr = int1 ^ 0x10000000; } // 2 bus clocks else if (wr == 3) { dramtlr = int1 ^ 0x00000000; } // 3 bus clocks // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x88, 4, dramtlr); __delay(500); ////////////////////////////////////////////// pci_conf_read(0, 24, 2, 0x8C, 4, &dramtlr); // Write-to read delay int1 = dramtlr | 0x1; if (wrt == 2) { dramtlr = int1 ^ 0x0; } else if (wrt == 1) { dramtlr = int1 ^ 0x1; } // else { dramtlr = dramtlr;} // Read-to Write delay int1 = dramtlr | 0x70; if (rwt == 1) { dramtlr = int1 ^ 0x70; } else if (rwt == 2) { dramtlr = int1 ^ 0x60; } else if (rwt == 3) { dramtlr = int1 ^ 0x50; } else if (rwt == 4) { dramtlr = int1 ^ 0x40; } else if (rwt == 5) { dramtlr = int1 ^ 0x30; } else if (rwt == 6) { dramtlr = int1 ^ 0x20; } // else { dramtlr = dramtlr;} //Refresh Rate int1 = dramtlr | 0x1800; if (ref == 1) { dramtlr = int1 ^ 0x1800; } // 15.6us else if (ref == 2) { dramtlr = int1 ^ 0x1000; } // 7.8us else if (ref == 3) { dramtlr = int1 ^ 0x0800; } // 3.9us // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x8c, 4, dramtlr); __delay(500); ///////////////////////////////////// pci_conf_read(0, 24, 2, 0x90, 4, &dramtlr); // Enable 2t command int1 = dramtlr | 0x10000000; if (en2t == 2) { dramtlr = int1 ^ 0x00000000; } // 2T else if (en2t == 1) { dramtlr = int1 ^ 0x10000000; } // 1T // else { dramtlr = dramtlr;} // Read Write queue bypass count int1 = dramtlr | 0xC000; if (rwqb == 2) { dramtlr = int1 ^ 0xC000; } else if (rwqb == 4) { dramtlr = int1 ^ 0x8000; } else if (rwqb == 8) { dramtlr = int1 ^ 0x4000; } else if (rwqb == 16) { dramtlr = int1 ^ 0x0000; } // else { dramtlr = dramtlr;} pci_conf_write(0, 24, 2, 0x90, 4, dramtlr); __delay(500); restart(); } memtest86+-5.01/cpuid.c0000644000000000000000000000500412201317426013311 0ustar rootroot/* * 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 max std cpuid & vendor ID */ cpuid(0x0, &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 processor family information & feature flags */ if (cpu_id.max_cpuid >= 1) { cpuid(0x00000001, &cpu_id.vers.flat, &cpu_id.info.flat, &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]); } /* Get the digital thermal sensor & power management status bits */ if(cpu_id.max_cpuid >= 6) { cpuid(0x00000006, &cpu_id.dts_pmp, &dummy[0], &dummy[1], &dummy[2]); } /* Get the max extended cpuid */ cpuid(0x80000000, &cpu_id.max_xcpuid, &dummy[0], &dummy[1], &dummy[2]); /* Get extended feature flags, only save EDX */ if (cpu_id.max_xcpuid >= 0x80000001) { cpuid(0x80000001, &dummy[0], &dummy[1], &dummy[2], &cpu_id.fid.uint32_array[2]); } /* Get the brand ID */ if (cpu_id.max_xcpuid >= 0x80000004) { 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_xcpuid >= 0x80000005) { cpuid(0x80000005, &dummy[0], &dummy[1], &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]); } if (cpu_id.max_xcpuid >= 0x80000006) { cpuid(0x80000006, &dummy[0], &dummy[1], &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]); } break; case 'G': /* Intel Processors, Need to do this in init.c */ break; } /* Turn off mon bit since monitor based spin wait may not be reliable */ cpu_id.fid.bits.mon = 0; }