# Исправление Slide значений KASLR
- Поддерживаемая версия: 0.6.9
Этот раздел предназначен для пользователей, которые хотят понять и исправить ошибки "Couldn't allocate runtime area". Чаще всего это встречается на Z390, X99 и X299.
- Примечание: Clover больше не поддерживается в этом руководстве, поэтому требуется OpenCore
# Что же такое KASLR?
Что ж, KASLR расшифровывается как Kernel adress space layout randomization (рус. - Рандомизация размещения/компоновки адресного пространства ядра), используется в целях безопасности. В частности, это делает более сложным определение расположения важных объектов в памяти, поскольку это всегда случайное значение как между компьютерами, так и между загрузками. Более подробное описание KASLR (opens new window)
Это становится проблемой, когда вы вводите (introduce) устройства либо с небольшими Memory Map, либо же просто вводите слишком много устройств. Вероятно, есть место для работы ядра, и также есть свободное место, куда ядро не помещается полностью. Здесь подходит slide=xxx
. Вместо того, чтобы позволить macOS выбирать случайную область для работы при каждой загрузке, мы ограничим ее той областью, которая, как мы знаем, будет работать.
# И для кого эта информация?
Как уже упомяналось ранее, это для пользователей, у которых нет достаточного места для ядра или происходит перемещение в слишком маленькое место. Как правило, при загрузке вы столкнетесь с аналогичной ошибкой:
Error allocating 0x1197b pages at 0x0000000017a80000 alloc type 2
Couldn't allocate runtime area
С различными вариациями:
Only 244/256 slide values are usable!
Или даже краш во время работы macOS:
panic(cpu 6 caller 0xffffff801fc057ba): a freed zone element has been modified in zone kalloc.4096: expected 0x3f00116dbe8a46f6 but found 0x3f00116d00000000
Веселая часть этих ошибок заключается в том, что они могут быть случайными, а также причина, почему 20-кратное включение и выключение питания вашего ПК также может решить проблему, но только временно.
Забавный факт: Поиск области для работы занимает около 31 мс, а ручная установка слайд значения может в среднем сократить время загрузки на 0.207%!!!
# Так как же мне это исправить?
Реальное решение этой проблемы довольно простое. Что вам понадобится:
- OpenRuntime (opens new window)
- OpenShell (opens new window)(Не забудьте включить это в разделе
Root -> Misc -> Tools
)
И также нам нужно настроить наш config.plist -> Booter:
- AvoidRuntimeDefrag: YES
- Исправляет рантайм сервисы UEFI, такие как дата, время, NVRAM, управление питанием, т.д.
- DevirtualiseMmio: YES
- Уменьшает объем Stolen памяти, расширяет возможные значения для
slide=N
, и очень полезен при устранении проблем с выделением памяти (Memory Allocation) на Z390.
- Уменьшает объем Stolen памяти, расширяет возможные значения для
- EnableSafeModeSlide: YES
- Позволяет использовать слайд значения в безопасном режиме
- ProtectUefiServices: NO
- Защищает UEFI сервисы от переопределения прошивкой, в основном актуально для виртуальных машин, 300 серии и более новых систем, таких как Ice Lake и Comet Lake
- ProvideCustomSlide: YES
- Это даёт уверенность, что ядро будет выбирать только хорошие регионы и избегать тех, которые могут привести к сбоям загрузки. Оно по-прежнему выбирает случайно, но не включает плохие регионы при рандомизации.
- RebuildAppleMemoryMap: YES
- Создает Memory Map совместимую с macOS, может сломаться с некоторыми OEM прошивками ноутбуков, поэтому если вы получили сбой ранней загрузки - отключите это. Это гарантирует, что наша Memory Map будет соответствовать соответствовать тому, что ожидает ядро.
# Подготовка BIOS
Причина, по которой нам нужно сбросить Memory Map, заключается в том, что мы хотим, чтобы она была более детерминированной, имеется ввиду, чтобы при каждой загрузке было меньше вариаций, поэтому у нас будет меньше крайних случаев (Memory Map не всегда согласованы при загрузке). Для подготовки:
- Обновите BIOS(чрезвычайно важно, поскольку известно, что ранние версии BIOS имеют проблемы с Memory Map, в особенности Z390)
- Сбросьте CMOS
- Включите необходимые настройки в BIOS:
Above4GDecoding
: Позволяет устройствам использовать области памяти размером более 4 ГБ, что означает, что в macOS будет больше места для размещения; может быть проблематичным на некоторых X99, X299, поэтому рекомендуется тестировать с и без.- Примечание: В BIOS поддерживаемых Resizable BAR Support, включение Above4G разблокирует эту опцию. Убедитесь, что BAR support отключен, если эта опция конечно же присутствует.
Boot Options -> Windows8.1/10 mode
: Это гарантирует, что не будет загружаться старый устаревший мусор. Интересный факт:other OS
разработан только для загрузки старых версий Windows, а не для других ОС
- Отключите как можно больше ненужных устройств в BIOS (это означает, что при каждой загрузке будет меньше изменений в Memory Map, и поэтому меньше шансов на сбой загрузки). Общие настройки:
CSM
: Для поддержки Legacy, добавляет кучу ненужного нам мусора. Это также может сломать Shell, и вы не сможете загрузиться в него.Intel SGX
: Software Guard Extensions, занимает много места и ничего не делает в macOS.Parallel Port
: macOS даже не видит параллельные порты.Serial Port
: Хотелось бы знать, насколько много тех, кто отлаживает ядро...iGPU
: В некоторых системах такие раздутые Memory Map, что iGPU просто не влезает.Thunderbolt
: У многих хаков нет рабочего Thunderbolt, платы, у которых нет Thunderbolt, но имеют эту опцию, просто тратят больше места.LED lighting
: Извини, приятель, время уходить.Legacy USB
: Больше Legacy Чепухи.
# Тестовая загрузка
С нашими скорректированными настройками EFI, config.plist и BIOS, пришло время опробовать наши новые настройки. Если у вас все еще есть проблемы, похоже, нам нужно глубоко погрузиться и рассчитать значение нашего Slide
# Нахождение Slide значения
Теперь вам нужно открыть EFI Shell в выбранном вами менеджере загрузок и запустить memmap
. Это даст вам список всех страниц и их размеров. Вот тут-то и начинается веселье.
Пример того, что вы увидите:
Type | Start | End | # Pages | Attributes |
---|---|---|---|---|
RT_Data | 0000000000000000 | 0000000000000FFF | 0000000000000001 | 800000000000000F |
Available | 0000000000001000 | 0000000000057FFF | 0000000000000057 | 000000000000000F |
Reserved | 0000000000058000 | 0000000000058FFF | 0000000000000001 | 000000000000000F |
Available | 0000000000059000 | 000000000008FFFF | 0000000000000037 | 000000000000000F |
RT_Code | 0000000000090000 | 0000000000090FFF | 0000000000000001 | 800000000000000F |
Available | 0000000000091000 | 000000000009DFFF | 000000000000000D | 000000000000000F |
Reserved | 000000000009E000 | 000000000009FFFF | 0000000000000002 | 000000000000000F |
Available | 0000000000100000 | 000000005B635FFF | 000000000005B536 | 000000000000000F |
BS_Data | 000000005B636000 | 000000005B675FFF | 0000000000000040 | 000000000000000F |
Available | 000000005B676000 | 000000006AF77FFF | 000000000000F902 | 000000000000000F |
LoaderCode | 000000006AF78000 | 000000006B155FFF | 00000000000001DE | 000000000000000F |
BS_Data | 000000006B156000 | 000000006B523FFF | 00000000000003CE | 000000000000000F |
ACPI_NVS | 000000006B524000 | 000000006B524FFF | 0000000000000001 | 000000000000000F |
BS_Data | 000000006B526000 | 000000006B625FFF | 0000000000000100 | 000000000000000F |
Available | 000000006B626000 | 000000006B634FFF | 000000000000000F | 000000000000000F |
Теперь вам может быть интересно, как, черт возьми, мы конвертируем это в значение слайда, ну, это довольно просто. Нас интересует самое наибольшее доступное значение в столбце Start
. В этом примере мы видим, что 000000006B626000
является нашим самым большим значением, обратите внимание, что они находятся в HEX, поэтому, если есть несколько значений, близких друг к другу, вам может потребоваться конвертировать их в десятичное значение. Для вычисления Slide значение (встроенный калькулятор macOS имеет функцию программирования, нажав ⌘ + 3):
000000006B626000
= 0x6B626000
(0x6B626000
- 0x100000
)/0x200000
= 0x35A
И чтобы убедиться, что это правильно:
0x100000
+ (0x35A
* 0x200000
) = 0x6B500000
Всякий раз, когда возвращаемое значение не оригинальное (0x6B500000
против 0x6B626000
), просто добавьте +1 к конечному Slide значению. Это связано с округлением. Так, например, конвертированный в десятичное счисление 0x35A
становится 858
, а +1 даст вам slide=859
.
Но подождите, это же больше 256!
Это верно. Это вызвано Memory Map включающими в себя сектора Above4GDecoding
, которые не могут быть использованы. Поэтому вам нужно будет спускаться вниз по списку, пока вы не найдете небольшое достаточное значение(для нас, это будет 0000000000100000
)
И чтобы было немного яснее, вот формула:
(HEX - 0x100000
)/0x200000
= Значение Slide в HEX
0x100000
+ (Значение Slide в HEX * 0x200000
) = Ваше изначальное HEX значение(если нет, то добавьте +1 к Slide значению)
Теперь перейдите в свой config.plist и добавьте своё слайд значение к остальным аргументам загрузки(для нас, это будет slide=0
при использовании 0x100000
). Если это значение по-прежнему выдаёт вам ошибки, вы можете перейти ко второму по велечине Start
значению и так далее.
Иногда вы можете обнаружить, что при вычислении слайда, вы получаете сверхмалые значения, такие как slide=-0.379150390625
, когда это происходит, округлите это до slide=0
.
А для пользователей, у которых возникают проблемы с поиском значения слайда, вы можете также ввести $slide [вставьте наибольшее значение #Pages]
в канале #Sandbox на Discord-сервере r/Hackintosh (opens new window)
Но это таааак тяжело
Ну, не волнуйтесь, ведь есть более простое решение. После запуска memmap
в оболочке запустите:
shell> fs0: //replace with your USB
fs0:\> dir //to verify this is the right directory, if not try fs1 and so on
Directory of fs0:\
01/01/01 3:30p EFI
fs0:\> memmap > memmap.txt
Это добавит файл memmap.txt
в корень вашего EFI, после чего вы сможете перетащить в канал #Sandbox Discord-сервера r/Hackintosh и написать $slide [вставьте ссылку на memmap.txt]
# Использование DevirtualiseMmio
DevirtualiseMmio - довольно интересный квирк, особенно в том, что он преодолевает огромное препятствие с многими системами PCI устройств, такими как некоторые Z390 платы и практические все HEDT платы, такие как X99 и X299. Как это происходит? Он берет MMIO области и удаляет рантайм атрибуты, позволяя тем самым использовать их в качестве пространства для удобного размещения ядра. В сочетании с квирком ProvideCustomSlide
, мы можем сохранить функцию безопасности слайда, а также получить загружаемую машину.
Для чрезвычайно проблематичных систем, таких как Threadripper TRX40 19H, нам нужно найти определенные обрасти, которые не требуются для правильной работы. Вот тут-то и вступает в игру MmioWhitelist
. Обратите внимание, что белый список не требуется для большинства систем.
Если вы запустите отладочную версию OpenCore со включенным DevirtualiseMmio, вы заметите в своих логах это:
21:495 00:009 OCABC: MMIO devirt start
21:499 00:003 OCABC: MMIO devirt 0x60000000 (0x10000 pages, 0x8000000000000001) skip 0
21:503 00:003 OCABC: MMIO devirt 0xFE000000 (0x11 pages, 0x8000000000000001) skip 0
21:506 00:003 OCABC: MMIO devirt 0xFEC00000 (0x1 pages, 0x8000000000000001) skip 0
21:510 00:003 OCABC: MMIO devirt 0xFED00000 (0x1 pages, 0x8000000000000001) skip 0
21:513 00:003 OCABC: MMIO devirt 0xFEE00000 (0x1 pages, 0x800000000000100D) skip 0
21:516 00:003 OCABC: MMIO devirt 0xFF000000 (0x1000 pages, 0x800000000000100D) skip 0
21:520 00:003 OCABC: MMIO devirt end, saved 278608 KB
- Примечание: См. Отладка OpenCore о том, как включить логирование в файл
Итак, у нас есть 6 регионов, через которые нам нужно пройти и посмотреть, какие из них плохие. Лучше всего заблокировать все MMIO области кроме одного и попробовать каждый регион, чтобы получить список хороших регионов.
Теперь давайте возьмем вышеприведенный пример и создадим наш собственный MmioWhitelist, нам нужно сначала преобразовать адрес из шестнадцатеричного в десятичное значение:
- MMIO devirt 0x60000000 -> 1610612736
- MMIO devirt 0xFE000000 -> 4261412864
- MMIO devirt 0xFEC00000 -> 4273995776
- MMIO devirt 0xFED00000 -> 4275044352
- MMIO devirt 0xFEE00000 -> 4276092928
- MMIO devirt 0xFF000000 -> 4278190080
Когда все сделано, должно выглядеть примерно так: