GuC

GuC-specific firmware loader
GuC-based command submission
GuC Firmware Layout

GuC-specific firmware loader

intel_guc_setup — finish preparing the GuC for activity
intel_guc_init — define parameters and fetch firmware
intel_guc_fini — clean up all allocated resources

intel_guc: Top level structure of guc. It handles firmware loading and manages client pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy ExecList submission.

Firmware versioning: The firmware build process will generate a version header file with major and minor version defined. The versions are built into CSS header of firmware. i915 kernel driver set the minimal firmware version required per platform. The firmware installation package will install (symbolic link) proper version of firmware.

GuC address space: GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is 512K. In order to exclude 0-512K address space from GGTT, all gfx objects used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM.

Firmware log: Firmware log is enabled by setting i915.guc_log_level to non-negative level. Log data is printed out via reading debugfs i915_guc_log_dump. Reading from i915_guc_load_status will print out firmware loading status and scratch registers value.

GuC-based command submission

i915_guc_wq_check_space — check that the GuC can accept a request
i915_guc_submit — Submit commands through GuC
gem_allocate_guc_obj — Allocate gem object for GuC usage
gem_release_guc_obj — Release gem object allocated for GuC usage
guc_client_alloc — Allocate an i915_guc_client
intel_guc_suspend — notify GuC entering suspend state
intel_guc_resume — notify GuC resuming from suspend state

i915_guc_client: We use the term client to avoid confusion with contexts. A i915_guc_client is equivalent to GuC object guc_context_desc. This context descriptor is allocated from a pool of 1024 entries. Kernel driver will allocate doorbell and workqueue for it. Also the process descriptor (guc_process_desc), which is mapped to client space. So the client can write Work Item then ring the doorbell.

To simplify the implementation, we allocate one gem object that contains all pages for doorbell, process descriptor and workqueue.

The Scratch registers: There are 16 MMIO-based registers start from 0xC180. The kernel driver writes a value to the action register (SOFT_SCRATCH_0) along with any data. It then triggers an interrupt on the GuC via another register write (0xC4C8). Firmware writes a success/fail code back to the action register after processes the request. The kernel driver polls waiting for this update and then proceeds. See host2guc_action

Doorbells: Doorbells are interrupts to uKernel. A doorbell is a single cache line (QW) mapped into process space.

Work Items: There are several types of work items that the host may place into a workqueue, each with its own requirements and limitations. Currently only WQ_TYPE_INORDER is needed to support legacy submission via GuC, which represents in-order queue. The kernel driver packs ring tail pointer and an ELSP context descriptor dword into Work Item. See guc_add_workqueue_item

GuC Firmware Layout

The GuC firmware layout looks like this:

+-------------------------------+ | guc_css_header | | contains major/minor version | +-------------------------------+ | uCode | +-------------------------------+ | RSA signature | +-------------------------------+ | modulus key | +-------------------------------+ | exponent val | +-------------------------------+

The firmware may or may not have modulus key and exponent data. The header, uCode and RSA signature are must-have components that will be used by driver. Length of each components, which is all in dwords, can be found in header. In the case that modulus and exponent are not present in fw, a.k.a truncated image, the length value still appears in header.

Driver will do some basic fw size validation based on the following rules:

1. Header, uCode and RSA are must-have components. 2. All firmware components, if they present, are in the sequence illustrated in the layout table above. 3. Length info of each component can be found in header, in dwords. 4. Modulus and exponent key are not required by driver. They may not appear in fw. So driver will load a truncated firmware in this case.