linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: Re: [PATCH] BadRAM for 2.5.73-mm2
@ 2003-07-02 12:58 steven.newbury1
  0 siblings, 0 replies; only message in thread
From: steven.newbury1 @ 2003-07-02 12:58 UTC (permalink / raw)
  To: Oleg Drokin; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2467 bytes --]

============================================================
From: Oleg Drokin <green@namesys.com>
Date: 2003/07/02 Wed AM 06:23:24 GMT
To: steven.newbury1@ntlworld.com
CC: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] BadRAM for 2.5.73-mm2

Hello!

On Wed, Jul 02, 2003 at 03:33:26AM +0000, steven.newbury1@ntlworld.com wrote:

> It will probably apply cleanly to 2.5.73 as well but I haven't checked it
> yet...

This

> It is based it on
> http://rick.vanrein.org/linux/badram/software/BadRAM-2.4.20.1.patch

and this patches both have a bug that effectively disables all highmem (if present)
when badram patch is activated. I contacted Rick, but never got any answer back.
(in fact I got an auto reply from some Debian bugtracking system, but that's about it).
Corrected 2.4.21 version of the patch is available at
http://linuxhacker.ru/patches/2.4.21-badram.diff

The arch/i386/mm/init.c part:
> +void __init one_highpage_init(struct page *page, int pfn, int bad_ppro,
> +                               _Bool *bad)
>   {
> +       *bad = 0;
>         if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
>                 ClearPageReserved(page);
>                 set_bit(PG_highmem, &page->flags);
>                 set_page_count(page, 1);
> -               __free_page(page);
> +#ifdef CONFIG_BADRAM
> +               if (PageBad(page))
> +                       *bad = 1;
> +               else
> +#else
> +                       __free_page(page);
> +#endif
>                 totalhigh_pages++;

should obviously get "#else" replaced with "#endif" and original "#endif" should be removed
because otherwise all of the highmem pages are either bad or used right from the initialisation.
(Yes, I have highmem (2G RAM) system with 2 bits bad and I am too lazy to to go to the store to
replace the RAM modules, so I given a patch a try and discovered this problem (which is there
for a long time it seems). I suspect that I am the only one who runs this patch on highmem system,
though ;) )

Bye,
    Oleg
============================================================
Thanks Oleg!

Strangely enough I had this right but then "fixed" it.  I obviously had to manually apply the patch to arch/i386/mm/init.c since there are a few logic changes etc.  I only re-inserted the bug when checking the changes I had made compared to the original patch and assumed that I had been wrong (I assumed the original patch worked ;-)).

Attached is the new patch.


[-- Attachment #2: BadRAM-2.5.73-mm2.1.diff --]
[-- Type: application/octet-stream, Size: 23991 bytes --]

diff -urN linux-2.5.73-mm2/CREDITS linux-2.5/CREDITS
--- linux-2.5.73-mm2/CREDITS	2003-06-17 05:20:07.000000000 +0100
+++ linux-2.5/CREDITS	2003-07-02 01:58:52.000000000 +0100
@@ -2365,6 +2365,12 @@
 S: 55127 Mainz
 S: Germany
 
+N: Steven Newbury
+E: s_j_newbury@yahoo.co.uk
+D: Forward ported BadRAM patch to 2.5.73 from 2.4.20
+S: Derby
+S: United Kingdom
+
 N: David C. Niemi
 E: niemi@tux.org
 W: http://www.tux.org/~niemi/
@@ -2601,6 +2607,14 @@
 S: Malvern, Pennsylvania 19355
 S: USA
 
+N: Rick van Rein
+E: vanrein@cs.utwente.nl
+W: http://www.cs.utwente.nl/~vanrein
+D: Memory, the BadRAM subsystem dealing with statically challanged RAM modules.
+S: Binnenes 67
+S: 9407 CX Assen
+S: The Netherlands
+
 N: Stefan Reinauer
 E: stepan@linux.de
 W: http://www.freiburg.linux.de/~stepan/
@@ -2819,6 +2833,13 @@
 E:
 D: Macintosh IDE Driver
 
+N: Nico Schmoigl
+E: nico@writemail.com
+W: http://webrum.uni-mannheim.de/math/schmoigl/linux/
+D: Migration of BadRAM patch to 2.4.4 series (with Rick van Rein)
+S: Mannheim, BW, Germany
+P: 2047/38FC9E03  5D DB 09 E4 3F F3 CD 09 75 59 - 11 17 9C 03 46 E3 38 FC 9E 03
+
 N: Peter De Schrijver
 E: stud11@cc4.kuleuven.ac.be
 D: Mitsumi CD-ROM driver patches March version
diff -urN linux-2.5.73-mm2/Documentation/badram.txt linux-2.5/Documentation/badram.txt
--- linux-2.5.73-mm2/Documentation/badram.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.5/Documentation/badram.txt	2003-07-01 20:02:27.000000000 +0100
@@ -0,0 +1,266 @@
+INFORMATION ON USING BAD RAM MODULES
+====================================
+
+Introduction
+	RAM is getting smaller and smaller, and as a result, also more and more
+	vulnerable. This makes the manufacturing of hardware more expensive,
+	since an excessive amount of RAM chips must be discarded on account of
+	a single cell that is wrong. Similarly, static discharge may damage a
+	RAM module forever, which is usually remedied by replacing it
+	entirely.
+
+	This is not necessary, as the BadRAM code shows: By informing the Linux
+	kernel which addresses in a RAM are damaged, the kernel simply avoids
+	ever allocating such addresses but makes all the rest available.
+
+Reasons for this feature
+	There are many reasons why this kernel feature is useful:
+	- Chip manufacture is resource intensive; waste less and sleep better
+	- It's another chance to promote Linux as "the flexible OS"
+	- Some laptops have their RAM soldered in... and then it fails!
+	- It's plain cool ;-)
+
+Running example
+	To run this project, I was given two DIMMs, 32 MB each. One, that we
+	shall use as a running example in this text, contained 512 faulty bits,
+	spread over 1/4 of the address range in a regular pattern. Some tricks
+	with a RAM tester and a few binary calculations were sufficient to
+	write these faults down in 2 longword numbers.
+
+	The kernel recognised the correct number of pages with faults and did
+	not give them out for allocation. The allocation routines could
+	therefore progress as normally, without any adaption.
+	So, I gained 30 MB of DIMM which would otherwise have been thrown
+	away. After booting the kernel, the kernel behaved exactly as it
+	always had.
+
+Initial checks
+	If you experience RAM trouble, first read /usr/src/linux/memory.txt
+	and try out the mem=4M trick to see if at least some initial parts
+	of your RAM work well. The BadRAM routines halt the kernel in panic
+	if the reserved area of memory (containing kernel stuff) contains
+	a faulty address.
+
+Running a RAM checker
+	The memory checker is not built into the kernel, to avoid delays at
+	runtime. If you experience problems that may be caused by RAM, run
+	a good RAM checker, such as
+		http://reality.sgi.com/cbrady_denver/memtest86
+	The output of a RAM checker provides addresses that went wrong. In
+	the 32 MB chip with 512 faulty bits mentioned above, the errors were
+	found in the 8MB-16MB range (the DIMM was in slot #0) at addresses
+		xxx42f4
+		xxx62f4
+		xxxc2f4
+		xxxe2f4
+	and the error was a "sticky 1 bit", a memory bit that stayed "1" no
+	matter what was written to it. The regularity of this pattern
+	suggests the death of a buffer at the output stages of a row on one of
+	the chips. I expect such regularity to be commonplace. Finding this
+	regularity currently is human effort, but it should not be hard to
+	alter a RAM checker to capture it in some sort of pattern, possibly
+	the BadRAM patterns described below.
+
+	By the way, if you manage to get hold of memtest86 version 2.3 or
+	beyond, you can configure the printing mode to produce BadRAM patterns,
+	which find out exactly what you must enter on the LILO: commandline,
+	except that you shouldn't mention the added spacing. That means that
+	you can skip the following step, which saves you a *lot* of work.
+
+	Also by the way, if your machine has the ISA memory gap in the 15M-16M
+	range unstoppable, Linux can get in trouble. One way of handling that
+	situation is by specifying the total memory size to Linux with a boot
+	parameter mem=... and then to tell it to treat the 15M-16M range as
+	faulty with an additional boot parameter, for instance:
+		mem=24M badram=0x00f00000,0xfff00000
+	if you installed 24MB of RAM in total.
+
+Capturing errors in a pattern
+	Instead of manually providing all 512 errors to the kernel, it's nicer
+	to generate a pattern. Since the regularity is based on address decoding
+	software, which generally takes certain bits into account and ignores
+	others, we shall provide a faulty address F, together with a bit mask M
+	that specifies which bits must be equal to F. In C code, an address A
+	is faulty if and only if
+		(F & M) == (A & M)
+	or alternately (closer to a hardware implementation):
+		~((F ^ A) & M)
+	In the example 32 MB chip, we had the faulty addresses in 8MB-16MB:
+		xxx42f4         ....0100....
+		xxx62f4         ....0110....
+		xxxc2f4         ....1100....
+		xxxe2f4         ....1110....
+	The second column represents the alternating hex digit in binary form.
+	Apperantly, the first and one-but last binary digit can be anything,
+	so the binary mask for that part is 0101. The mask for the part after
+	this is 0xfff, and the part before should select anything in the range
+	8MB-16MB, or 0x00800000-0x01000000; this is done with a bitmask
+	0xff80xxxx. Combining these partial masks, we get:
+		F=0x008042f4    M=0xff805fff
+	That covers everything for this DIMM; for more complicated failing
+	DIMMs, or for a combination of multiple failing DIMMs, it can be
+	necessary to set up a number of such F/M pairs.
+
+Rebooting Linux
+	Now that these patterns are known (and double-checked, the calculations
+	are highly error-prone... it would be neat to test them in the RAM
+	checker...) we simply restart Linux with these F/M pairs as a parameter.
+	If you normally boot as follows:
+	       LILO: linux
+	you should now boot with
+	       LILO: linux badram=0x008042f4,0xff805fff
+	or perhaps by mentioning more F/M pairs in an order F0,M0,F1,M1,...
+	When you provide an odd number of arguments to badram, the default mask
+	0xffffffff (only one address matched) is applied to the pattern.
+
+	Beware of the commandline length. At least up to LILO version 0.21,
+	the commandline is cut off after the 78th character; later versions
+	may go as far as the kernel goes, namely 255 characters. In no way is
+	it possible to enter more than 10 numbers to the badram boot option.
+
+	When the kernel now boots, it should not give any trouble with RAM.
+	Mind you, this is under the assumption that the kernel and its data
+	storage do not overlap an erroneous part. If this happens, and the
+	kernel does not choke on it right away, it will stop with a panic.
+	You will need to provide a RAM where the initial, say 2MB, is faultless.
+
+	Now look up your memory status with
+	       dmesg | grep ^Memory:
+	which prints a single line with information like
+		Memory: 158524k/163840k available
+			(940k kernel code,
+			412k reserved,
+			1856k data,
+			60k init,
+			0k highmem,
+			2048k BadRAM)
+	The latter entry, the badram, is 2048k to represent the loss of 2MB
+	of general purpose RAM due to the errors. Or, positively rephrased,
+	instead of throwing out 32MB as useless, you only throw out 2MB.
+
+	If the system is stable (try compiling a few kernels, and do a few
+	finds in / or so) you may add the boot parameter to /etc/lilo.conf
+	as a line to _all_ the kernels that handle this trouble with a line
+		append="badram=0x008042f4,0xff805fff"
+	after which you run "lilo".
+	Warning: Don't experiment with these settings on your only boot image.
+	If the BadRAM overlays kernel code, data, init, or other reserved
+	memory, the kernel will halt in panic. Try settings on a test boot
+	image first, and if you get a panic you should change the order of
+	your DIMMs [which may involve buying a new one just to be able to
+	change the order].
+
+	You are allowed to enter any number of BadRAM patterns in all the
+	places documented in this file. They will all apply. It is even
+	possible to mention several BadRAM patterns in a single place. The
+	completion of an odd number of arguments with the default mask is
+	done separately for each badram=... option.
+
+Kernel Customisation
+	Some people prefer to enter their badram patterns in the kernel, and
+	this is also possible. In mm/page_alloc.c there is an array of unsigned
+	long integers into which the parameters can be entered, prefixed with
+	the number of integers (twice the number of patterns). The array is
+	named badram_custom and it will be added to the BadRAM list whenever an
+	option 'badram' is provided on the commandline when booting, ealancing, Kanoj Sarcar, SGI, Jan 2000
  *  Per cpu hot/cold page lists, bulk allocation, Martin J. Bligh, Sept 2002
  *          (lots of bits borrowed from Ingo Molnar & Andrew Morton)
+ *  BadRAM handling, Rick van Rein, Feb 2001
  */
 
 #include <linux/config.h>
@@ -1615,3 +1616,96 @@
 	setup_per_zone_pages_min();
 	return 0;
 }
+
+
+#ifdef CONFIG_BADRAM
+
+/* Given a pointed-at address and a mask, increment the page so that the
+ * mask hides the increment. Return 0 if no increment is possible.
+ */
+static int __init next_masked_address (unsigned long *addrp, unsigned long mask)
+{
+        unsigned long inc=1;
+        unsigned long newval = *addrp;
+	while (inc & mask)
+		inc += inc;
+        while (inc != 0) {
+		newval += inc;
+		newval &= ~mask;
+		newval |= ((*addrp) & mask);
+		if (newval > *addrp) {
+			*addrp = newval;
+			return 1;
+		}
+		do {
+			inc += inc;
+		} while (inc & ~mask);
+		while (inc & mask)
+			inc += inc;
+        }
+        return 0;
+}
+
+
+void __init badram_markpages (int argc, unsigned long *argv) {
+	unsigned long addr, mask;
+        while (argc-- > 0) {
+                addr = *argv++;
+                mask pro;
 
@@ -467,13 +479,17 @@
 	totalram_pages += __free_all_bootmem();
 
 	reservedpages = 0;
+	badpages = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
 		/*
-		 * Only count reserved RAM pages
+		 * Only count reserved and bad RAM pages
 		 */
 		
+	Note that this scheme has delibpfn)		((pfn) < max_mapnr)
 #endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define phys_to_page(x)		(mem_map + ((unsigned long)(x) >> PAGE_SHIFT))
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -urN linux-2.5.73-mm2/mm/bootmem.c linux-2.5/mm/bootmem.c
--- linux-2.5.73-mm2/mm/bootmem.c	2003-06-17 05:19:47.000000000 +0100
+++ linux-2.5/mm/bootmem.c	2003-07-01 20:42:25.000000000 +0100
@@ -274,8 +274,17 @@
 				if (v & m) {
 					count++;
 					ClearPageReserved(page);
+
+#ifdef CONFIG_BADRAM
+					if (!PageBad(page)) {
+						set_page_count(page, 1);
+						__free_page(page);
+					}
+#else
+
 					set_page_count(page, 1);
 					__free_page(page);
+#endif
 				}
 			}
 		} else {
@@ -294,8 +303,16 @@
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
 		ClearPageReserved(page);
-		set_page_count(page, 1);
+
+#ifdef CONFIG_BADRAM
+		if (!PageBad(page)) {
+			set_page_count(page, 1);
+			__free_page(page);
+		}
+#else
+ 		set_page_count(page, 1);
 		__free_page(page);
+#endif
 	}
 	total += count;
 	bdata->node_bootmem_map = NULL;
diff -urN linux-2.5.73-mm2/mm/page_alloc.c linux-2.5/mm/page_alloc.c
--- linux-2.5.73-mm2/mm/page_alloc.c	2003-07-01 19:59:57.000000000 +0100
+++ linux-2.5/mm/page_alloc.c	2003-07-02 01:12:09.000000000 + a preference for BadRAM pages, anpfn)		((pfn) < max_mapnr)
 #endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define phys_to_page(x)		(mem_map + ((unsigned long)(x) >> PAGE_SHIFT))
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -urN linux-2.5.73-mm2/mm/bootmem.c linux-2.5/mm/bootmem.c
--- linux-2.5.73-mm2/mm/bootmem.c	2003-06-17 05:19:47.000000000 +0100
+++ linux-2.5/mm/bootmem.c	2003-07-01 20:42:25.000000000 +0100
@@ -274,8 +274,17 @@
 				if (v & m) {
 					count++;
 					ClearPageReserved(page);
+
+#ifdef CONFIG_BADRAM
+					if (!PageBad(page)) {
+						set_page_count(page, 1);
+						__free_page(page);
+					}
+#else
+
 					set_page_count(page, 1);
 					__free_page(page);
+#endif
 				}
 			}
 		} else {
@@ -294,8 +303,16 @@
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
 		ClearPageReserved(page);
-		set_page_count(page, 1);
+
+#ifdef CONFIG_BADRAM
+		if (!PageBad(page)) {
+			set_page_count(page, 1);
+			__free_page(page);
+		}
+#else
+ 		set_page_count(page, 1);
 		__free_page(page);
+#endif
 	}
 	total += count;
 	bdata->node_bootmem_map = NULL;
diff -urN linux-2.5.73-mm2/mm/page_alloc.c linux-2.5/mm/page_alloc.c
--- linux-2.5.73-mm2/mm/page_alloc.c	2003-07-01 19:59:57.000000000 +0100
+++ linux-2.5/mm/page_alloc.c	2003-07-02 01:12:09.000000000 +ject is an idea and implementationpfn)		((pfn) < max_mapnr)
 #endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define phys_to_page(x)		(mem_map + ((unsigned long)(x) >> PAGE_SHIFT))
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -urN linux-2.5.73-mm2/mm/bootmem.c linux-2.5/mm/bootmem.c
--- linux-2.5.73-mm2/mm/bootmem.c	2003-06-17 05:19:47.000000000 +0100
+++ linux-2.5/mm/bootmem.c	2003-07-01 20:42:25.000000000 +0100
@@ -274,8 +274,17 @@
 				if (v & m) {
 					count++;
 					ClearPageReserved(page);
+
+#ifdef CONFIG_BADRAM
+					if (!PageBad(page)) {
+						set_page_count(page, 1);
+						__free_page(page);
+					}
+#else
+
 					set_page_count(page, 1);
 					__free_page(page);
+#endif
 				}
 			}
 		} else {
@@ -294,8 +303,16 @@
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
 		ClearPageReserved(page);
-		set_page_count(page, 1);
+
+#ifdef CONFIG_BADRAM
+		if (!PageBad(page)) {
+			set_page_count(page, 1);
+			__free_page(page);
+		}
+#else
+ 		set_page_count(page, 1);
 		__free_page(page);
+#endif
 	}
 	total += count;
 	bdata->node_bootmem_map = NULL;
diff -urN linux-2.5.73-mm2/mm/page_alloc.c linux-2.5/mm/page_alloc.c
--- linux-2.5.73-mm2/mm/page_alloc.c	2003-07-01 19:59:57.000000000 +0100
+++ linux-2.5/mm/page_alloc.c	2003-07-02 01:12:09.000000000 +exchanging your 
            mothealancing, Kanoj Sarcar, SGI, Jan 2000
  *  Per cpu hot/cold page lists, bulk allocation, Martin J. Bligh, Sept 2002
  *          (lots of bits borrowed from Ingo Molnar & Andrew Morton)
+ *  BadRAM handling, Rick van Rein, Feb 2001
  */
 
 #include <linux/config.h>
@@ -1615,3 +1616,96 @@
 	setup_per_zone_pages_min();
 	return 0;
 }
+
+
+#ifdef CONFIG_BADRAM
+
+/* Given a pointed-at address and a mask, increment the page so that the
+ * mask hides the increment. Return 0 if no increment is possible.
+ */
+static int __init next_masked_address (unsigned long *addrp, unsigned long mask)
+{
+        unsigned long inc=1;
+        unsigned long newval = *addrp;
+	while (inc & mask)
+		inc += inc;
+        while (inc != 0) {
+		newval += inc;
+		newval &= ~mask;
+		newval |= ((*addrp) & mask);
+		if (newval > *addrp) {
+			*addrp = newval;
+			return 1;
+		}
+		do {
+			inc += inc;
+		} while (inc & ~mask);
+		while (inc & mask)
+			inc += inc;
+        }
+        return 0;
+}
+
+
+void __init badram_markpages (int argc, unsigned long *argv) {
+	unsigned long addr, mask;
+        while (argc-- > 0) {
+                addr = *argv++;
+                mask pro;
 
@@ -467,13 +479,17 @@
 	totalram_pages += __free_all_bootmem();
 
 	reservedpages = 0;
+	badpages = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
 		/*
-		 * Only count reserved RAM pages
+		 * Only count reserved and bad RAM pages
 		 */
 		0
@@ -223,12 +223,22 @@
 	pkmap_paalancing, Kanoj Sarcar, SGI, Jan 2000
  *  Per cpu hot/cold page lists, bulk allocation, Martin J. Bligh, Sept 2002
  *          (lots of bits borrowed from Ingo Molnar & Andrew Morton)
+ *  BadRAM handling, Rick van Rein, Feb 2001
  */
 
 #include <linux/config.h>
@@ -1615,3 +1616,96 @@
 	setup_per_zone_pages_min();
 	return 0;
 }
+
+
+#ifdef CONFIG_BADRAM
+
+/* Given a pointed-at address and a mask, increment the page so that the
+ * mask hides the increment. Return 0 if no increment is possible.
+ */
+static int __init next_masked_address (unsigned long *addrp, unsigned long mask)
+{
+        unsigned long inc=1;
+        unsigned long newval = *addrp;
+	while (inc & mask)
+		inc += inc;
+        while (inc != 0) {
+		newval += inc;
+		newval &= ~mask;
+		newval |= ((*addrp) & mask);
+		if (newval > *addrp) {
+			*addrp = newval;
+			return 1;
+		}
+		do {
+			inc += inc;
+		} while (inc & ~mask);
+		while (inc & mask)
+			inc += inc;
+        }
+        return 0;
+}
+
+
+void __init badram_markpages (int argc, unsigned long *argv) {
+	unsigned long addr, mask;
+        while (argc-- > 0) {
+                addr = *argv++;
+                mask pro;
 
@@ -467,13 +479,17 @@
 	totalram_pages += __free_all_bootmem();
 
 	reservedpages = 0;
+	badpages = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
 		/*
-		 * Only count reserved RAM pages
+		 * Only count reserved and bad RAM pages
 		 */
 		if (page_is_ram(tmp) && PageReservpfn)		((pfn) < max_mapnr)
 #endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define phys_to_page(x)		(mem_map + ((unsigned long)(x) >> PAGE_SHIFT))
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -urN linux-2.5.73-mm2/mm/bootmem.c linux-2.5/mm/bootmem.c
--- linux-2.5.73-mm2/mm/bootmem.c	2003-06-17 05:19:47.000000000 +0100
+++ linux-2.5/mm/bootmem.c	2003-07-01 20:42:25.000000000 +0100
@@ -274,8 +274,17 @@
 				if (v & m) {
 					count++;
 					ClearPageReserved(page);
+
+#ifdef CONFIG_BADRAM
+					if (!PageBad(page)) {
+						set_page_count(page, 1);
+						__free_page(page);
+					}
+#else
+
 					set_page_count(page, 1);
 					__free_page(page);
+#endif
 				}
 			}
 		} else {
@@ -294,8 +303,16 @@
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
 		ClearPageReserved(page);
-		set_page_count(page, 1);
+
+#ifdef CONFIG_BADRAM
+		if (!PageBad(page)) {
+			set_page_count(page, 1);
+			__free_page(page);
+		}
+#else
+ 		set_page_count(page, 1);
 		__free_page(page);
+#endif
 	}
 	total += count;
 	bdata->node_bootmem_map = NULL;
diff -urN linux-2.5.73-mm2/mm/page_alloc.c linux-2.5/mm/page_alloc.c
--- linux-2.5.73-mm2/mm/page_alloc.c	2003-07-01 19:59:57.000000000 +0100
+++ linux-2.5/mm/page_alloc.c	2003-07-02 01:12:09.000000000 +54,6 +154,7 @@
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
 #endif /* !CONFIG_DISCONTIGMEM */
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define phys_to_page(x)		(mem_map + ((unsigned long)(x) >> PAGE_SHIFT))
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff -urN linux-2.5.73-mm2/mm/bootmem.c linux-2.5/mm/bootmem.c
--- linux-2.5.73-mm2/mm/bootmem.c	2003-06-17 05:19:47.000000000 +0100
+++ linux-2.5/mm/bootmem.c	2003-07-01 20:42:25.000000000 +0100
@@ -274,8 +274,17 @@
 				if (v & m) {
 					count++;
 					ClearPageReserved(page);
+
+#ifdef CONFIG_BADRAM
+					if (!PageBad(page)) {
+						set_page_count(page, 1);
+						__free_page(page);
+					}
+#else
+
 					set_page_count(page, 1);
 					__free_page(page);
+#endif
 				}
 			}
 		} else {
@@ -294,8 +303,16 @@
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
 		ClearPageReserved(page);
-		set_page_count(page, 1);
+
+#ifdef CONFIG_BADRAM
+		if (!PageBad(page)) {
+			set_page_count(page, 1);
+			__free_page(page);
+		}
+#else
+ 		set_page_count(page, 1);
 		__free_page(page);
+#endif
 	}
 	total += count;
 	bdata->node_bootmem_map = NULL;
diff -urN linux-2.5.73-mm2/mm/page_alloc.c linux-2.5/mm/page_alloc.c
--- linux-2.5.73-mm2/mm/page_alloc.c	2003-07-01 19:59:57.000000000 +0100
+++ linux-2.5/mm/page_alloc.c	2003-07-02 01:12:09.000000000 +0100
@@ -12,6 +12,7 @@
  *  Zone balancing, Kanoj Sarcar, SGI, Jan 2000
  *  Per cpu hot/cold page lists, bulk allocation, Martin J. Bligh, Sept 2002
  *          (lots of bits borrowed from Ingo Molnar & Andrew Morton)
+ *  BadRAM handling, Rick van Rein, Feb 2001
  */
 
 #include <linux/config.h>
@@ -1615,3 +1616,96 @@
 	setup_per_zone_pages_min();
 	return 0;
 }
+
+
+#ifdef CONFIG_BADRAM
+
+/* Given a pointed-at address and a mask, increment the page so that the
+ * mask hides the increment. Return 0 if no increment is possible.
+ */
+static int __init next_masked_address (unsigned long *addrp, unsigned long mask)
+{
+        unsigned long inc=1;
+        unsigned long newval = *addrp;
+	while (inc & mask)
+		inc += inc;
+        while (inc != 0) {
+		newval += inc;
+		newval &= ~mask;
+		newval |= ((*addrp) & mask);
+		if (newval > *addrp) {
+			*addrp = newval;
+			return 1;
+		}
+		do {
+			inc += inc;
+		} while (inc & ~mask);
+		while (inc & mask)
+			inc += inc;
+        }
+        return 0;
+}
+
+
+void __init badram_markpages (int argc, unsigned long *argv) {
+	unsigned long addr, mask;
+        while (argc-- > 0) {
+                addr = *argv++;
+                mask = (argc-- > 0) ? *argv++ : ~0L;
+                mask |= ~PAGE_MASK;	// Optimalisation
+		addr &= mask;		//  Normalisation
+                do {
+			struct page *pg = phys_to_page(addr);
+printk ("%05lx ", __pa(__va(addr)) >> PAGE_SHIFT);
+printk ("=%05lx/%05lx ", pg-mem_map, max_mapnr);
+			// if (VALID_PAGE(pg)) {
+				if (PageTestandSetBad (pg)) {
+					reserve_bootmem (addr, PAGE_SIZE);
+printk ("BAD ");
+				}
+else printk ("BFR ");
+			// }
+// else printk ("INV ");
+                } while (next_masked_address (&addr,mask));
+        }
+}
+
+
+
+/*********** CONFIG_BADRAM: CUSTOMISABLE SECTION STARTS HERE ******************/
+
+
+// Enter your custom BadRAM patterns here as pairs of unsigned long integers.
+// For more information on these F/M pairs, refer to Documentation/badram.txt
+
+
+static unsigned long __devinitdata badram_custom[] = {
+	0,	// Number of longwords that follow, as F/M pairs
+};
+
+
+/*********** CONFIG_BADRAM: CUSTOMISABLE SECTION ENDS HERE ********************/
+
+
+
+static int __init badram_setup (char *str)
+{
+	unsigned long opts[3];
+	if (!mem_map) BUG();
+printk ("PAGE_OFFSET=0x%08lx\n", PAGE_OFFSET);
+printk ("BadRAM option is %s\n", str);
+	if (*str++ == '=')
+		while (str=get_options (str, 3, (int *) opts), *opts) {
+printk ("   --> marking 0x%08lx, 0x%08lx  [%ld]\n", opts[1], opts[2], opts[0]);
+			badram_markpages (*opts, opts+1);
+			if (*opts==1)
+				break;
+		};
+	badram_markpages (*badram_custom, badram_custom+1);
+	return 0;
+}
+
+__setup("badram", badram_setup);
+
+#endif /* CONFIG_BADRAM */
+

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-07-02 12:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-02 12:58 Re: [PATCH] BadRAM for 2.5.73-mm2 steven.newbury1

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).