Jump to content

DVMT/stolenmem/fbmem/cursormem, why do we patch these for Broadwell and later?


Hervé

Recommended Posts

  • Administrators

NB: This is a revival of the article I had initially published at InsanelyMac to answer recurring questions that had been raised in the Opencore thread that lives there.

 

Posted October 2, 2021

 

The Dortania documentation refers to the DVMT pre-allocated memory or "stolen memory" when they mention "memory reserved for the iGPU". Years ago, @Firewolf described in details the relationship between stolen memory and DVMT pre-allocated memory on his blog:

https://www.firewolf.science/2015/04/guide-intel-hd-graphics-5500-on-os-x-yosemite-10-10-3/

 

There's a more recent thread from him here:

https://www.insanelymac.com/forum/topic/345377-surface-pro-patch-the-framebuffer-properly-to-get-rid-of-the-dvmt-assertion-patch/

 

It can be difficult to understand and differentiate DVMT pre-allocated memory, stolen memory, framebuffer memory, cursor memory, framebuffer size, cursor bytes, etc. And all of these have got nothing to do with VRAM of course... Some of us are familiar with the information provided by @Pike R Alpha many moons ago, the WhateverGreen User Manual or the Hackintool app though none of those clearly define what the various memory instances are. Several years ago, @Rehabman also attempted to explain this and his writings somehow collided with most people's comprehension of things. For instance, when @Pike, WhateverGreen or Hackintool refer to stolenmem and fbmem, @Rehabman spoke of framebuffer memory size and cursor bytes. In the case of the Haswell Azul framebuffer layouts, @Rehabman also spoke of the DVMT pre-alloc requirements when the others speak of stolenmem. Inevitably, this can lead to confusion...

 

Definitions:

See wikipedia and Google searches.

  • VRAM = Video RAM. Common definition is that it stores the pixels and other graphics data rendered on a computer screen.
  • DVMT = Dynamic Video Memory Technology. A technology used by Intel to dynamically allocate system memory to use as video memory to handle graphics. DVMT pre-allocated memory is the minimum amount, in multiples of 32MB, that will be allocated to the iGPU for handling graphics. By far and large, manufacturers set this to 32MB by default in BIOS (or certainly used to).
  • Framebuffer = a memory buffer held in RAM and containing a bitmap of a video frame, i.e. all the data related to the pixels of an image to be displayed on screen (eg: colours, resolution, etc.).
  • Stolen memory = basically, this is the same as the DVMT pre-allocated memory.

As far as Apple's framebuffer drivers/kexts are concerned:

  • framebuffer size (aka stolenmem for WhateverGreen*) = the size, in bytes, of a framebuffer layout (it may change according to image characteristics), as defined in the driver/kext.
  • cursor bytes (aka fbmem for WhateverGreen*) = the size, in bytes, of a framebuffer layout's overlay used for handling mouse cursor (without modifying the framebuffer's data), as defined in the driver/kext.
  • framebuffer VRAM (aka unifiedmem for WhateverGreen) = the max. amount, in bytes, of VRAM allocated by a framebuffer layout, as defined in the driver/kext (since Haswell and Yosemite, this usually is 1536MB).

* As stated above, I believe that Whatevergreen only got it right for Haswell Azul framebuffer layouts with which stolenmem, fbmem and cursormem match their target. Thereafter, I'm of the opinion that WhateverGreen used incorrect names where stolenmem means the actual framebuffer size and fbmem means the actual cursor bytes (size), as stated by @Rehabman.

 

Mac OS X/OS X/macOS graphics framebuffers:

Let's start by looking at a few examples as illustrated in the WhateverGreen User Manual.

 

1) Haswell Azul mobile framebuffer 0x0a260006 (used for HD4200/HD4400/HD4600 iGPUs on laptops):

ID: 0A260006, STOLEN: 32 MB, FBMEM: 19 MB, VRAM: 1536 MB, Flags: 0x0000000F
TOTAL STOLEN: 52 MB, TOTAL CURSOR: 1 MB (1572864 bytes), MAX STOLEN: 116 MB, MAX OVERALL: 117 MB (123219968 bytes)
Camellia: CamelliaDisabled (0), Freq: 2777 Hz, FreqMax: 2777 Hz
Mobile: 1, PipeCount: 3, PortCount: 3, FBMemoryCount: 3
[0] busId: 0x00, pipe: 8, type: 0x00000002, flags: 0x00000030 - ConnectorLVDS
[1] busId: 0x05, pipe: 9, type: 0x00000400, flags: 0x00000087 - ConnectorDP
[2] busId: 0x04, pipe: 9, type: 0x00000400, flags: 0x00000087 - ConnectorDP
00000800 02000000 30000000
01050900 00040000 87000000
02040900 00040000 87000000

If we look inside the binary code of the Haswell Azul framebuffer kext, we'll find:

0600260A 01030303 00000002 00003001
00006000 00000060 D90A0000 D90A0000
00000000 00000000 00000800 02000000
30000000 01050900 00040000 87000000
02040900 00040000 87000000 FF000000
01000000 40000000 0F000000 01010000
04000000 00000000 0E000000 00000000

which translates to:

0600260A                    -> layout id       (AAPL,ig-platform-id)
01                          -> mobile type     (framebuffer-mobile) 
03                          -> 3 x pipes       (framebuffer-pipecount)
03                          -> 3 x ports       (framebuffer-portcount)
03                          -> 3 x memories    (framebuffer-memorycount)
00000002                    -> 32MB stolen mem (framebuffer-stolenmem)      // Rehabman's DVMT-prealloc requirement
00003001                    -> 19MB FB mem     (framebuffer-fbmem)          // Rehabman's framebuffer size
00006000                    -> 6MB Cursor mem  (framebuffer-cursormem)      // Rehabman's cursor bytes
00000060                    -> 1536MB VRAM     (framebuffer-unifiedmem)
D90A0000                    -> Backlight freq 2777MHz
D90A0000                    -> Max. backlight freq 2777MHz
00000000 00000000
00000800 02000000 30000000  -> port #1/FB@0: index 00, busid 00, pipe 0800, type 02000000=LVDS/eDP (framebuffer-con0-type), flags 30020000
01050900 00040000 87000000  -> port #2/FB@1: index 01, busid 05, pipe 0900, type 00040000=DP       (framebuffer-con1-type), flags 87000000
02040900 00040000 87000000  -> port #3/FB@2: index 02, busid 04, pipe 0900, type 00040000=DP       (framebuffer-con2-type), flags 87000000
FF000000 01000000 40000000 0F000000
01010000 04000000 00000000 0E000000
00000000

 

2) Broadwell BDW mobile framebuffer 0x1626006 (used for HD5300/HD5500/HD5600 iGPUs on laptops):

ID: 16260006, STOLEN: 34 MB, FBMEM: 21 MB, VRAM: 1536 MB, Flags: 0x00000B0B
TOTAL STOLEN: 56 MB, TOTAL CURSOR: 1 MB (1572864 bytes), MAX STOLEN: 124 MB, MAX OVERALL: 125 MB (131608576 bytes)
Camellia: CamelliaDisabled (0), Freq: 2777 Hz, FreqMax: 2777 Hz
Mobile: 1, PipeCount: 3, PortCount: 3, FBMemoryCount: 3
[0] busId: 0x00, pipe: 8, type: 0x00000002, flags: 0x00000230 - ConnectorLVDS
[1] busId: 0x05, pipe: 11, type: 0x00000400, flags: 0x00000507 - ConnectorDP
[2] busId: 0x04, pipe: 11, type: 0x00000400, flags: 0x00000507 - ConnectorDP
00000800 02000000 30020000
01050B00 00040000 07050000
02040B00 00040000 07050000

If we look inside the binary code of the Broadwell BDW framebuffer kext, we'll find:

06002616 01030303 00002002 00005001
00000060 D90A0000 D90A0000 00000000
00000000 00000000 00000800 02000000
30020000 01050B00 00040000 07050000
02040B00 00040000 07050000 FF000000
01000000 40000000 0B0B0000 01010500
00000000 05000000 00000000 04000000
00000000 00000000 00000000 00000000
00000000 C8000000

which translates to:

06002616                    -> layout id       (AAPL,ig-platform-id)
01                          -> mobile type     (framebuffer-mobile) 
03                          -> 3 x pipes       (framebuffer-pipecount)
03                          -> 3 x ports       (framebuffer-portcount)
03                          -> 3 x memories    (framebuffer-memorycount)
00002002                    -> 34MB stolen mem (framebuffer-stolenmem)     // Rehabman's framebuffer size
00005001                    -> 21MB FB mem     (framebuffer-fbmem)         // Rehabman's cursor bytes
00000060                    -> 1536MB VRAM     (framebuffer-unifiedmem)
D90A0000                    -> Backlight freq 2777MHz
D90A0000                    -> Max. backlight freq 2777MHz
00000000 00000000 00000000
00000800 02000000 30020000  -> port #1/FB@0: index 00, busid 00, pipe 0800, type 02000000=LVDS/eDP (framebuffer-con0-type), flags 30020000
01050B00 00040000 07050000  -> port #2/FB@1: index 01, busid 05, pipe 0B00, type 00040000=DP       (framebuffer-con1-type), flags 07050000
02040B00 00040000 07050000  -> port #3/FB@2: index 02, busid 04, pipe 0B00, type 00040000=DP       (framebuffer-con2-type), flags 07050000
FF000000 01000000 40000000 0B0B0000
01010500 00000000 05000000 00000000
04000000 00000000 00000000 00000000
00000000 00000000 C8000000

 

3) Skylake SKL mobile framebuffer 0x19160000 (used for HD520/HD530/HD540 iGPU on laptops):

ID: 19160000, STOLEN: 34 MB, FBMEM: 21 MB, VRAM: 1536 MB, Flags: 0x0000090F
TOTAL STOLEN: 56 MB, TOTAL CURSOR: 1 MB (1572864 bytes), MAX STOLEN: 124 MB, MAX OVERALL: 125 MB (131608576 bytes)
Model name: Intel HD Graphics SKL CRB
Camellia: CamelliaDisabled (0), Freq: 1388 Hz, FreqMax: 1388 Hz
Mobile: 1, PipeCount: 3, PortCount: 3, FBMemoryCount: 3
[0] busId: 0x00, pipe: 8, type: 0x00000002, flags: 0x00000098 - ConnectorLVDS
[1] busId: 0x05, pipe: 9, type: 0x00000400, flags: 0x00000187 - ConnectorDP
[2] busId: 0x04, pipe: 10, type: 0x00000400, flags: 0x00000187 - ConnectorDP
00000800 02000000 98000000
01050900 00040000 87010000
02040A00 00040000 87010000

We can't look at the binary code of the Skylake SKL framebuffer because Apple changed the way things are coded inside but it basically translates as follows:

00001619                    -> layout id       (AAPL,ig-platform-id)
01                          -> mobile type     (framebuffer-mobile) 
03                          -> 3 x pipes       (framebuffer-pipecount)
03                          -> 3 x ports       (framebuffer-portcount)
03                          -> 3 x memories    (framebuffer-memorycount)
00002002                    -> 34MB stolen mem (framebuffer-stolenmem)     // Rehabman's framebuffer size
00005001                    -> 21MB FB mem     (framebuffer-fbmem)         // Rehabman's cursor bytes
00000060                    -> 1536MB VRAM     (framebuffer-unifiedmem)
6C050000                    -> Backlight freq 1388MHz
6C050000                    -> Max. backlight freq 1388MHz

00000800 02000000 98000000  -> port #1/FB@0: index 00, busid 00, pipe 0800, type 02000000=LVDS/eDP (framebuffer-con0-type), flags 98000000
01050900 00040000 87010000  -> port #2/FB@1: index 01, busid 05, pipe 0900, type 00040000=DP       (framebuffer-con1-type), flags 87010000
02040a00 00040000 87010000  -> port #3/FB@2: index 02, busid 04, pipe 0a00, type 00040000=DP       (framebuffer-con2-type), flags 87010000

 

With the exception of the Haswell Azul framebuffer, we can see that Broadwell BDW and Skylake SKL framebuffers define framebuffer size (WEG's stolenmem) and cursor bytes (WEG's fbmem) characteristics and no DVMT pre-allocated memory (i.e. proper stolen memory). This extends to Kaby Lake KBL framebuffers and later. In my opinion, it's fair to say that @Rehabman's description and wording are the most appropriate/best ones when the WEG view of things got somehow misled by following through on the Haswell framebuffer decoding. To me, there was some mixup, leading to confusion and the said confusion has remained ever since...

 

Confusion... why?

Because of several things:

 

1) the observation that the Haswell Azul framebuffers used on Hacks (0x0D220003 for desktops and 0x0A260006 for laptops) defined:

  • a DVMT pre-allocated memory (= Stolen memory) size of 32MB
  • a framebuffer size of 19MB
  • a cursor bytes of 0MB (desktops) and 6MB (laptops; required to be increased to 9MB to fix a minor graphics glitch on some systems)

2) the observation that the Broadwell BDW framebuffers used on Hacks (0x16220007 for desktops and 0x16160006 for laptops) defined:

  • no DVMT pre-allocated memory requirement at all
  • framebuffer sizes of 38MB and 34MB respectively
  • cursor bytes of 38MB and 21MB respectively

3) the observation that the sum of framebuffer size + cursor bytes must be lower than the size of the DVMT pre-allocated memory, failing which a KP occurs at graphics initialisation during startup/boot.

 

4) In the case of the Haswell Azul framebuffers:

  1. DVMT pre-allocated memory requirement is set at 32MB
  2. framebuffer size + cursor bytes = 19+0 | 19+6 (or 19+9) = 19MB | 25MB (or 28MB) which is lower than DVMT pre-allocated memory 32MB

-> All is Ok by default.

 

5) In the case of the Broadwell BDW framebuffers:

  1. framebuffer size + cursor bytes for desktops = 38+38 = 76MB which is greater than the usual/default 32MB DVMT pre-allocated memory of most desktops, unless adjusted in BIOS
  2. framebuffer size + cursor bytes for laptops = 34+21 = 55MB which is greater than the usual/default 32MB DVMT pre-allocated memory of most laptops, unless adjusted in BIOS

-> Not Ok by default, Kernel Panic (KP) encountered.

 

6) And the story is the same with subsequent Skylake, Kaby Lake, etc. framebuffers.

 

Solution:

2 x solutions were engineered to address the issue of KP at graphics initialisation.

  1. increase the DVMT pre-allocated memory set in BIOS. Could be complicated and tricky for PCs that do not offer this in BIOS Setup but made easy with Grub Shell if DVMT pre-allocated memory can be identified in BIOS. This method is usually required to gain 4K output.
  2. patch the Broadwell, Skylake, Kaby Lake, etc. framebuffer layouts to reduce framebuffer size and cursor bytes so that the sum of them totals less than the usual default DVMT pre-allocated memory of 32MB. This solution does not usually support 4K output.

Although some people do opt for the 1st solution, most people just adopt the 2nd one.

 

How were the framebuffer patches derived?

If we look at the framebuffer patches that are commonly and generally used, we can observe that they set:

  • WEG's framebuffer-stolenmem property , i.e. framebuffer size to 0x01300000 = 19MB (DATA type set to 00003001)
  • WEG's framebuffer-fbmem property, i.e. cursor bytes to 0x00900000 = 9MB (DATA type set to 00009000)

i.e. the values typically used on laptops with Haswell iGPUs, this simply because 19+9=28MB which is < 32MB. This is where it all appears to come from.

 

Is this correct?

By far and large, it is.

 

But the need to apply such framebuffer patches depends entirely on the host PC's default DVMT pre-allocated memory. On desktop and laptop PCs where DVMT pre-allocated memory can be adjusted in BIOS setup, the patches are unnecessary as long as the DVMT value that is set exceeds the total of the framebuffer size + cursor bytes of the selected/target graphics framebuffer. Typically, a value of 64MB or 96MB takes care of things perfectly, including 4K. Of course, those PCs manufactured with default DVMT pre-allocated memory set to 64MB or more are unlikely to encounter any issue at all.

 

The framebuffer patches are also unnecessary if the default DVMT pre-allocated memory is increased either though BIOS binmod (difficult and risky) or through Grub shell mod (easy and quickly reversible). This is well illustrated on @Firewolf's blog, linked above (there are other places too such as @Jake Lo's FAQ item here). To give an example, on some Dell laptops (eg. Broadwell Latitude E7x50 or Skylake Latitude E7x70), DVMT pre-allocated memory can be increased by booting a Grub shell and entering the following command:

setup_var 0x432 0x3

This sets DVMT pre-allocated memory parameter located at offset 0x432 to 96MB (0x1 for 32MB, 0x2 for 64MB, 0x3 for 96MB, etc.), the default setting for the laptop in this example being 32MB. This setting will remain valid/in place until BIOS is reset to default settings. It's required to obtain 4K output out of DP/HDMI. Of course, different computers will have different locations/offsets for DVMT pre-allocated memory.

 

What should I do then?

As stated above, the framebuffer patches apply to most if not all cases. But not for 4K output. Those who feel adventurous or who are computing-literate may opt for the BIOS adjustment alternative. In all cases, the 1st thing to do is to look at the default framebuffer size and cursor bytes settings of the targeted graphics framebuffer, then decide if the sum of them both fits or not in 32MB or any other value set in BIOS for DVMT pre-allocated memory.

 

Can I use different values?

Absolutely! As long as the golden rule is respected: framebuffer size + cursor bytes < DVMT pre-alloc mem or, in WEG's conventions, stolenmem + fbmem < DVMT pre-alloc mem.

 

To give a practical example, I experimented on my Skylake/HD520 Dell Latitude E7270 Hackintosh laptop:

  • default DVMT pre-allocated memory value set in BIOS: 32MB
  • target SKL framebuffer layout: 0x19160000
  • default framebuffer size: 34MB
  • default cursor bytes: 21MB
  • sum of framebuffer size + cursor bytes: 55MB (i.e. > 32MB)
  1. Booting with default DVMT pre-alloc mem + no framebuffer patches -> KP/freeze
  2. Booting with default DVMT pre-alloc mem + framebuffer size 20MB + cursor bytes 12MB -> KP
  3. Booting with default DVMT pre-alloc mem + framebuffer size 19MB + cursor bytes 9MB -> Ok, full graphics acceleration, no 4K output
  4. Booting with default DVMT pre-alloc mem + framebuffer size 20MB + cursor bytes 10MB -> Ok, full graphics acceleration, no 4K output
  5. Booting with DVMT pre-alloc mem set to 64MB (Grub shell) + no framebuffer patches -> Ok, full graphics acceleration + 4K output
  6. Booting with DVMT pre-alloc mem set to 96MB (Grub shell) + no framebuffer patches -> Ok, full graphics acceleration + 4K output
  • Like 4
  • Thanks 1
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...