* [PATCH] 2.6.2: Shutdown kernel on zone-alignment failure
@ 2004-02-07 20:30 Michael Frank
2004-02-07 20:36 ` Michael Frank
0 siblings, 1 reply; 2+ messages in thread
From: Michael Frank @ 2004-02-07 20:30 UTC (permalink / raw)
To: linux-kernel
Andrew,
The following is applicable to all architectures using zones.
When zone alignment goes wrong, a message is printed:
BUG: wrong zone alignment, it will crash
_BUT_ kernel runs until it dies of the alignment problems - it took me
hours until I found the message after looking elsewhere ;)
This patch:
- Should zone alignment fail, it will force a BUG() once the BUG handler inits
- Improves the messages of zone init to help debug zone alignment problems
Regards
Michael
Example invalid zone alignment after disabling auto-alignment:
300MB HIGHMEM available.
195MB LOWMEM available.
On node 0 totalpages: 126960, zones aligned at: 0x400000
DMA zone: 4096 pages, LIFO batch:1, physical start address at: 0x0
Normal zone: 46064 pages, LIFO batch:11, physical start address at: 0x1000000
HighMem zone: 76800 pages, LIFO batch:16, physical start address at: 0xc3f0000
HighMem zone: FATAL ERROR invalid zone alignment at: 0x3f0000 - will force kernel BUG
DMI 2.3 present.
Building zonelist for node : 0
Kernel command line: vga=0xf07 root=/dev/hda4 console=tty0 console=ttyS0,115200n8r devfs=nomount nousb acpi=off init=/bin/bash highmem=300m
Initializing CPU#0
PID hash table entries: 2048 (order 11: 16384 bytes)
Detected 2399.836 MHz processor.
Using tsc for high-res timesource
Console: colour VGA+ 80x60
Memory: 498216k/507840k available (1930k kernel code, 8600k reserved, 990k data, 160k init, 307200k highmem)
Checking if this processor honours the WP bit even in supervisor mode... Ok.
Calibrating delay loop... 4734.97 BogoMIPS
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
------------[ cut here ]------------
kernel BUG at init/main.c:464!
invalid operand: 0000 [#1]
CPU: 0
EIP: 0060:[<c03de5e7>] Not tainted
EFLAGS: 00010202
EIP is at start_kernel+0x14f/0x190
eax: cc3e7a60 ebx: 00010809 ecx: c044af48 edx: cc3e7ad0
esi: 00099800 edi: c0105000 ebp: 0008e000 esp: c03ddff8
ds: 007b es: 007b ss: 0068
Process swapper (pid: 0, threadinfo=c03dc000 task=c035e7e0)
Stack: c0406ea0 c010017e
Call Trace:
Code: 0f 0b d0 01 7b 3f 2e c0 e8 80 95 00 00 e8 6f 23 00 00 e8 c2
<0>Kernel panic: Attempted to kill the idle task!
In idle task - not syncing
diff -uN -r -X /home/mhf/sys/dont/dontdiff linux-2.6.2-Vanilla/arch/i386/kernel/setup.c linux-2.6.2-mhf177/arch/i386/kernel/setup.c
--- linux-2.6.2-Vanilla/arch/i386/kernel/setup.c 2004-02-06 19:36:54.000000000 +0800
+++ linux-2.6.2-mhf177/arch/i386/kernel/setup.c 2004-02-08 04:07:39.000000000 +0800
@@ -581,9 +581,12 @@
#endif /* CONFIG_ACPI_BOOT */
/*
- * highmem=size forces highmem to be exactly 'size' bytes.
+ * highmem=size forces highmem to be at most 'size' bytes.
* This works even on boxes that have no highmem otherwise.
* This also works to reduce highmem size on bigger boxes.
+ *
+ * Note: highmem sise is adjusted downward for proper zone
+ * alignment of the highmem physical start address.
*/
if (c == ' ' && !memcmp(from, "highmem=", 8))
highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
@@ -650,6 +653,11 @@
/*
* Determine low and high memory ranges:
*/
+
+#define ZONE_REQUIRED_PAGE_ALIGNMENT (1UL << (MAX_ORDER-1))
+#define ZONE_REQUIRED_PAGE_ALIGNMENT_MASK (ZONE_REQUIRED_PAGE_ALIGNMENT-1)
+#define PAGES_FOR_64MB (64*1024*1024/PAGE_SIZE)
+
unsigned long __init find_max_low_pfn(void)
{
unsigned long max_low_pfn;
@@ -661,14 +669,16 @@
if (highmem_pages + MAXMEM_PFN < max_pfn)
max_pfn = MAXMEM_PFN + highmem_pages;
if (highmem_pages + MAXMEM_PFN > max_pfn) {
- printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
- highmem_pages = 0;
+ printk("Warning reducing highmem=%uMB to: %luMB.\n",
+ pages_to_mb(highmem_pages),
+ pages_to_mb((max_pfn - MAXMEM_PFN)));
+ highmem_pages = max_pfn - MAXMEM_PFN;
}
max_low_pfn = MAXMEM_PFN;
#ifndef CONFIG_HIGHMEM
/* Maximum memory usable is what is directly addressable */
- printk(KERN_WARNING "Warning only %ldMB will be used.\n",
- MAXMEM>>20);
+ printk(KERN_WARNING "Warning only %dMB will be used.\n",
+ MAXMEM>>20);
if (max_pfn > MAX_NONPAE_PFN)
printk(KERN_WARNING "Use a PAE enabled kernel.\n");
else
@@ -683,26 +693,61 @@
}
#endif /* !CONFIG_X86_PAE */
#endif /* !CONFIG_HIGHMEM */
- } else {
- if (highmem_pages == -1)
- highmem_pages = 0;
+ } else if (highmem_pages == -1)
+ highmem_pages = 0;
#ifdef CONFIG_HIGHMEM
- if (highmem_pages >= max_pfn) {
- printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
- highmem_pages = 0;
- }
- if (highmem_pages) {
- if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
- printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
- highmem_pages = 0;
- }
- max_low_pfn -= highmem_pages;
- }
+ if (!highmem_pages)
+ goto out;
+ if (max_pfn < PAGES_FOR_64MB + ZONE_REQUIRED_PAGE_ALIGNMENT * 2) {
+ printk(KERN_ERR
+ "Error highmem support requires at least %luMB but only %luMB are available.\n",
+ pages_to_mb(PAGES_FOR_64MB + ZONE_REQUIRED_PAGE_ALIGNMENT * 2),
+ pages_to_mb(max_pfn));
+ highmem_pages = 0;
+ goto out;
+ }
+ if (highmem_pages > max_pfn) {
+ printk(KERN_WARNING
+ "Warning highmem=%uMB is bigger than available %luMB and will be adjusted.\n",
+ pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
+ }
+ if (highmem_pages <= ZONE_REQUIRED_PAGE_ALIGNMENT) {
+ printk(KERN_WARNING
+ "Warning highmem=%uMB is too small and has been adjusted to: %luMB.\n",
+ pages_to_mb(highmem_pages),
+ pages_to_mb(ZONE_REQUIRED_PAGE_ALIGNMENT * 2));
+ highmem_pages = ZONE_REQUIRED_PAGE_ALIGNMENT * 2;
+ }
+ if (max_low_pfn < highmem_pages || max_low_pfn-highmem_pages < PAGES_FOR_64MB){
+ highmem_pages = max_low_pfn - PAGES_FOR_64MB;
+ printk(KERN_WARNING
+ "Warning highmem size adjusted for a minimum of 64MB lowmem to: %uMB.\n",
+ pages_to_mb(highmem_pages));
+ }
+ max_low_pfn -= highmem_pages;
+ goto out;
+ /* remove this when done testing bad zone alignment kernel shutdown: end */
+
+ if (max_low_pfn & ZONE_REQUIRED_PAGE_ALIGNMENT_MASK) {
+ printk(KERN_WARNING
+ "Warning bad highmem zone alignment 0x%lx, highmem size will be adjusted.\n",
+ (max_low_pfn & ZONE_REQUIRED_PAGE_ALIGNMENT_MASK) << PAGE_SHIFT);
+ highmem_pages -= ZONE_REQUIRED_PAGE_ALIGNMENT -
+ (max_low_pfn & ZONE_REQUIRED_PAGE_ALIGNMENT_MASK);
+ max_low_pfn &= ~ZONE_REQUIRED_PAGE_ALIGNMENT_MASK;
+ max_low_pfn += ZONE_REQUIRED_PAGE_ALIGNMENT;
+ printk(KERN_WARNING
+ "Warning lowmem size adjusted for zone alignment to: %luMB.\n",
+ pages_to_mb(max_low_pfn));
+ printk(KERN_WARNING
+ "Warning highmem size adjusted for zone alignment to: %uMB.\n",
+ pages_to_mb(highmem_pages));
+ }
#else
- if (highmem_pages)
- printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
+ if (highmem_pages)
+ printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
#endif
- }
+out:
return max_low_pfn;
}
diff -uN -r -X /home/mhf/sys/dont/dontdiff linux-2.6.2-Vanilla/Documentation/kernel-parameters.txt linux-2.6.2-mhf177/Documentation/kernel-parameters.txt
--- linux-2.6.2-Vanilla/Documentation/kernel-parameters.txt 2004-02-06 19:36:53.000000000 +0800
+++ linux-2.6.2-mhf177/Documentation/kernel-parameters.txt 2004-02-08 03:17:40.000000000 +0800
@@ -387,6 +387,14 @@
hd?= [HW] (E)IDE subsystem
hd?lun= See Documentation/ide.txt.
+ highmem=size[KMG] [IA32,KNL,BOOT] forces highmem to be at most 'size' bytes.
+ This works even on boxes with at least 72MB RAM that have no
+ highmem otherwise. This also works to reduce highmem size on
+ bigger boxes.
+
+ Note: highmem is adjusted downward for proper zone alignment
+ of the highmem physical start address
+
hisax= [HW,ISDN]
See Documentation/isdn/README.HiSax.
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] 2.6.2: Shutdown kernel on zone-alignment failure
2004-02-07 20:30 [PATCH] 2.6.2: Shutdown kernel on zone-alignment failure Michael Frank
@ 2004-02-07 20:36 ` Michael Frank
0 siblings, 0 replies; 2+ messages in thread
From: Michael Frank @ 2004-02-07 20:36 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel
The last msg repeated the alignment patch. Here is it.
diff -uN -r -X /home/mhf/sys/dont/dontdiff linux-2.6.2-Vanilla/include/linux/kernel.h linux-2.6.2-mhf177/include/linux/kernel.h
--- linux-2.6.2-Vanilla/include/linux/kernel.h 2004-02-06 19:37:44.000000000 +0800
+++ linux-2.6.2-mhf177/include/linux/kernel.h 2004-02-08 02:12:17.000000000 +0800
@@ -104,6 +104,15 @@
extern void bust_spinlocks(int yes);
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
+
+/* If force_bug set, a BUG() will be forced when bug handler/console initialized.
+ * This is useful when something fatal happens very early during kernel init.
+ * To use:
+ * printk("FATAL ERROR: my error message - will force kernel BUG\n");
+ * force_bug = 1;
+ */
+extern int force_bug;
+
extern int panic_on_oops;
extern int system_running;
extern int tainted;
diff -uN -r -X /home/mhf/sys/dont/dontdiff linux-2.6.2-Vanilla/init/main.c linux-2.6.2-mhf177/init/main.c
--- linux-2.6.2-Vanilla/init/main.c 2004-02-06 19:37:45.000000000 +0800
+++ linux-2.6.2-mhf177/init/main.c 2004-02-08 02:19:15.000000000 +0800
@@ -96,6 +96,7 @@
* set up)
*/
int system_running;
+int force_bug;
/*
* Boot command-line arguments
@@ -454,6 +455,13 @@
vfs_caches_init(num_physpages);
radix_tree_init();
signals_init();
+ /*
+ * Something went badly wrong during the early initialisation process,
+ * so lets die before doing any damage or wasting people's time
+ * running a half dead kernel.
+ */
+ if (force_bug)
+ BUG();
/* rootfs populating might need page-writeback */
page_writeback_init();
populate_rootfs();
diff -uN -r -X /home/mhf/sys/dont/dontdiff linux-2.6.2-Vanilla/mm/page_alloc.c linux-2.6.2-mhf177/mm/page_alloc.c
--- linux-2.6.2-Vanilla/mm/page_alloc.c 2004-02-06 19:37:45.000000000 +0800
+++ linux-2.6.2-mhf177/mm/page_alloc.c 2004-02-08 04:14:06.000000000 +0800
@@ -1179,7 +1179,9 @@
for (i = 0; i < MAX_NR_ZONES; i++)
realtotalpages -= zholes_size[i];
pgdat->node_present_pages = realtotalpages;
- printk("On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages);
+ printk("On node %d totalpages: %lu, zones aligned at: 0x%lx\n",
+ pgdat->node_id, realtotalpages,
+ 1UL << (MAX_ORDER-1 + PAGE_SHIFT));
}
/*
@@ -1240,14 +1242,14 @@
unsigned long *zones_size, unsigned long *zholes_size)
{
unsigned long i, j;
- const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
int cpu, nid = pgdat->node_id;
struct page *lmem_map = pgdat->node_mem_map;
unsigned long zone_start_pfn = pgdat->node_start_pfn;
+ unsigned long zone_bad_alignment;
pgdat->nr_zones = 0;
init_waitqueue_head(&pgdat->kswapd_wait);
-
+
for (j = 0; j < MAX_NR_ZONES; j++) {
struct zone *zone = pgdat->node_zones + j;
unsigned long size, realsize;
@@ -1299,8 +1301,11 @@
pcp->batch = 1 * batch;
INIT_LIST_HEAD(&pcp->list);
}
- printk(" %s zone: %lu pages, LIFO batch:%lu\n",
- zone_names[j], realsize, batch);
+ if (realsize)
+ printk(" %s zone: %lu pages, LIFO batch:%lu, "
+ "physical start address at: 0x%lx\n",
+ zone_names[j], realsize, batch,
+ zone_start_pfn << PAGE_SHIFT);
INIT_LIST_HEAD(&zone->active_list);
INIT_LIST_HEAD(&zone->inactive_list);
atomic_set(&zone->refill_counter, 0);
@@ -1328,8 +1333,17 @@
zone->zone_mem_map = lmem_map;
zone->zone_start_pfn = zone_start_pfn;
- if ((zone_start_pfn) & (zone_required_alignment-1))
- printk("BUG: wrong zone alignment, it will crash\n");
+ /*
+ * Here the alignment of a zone is checked. Should alignment
+ * be wrong, all that can be done is to print an error message
+ * and defer the the BUG handler as it is not yet initialized.
+ */
+ if ((zone_bad_alignment = zone_start_pfn & ((1UL << (MAX_ORDER-1))-1))) {
+ printk(" %s zone: FATAL ERROR invalid zone alignment at: 0x%lx"
+ " - will force kernel BUG\n",
+ zone_names[j],zone_bad_alignment << PAGE_SHIFT);
+ force_bug = 1;
+ }
memmap_init(lmem_map, size, nid, j, zone_start_pfn);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-02-07 20:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-07 20:30 [PATCH] 2.6.2: Shutdown kernel on zone-alignment failure Michael Frank
2004-02-07 20:36 ` Michael Frank
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox