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(¤t->sighand->siglock);
set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL);
spin_unlock_irq(¤t->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 */