Re: i386 memory corrupted by free_initmem()
Sat, 17 May 1997 01:03:03 +0200

From Fri May 16 18:04:02 1997

> In recent kernels I noticed some strange memory corruption.
> This turns out to be caused by free_initmem() in
> arch/i386/mm/init.c. (It frees too much.)

I've looked at it and all addresses seem to be calculated properly.
Can you send me your configuration, version of binutils and an output
of "objdump --all vmlinux"? I would also appreciate a more detailed
description of the crash.

Well, my description is good enough: free_initmem() frees too much.
Replace it by

void free_initmem(void)
unsigned long begin, end, addr;

begin = (unsigned long)(&__init_begin);
end = (unsigned long)(&__init_end);

for (addr = ((begin + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
addr+PAGE_SIZE-1 < end; addr += PAGE_SIZE) {
mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
atomic_set(&mem_map[MAP_NR(addr)].count, 1);

printk ("Freeing unused kernel memory: %luk freed\n",
(end - begin) >> 10);

and all is fine, except that the printk may be overly optimistic.

(In fact I think you should do this - maybe with the latest
binutils this is not required, but the above code is more
robust, and equivalent to yours in case init_begin and init_end
are aligned on a page boundary.)

I got c0217610 and c021fc6c for init_begin and init_end, respectively.
Thus, the original code will allow all data in c0217000 - c0217610
to be overwritten. This had various amusing consequences.

I know that contains the line . = ALIGN(4096) ,
but on this machine here (binutils that does not cause
init_begin to be page-aligned.

[I just installed binutils on this machine, and since
the release notes asked for libc-5.4.23, also that, and since
the release notes asked for at least gcc 2.7.2 also gcc-
Unfortunately this breaks gcc (only gcc -V 2.7.0 now works).
That is how one gets punished for trusting binary distributions.
Probably someone knows what is wrong with these distributions,
or what action not mentioned in the release notes is required.]