kgd_gfx_v12_...cu_occupancy(9)
πΈ 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 withwave_cntand 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. awaitRegMemcommand β.
For each bit that is ON from above:
- 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 π . - If non-zero waves are in flight, store the corresponding doorbell offset of the queue, along with the wave count π.
- 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
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms