Какой смысл в ядре резервировать память CONFIG _X86 _RESERVE _LOW для BIOS?

Если вы знаете, что маркеры Fnупорядочены, вы можете использовать их в качестве разделителей полей:

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    awk -F'(F2|F6)' '{print substr($2,1,5), substr($3,1,6)}'
B3094 BC313D

или, разбив на все маркеры Fnи соответствующим образом пронумеровав поля

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    awk -F'F[0-9]' '{print substr($3,1,5), substr($7,1,6)}'
B3094 BC313D

(в этом случае вам может вообще не понадобиться substr, если вы просто хотите все до следующегоFn-это не ясно из вашего описания проблемы ).

С помощью GNU Awk вы могли захватить обе подстроки в одном шаблоне и получить к ним доступ через необязательный массив match:

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    gawk 'match($0, /F2(.{5}).*F6(.{6})/, a) {print a[1], a[2]}'
B3094 BC313D

Кроме того, с помощью Perl вы можете захватывать символы после маркеров, используя просмотр назад:

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    perl -lne 'print join " ", /(?<=F2).{5}|(?<=F6).{6}/g'
B3094 BC313D

или

echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' | 
    perl -lne 'print "$1 $2" if /(?<=F2)(.{5}).*?(?<=F6)(.{6})/g'
B3094 BC313D
2
03.08.2020, 15:17
1 ответ

Вы должны увидеть более длинный текст справки для этой опции конфигурации. Он предлагает две причины.

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]

Аналогичный комментарий есть в коде :

     * 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.

Традиционный BIOS будет использовать первые 1280 байт (0x500 ).Linux выделяет оперативную память в единицах размера страницы MMU (4096 байт ). OSDev указывает-

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 обычно не может обращаться к BIOS. Однако это может произойти в несколько ужасных моментов :ранней загрузки, выключения и выхода из спящего режима. Если ваша система была загружена с использованием UEFI, то, насколько Linux может сказать, она не может вызывать BIOS.

Кроме того, резервирование первой страницы означает, что успешное выделение физической памяти никогда не возвращает значение 0. Программирование на C традиционно резервирует адрес 0 для представления «НУЛЕВОГО указателя». Мы можем видеть это отраженным в memblock _phys _alloc _range(). На данный момент маловероятно, что его изменение окупит усилия (и риски :-).

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

Вот вторая причина:

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.

Самое безопасное предположение состоит в том, что это может относиться и к прошивке UEFI, как и к BIOS :-).

Начиная с версии 3.9 сверхнизкий резерв не отображается в сообщениях журнала ядра. Это также не показано в /proc/iomem. Ядро показывает только первые 4 КБ зарезервированных, хотя остальная часть памяти все еще должна быть зарезервирована. Его просто нет в карте e820. Вместо этого он добавляется в другой список. Патч для этого изменения находится здесь:x86, мм :Переместить резервирование малой памяти позже при инициализации .

Если вы хотите узнать больше о дополнительном резервировании и о горе, которое его потребовало, вот сообщения об исправлении:

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.

8
18.03.2021, 23:15

Теги

Похожие вопросы