2

Since at least 2.6 kernels, Kconfig offers the option CONFIG_X86_RESERVE_LOW, described as the "Amount of low memory, in kilobytes, to reserve for the BIOS". (Starting from physical address 0 as I understand it and ranging from 4K to 640K)

Booting on my system, my logs inform me close to the beginning of the boot process :

BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009ebff] usable

From which I infer that the BIOS is telling the kernel that the very first 0x9ebff (~640K) bytes of ram are usable. (not reserved)

A couple of lines further, I can read :

e820: update [mem 0x00000000-0x00000fff] usable ==> reserved

That I understand as a consequence of my setting : CONFIG_X86_RESERVE_LOW = 4K

But, considering the BIOS itself asserting that the 0-0x9ebff range is usable, what is the point for the kernel to "reserve" whatever amount of low memory < ~ 640K for the BIOS ?

8

You should see a longer help text for this config option. It offers two reasons.

config X86_RESERVE_LOW
int "Amount of low memory, in kilobytes, to reserve for the BIOS"
default 64
range 4 640
help

Specify the amount of low memory to reserve for the BIOS.

The first page contains BIOS data structures that the kernel must not use, so that page must always be reserved.

[snip]

There is a similar comment in the code:

     * A special case is the first 4Kb of memory;
     * This is a BIOS owned area, not kernel ram, but generally
     * not listed as such in the E820 table.

The traditional BIOS would use the first 1280 bytes (0x500). Linux allocates RAM in units of the MMU page size (4096 bytes). OSDev points out -

After all the BIOS functions have been called, and your kernel is loaded into memory somewhere, the bootloader or kernel may exit Real Mode forever (often by going into 32bit Protected Mode). If the kernel never uses Real Mode again, then the first 0x500 bytes of memory in the PC may be reused and overwritten.

Linux is not generally able to call into the BIOS. However it may do so in a few terrifying moments: early boot, shutdown, and resume from sleep mode. If your system was booted using UEFI, then as far as Linux can tell there is no BIOS it can call.

Also, reserving the first page means that successful physical memory allocations never return the value 0. C programming traditionally reserves the address 0 to represent a "NULL pointer". We can see this reflected in memblock_phys_alloc_range(). At this point, changing it seems unlikely to repay the effort (and the risks :-).

 * Return: physical address of the allocated memory block on success,
 * %0 on failure.
 */
phys_addr_t __init memblock_phys_alloc_range(

Here is the second reason:

By default we reserve the first 64K of physical RAM, as a number of BIOSes are known to corrupt that memory range during events such as suspend/resume or monitor cable insertion, so it must not be used by the kernel.

You can set this to 4 if you are absolutely sure that you trust the BIOS to get all its memory reservations and usages right. If you know your BIOS have problems beyond the default 64K area, you can set this to 640 to avoid using the entire low memory range.

If you have doubts about the BIOS (e.g. suspend/resume does not work or there's kernel crashes after certain hardware hotplug events) then you might want to enable X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical corruption patterns.

Leave this to the default value of 64 if you are unsure.

The safest assumption is that this could apply to UEFI firmware as well, just as it did to BIOS :-).

Since v3.9, the extra low reserve is not shown in the kernel log messages. It is also not shown in /proc/iomem. The kernel only shows the first 4k reserved, even though the rest of the memory should still be reserved. It is just not added in the e820 map. It is added to a different list instead. The patch for this change is here: x86, mm: Move reserving low memory later in initialization.

If you want to find out more about the extra reservation, and the tale of woe that required it, here are the patch messages:

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.

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.

x86, bios: By default, reserve the low 64K for all BIOSes

The laundry list of BIOSes that need the low 64K reserved is getting very long, so make it the default across all BIOSes. This also allows the code to be simplified and unified with the reservation code for the first 4K.

This resolves kernel bugzilla 16661 and who knows what else...

Bug 16661 - Corrupted low memory

[...] It means we should add his BIOS (dmidecode info please) to the blacklist bad_bios_dmi_table in arch/x86/kernel/setup.c. However, the bottom line is that 64K is such a small amount of memory and the list by now covers such a vast number of existing BIOSes, that we should just make it unconditional.

As far as I know, Windows 7 actually reserves all memory below 1 MiB to avoid BIOS bugs.

| improve this answer | |
  • Thank you a lot, @sourcejedi, for this detailed explanation. Thanks to the links you provided, I realize that the surprise made its way up to as high as Ingo Molnar and I definitely share his opinion that it should be considered inacceptable to waste 64k of low mem. Anyway! – MC68020 Aug 3 at 6:36
  • Could you please restore the valuable piece of info (some link on linus git if I can remember) I have had only the time for a glance. I did not know it but realized that it would be very useful to me. – MC68020 Aug 3 at 6:41
  • And BTW sorry for not being capable to increase your reputation because of my own score. – MC68020 Aug 3 at 6:44
  • @MC68020 it's in the edit history. You can see the full edit history by clicking "edited 6 hours ago" at the bottom of the post. I felt the help text was the most important thing to look at. Methods to find commits/patches are a little more involved, and I can't say "git blame" is how I found these :-). – sourcejedi Aug 3 at 8:52
  • Thanks again. Point is that I get an out-of-this-topic problem (Some msi-capable network adapter having msi disabled at init). Almost certainly because of a patch that I think your "git blame" would enable me to find in two clicks... and a half! ;-) – MC68020 Aug 3 at 9:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.