Patches contributed by Eötvös Lorand University


commit 9a22b6e76ba75fa0f3963cdec7829156d00a7173
Author: Ingo Molnar <mingo@elte.hu>
Date:   Thu Sep 18 12:50:18 2008 +0200

    dmi scan: warn about too early calls to dmi_check_system()
    
    It happened to me recently that i added a dmi_check_system() quirk
    in a too early codepath, and it was silently ignored because all the
    DMI tables and strings were still empty.
    
    As this situation is clearly a programming error / kernel bug,
    warn when it happens, instead of silently ignoring quirks.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 455575be3560..3e526b6d00cb 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -15,6 +15,11 @@
  */
 static char dmi_empty_string[] = "        ";
 
+/*
+ * Catch too early calls to dmi_check_system():
+ */
+static int dmi_initialized;
+
 static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 {
 	const u8 *bp = ((u8 *) dm) + dm->length;
@@ -366,7 +371,7 @@ void __init dmi_scan_machine(void)
 
 	if (efi_enabled) {
 		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
-			goto out;
+			goto error;
 
 		/* This is called as a core_initcall() because it isn't
 		 * needed during early boot.  This also means we can
@@ -374,13 +379,13 @@ void __init dmi_scan_machine(void)
 		 */
 		p = dmi_ioremap(efi.smbios, 32);
 		if (p == NULL)
-			goto out;
+			goto error;
 
 		rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
 		dmi_iounmap(p, 32);
 		if (!rc) {
 			dmi_available = 1;
-			return;
+			goto out;
 		}
 	}
 	else {
@@ -391,19 +396,22 @@ void __init dmi_scan_machine(void)
 		 */
 		p = dmi_ioremap(0xF0000, 0x10000);
 		if (p == NULL)
-			goto out;
+			goto error;
 
 		for (q = p; q < p + 0x10000; q += 16) {
 			rc = dmi_present(q);
 			if (!rc) {
 				dmi_available = 1;
 				dmi_iounmap(p, 0x10000);
-				return;
+				goto out;
 			}
 		}
 		dmi_iounmap(p, 0x10000);
 	}
- out:	printk(KERN_INFO "DMI not present or invalid.\n");
+ error:
+	printk(KERN_INFO "DMI not present or invalid.\n");
+ out:
+	dmi_initialized = 1;
 }
 
 /**
@@ -424,6 +432,8 @@ int dmi_check_system(const struct dmi_system_id *list)
 	int i, count = 0;
 	const struct dmi_system_id *d = list;
 
+	WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+
 	while (d->ident) {
 		for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
 			int s = d->matches[i].slot;

commit fc38151947477596aa27df6c4306ad6008dc6711
Author: Ingo Molnar <mingo@elte.hu>
Date:   Tue Sep 16 10:07:34 2008 +0200

    x86: add X86_RESERVE_LOW_64K
    
    This bugzilla:
    
      http://bugzilla.kernel.org/show_bug.cgi?id=11237
    
    Documents a wide range of systems where the BIOS utilizes the first
    64K of physical memory during suspend/resume and other hardware events.
    
    Currently we reserve this memory on all AMI and Phoenix BIOS systems.
    Life is too short to hunt subtle memory corruption problems like this,
    so we try to be robust by default.
    
    Still, allow this to be overriden: allow users who want that first 64K
    of memory to be available to the kernel disable the quirk, via
    CONFIG_X86_RESERVE_LOW_64K=n.
    
    Also, allow the early reservation to overlap with other
    early reservations.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 7820d447bb8d..633f25dd9ee2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1089,6 +1089,26 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK
 	 Set whether the default state of memory_corruption_check is
 	 on or off.
 
+config X86_RESERVE_LOW_64K
+        bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
+	default y
+	help
+	 Reserve the first 64K of physical RAM on BIOSes that are known
+	 to potentially corrupt that memory range. A numbers of BIOSes are
+	 known to utilize this area during suspend/resume, so it must not
+	 be used by the kernel.
+
+	 Set this to N if you are absolutely sure that you trust the BIOS
+	 to get all its memory reservations and usages right.
+
+	 If you have doubts about the BIOS (e.g. suspend/resume does not
+	 work or there's kernel crashes after certain hardware hotplug
+	 events) and it's not AMI or Phoenix, then you might want to enable
+	 X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical
+	 corruption patterns.
+
+	 Say Y if unsure.
+
 config MATH_EMULATION
 	bool
 	prompt "Math emulation" if X86_32
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 33719544a224..786c1886ae53 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -735,13 +735,14 @@ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
 		"%s detected: BIOS may corrupt low RAM, working it around.\n",
 		d->ident);
 
-	reserve_early(0x0, 0x10000, "BIOS quirk");
+	reserve_early_overlap_ok(0x0, 0x10000, "BIOS quirk");
 
 	return 0;
 }
 
 /* List of systems that have known low memory corruption BIOS problems */
 static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
+#ifdef CONFIG_X86_RESERVE_LOW_64K
 	{
 		.callback = dmi_low_memory_corruption,
 		.ident = "AMI BIOS",
@@ -757,6 +758,7 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
 		},
 	},
 	{}
+#endif
 };
 
 /*

commit 1e22436eba84edfec9c25e5a25d09062c4f91ca9
Author: Ingo Molnar <mingo@elte.hu>
Date:   Tue Sep 16 09:58:02 2008 +0200

    x86: reserve low 64K on AMI and Phoenix BIOS boxen
    
    there's multiple reports about suspend/resume related low memory
    corruption in this bugzilla:
    
      http://bugzilla.kernel.org/show_bug.cgi?id=11237
    
    the common pattern is that the corruption is caused by the BIOS,
    and that it affects some portion of the first 64K of physical RAM.
    
    So add a DMI quirk
    
    This will waste 64K RAM on 'good' systems too, but without knowing
    the exact nature of this BIOS memory corruption this is the safest
    approach.
    
    This might as well solve a wide range of suspend/resume breakages
    under Linux.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 3109ca37a67c..33719544a224 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -732,10 +732,10 @@ void start_periodic_check_for_corruption(void)
 static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
 {
 	printk(KERN_NOTICE
-		"%s detected: BIOS corrupts 0xc000, working it around.\n",
+		"%s detected: BIOS may corrupt low RAM, working it around.\n",
 		d->ident);
 
-	reserve_early(0xc000, 0xc400, "BIOS quirk");
+	reserve_early(0x0, 0x10000, "BIOS quirk");
 
 	return 0;
 }
@@ -749,6 +749,13 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
 			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
 		},
 	},
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "Phoenix BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+		},
+	},
 	{}
 };
 

commit 5649b7c30316a51792808422ac03ee825d26aa5e
Author: Ingo Molnar <mingo@elte.hu>
Date:   Tue Sep 16 09:29:09 2008 +0200

    x86: add DMI quirk for AMI BIOS which corrupts address 0xc000 during resume
    
    Alan Jenkins and Andy Wettstein reported a suspend/resume memory
    corruption bug and extensively documented it here:
    
       http://bugzilla.kernel.org/show_bug.cgi?id=11237
    
    The bug is that the BIOS overwrites 1K of memory at 0xc000 physical,
    without registering it in e820 as reserved or giving the kernel any
    idea about this.
    
    Detect AMI BIOSen and reserve that 1K.
    
    We paint this bug around with a very broad brush (reserving that 1K on all
    AMI BIOS systems), as the bug was extremely hard to find and needed several
    weeks and lots of debugging and patching.
    
    The bug was found via the CONFIG_X86_CHECK_BIOS_CORRUPTION=y debug feature,
    if similar bugs are suspected then this feature can be enabled on other
    systems as well to scan low memory for corrupted memory.
    
    Reported-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
    Reported-by: Andy Wettstein <ajw1980@gmail.com>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index ec7e56c1b984..3109ca37a67c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -729,6 +729,29 @@ void start_periodic_check_for_corruption(void)
 }
 #endif
 
+static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE
+		"%s detected: BIOS corrupts 0xc000, working it around.\n",
+		d->ident);
+
+	reserve_early(0xc000, 0xc400, "BIOS quirk");
+
+	return 0;
+}
+
+/* List of systems that have known low memory corruption BIOS problems */
+static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
+	{
+		.callback = dmi_low_memory_corruption,
+		.ident = "AMI BIOS",
+		.matches = {
+			DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
+		},
+	},
+	{}
+};
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -752,6 +775,8 @@ void __init setup_arch(char **cmdline_p)
 	printk(KERN_INFO "Command line: %s\n", boot_command_line);
 #endif
 
+	dmi_check_system(bad_bios_dmi_table);
+
 	early_cpu_init();
 	early_ioremap_init();
 
@@ -1037,3 +1062,5 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 }
+
+

commit e3bbaa3cb6ac5a245e5ecc28b09f9b7b93b2dd8a
Merge: 9c3254ad42e7 adee14b2e155
Author: Ingo Molnar <mingo@elte.hu>
Date:   Tue Sep 16 09:34:23 2008 +0200

    Merge commit 'v2.6.27-rc6' into x86/memory-corruption-check

commit 83bd6998b04fc1bb7280b14f16b2bdbdc07c914b
Merge: e7250b8ae387 adee14b2e155
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sun Sep 14 18:24:00 2008 +0200

    Merge commit 'v2.6.27-rc6' into timers/hpet

commit f81b691a3df09806385ea413c3a2ee094c705ca3
Merge: 110e0358e7df adee14b2e155
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sun Sep 14 17:26:53 2008 +0200

    Merge commit 'v2.6.27-rc6' into x86/pat

commit 9dfed08eb4086584205717894177a9ee930c88c4
Merge: 1cf44baad76b adee14b2e155
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sun Sep 14 17:23:29 2008 +0200

    Merge commit 'v2.6.27-rc6' into core/resources

commit 5ce73a4a5a4893a1aa4cdeed1b1a5a6de42c43b6
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sun Sep 14 17:11:46 2008 +0200

    timers: fix itimer/many thread hang, cleanups
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/include/linux/sched.h b/include/linux/sched.h
index ed355f02d329..7ce8d4e53565 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -430,7 +430,7 @@ struct pacct_struct {
  * @utime:		time spent in user mode, in &cputime_t units
  * @stime:		time spent in kernel mode, in &cputime_t units
  * @sum_exec_runtime:	total time spent on the CPU, in nanoseconds
- * 
+ *
  * This structure groups together three kinds of CPU time that are
  * tracked for threads and thread groups.  Most things considering
  * CPU time want to group these counts together and treat all three
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index dba1c334c3e8..9a7ea049fcdc 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -94,7 +94,7 @@ void update_rlimit_cpu(unsigned long rlim_new)
 
 	cputime = secs_to_cputime(rlim_new);
 	if (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
-            cputime_lt(current->signal->it_prof_expires, cputime)) {
+	    cputime_lt(current->signal->it_prof_expires, cputime)) {
 		spin_lock_irq(&current->sighand->siglock);
 		set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);
 		spin_unlock_irq(&current->sighand->siglock);
@@ -1372,9 +1372,9 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 	 * tsk->signal is non-NULL; this probably can't happen but cover the
 	 * possibility anyway.
 	 */
-	if (unlikely(!sig) || !fastpath_timer_check(tsk, sig)) {
+	if (unlikely(!sig) || !fastpath_timer_check(tsk, sig))
 		return;
-	}
+
 	sighand = lock_task_sighand(tsk, &flags);
 	if (likely(sighand)) {
 		/*

commit 0a8eaa4f9b58759595a1bfe13a1295fdc25ba026
Author: Ingo Molnar <mingo@elte.hu>
Date:   Sun Sep 14 17:03:52 2008 +0200

    timers: fix itimer/many thread hang, fix #2
    
    fix the UP build:
    
    In file included from arch/x86/kernel/asm-offsets_32.c:9,
                     from arch/x86/kernel/asm-offsets.c:3:
    include/linux/sched.h: In function ‘thread_group_cputime_clone_thread’:
    include/linux/sched.h:2272: warning: no return statement in function returning non-void
    include/linux/sched.h: In function ‘thread_group_cputime_account_user’:
    include/linux/sched.h:2284: error: invalid type argument of ‘->’ (have ‘struct task_cputime’)
    include/linux/sched.h:2284: error: invalid type argument of ‘->’ (have ‘struct task_cputime’)
    include/linux/sched.h: In function ‘thread_group_cputime_account_system’:
    include/linux/sched.h:2291: error: invalid type argument of ‘->’ (have ‘struct task_cputime’)
    include/linux/sched.h:2291: error: invalid type argument of ‘->’ (have ‘struct task_cputime’)
    include/linux/sched.h: In function ‘thread_group_cputime_account_exec_runtime’:
    include/linux/sched.h:2298: error: invalid type argument of ‘->’ (have ‘struct task_cputime’)
    distcc[14501] ERROR: compile arch/x86/kernel/asm-offsets.c on a/30 failed
    make[1]: *** [arch/x86/kernel/asm-offsets.s] Error 1
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 26d7a5f2d0ba..ed355f02d329 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2251,6 +2251,7 @@ static inline void thread_group_cputime_free(struct signal_struct *sig)
 static inline int thread_group_cputime_clone_thread(struct task_struct *curr,
 						     struct task_struct *tsk)
 {
+	return 0;
 }
 
 static inline void thread_group_cputime(struct task_struct *tsk,
@@ -2263,21 +2264,21 @@ static inline void thread_group_cputime_account_user(
 	struct thread_group_cputime *tgtimes,
 	cputime_t cputime)
 {
-	tgtimes->totals->utime = cputime_add(tgtimes->totals->utime, cputime);
+	tgtimes->totals.utime = cputime_add(tgtimes->totals.utime, cputime);
 }
 
 static inline void thread_group_cputime_account_system(
 	struct thread_group_cputime *tgtimes,
 	cputime_t cputime)
 {
-	tgtimes->totals->stime = cputime_add(tgtimes->totals->stime, cputime);
+	tgtimes->totals.stime = cputime_add(tgtimes->totals.stime, cputime);
 }
 
 static inline void thread_group_cputime_account_exec_runtime(
 	struct thread_group_cputime *tgtimes,
 	unsigned long long ns)
 {
-	tgtimes->totals->sum_exec_runtime += ns;
+	tgtimes->totals.sum_exec_runtime += ns;
 }
 
 #endif /* CONFIG_SMP */