Skip to content

Instantly share code, notes, and snippets.

@Brainiarc7
Last active March 30, 2024 16:01
Show Gist options
  • Save Brainiarc7/aa43570f512906e882ad6cdd835efe57 to your computer and use it in GitHub Desktop.
Save Brainiarc7/aa43570f512906e882ad6cdd835efe57 to your computer and use it in GitHub Desktop.
This gist will show you how to tune your Intel-based Skylake, Kabylake and beyond Integrated Graphics Core for performance and reliability through GuC and HuC firmware usage on Linux.

Tuning Intel Skylake and beyond for optimal performance and feature level support on Linux:

Note that on Skylake, Kabylake (and the now cancelled "Broxton") SKUs, functionality such as power saving, GPU scheduling and HDMI audio have been moved onto binary-only firmware, and as such, the GuC and the HuC blobs must be loaded at run-time to access this functionality.

Enabling GuC and HuC on Skylake and above requires a few extra parameters be passed to the kernel before boot.

Instructions provided for both Fedora and Ubuntu (including Debian):

Note that the firmware for these GPUs is often packaged by your distributor, and as such, you can confirm the firmware blob's availability by running:

1. On Fedora:

rpm -ql linux-firmware | fgrep i915

Sample output:

/usr/lib/firmware/i915 
/usr/lib/firmware/i915/bxt_dmc_ver1_07.bin 
/usr/lib/firmware/i915/kbl_dmc_ver1.bin
/usr/lib/firmware/i915/kbl_dmc_ver1_01.bin 
/usr/lib/firmware/i915/skl_dmc_ver1_23.bin 
/usr/lib/firmware/i915/skl_guc_ver1.bin 
/usr/lib/firmware/i915/skl_guc_ver4.bin 
/usr/lib/firmware/i915/skl_guc_ver6.bin 
/usr/lib/firmware/i915/skl_guc_ver6_1.bin 
/usr/share/doc/linux-firmware/LICENSE.i915

2. On Ubuntu:

dpkg -L linux-firmware | fgrep i915

It may be wise to install the linux-firmware-nonfree package as it may contain extra firmware blobs on Ubuntu releases prior to 16.04LTS. Don't install this on 16.04LTS and above.

Now, to the real meat:

See the supported module options:

Let's see if the features we're after are supported:

sudo modinfo i915 | egrep -i "guc|huc|dmc"

firmware:       i915/bxt_dmc_ver1_07.bin
firmware:       i915/skl_dmc_ver1_27.bin
firmware:       i915/kbl_dmc_ver1_04.bin
firmware:       i915/glk_dmc_ver1_04.bin
firmware:       i915/cnl_dmc_ver1_07.bin
firmware:       i915/icl_dmc_ver1_07.bin
firmware:       i915/kbl_guc_ver9_39.bin
firmware:       i915/bxt_guc_ver9_29.bin
firmware:       i915/skl_guc_ver9_33.bin
firmware:       i915/kbl_huc_ver02_00_1810.bin
firmware:       i915/bxt_huc_ver01_8_2893.bin
firmware:       i915/skl_huc_ver01_07_1398.bin
parm:           enable_guc:Enable GuC load for GuC submission and/or HuC load. Required functionality can be selected using bitmask values. (-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load) (int)
parm:           guc_log_level:GuC firmware logging level. Requires GuC to be loaded. (-1=auto [default], 0=disable, 1..4=enable with verbosity min..max) (int)
parm:           guc_firmware_path:GuC firmware path to use instead of the default one (charp)
parm:           huc_firmware_path:HuC firmware path to use instead of the default one (charp)
parm:           dmc_firmware_path:DMC firmware path to use instead of the default one (charp)

Note: The intel_pstate driver is the default since Linux 4.10 on SKL+. Thanks for the updates on this @pcordes and the correction on module options syntax in /etc/modprobe.d/i915.conf, @vinzent. Gr33ts ;-)

Then, update grub on Fedora:

(Run commands as root):

For EFI boot (More common):

grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg

And if you're still booting up in legacy BIOS mode on an MBR-style partitioning scheme or with CSM enabled on Fedora for whatever reason:

grub2-mkconfig -o /boot/grub2/grub.cfg

Then rebuild initramfs:

On Fedora:

dracut --force

On Debian-based distributions:

Simply run:

sudo update-initramfs

update-grub

Then reboot.

Your modern Intel HD Graphics processor graphics will work just fine.

You can also add this to: /etc/modprobe.d/i915.conf

In the following syntax:

options i915 enable_guc=3

Other safe options to pass are enable_fbc=1.

Reference:

See modinfo output for i915 for available GuC options:

modinfo i915 | grep guc

Further notes:

A list of all options along with short descriptions and default values can be generated with the following command:

$ modinfo -p i915

To check which options are currently enabled, run:

# systool -m i915 -av

You will note that many options default to -1, resulting in per-chip power-saving defaults. It is however possible to configure more aggressive powersaving by using module options. Warning: Diverting from the defaults will mark the kernel as tainted from Linux 3.18 onwards. This basically implies using other options than the per-chip defaults is considered experimental and not supported by the developers.

The following set of options should be generally safe to enable:

/etc/modprobe.d/i915.conf

options i915 enable_fbc=1 enable_guc=3

On Linux 4.16+, GuC firmware loading and submission is now handled by the enable_guc parameter in place of the former enable_guc_loading=1 and enable_guc_submission=1 parameters. Adjust as needed.

RC6 sleep modes (enable_rc6):

You can experiment with higher values for enable_rc6, but your GPU may not support them or the activation of the other options:

The available enable_dc values are a bitmask with bit values RC6=1, RC6p=2, RC6pp=4[4] - where "RC6p" and "RC6pp" are lower power states.

To confirm the current running RC6 level, you can look in sysfs:

# cat /sys/class/drm/card0/power/rc6_enable

If the value read is a lower number than expected, the other RC6 level are probably not supported. Passing drm.debug=0xe to the kernel boot options will add DRM debugging information to the kernel log - possibly including a line like this:

[drm:sanitize_rc6_option] Adjusting RC6 mask to 1 (requested 7, valid 1)

Framebuffer compression (enable_fbc):

Framebuffer compression may be unreliable or unavailable on Intel GPU generations before Sandy Bridge (generation 6). This results in messages logged to the system journal similar to this one:

kernel: drm: not enough stolen space for compressed buffer, disabling.

Tear-free video:

With the SNA acceleration method enabled, tearing may be observed. To fix this, enable the "TearFree" option in the driver by adding the following line to your xorg.conf (or ideally, a sub-configuration file under xorg.conf.d) configuration file:

Option "TearFree" "true"

This is not needed on server-grade SKUs where Xorg is unwelcome.

Debugging:

Simply inspect dmesg:

dmesg | grep drm

And also look at the output of:

journalctl -b -o short-monotonic -k

To confirm that the settings you wanted have been applied, run:

dmesg | grep -iE "huc|guc|dmc"

Output may look like this:

[    2.014699] Setting dangerous option enable_guc - tainting kernel
[    2.019971] [drm] Finished loading DMC firmware i915/kbl_dmc_ver1_04.bin (v1.4)
[    2.030651] [drm] HuC: Loaded firmware i915/kbl_huc_ver02_00_1810.bin (version 2.0)
[    2.040648] [drm] GuC: Loaded firmware i915/kbl_guc_ver9_39.bin (version 9.39)
[    2.051850] i915 0000:00:02.0: GuC firmware version 9.39
[    2.051850] i915 0000:00:02.0: GuC submission enabled
[    2.051851] i915 0000:00:02.0: HuC enabled

Which means you're good to go.

You can also take a look at:

  1. GuC load status:
sudo cat /sys/kernel/debug/dri/0/i915_guc_load_status
GuC firmware: i915/kbl_guc_ver9_39.bin
	status: fetch SUCCESS, load SUCCESS
	version: wanted 9.39, found 9.39
	header: offset 0, size 128
	uCode: offset 128, size 147392
	RSA: offset 147520, size 256

GuC status 0x800330ec:
	Bootrom status = 0x76
	uKernel status = 0x30
	MIA Core status = 0x3

Scratch registers:
	 0: 	0xf0000000
	 1: 	0x1
	 2: 	0xc
	 3: 	0x0
	 4: 	0x2
	 5: 	0x0
	 6: 	0x7f2000
	 7: 	0x8
	 8: 	0x3
	 9: 	0x403240
	10: 	0x0
	11: 	0x0
	12: 	0x0
	13: 	0x0
	14: 	0x0
	15: 	0x0
  1. HuC load status:
sudo cat /sys/kernel/debug/dri/0/i915_huc_load_status
 HuC firmware: i915/kbl_huc_ver02_00_1810.bin
	status: fetch SUCCESS, load SUCCESS
	version: wanted 2.0, found 2.0
	header: offset 0, size 128
	uCode: offset 128, size 218304
	RSA: offset 218432, size 256

HuC status 0x00006080:

Also see: https://01.org/linuxgraphics/downloads/firmware

Screen corruption observed when waking up from suspend

This is often observed as font and screen corruption in GTK+ applications (missing glyphs after suspend/resume).

Should you experience missing font glyphs in GTK+ applications, the following workaround might help. Edit /etc/environment to add the following line:

/etc/environment
COGL_ATLAS_DEFAULT_BLIT_MODE=framebuffer

See this bug here for more details.

Thanks and regards,

Brainiarc7

@prodisDown
Copy link

Hi, i don't know about anything and how this stuff should work, but long story short my /etc/modprobe.d/i915.conf
options i915 enable_dc=2 enable_fbc=0
By default enable_fbc was 1, and i decided to turn it off because my CPU was hot as f when i was playing some youtube in 1080p60 or something. I found about this feature and decided to play with it a little and in result my CPU is no more on fire and i wasting less energy in semi-stale situations. Don't know what enable_dc=2 does btw, but it sound good to me and i turned it on too.

Disabling this feature (Framebuffer compression) resulted in no lags in highres video but significantly higher power usage (and lesser °C on CPU) and lesser power usage in stale and browser surfing modes.
i5-8625U with UHD 620. Now my laptop draws down to 5 watts and even 4 watts if i turn down backlight (on max it adds up to +2 watts), and all this with wi-fi on and active internet usage.

@h1ght
Copy link

h1ght commented Jan 7, 2023

@mupuf
hmm i know this is old, dunno if u are still active, can u give us some kind of update if something if this is fixed? or were we can look for known bugs. i fiddle around with it and there is more stuff that doenst seem to work like c-states on package level.

@kev300
Copy link

kev300 commented Jan 7, 2023

I lost all hope that intel is ever going to fix their drivers...
It gets more broken with every new kernel version

@mupuf
Copy link

mupuf commented Jan 8, 2023

@h1ght: Sorry, I don't work at Intel anymore nor do I use any Intel hardware hardware anymore (save a couple of nvme drives).

@kev300: I am not surprised. Hundreds of thousands of man hours have been spent refactoring a driver really not meant for discrete GPUs before finally doing what was needed to do (create a new driver, xe), along with the people the most vocal and active about quality quitting. Everything was foretold years ago, but met with deaf hears.

@kevindd992002
Copy link

When is this going to be fixed? I tried this on a new system (Intel NUC 11) and it's still not loading the proper firmware:

echo "options i915 enable_guc=2" > /etc/modprobe.d/i915.conf

[    3.771239] i915 0000:00:02.0: firmware: direct-loading firmware i915/tgl_dmc_ver2_12.bin
[    3.771701] i915 0000:00:02.0: [drm] Finished loading DMC firmware i915/tgl_dmc_ver2_12.bin (v2.12)
[    3.772206] i915 0000:00:02.0: firmware: failed to load i915/tgl_guc_70.1.1.bin (-2)
[    3.772212] firmware_class: See https://wiki.debian.org/Firmware for information about missing firmware
[    3.772222] i915 0000:00:02.0: firmware: failed to load i915/tgl_guc_70.1.1.bin (-2)
[    3.772226] i915 0000:00:02.0: GuC firmware i915/tgl_guc_70.1.1.bin: fetch failed with error -2
[    3.772229] i915 0000:00:02.0: [drm] GuC firmware(s) can be downloaded from https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915
[    3.772817] i915 0000:00:02.0: [drm] GuC firmware i915/tgl_guc_70.1.1.bin version 0.0
[    3.772833] i915 0000:00:02.0: [drm] GuC is uninitialized
[    3.781715] [drm] Initialized i915 1.6.0 20201103 for 0000:00:02.0 on minor 0
[    3.782541] ACPI: video: Video Device [GFX0] (multi-head: yes  rom: no  post: no)

What am I missing here?

@Jiab77
Copy link

Jiab77 commented Feb 19, 2023

@kevindd992002, sounds like you're missing some firmware files... You can try this project and see if it solves your issue.

@Jiab77
Copy link

Jiab77 commented Feb 19, 2023

@Brainiarc7,

I've just did the required changes except I've used 2 instead of 3 as value for enable_guc and the two commands you're giving to check the status does not work anymore:

$ sudo cat /sys/kernel/debug/dri/0/i915_guc_load_status
cat: /sys/kernel/debug/dri/0/i915_guc_load_status: No such file or directory

$ sudo cat /sys/kernel/debug/dri/0/i915_huc_load_status
cat: /sys/kernel/debug/dri/0/i915_huc_load_status: No such file or directory

But I've found something equivalent:

$ sudo cat /sys/kernel/debug/dri/0/i915_gpu_info
Kernel: 5.15.0-60-generic x86_64
Driver: 20201103
Time: 1676850545 s 362798 us
Boottime: 606 s 323519 us
Uptime: 604 s 787730 us
Capture: 4295043846 jiffies; 0 ms ago
Reset count: 0
Suspend count: 0
Platform: SKYLAKE
Subplatform: 0x0
PCI ID: 0x193b
PCI Revision: 0x09
PCI Subsystem: 8086:2064
IOMMU enabled?: 0
DMC loaded: yes
DMC fw version: 1.27
RPM wakelock: yes
PM suspended: no
GT awake: no
EIR: 0x00000000
IER: 0x08080000
GTIER[0]: 0x09090909
GTIER[1]: 0x09090909
GTIER[2]: 0x80000000
GTIER[3]: 0x00000909
PGTBL_ER: 0x00000000
FORCEWAKE: 0xffff0001
DERRMR: 0x2077efef
  fence[0] = 00000000
  fence[1] = 00000000
  fence[2] = 00000000
  fence[3] = 00000000
  fence[4] = 00000000
  fence[5] = 00000000
  fence[6] = 00000000
  fence[7] = 00000000
  fence[8] = 00000000
  fence[9] = 00000000
  fence[10] = 00000000
  fence[11] = 00000000
  fence[12] = 00000000
  fence[13] = 00000000
  fence[14] = 00000000
  fence[15] = 00000000
  fence[16] = 00000000
  fence[17] = 00000000
  fence[18] = 00000000
  fence[19] = 00000000
  fence[20] = 00000000
  fence[21] = 00000000
  fence[22] = 00000000
  fence[23] = 00000000
  fence[24] = 00000000
  fence[25] = 00000000
  fence[26] = 00000000
  fence[27] = 00000000
  fence[28] = 00000000
  fence[29] = 00000000
  fence[30] = 00000000
  fence[31] = 00000000
ERROR: 0x00000000
DONE_REG: 0x07ffffff
FAULT_TLB_DATA: 0x00000011 0xbe6b88de
GTT_CACHE_EN: 0xf0007fff
GuC firmware: i915/skl_guc_62.0.0.bin
	status: RUNNING
	version: wanted 62.0, found 62.0
	uCode: 199168 bytes
	RSA: 256 bytes
HuC firmware: i915/skl_huc_2.0.0.bin
	status: RUNNING
	version: wanted 2.0, found 2.0
	uCode: 135936 bytes
	RSA: 256 bytes
global --- GuC log buffer = 0x00000000 007ef000
:cg@6I5f*i4Mr4dR*BQ;RZk^D"E/+R?:0+`W1(jZIXfl,`e?Q6+5mtUCr"KIVpUdq!mOQW?Y8uH)d1)uI&jj4)''d'"Y?e$sHm6I7!!!#[$p3pnDiHfYBZ6=+fV]06LbNg]Bti?.e'G;FCsMI_(.m%]^V>'31A+W%qqpR`!!!!*zzzzzzzzzzzzzzzz^]4?7,QN1@!8/`5
available engines: 40f
slice total: 3, mask=0007
subslice total: 9
slice0: 3 subslices, mask=00000007
slice1: 3 subslices, mask=00000007
slice2: 3 subslices, mask=00000007
EU total: 72
EU per subslice: 8
has slice power gating: yes
has subslice power gating: no
has EU power gating: yes
slice0: 3 subslice(s) (0x00000007):
	subslice0: 8 EUs (0xff)
	subslice1: 8 EUs (0xff)
	subslice2: 8 EUs (0xff)
	subslice3: 0 EUs (0x0)
slice1: 3 subslice(s) (0x00000007):
	subslice0: 8 EUs (0xff)
	subslice1: 8 EUs (0xff)
	subslice2: 8 EUs (0xff)
	subslice3: 0 EUs (0x0)
slice2: 3 subslice(s) (0x00000007):
	subslice0: 8 EUs (0xff)
	subslice1: 8 EUs (0xff)
	subslice2: 8 EUs (0xff)
	subslice3: 0 EUs (0x0)
graphics version: 9
media version: 9
display version: 9
gt: 4
iommu: disabled
memory-regions: 5
page-sizes: 11000
platform: SKYLAKE
ppgtt-size: 48
ppgtt-type: 2
dma_mask_size: 39
is_mobile: no
is_lp: no
require_force_probe: no
is_dgfx: no
has_64bit_reloc: yes
gpu_reset_clobbers_display: no
has_reset_engine: yes
has_global_mocs: no
has_gt_uc: yes
has_l3_dpf: no
has_llc: yes
has_logical_ring_contexts: yes
has_logical_ring_elsq: no
has_mslices: no
has_pooled_eu: no
has_rc6: yes
has_rc6p: no
has_rps: yes
has_runtime_pm: yes
has_snoop: no
has_coherent_ggtt: yes
unfenced_needs_alignment: no
hws_needs_physical: no
cursor_needs_physical: no
has_cdclk_crawl: no
has_dmc: yes
has_ddi: yes
has_dp_mst: yes
has_dsb: no
has_dsc: no
has_fbc: yes
has_fpga_dbg: yes
has_gmch: no
has_hdcp: yes
has_hotplug: yes
has_hti: no
has_ipc: yes
has_modular_fia: no
has_overlay: no
has_psr: yes
has_psr_hw_tracking: yes
overlay_needs_physical: no
supports_tv: no
rawclk rate: 24000 kHz
Has logical contexts? yes
scheduler: 1f
i915.vbt_firmware=(null)
i915.modeset=-1
i915.lvds_channel_mode=0
i915.panel_use_ssc=-1
i915.vbt_sdvo_panel_type=-1
i915.enable_dc=-1
i915.enable_fbc=1
i915.enable_psr=-1
i915.psr_safest_params=no
i915.enable_psr2_sel_fetch=no
i915.disable_power_well=1
i915.enable_ips=1
i915.invert_brightness=0
i915.enable_guc=2
i915.guc_log_level=-1
i915.guc_firmware_path=(null)
i915.huc_firmware_path=(null)
i915.dmc_firmware_path=(null)
i915.mmio_debug=0
i915.edp_vswing=0
i915.reset=3
i915.inject_probe_failure=0
i915.fastboot=-1
i915.enable_dpcd_backlight=-1
i915.force_probe=
i915.fake_lmem_start=0
i915.request_timeout_ms=20000
i915.enable_hangcheck=yes
i915.load_detect_test=no
i915.force_reset_modeset_test=no
i915.error_capture=yes
i915.disable_display=no
i915.verbose_state_checks=yes
i915.nuclear_pageflip=no
i915.enable_dp_mst=yes
i915.enable_gvt=no

And you can filter it to just get the guc and huc status that way:

$ sudo cat /sys/kernel/debug/dri/0/i915_gpu_info | grep -i "firmware:" -A1
GuC firmware: i915/skl_guc_62.0.0.bin
	status: RUNNING
--
HuC firmware: i915/skl_huc_2.0.0.bin
	status: RUNNING

Just found on the ArchWiki page that the right commands are:

$ sudo cat /sys/kernel/debug/dri/0/gt/uc/guc_info
GuC firmware: i915/skl_guc_62.0.0.bin
	status: RUNNING
	version: wanted 62.0, found 62.0
	uCode: 199168 bytes
	RSA: 256 bytes

GuC status 0x800330ec:
	Bootrom status = 0x76
	uKernel status = 0x30
	MIA Core status = 0x3

Scratch registers:
	 0: 	0xf0000000
	 1: 	0x0
	 2: 	0x1021000
	 3: 	0x1022000
	 4: 	0x40
	 5: 	0x1004
	 6: 	0x0
	 7: 	0x0
	 8: 	0x0
	 9: 	0x0
	10: 	0x0
	11: 	0x0
	12: 	0x0
	13: 	0x0
	14: 	0x0
	15: 	0x0

GuC log relay not created

$ sudo cat /sys/kernel/debug/dri/0/gt/uc/huc_info
HuC firmware: i915/skl_huc_2.0.0.bin
	status: RUNNING
	version: wanted 2.0, found 2.0
	uCode: 135936 bytes
	RSA: 256 bytes
HuC status: 0x00006080

Hope it can be helpful to someone else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment