Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
141 lines (97 sloc) 9.57 KB

Fixing KALSR slide values

This section is for users who wish to understand and fix "Couldn't allocate runtime area" errors. This is most common with either Z390, X99 and X299. This section will also support Clover as the info is also useful for them.

So what is KASLR?

Well KASLR stands for Kernel address space layout randomization, what it's used for is security purposes. Specifically, this makes it much harder for attackers to figure out where the important objects are in memory as it's always random both between machines and between boots. More in-depth explainer on KASLR

Where this becomes an issue is when you introduce devices with either small memory maps or just way too many devices present. There likely is space for the kernel to operate but there's also free space where the kernel won't fit entirely. This is where slide=xxx fits in. Instead of letting macOS choose a random area to operate in each boot, we'll constrain it to somewhere that we know will work.

And who is this info for?

Well as I mentioned earlier, this is for users who don't have enough space for the kernel or moves to a place that is too small. You'll generally experience an error similar to this when booting:

Error allocating 0x1197b pages at 0x0000000017a80000 alloc type 2
Couldn't allocate runtime area

With some variation:

Only 244/256 slide values are usable!

Or even crashes while running macOS:

panic(cpu 6 caller 0xffffff801fc057ba): a freed zone element has been modified in zone kalloc.4096: expected 0x3f00116dbe8a46f6 but found 0x3f00116d00000000

The best part about these errors is that they can be random, also the reason why power cycling your PC 20 times also can fix the issue but only temporarily.

Fun Fact: It takes around 31 ms to find an area to operate in, manually setting a slide value can on average can reduce boot times by 0.207%!!!

So how do I fix this?

The real fix to this is quite simple actually, the process is both the same for Clover and OpenCore users. What you'll need:

  • Clover users:
    • AptioMemoryFix(Don't mix Aptio fixes together or use OsxAptioFixDrvX, only AptioMemoryFix is supported in this guide)
    • Clover Shell(most users already have this included, usually called shell64.efi or some variation)
  • OpenCore users:
    • FwRuntimeServices
    • OpenCoreShell(Don't forget to enable this under Root->Misc->Tools)
    • Config.plist settings:
    • AvoidRuntimeDefrag: Fixes UEFI runtime services like date, time, NVRAM, etc
    • DevirtualiseMmio: Reduces stolen memory footprint so we're given more options for slide values
    • DisableVariableWrite: Reroutes NVRAM to nvram.plist, needed for systems without supported NVRAM(B360, B365, H310, H370, Q370, Z390). Some C612, X79, X99, X299 systems will also need this.
    • EnableSafeModeSlide: Allows us to use slide in safe mode, just so if you have other issues troubleshooting won't mess it up.
    • EnableWriteUnprotector: Allows us to write to certain areas that the firmware locks, specifically the CR0 register.
    • ProvideCustomSlide: Kinda need that slide to do any real work.
    • SetupVirtualMap: Creates a layer between macOS and your memory map for greater support and fewer chances of insecure write access.
    • ShrinkMemoryMap: Fixes issues with very large memory maps that don't fit, very useful for X99 and X299 platforms and sometimes for Z390.

Resetting the Memory Map

The reason we need to reset the memory map is we want it to be more deterministic, what I mean by this is that there will be less variation on each boot so we have fewer edge cases(Memory Maps are not always consistent on boots). To prep:

  • Update BIOS(extremely important as early BIOS's shipped are known to have memory map issues, especially with Z390)
  • Clear CMOS
  • Enable much needed BIOS settings:
    • Above4GDecoding: This allows devices to use memory regions above 4GB meaning macOS will have more room to fit, can be problematic on X99, X299 so recommended to disable for them.
    • Boot Options -> Windows8.1/10 mode: This will make sure no old legacy garbage is loaded. Fun fact, other OS is only designed for booting older versions of Windows and not for other OS.
    • Disable as many unneeded devices in the BIOS(this means there is less variation in the map on each boot, so fewer chances of boot failure). Common settings:
    • CSM: For legacy support, adds a bunch of garbage we don't want. This also can break the shell so you can't boot into it.
    • Intel SGX: Software Guard Extensions, takes up a lot of space and does nothing in macOS.
    • Parallel Port: macOS can't even see parallel.
    • Serial Port: I'd like to know how many of you are debugging the kernel...
    • iGPU: No ideal but some systems have such bloated maps that the iGPU just can't fit.
    • Thunderbolt: Many hacks don't have thunderbolt working, boards that don't have thunderbolt but have this option just waste more space.
    • LED lighting: Sorry mate, time to go.
    • Legacy USB: More Legacy Crap.

Now we can start the fun part, resetting the Memory Map. This is done each time the memory is trained, so all we need to do is trigger it so we have a clean base to start with(most important for users who ran OsxAptioFree2000.efi but still needed for everyone). There are 2 common ways:

  • Enabling XMP, let it train then disable and train again
  • Taking a stick of RAM out, let the system train, put the stick back and train again

With that done, we can no finally proceed to find a slide value

Finding the Slide value

Now what you'll want to do is open the EFI shell in your boot manager of choice and run memmap. This will give you a list of all pages and their sizes. This is where the fun begins.

Example of what you'll see:

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

Now you may be wondering how the hell we convert this to a slide value, well it's quite simple. What we're interested in is the largest available value within the Start column. In this example we see that 000000006B626000 is our largest, do note that these are in HEX so if there are multiple values close to each other you may need to convert them to decimal. To the calculate slide value(macOS's built-in calculator has a programming function by pressing ⌘+3):

000000006B626000 = 0x6B626000

(0x6B626000 - 0x100000)/0x200000 = 0x35A

And to verify that this is correct:

0x100000 + (0x35A * 0x200000) = 0x6B500000

Whenever the returned value is not the original(0x6B500000 vs 0x6B626000), just add +1 to your final slide value. This is due to rounding. So for example 0x35A converted to decimal becomes 858 and then +1 will give you slide= 858.

But wait for just a second, this is higher than 256!

That is correct, this is caused by memory maps that include Above4GDecoding sectors which cannot be used. So you will need to keep going down the list until you find a small enough value(for us that would be 0000000000100000)

And just to make it a bit clearer on the formula:

(HEX - 0x100000)/0x200000 = Slide Value in HEX

0x100000 + (Slide Value in HEX * 0x200000) = Your original HEX value(if not then add +1 to your slide value)

Now navigate into your config.plist and add your slide value with the rest of your boot arguments(for us it would be slide=0 when using 0x100000). If this value still gives you errors then you may proceed to the second-largest Start value and so on.

Sometimes you may find that when you calculate slide that you receive super small vales like slide=-0.379150390625, when this happens round this to slide=0.

And for users who are having issues finding their slide value can also type $slide [insert largest #Pages value] in the #Sandbox channel on the r/Hackintosh Discord

But this is soooooo hard

Well fret not, for there is a simple solution. After running memmap in the shell, run:

memmap > memmap.txt

This will add a memmap.txt file to the root of your EFI for OpenCore users (You may need to specify the drive location like fs0:), you can then proceed to drop it into the r/Hackintosh discord and type $slide [insert a link to memmap.txt]. Do note that this doesn't always work so so may still need to do this manually.

You can’t perform that action at this time.