Re: [PATCH RFC] x86: check for and defend against BIOS memory corruption

From: Yinghai Lu
Date: Thu Aug 28 2008 - 21:50:09 EST


On Thu, Aug 28, 2008 at 12:52 PM, Jeremy Fitzhardinge <jeremy@xxxxxxxx> wrote:
> Some BIOSes have been observed to corrupt memory in the low 64k. This
> patch does two things:
> - Reserves all memory which does not have to be in that area, to
> prevent it from being used as general memory by the kernel. Things
> like the SMP trampoline are still in the memory, however.
> - Clears the reserved memory so we can observe changes to it.
> - Adds a function check_for_bios_corruption() which checks and reports on
> memory becoming unexpectedly non-zero. Currently it's called in the
> x86 fault handler, and the powermanagement debug output.
>
> RFC: What other places should we check for corruption in?
>
> [ Alan, Rafał: could you check you see:
> 1: corruption messages
> 2: no crashes
> Thanks -J
> ]
>
> Signed-off-by: Jeremy Fitzhardinge <jeremy@xxxxxxxx>
> Cc: Alan Jenkins <alan-jenkins@xxxxxxxxxxxxxx>
> Cc: Hugh Dickens <hugh@xxxxxxxxxxx>
> Cc: Ingo Molnar <mingo@xxxxxxx>
> Cc: Rafael J. Wysocki <rjw@xxxxxxx>
> Cc: Rafał Miłecki <zajec5@xxxxxxxxx>
> Cc: H. Peter Anvin <hpa@xxxxxxxxx>
> ---
> Documentation/kernel-parameters.txt | 5 ++
> arch/x86/Kconfig | 3 +
> arch/x86/kernel/setup.c | 86 +++++++++++++++++++++++++++++++++++
> arch/x86/mm/fault.c | 2
> drivers/base/power/main.c | 1
> include/linux/kernel.h | 12 ++++
> 6 files changed, 109 insertions(+)
>
> ===================================================================
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -359,6 +359,11 @@
> BayCom Serial Port AX.25 Modem (Half Duplex Mode)
> Format: <io>,<irq>,<mode>
> See header of drivers/net/hamradio/baycom_ser_hdx.c.
> +
> + bios_corruption_check=0/1 [X86]
> + Some BIOSes seem to corrupt the first 64k of memory
> + when doing things like suspend/resume. Setting this
> + option will scan the memory looking for corruption.
>
> boot_delay= Milliseconds to delay each printk during boot.
> Values larger than 10 seconds (10000) are changed to
> ===================================================================
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -203,6 +203,9 @@
> bool
> depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP)
> default y
> +
> +config X86_CHECK_BIOS_CORRUPTION
> + def_bool y
>
> config KTIME_SCALAR
> def_bool X86_32
> ===================================================================
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -582,6 +582,88 @@
> struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
>
> /*
> + * Some BIOSes seem to corrupt the low 64k of memory during events
> + * like suspend/resume and unplugging an HDMI cable. Reserve all
> + * remaining free memory in that area and fill it with a distinct
> + * pattern.
> + */
> +#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
> +#define MAX_SCAN_AREAS 8
> +static struct e820entry scan_areas[MAX_SCAN_AREAS];
> +static int num_scan_areas;
> +
> +static void __init setup_bios_corruption_check(void)
> +{
> + u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */
> +

can you please not punish systems without this bios problem?

if (!bios_corruption_check)
return;

> + while(addr < 0x10000 && num_scan_areas < MAX_SCAN_AREAS) {
> + u64 size;
> + addr = find_e820_area_size(addr, &size, PAGE_SIZE);
> +
> + if (addr == 0)
> + break;
> +
> + if ((addr + size) > 0x10000)
> + size = 0x10000 - addr;
> +
> + if (size == 0)
> + break;
> +
> + e820_update_range(addr, size, E820_RAM, E820_RESERVED);
> + scan_areas[num_scan_areas].addr = addr;
> + scan_areas[num_scan_areas].size = size;
> + num_scan_areas++;
> +
> + /* Assume we've already mapped this early memory */
> + memset(__va(addr), 0, size);
> +
> + addr += size;
> + }
> +
> + printk(KERN_INFO "scanning %d areas for BIOS corruption\n",
> + num_scan_areas);
> + update_e820();
> +}
> +
> +static int __read_mostly bios_corruption_check = 1;

move earlier and
bios_corruption_check = 0;

BTW: SMI evil damaged that area?

YH
čş{.nÇ+?ˇ?Ž?­?+%?Ëlzwm?éb?맲ćěr¸?zX§ťŽwĽ?{ayşĘ?Ú?ë,j­˘fŁ˘ˇh??ŕzšŽwĽ˘¸ ˘ˇŚj:+v?¨?wčjŘmś?˙žŤ?ęçzZ+?ů???ݢj"?ú!śiO?ćŹzˇ?vŘ^śm§˙đĂ nĆ?ŕţY&?