Re: Perform minimal RAM test at boot

Peter Steiner (p.steiner@t-online.de)
Sun, 31 Oct 1999 00:57:07 +0200


>> Why can't we use something similar to check memory sizes? I have a thinkpad
>
>That code isnt actually good enough in theory (tho practice may be different)
>to detect missing ram.

What about the attached code? It's for 2.3.20 but it should be easy to
apply to other versions.

>> 770X with 192MB and 2.2.13 only reports 64MB. If I tell linux that it has
>> 192MB then it will crash - I need to tell it 191MB (or rather, the amount
>> that the machine displays on boot.
>
>Your machine has 192Mb but the top 4K is probably real RAM used by the SMM
>system bios code. A RAM test wont help you

Without e820 it's almost impossible to tell anyway. My computer seems
to have a 16kB area reserved for the BIOS.

e820: 12288 @ 03ffc000 (ACPI data)
e820: 4096 @ 03fff000 type 4

--8<--

If the test is too slow on machines with much memory the TEST_SIZE
could be reduced down to 64, bigger is better. It's hardly noticeable
on my 64MB system, though. Bogus memory is disabled. The system should
boot (and run) fine anyway. This is not a real memory test. It is
specially designed to verify the memory map. Suggestions welcome.

--- ./arch/i386/mm/init.c.original Fri Oct 29 15:18:42 1999
+++ ./arch/i386/mm/init.c Sun Oct 31 00:32:33 1999
@@ -368,6 +368,81 @@
printk(".\n");
}

+#define TEST_SIZE PAGE_SIZE
+
+void __init verify_memory_map(unsigned long start_mem, unsigned long end_mem)
+{
+ unsigned long tmp;
+ unsigned long last_bad = 0;
+ volatile unsigned long *addr;
+ int Ok = 1;
+ int err_type_old = 0;
+ int err_type = 0;
+
+ end_mem = PAGE_ALIGN(end_mem);
+
+ printk("Verifying memory map... ");
+ for (tmp = end_mem-PAGE_SIZE; tmp >= start_mem; tmp -= PAGE_SIZE) {
+ /* reserved pages may already contain valid data */
+ if (!PageReserved(mem_map+MAP_NR(tmp))) {
+ unsigned long *e = (unsigned long *) (tmp+TEST_SIZE);
+ for (addr=(unsigned long *) tmp; addr<e; addr++) {
+ *addr=(unsigned long) addr;
+ if (*addr != (unsigned long) addr)
+ break;
+ }
+ }
+ }
+
+ for (tmp = start_mem; tmp < end_mem ; tmp += PAGE_SIZE) {
+ if (!PageReserved(mem_map+MAP_NR(tmp))) {
+ unsigned long *i;
+ unsigned long *j = 0;
+ int c1 = 0;
+ int c2 = 0;
+ unsigned long *e = (unsigned long *) (tmp+TEST_SIZE);
+ for (addr=(unsigned long *) tmp; addr<e; addr++, j++) {
+ if ((i = (unsigned long *) *addr) != addr) {
+ c2++;
+ if (!c1) j=i; /* check for aliasing */
+ if (i==j) c1++;
+ if (c2>=10) break;
+ }
+ }
+ err_type_old = err_type;
+ if (c2) {
+ if (Ok) {
+ Ok=0;
+ printk("\n");
+ }
+ if (c1>=10) err_type=1;
+ else if (c2>=10) err_type=2;
+ else err_type=3;
+ set_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+ last_bad = tmp-PAGE_OFFSET;
+ } else {
+ err_type = 0;
+ }
+ if (err_type != err_type_old) {
+ if (err_type==1)
+ printk(" Memory aliasing");
+ else if (err_type==2)
+ printk(" No RAM");
+ else if (err_type==3)
+ printk(" Bad memory?");
+ if (err_type)
+ printk(" @ %08lx",last_bad);
+ else
+ printk(" - %08lx ... disabled\n", last_bad+PAGE_SIZE-1);
+ }
+ }
+ }
+ if (err_type)
+ printk(" - %08lx ... disabled.\n", last_bad+PAGE_SIZE-1);
+ if (Ok) printk("Ok.\n");
+}
+
+
void __init mem_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long start_low_mem = PAGE_SIZE;
@@ -454,6 +529,8 @@
}
}

+ verify_memory_map(PAGE_OFFSET, end_mem);
+
for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/