kgd_gfx_v12_...cu_occupancy(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

🌸 kgd_gfx_v12_...cu_occupancy(9) πŸ’…

okay bestie, welcome to the Kernel API Manual β€” yes that's the whole manual name, we're fancy like that πŸŽ€. This page is about one function and honestly it's kind of a baddie: it goes digging through registers, peeks at every shader engine, and counts up all the waves your process has floating around. Let's get into it ✨


πŸ‘‘ NAME πŸ‘‘

  • kgd_gfx_v12_get_cu_occupancy β€” this icon reads the relevant registers that live on each shader engine, then aggregates the number of waves that are in flight for the process whose pasid you hand in as a parameter πŸ¦‹. And like, the process could have ZERO or more queues running and submitting waves to compute units β€” zero is a totally valid vibe, no judgment πŸ’œ.

✨ SYNOPSIS ✨

void kgd_gfx_v12_get_cu_occupancy (struct amdgpu_device *adev , struct
kfd_cu_occupancy *cu_occupancy , int *max_waves_per_cu , uint32_t inst
);

🫢 ARGUMENTS 🫢

  • adev β€” the handle of the device you're pulling the number of waves in flight from πŸŽ€. like, which GPU are we snooping on, bestie?
  • cu_occupancy β€” the array that gets filled with wave_cnt and the doorbell offset, so we can do a little comparison later πŸ”₯.
  • max_waves_per_cu β€” an output parameter that gets updated with the maximum number of waves possible per Compute Unit πŸ‘‘. it's giving "the ceiling, the limit, the final boss".
  • inst β€” the xcc's instance number on a multi-XCC setup 🌈. yes, there's more than one, and you gotta say which one, iykyk.

πŸ’€ NOTE πŸ’€

so here's the tea, and it's a lil messy πŸ™ˆ: it's possible that the device has too many queues (oversubscription), and in that case a VMID could get remapped to a different PASID. which could lead to an inaccurate wave count 😭. the high-level sequence goes like this:

  • Time T1: vmid = getVmid; β€” vmid is associated with Pasid P1
  • Time T2: passId = getPasId(vmid); β€” vmid is associated with Pasid P2

in the sequence above, the wave count obtained from time T1 will be incorrectly lost or added to the total wave count πŸ’…. not me crying over a race condition. anyway.

The registers that provide the waves in flight are:

  • SPI_CSQ_WF_ACTIVE_STATUS β€” a bit-map of queues per pipe πŸ¦‹. the bit is ON if a queue is slotted, OFF if there is no queue. a process could have ZERO or more queues slotted and submitting waves to be run on compute units. and even when there is a queue, it is possible there could be zero wave fronts β€” this can happen when the queue is waiting on top-of-pipe events, e.g. a waitRegMem command ⭐.

For each bit that is ON from above:

  1. Read the (SPI_CSQ_WF_ACTIVE_COUNT_0 + queue_idx) register πŸŽ€. it provides the number of waves that are in flight for the queue at that specified index. and the index ranges from 0 to 7 β€” not 8, bestie, 7 πŸ’….
  2. If non-zero waves are in flight, store the corresponding doorbell offset of the queue, along with the wave count πŸ“.
  3. Determine if the queue belongs to the process by comparing the doorbell offset against the process's queues 🌸. if it matches, aggregate the wave count for the process πŸ”₯.
Reading the registers referenced above involves programming GRBM appropriately, so like… don't skip that step, fr fr πŸ’€.

🧚 SEE ALSO 🧚

  • Kernel file ./drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c πŸ’–
  • get_wave_count(9) ✨

and that's the whole page, bestie 🫢! this cutie lives in ./drivers/gpu/drm/amd/amdgpu, dated October 2026, and it's filed under kgd_gfx_v12_...cu_occupancy(9) β€” periodt πŸ’…πŸ‘‘πŸŒˆ

πŸ“¦ where this page comes from