coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
ramtest.c
Go to the documentation of this file.
1 #include <stdint.h>
2 #include <lib.h>
3 #include <console/console.h>
4 #include <device/mmio.h>
5 
6 #if ENV_X86 && CONFIG(SSE2)
7 /* Assembler in lib/ is ugly. */
8 static void write_phys(uintptr_t addr, u32 value)
9 {
10  asm volatile (
11  "movnti %1, (%0)"
12  : /* outputs */
13  : "r" (addr), "r" (value) /* inputs */
14  );
15 }
16 
17 static void phys_memory_barrier(void)
18 {
19  // Needed for movnti
20  asm volatile ("sfence" ::: "memory");
21 }
22 #else
24 {
25  write32((void *)addr, value);
26 }
27 
28 static void phys_memory_barrier(void)
29 {
30  asm volatile ("" ::: "memory");
31 }
32 #endif
33 
35 {
36  return read32((void *)addr);
37 }
38 
39 /**
40  * Rotate ones test pattern that access every bit on a 128bit wide
41  * memory bus. To test most address lines, addresses are scattered
42  * using 256B, 4kB and 64kB increments.
43  *
44  * @param idx Index to test pattern (0=<idx<0x400)
45  * @param addr Memory to access on idx
46  * @param value Value to write or read at addr
47  */
48 static inline void test_pattern(unsigned short int idx,
49  unsigned long *addr, unsigned long *value)
50 {
51  uint8_t j, k;
52 
53  k = (idx >> 8) + 1;
54  j = (idx >> 4) & 0x0f;
55  *addr = idx & 0x0f;
56  *addr |= j << (4*k);
57  *value = 0x01010101 << (j & 7);
58  if (j & 8)
59  *value = ~(*value);
60 }
61 
62 /**
63  * Simple write-read-verify memory test. See console debug output for
64  * any dislocated bytes.
65  *
66  * Tests 1MiB of memory starting from start.
67  *
68  * @param start System memory offset, aligned to 128bytes
69  */
70 static int ram_bitset_nodie(uintptr_t start)
71 {
72  unsigned long addr, value, value2;
73  unsigned short int idx;
74  unsigned char failed, failures;
75  uint8_t verbose = 0;
76 
77  printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start);
78  for (idx = 0; idx < 0x400; idx += 4) {
79  test_pattern(idx, &addr, &value);
80  write_phys(start + addr, value);
81  }
82 
83  /* Make sure we don't read before we wrote */
85 
86  printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start);
87  failures = 0;
88  for (idx = 0; idx < 0x400; idx += 4) {
89  test_pattern(idx, &addr, &value);
90  value2 = read_phys(start + addr);
91 
92  failed = (value2 != value);
93  failures |= failed;
94  if (failed && !verbose) {
95  printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
96  start + addr, value, value2);
97  }
98  if (verbose) {
99  if ((addr & 0x0f) == 0)
100  printk(BIOS_DEBUG, "%08lx wr: %08lx rd:",
101  start + addr, value);
102  if (failed)
103  printk(BIOS_DEBUG, " %08lx!", value2);
104  else
105  printk(BIOS_DEBUG, " %08lx ", value2);
106  if ((addr & 0x0f) == 0xc)
107  printk(BIOS_DEBUG, "\n");
108  }
109  }
110  if (failures) {
111  post_code(0xea);
112  printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
113  return 1;
114  }
115  printk(BIOS_DEBUG, "\nDRAM range verified.\n");
116  return 0;
117 }
118 
119 
120 void ram_check(uintptr_t start)
121 {
122  /*
123  * This is much more of a "Is my DRAM properly configured?"
124  * test than a "Is my DRAM faulty?" test. Not all bits
125  * are tested. -Tyson
126  */
127  printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
128  if (ram_bitset_nodie(start))
129  die("DRAM ERROR");
130  printk(BIOS_DEBUG, "Done.\n");
131 }
132 
133 
135 {
136  int ret;
137  /*
138  * This is much more of a "Is my DRAM properly configured?"
139  * test than a "Is my DRAM faulty?" test. Not all bits
140  * are tested. -Tyson
141  */
142  printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);
143 
144  ret = ram_bitset_nodie(start);
145  printk(BIOS_DEBUG, "Done.\n");
146  return ret;
147 }
148 
150 {
151  unsigned long addr, value, value2;
152  unsigned short int idx;
153  unsigned char failed, failures;
154 
155  for (idx = 0; idx < 0x400; idx += 4) {
156  test_pattern(idx, &addr, &value);
157  write_phys(start + addr, value);
158  }
159 
160  /* Make sure we don't read before we wrote */
162 
163  failures = 0;
164  for (idx = 0; idx < 0x400; idx += 4) {
165  test_pattern(idx, &addr, &value);
166  value2 = read_phys(start + addr);
167 
168  failed = (value2 != value);
169  failures |= failed;
170  }
171  return failures;
172 }
173 
174 /* Assumption is 32-bit addressable UC memory at dst. This also executes
175  * on S3 resume path so target memory must be restored.
176  */
178 {
179  int fail = 0;
180  u32 backup;
181  backup = read_phys(dst);
182  write_phys(dst, 0x55555555);
184  if (read_phys(dst) != 0x55555555)
185  fail = 1;
186  write_phys(dst, 0xaaaaaaaa);
188  if (read_phys(dst) != 0xaaaaaaaa)
189  fail = 1;
190  write_phys(dst, 0x00000000);
192  if (read_phys(dst) != 0x00000000)
193  fail = 1;
194  write_phys(dst, 0xffffffff);
196  if (read_phys(dst) != 0xffffffff)
197  fail = 1;
198 
199  write_phys(dst, backup);
200  if (fail) {
201  post_code(0xea);
202  die("RAM INIT FAILURE!\n");
203  }
205 }
pte_t value
Definition: mmu.c:91
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
void __noreturn die(const char *fmt,...)
Definition: die.c:17
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define post_code(value)
Definition: post_code.h:12
void ram_check(uintptr_t start)
Definition: ramtest.c:120
static void phys_memory_barrier(void)
Definition: ramtest.c:28
int ram_check_nodie(uintptr_t start)
Definition: ramtest.c:134
static void test_pattern(unsigned short int idx, unsigned long *addr, unsigned long *value)
Rotate ones test pattern that access every bit on a 128bit wide memory bus.
Definition: ramtest.c:48
static u32 read_phys(uintptr_t addr)
Definition: ramtest.c:34
static void write_phys(uintptr_t addr, u32 value)
Definition: ramtest.c:23
static int ram_bitset_nodie(uintptr_t start)
Simple write-read-verify memory test.
Definition: ramtest.c:70
int ram_check_noprint_nodie(uintptr_t start)
Definition: ramtest.c:149
void quick_ram_check_or_die(uintptr_t dst)
Definition: ramtest.c:177
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8