GPU 메모리 관리 및 스케줄러
Linux GPU 서브시스템의 메모리 관리와 작업 스케줄링을 심층 분석합니다. GEM(Graphics Execution Manager)과 TTM(Translation Table Manager) 메모리 관리, DMA-BUF 기반 디바이스 간 버퍼 공유, GPU 커맨드 서브미션과 fence 동기화, drm_sched 스케줄러, GPUVM 가상 메모리, 전원·클럭 관리, GPU 리셋 및 복구, 커널 설정과 디버깅 방법을 다룹니다.
GEM (Graphics Execution Manager) 메모리 관리
GEM은 GPU 메모리 버퍼 객체를 관리하는 프레임워크입니다. 유저 공간에서는 정수 핸들로 버퍼를 참조하고,
커널은 내부적으로 drm_gem_object로 관리합니다.
/* drm_gem_object 핵심 필드 발췌 (include/drm/drm_gem.h) */
struct drm_gem_object {
struct kref refcount; /* 참조 카운팅 */
unsigned handle_count; /* 유저 핸들 수 */
struct drm_device *dev; /* 소속 디바이스 */
struct file *filp; /* shmem backing store 또는 NULL */
struct drm_vma_offset_node vma_node; /* mmap 오프셋 관리 */
size_t size; /* 버퍼 크기 */
int name; /* flink 이름 (레거시) */
struct dma_buf *dma_buf; /* PRIME export/import 연결점 */
struct dma_buf_attachment *import_attach;
struct dma_resv *resv; /* 공유 fence 컨테이너 */
const struct drm_gem_object_funcs *funcs;
};
/* GEM 오퍼레이션 콜백 */
struct drm_gem_object_funcs {
void (*free)(struct drm_gem_object *obj);
int (*open)(struct drm_gem_object *obj, struct drm_file *file);
void (*close)(struct drm_gem_object *obj, struct drm_file *file);
int (*pin)(struct drm_gem_object *obj);
int (*vmap)(struct drm_gem_object *obj, struct iosys_map *map);
struct sg_table *(*get_sg_table)(struct drm_gem_object *obj);
};
DRM_IOCTL_MODE_CREATE_DUMB는 CPU mmap과 scanout을 위한 최소 공통 경로입니다.
반면 GBM이나 vendor UAPI가 만드는 렌더 타깃 BO는 tiling/modifier, 압축 메타데이터, 엔진별 배치 제약,
수입된 DMA-BUF attachment까지 함께 고려합니다.
GEM 버퍼 생명주기
| 단계 | ioctl / 함수 | 설명 |
|---|---|---|
| 생성 | DRM_IOCTL_MODE_CREATE_DUMB |
비가속 dumb 버퍼 생성 (KMS 전용). 드라이버별 ioctl로 가속 버퍼 생성 |
| 매핑 | DRM_IOCTL_MODE_MAP_DUMB → mmap() |
가짜 오프셋(Offset) 반환 후 mmap으로 유저 공간에 매핑 |
| 공유 | DRM_IOCTL_PRIME_HANDLE_TO_FD |
GEM 핸들을 DMA-BUF fd로 변환하여 다른 디바이스와 공유 |
| 임포트 | DRM_IOCTL_PRIME_FD_TO_HANDLE |
외부 DMA-BUF fd를 로컬 GEM 핸들로 변환 |
| 해제 | DRM_IOCTL_GEM_CLOSE |
핸들 해제. 참조 카운트(Reference Count)가 0이 되면 실제 메모리 반환 |
GEM SHMEM 헬퍼
대부분의 임베디드/모바일 GPU 드라이버는 drm_gem_shmem_object를 사용합니다.
시스템 메모리(shmem)에 버퍼를 할당하며, CMA(Contiguous Memory Allocator) 통합도 지원합니다.
#include <drm/drm_gem_shmem_helper.h>
/* GEM SHMEM 기반 드라이버의 dumb_create 구현 */
static int my_dumb_create(struct drm_file *file,
struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
/* pitch 정렬 (하드웨어 요구사항에 맞춤) */
args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64);
args->size = args->pitch * args->height;
/* shmem 헬퍼가 할당 + 핸들 반환 */
return drm_gem_shmem_dumb_create(file, dev, args);
}
/* 드라이버에서 vmap으로 커널 가상 주소 획득 */
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem_obj);
struct iosys_map map;
drm_gem_shmem_vmap(shmem, &map);
/* map.vaddr로 커널에서 버퍼 접근 */
TTM (Translation Table Manager)
TTM은 전용 VRAM(비디오 메모리)이 있는 GPU를 위한 메모리 관리자입니다. 버퍼를 VRAM과 시스템 메모리 사이에서 이동(eviction/migration)시키는 고급 기능을 제공합니다.
| 메모리 관리자 | 백업 스토리지 | VRAM 지원 | 사용 드라이버 |
|---|---|---|---|
| GEM (shmem) | 시스템 메모리 (shmem/CMA) | 없음 | panfrost, lima, vc4, v3d, virtio-gpu |
| GEM + VRAM helper | 시스템 + VRAM | 단순 | ast, simpledrm, hibmc |
| TTM | 시스템 + VRAM + GART | 전체 (eviction, migration) | amdgpu, nouveau, i915 (부분), vmwgfx, radeon |
/* TTM 메모리 도메인 기술자 */
struct ttm_place {
uint32_t mem_type; /* TTM_PL_SYSTEM, TTM_PL_VRAM, TTM_PL_TT */
uint32_t flags; /* TTM_PL_FLAG_CONTIGUOUS 등 */
uint64_t fpfn; /* 시작 페이지 프레임 번호 */
uint64_t lpfn; /* 끝 페이지 프레임 번호 (0=제한 없음) */
};
/* ttm_buffer_object 핵심 필드 발췌 */
struct ttm_buffer_object {
struct drm_gem_object base; /* GEM 상속 */
struct ttm_device *bdev; /* TTM 디바이스 */
enum ttm_bo_type type;
uint32_t page_alignment;
void (*destroy)(struct ttm_buffer_object *bo);
struct kref kref;
struct ttm_resource *resource; /* 현재 메모리 위치 */
struct ttm_tt *ttm; /* 시스템 메모리 페이지 */
bool deleted;
unsigned priority;
unsigned pin_count;
struct sg_table *sg;
};
/* TTM 메모리 도메인 상수 */
#define TTM_PL_SYSTEM 0 /* 시스템 RAM (커널 관리) */
#define TTM_PL_TT 1 /* GART/GTT 매핑된 시스템 메모리 */
#define TTM_PL_VRAM 2 /* 디바이스 전용 비디오 메모리 */
ttm_place/ttm_placement는 “이번 validate에서 허용할 위치 후보”를 설명하는 정책 객체입니다.
현재 실제 위치는 ttm_buffer_object.resource가 나타내며, TTM은 이 값과 새 placement 후보를 비교해
VRAM↔TT↔SYSTEM migration을 결정합니다.
ttm_device_funcs.evict_flags 콜백으로 퇴거 정책을 설정합니다.
GPU가 해당 버퍼에 접근하면 다시 VRAM으로 마이그레이션됩니다.
DMA-BUF (버퍼 공유)
DMA-BUF는 디바이스 간 버퍼 공유를 위한 커널 프레임워크입니다. GPU에서 렌더링한 버퍼를 디스플레이 컨트롤러, 비디오 인코더, 카메라 등 다른 디바이스와 복사 없이 공유할 수 있습니다.
/* DMA-BUF exporter 오퍼레이션 (드라이버 구현) */
static const struct dma_buf_ops my_dmabuf_ops = {
.attach = my_dmabuf_attach, /* importer 디바이스 등록 */
.detach = my_dmabuf_detach,
.map_dma_buf = my_dmabuf_map, /* sg_table 반환 (DMA 주소) */
.unmap_dma_buf = my_dmabuf_unmap,
.release = my_dmabuf_release, /* 버퍼 해제 */
.mmap = my_dmabuf_mmap, /* 유저 공간 매핑 */
.vmap = my_dmabuf_vmap, /* 커널 가상 주소 매핑 */
};
/* GEM → DMA-BUF export (PRIME) */
struct dma_buf *dmabuf = drm_gem_prime_export(gem_obj, flags);
/* → 유저 공간에서 fd = DRM_IOCTL_PRIME_HANDLE_TO_FD(handle) */
/* DMA-BUF → GEM import (PRIME) */
struct drm_gem_object *obj = drm_gem_prime_import(dev, dmabuf);
/* → 유저 공간에서 handle = DRM_IOCTL_PRIME_FD_TO_HANDLE(fd) */
dma_fence & dma_resv (동기화)
GPU 작업은 비동기로 실행되므로, 버퍼를 공유하는 디바이스들은 작업 완료를 동기화해야 합니다.
| 구조체 | 역할 | 사용 예 |
|---|---|---|
dma_fence |
GPU 작업 하나의 완료를 나타내는 동기화 프리미티브 | GPU 커맨드 서브미션 후 fence 생성 |
dma_resv |
버퍼별 fence 집합 관리 (reservation object) | DMA-BUF에 내장. 읽기/쓰기 fence 추적 |
sync_file |
dma_fence를 유저 공간 fd로 노출 | Explicit sync (Vulkan, Android) |
/* Fence 기본 사용 패턴 */
struct dma_fence *fence;
/* GPU 작업 제출 시 fence 생성 */
fence = my_gpu_submit_job(job);
/* 버퍼의 reservation object에 fence 등록 */
dma_resv_add_fence(bo->base.resv, fence, DMA_RESV_USAGE_WRITE);
/* 다른 디바이스가 이 버퍼를 사용하기 전에 대기 */
ret = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_WRITE,
true, msecs_to_jiffies(5000));
/* Fence 시그널 (GPU 인터럽트 핸들러에서 호출) */
dma_fence_signal(fence);
dma_fence_put(fence);
Implicit Sync vs Explicit Sync
GPU 동기화 모델은 두 가지로 나뉩니다. Linux DRM은 전통적으로 implicit sync를 사용했으나, Vulkan과 Android를 중심으로 explicit sync로 전환하고 있습니다.
| 항목 | Implicit Sync (암시적) | Explicit Sync (명시적) |
|---|---|---|
| fence 관리 | 커널이 dma_resv에 자동 등록/확인 |
유저 공간이 sync_file fd로 직접 관리 |
| KMS 인터페이스 | 커널이 프레임버퍼의 fence를 자동 대기 | IN_FENCE_FD / OUT_FENCE_PTR plane property 사용 |
| 장점 | 유저 공간 구현 단순, 레거시 호환 | 세밀한 동기화 제어, GPU 파이프라인 최적화 가능 |
| 단점 | 불필요한 대기 발생 가능, 최적화 어려움 | 유저 공간 복잡도 증가 |
| 사용 API | OpenGL (EGL), GBM | Vulkan, Android HWC, Wayland explicit sync |
| 커널 구성 | dma_resv + 자동 fence 추적 |
sync_file + SYNC_IOC_MERGE / SYNC_IOC_FILE_INFO |
/* Explicit Sync: KMS IN/OUT fence 사용 */
/* 유저 공간: GPU 렌더링 완료 fence fd를 Plane에 전달 */
drmModeAtomicAddProperty(req, plane_id, IN_FENCE_FD_prop, gpu_fence_fd);
/* 유저 공간: 커밋 완료 fence fd를 받을 위치 지정 */
int64_t out_fence_fd = -1;
drmModeAtomicAddProperty(req, crtc_id, OUT_FENCE_PTR_prop,
(uint64_t)(uintptr_t)&out_fence_fd);
/* Atomic 커밋 */
drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_NONBLOCK |
DRM_MODE_PAGE_FLIP_EVENT, NULL);
/* out_fence_fd에 유효한 fd가 설정됨
* → 다음 렌더링 시작 전에 이 fence를 GPU에 제출하여 대기
* → 완전한 파이프라인 동기화 */
wp_linux_drm_syncobj_v1 계열 프로토콜로 DRM syncobj 기반 explicit sync를 협상할 수 있습니다.
핵심은 “커널 버전 숫자”보다 사용 중인 compositor, Mesa/driver, 커널 UAPI가 모두 syncobj timeline과 KMS fence를 연결할 수 있는지입니다.
즉, explicit sync는 render node 제출 경로와 KMS atomic commit 경로가 같은 fence 언어를 공유할 때 가장 큰 효과를 냅니다.
GPU 커맨드 서브미션
GPU 렌더링 작업은 커맨드 버퍼(command buffer)를 통해 제출됩니다. 유저 공간(Mesa/Vulkan 드라이버)이 GPU 명령어를 버퍼에 기록하고, 커널 드라이버가 이를 GPU 하드웨어에 전달합니다.
서브미션 모델 비교
| 모델 | 드라이버 | ioctl | 특징 |
|---|---|---|---|
| Ring Buffer | i915 (레거시) | I915_GEM_EXECBUFFER2 |
커맨드 버퍼를 링 버퍼(Ring Buffer)에 복사. relocation으로 GPU 주소 패칭 |
| Submit Queue | amdgpu | AMDGPU_CS |
IB(Indirect Buffer) 체인 제출. 다중 엔진(GFX/SDMA/UVD) 지원 |
| Exec Queue | xe (Intel) | DRM_XE_EXEC |
VM-bind 기반. relocation 없음, GPU 페이지 테이블(Page Table) 직접 관리 |
| Submitqueue | msm (Qualcomm) | MSM_GEM_SUBMIT |
우선순위별 큐. faults 지원 (sparse binding) |
| Simple Submit | panfrost, lima | 드라이버별 | drm_sched 기반. 단순 job 제출 |
/* amdgpu 커맨드 서브미션 예시 (유저 공간, libdrm_amdgpu) */
struct amdgpu_cs_request cs_req = {};
struct amdgpu_cs_ib_info ib_info = {
.ib_mc_address = ib_gpu_addr, /* IB의 GPU 가상 주소 */
.size = ib_size_dw, /* 더블워드 단위 크기 */
};
cs_req.ip_type = AMDGPU_HW_IP_GFX; /* GFX 엔진 */
cs_req.number_of_ibs = 1;
cs_req.ibs = &ib_info;
/* 의존 fence 목록 (이전 작업 완료 대기) */
struct amdgpu_cs_fence_info fence_info = { ... };
cs_req.fence_info = fence_info;
/* 서브미션 */
amdgpu_cs_submit(ctx, 0, &cs_req, 1);
/* 완료 대기 (선택적) */
struct amdgpu_cs_fence fence = {
.context = ctx,
.ip_type = AMDGPU_HW_IP_GFX,
.fence = cs_req.seq_no,
};
amdgpu_cs_query_fence_status(&fence, timeout_ns, 0, &expired);
- 커널 드라이버의 커맨드 서브미션 검증 (보안상 중요) */
- 버퍼 오브젝트 유효성 */
- 유저가 전달한 GEM 핸들이 실제 소유인지 확인 */
- BO가 올바른 메모리 도메인에 있는지 확인 */
- 커맨드 파싱 (일부 드라이버) */
- 금지된 GPU 레지스터 접근 차단 */
- 다른 프로세스의 GPU 주소 공간(Address Space) 접근 방지 */
- 최신 GPU는 하드웨어 격리 (per-context page table)로 대체 */
- 의존성 처리 */
- 공유 BO의 dma_resv에서 기존 fence 확인 */
- 의존 fence를 drm_sched_job의 dependency로 등록 */
- 모든 의존 fence가 시그널(Signal)된 후에만 GPU에 제출 */
- fence 등록 */
- 새 작업의 fence를 사용 BO의 dma_resv에 추가 */
- explicit sync: fence를 sync_file fd로 유저에게 반환 */
GPU 스케줄러 (drm_sched)
DRM GPU 스케줄러(drivers/gpu/drm/scheduler/)는 여러 프로세스의 GPU 작업을 우선순위 기반으로 공정하게 스케줄링하고, GPU 행(hang) 감지 시 타임아웃 콜백을 통해 GPU 리셋 및 복구를 처리합니다. drm_sched_entity, drm_sched_job, drm_gpu_scheduler가 핵심 구성 요소입니다.
GPU 가상 메모리 (GPUVM)
현대 GPU는 자체 MMU를 가지며, 프로세스별 독립적인 GPU 가상 주소 공간을 제공합니다.
커널 DRM 프레임워크는 drm_gpuvm(drivers/gpu/drm/drm_gpuvm.c)으로 이를 추상화합니다.
GPU 전원 관리(Power Management)
GPU는 시스템에서 가장 전력을 많이 소비하는 디바이스 중 하나이므로, 정교한 전원 관리가 매우 중요합니다.
| 메커니즘 | 설명 | 커널 인터페이스 |
|---|---|---|
| Runtime PM | GPU 유휴 시 자동 절전. D3cold까지 진입 가능 | pm_runtime_get_sync() / pm_runtime_put_autosuspend() |
| DVFS | Dynamic Voltage and Frequency Scaling. 부하에 따라 클럭/전압 조절 | devfreq 프레임워크 또는 드라이버 자체 구현 |
| Power Gating | 미사용 GPU 블록(셰이더 유닛 등)의 전원을 완전히 차단 | 드라이버별 구현 (HW 의존) |
| Clock Gating | 미사용 블록의 클럭만 차단 (power gating보다 빠른 복구) | 드라이버별 구현 |
| Hybrid GPU | 내장/외장 GPU 전환 (PRIME offload, reverse PRIME) | DRI_PRIME=1 환경 변수, switcheroo sysfs |
# GPU Runtime PM 상태 확인
cat /sys/class/drm/card0/device/power/runtime_status
# active / suspended / suspending
# Runtime PM 자동 절전 지연 설정 (밀리초)
echo 5000 > /sys/class/drm/card0/device/power/autosuspend_delay_ms
# GPU 클럭 주파수 확인 (amdgpu 예시)
cat /sys/class/drm/card0/device/pp_dpm_sclk
# 0: 300Mhz
# 1: 600Mhz *
# 2: 900Mhz
# PRIME GPU 오프로드 (외장 GPU로 렌더링)
DRI_PRIME=1 glxinfo | grep "OpenGL renderer"
# vga_switcheroo 상태 (하이브리드 GPU)
cat /sys/kernel/debug/vgaswitcheroo/switch
GPU 리셋 및 복구
GPU는 잘못된 셰이더, 무한 루프, 하드웨어 결함 등으로 응답 불능(hang) 상태에 빠질 수 있습니다. DRM 프레임워크는 hang 감지, GPU 리셋, 작업 재제출의 3단계 복구 메커니즘을 제공합니다.
Hang 감지
| 메커니즘 | 설명 | 구현 |
|---|---|---|
| 스케줄러 타임아웃 | drm_sched이 job별 타이머(Timer) 설정. 만료 시 timedout_job 콜백 |
대부분의 현대 드라이버 |
| 하드웨어 워치독 | GPU 내부 워치독 타이머가 hang 감지 후 인터럽트(Interrupt) 발생 | amdgpu (UVD/VCE), 일부 ARM GPU |
| Heartbeat | 주기적으로 GPU에 nop 작업 제출 후 완료 확인 | i915 (engine heartbeat) |
| Seqno 모니터링 | GPU가 작업 완료 시 증가시키는 시퀀스 번호를 주기적으로 확인 | 레거시 드라이버 |
리셋 수준
/* GPU 리셋 수준 (세밀한 것부터 거친 순서) */
/* Level 1: Per-engine 리셋 (권장, 최소 영향) */
/* 특정 GPU 엔진(GFX, SDMA, 비디오 등)만 리셋 */
/* 다른 엔진은 계속 동작 */
amdgpu_device_reset_engine(adev, ring); /* amdgpu 예시 */
/* Level 2: Per-context 리셋 (하드웨어 지원 필요) */
/* 특정 GPU 컨텍스트만 무효화 */
/* i915: 잘못된 컨텍스트를 ban (금지) 처리 */
intel_context_ban(ce, NULL);
/* Level 3: 전체 GPU 리셋 */
/* 모든 엔진/컨텍스트 중단 후 GPU 완전 재초기화 */
amdgpu_device_gpu_recover(adev, NULL, false);
/* Level 4: FLR (Function Level Reset) - PCIe */
/* PCIe 레벨에서 디바이스 전체 리셋 */
pci_reset_function(pdev);
/* Level 5: BACO (Bus Active, Chip Off) - AMD */
/* GPU 전원을 완전히 차단 후 재투입 */
amdgpu_device_baco_enter(adev_to_drm(adev));
amdgpu_device_baco_exit(adev_to_drm(adev));
복구 흐름
/* drm_sched 타임아웃 → 복구 흐름 */
/* 1. 타임아웃 콜백 호출 */
static enum drm_gpu_sched_stat
my_timedout_job(struct drm_sched_job *job)
{
struct my_device *dev = job_to_dev(job);
/* 2. GPU 상태 덤프 (디버깅용) */
dev_coredump_snapshot(dev); /* devcoredump 프레임워크 */
/* 3. GPU 리셋 수행 */
my_gpu_reset(dev);
/* 4. 스케줄러에 리셋 완료 통보 */
/* → 대기 중인 fence들을 에러로 시그널 */
/* → guilty 작업의 entity에 guilty 플래그 설정 */
return DRM_GPU_SCHED_STAT_NOMINAL;
}
/* 5. 유저 공간 알림 */
/* - 리셋 후 fence가 에러(-EIO)로 시그널됨 */
/* - Vulkan: VK_ERROR_DEVICE_LOST 반환 */
/* - GL: GL_CONTEXT_LOST 또는 glGetGraphicsResetStatusARB() */
/* - amdgpu: AMDGPU_CTX_QUERY2 ioctl로 리셋 감지 */
- VRAM 콘텐츠: 전체 리셋 시 VRAM 내용이 소실될 수 있음. TTM이 시스템 메모리에 백업한 BO만 복구 가능
- 디스플레이: GPU 리셋 중 화면이 일시적으로 검은색으로 전환될 수 있음 (modeset 재설정 필요)
- 멀티 GPU: SR-IOV 환경에서는 VF(Virtual Function) 리셋이 다른 VF에 영향을 줄 수 있음
- RAS (Reliability): amdgpu는
ras_controller로 ECC 에러 감지 후 수정 불가 에러 시 자동 리셋
# GPU 리셋 관련 sysfs/debugfs
# amdgpu: 수동 GPU 복구 트리거
echo 1 > /sys/kernel/debug/dri/0/amdgpu_gpu_recover
# i915: 엔진 리셋 카운트
cat /sys/kernel/debug/dri/0/i915_reset_info
# devcoredump: GPU 상태 덤프 읽기
cat /sys/class/devcoredump/devcd0/data > gpu_dump.bin
# devcoredump 삭제 (5분 후 자동 삭제)
echo 1 > /sys/class/devcoredump/devcd0/data
# dmesg에서 GPU 리셋 로그 확인
dmesg | grep -i "gpu\|reset\|hang\|timed out"
커널 설정 (Kconfig)
# DRM 핵심 설정
CONFIG_DRM=m # DRM 코어 모듈
CONFIG_DRM_KMS_HELPER=m # KMS 헬퍼 함수
CONFIG_DRM_GEM_SHMEM_HELPER=m # GEM shmem 헬퍼
CONFIG_DRM_SCHED=m # GPU 스케줄러
CONFIG_DRM_TTM=m # TTM 메모리 관리자
CONFIG_DRM_DISPLAY_HELPER=m # DP/HDMI 디스플레이 헬퍼
# 드라이버별 설정
CONFIG_DRM_I915=m # Intel i915
CONFIG_DRM_XE=m # Intel Xe
CONFIG_DRM_AMDGPU=m # AMD GPU
CONFIG_DRM_NOUVEAU=m # NVIDIA (오픈소스)
CONFIG_DRM_PANFROST=m # ARM Mali (Midgard/Bifrost)
CONFIG_DRM_LIMA=m # ARM Mali (Utgard)
CONFIG_DRM_VC4=m # Broadcom VideoCore
CONFIG_DRM_MSM=m # Qualcomm Adreno
CONFIG_DRM_VIRTIO_GPU=m # 가상 GPU (QEMU)
CONFIG_DRM_SIMPLEDRM=y # EFI/BIOS 프레임버퍼
# fbdev 에뮬레이션 (DRM 위에서 /dev/fb0 제공)
CONFIG_DRM_FBDEV_EMULATION=y
# DMA-BUF
CONFIG_DMA_SHARED_BUFFER=y
DRM 디버깅(Debugging)
디버깅 도구
| 도구 | 용도 | 사용법 |
|---|---|---|
modetest |
KMS 오브젝트 나열, 모드 테스트 | modetest -M i915 (libdrm 제공) |
drm_info |
DRM 디바이스 전체 정보 출력 (JSON) | drm_info |
intel_gpu_top |
Intel GPU 엔진별 사용률 모니터링 | intel_gpu_top (intel-gpu-tools) |
umr |
AMD GPU 레지스터 읽기/디코딩 | umr -O bits -r *.mmMC_VM_FB_LOCATION_BASE |
weston-debug |
Wayland compositor 디버깅 | Weston의 DRM backend 로그 |
| debugfs | DRM 내부 상태 확인 | /sys/kernel/debug/dri/0/ |
커널 디버그 메시지
# DRM 디버그 레벨 설정 (비트마스크)
echo 0x1ff > /sys/module/drm/parameters/debug
# 비트마스크 의미:
# 0x001 = DRM_UT_CORE — DRM 코어
# 0x002 = DRM_UT_DRIVER — 드라이버
# 0x004 = DRM_UT_KMS — 모드 설정
# 0x008 = DRM_UT_PRIME — PRIME/DMA-BUF
# 0x010 = DRM_UT_ATOMIC — Atomic modesetting
# 0x020 = DRM_UT_VBL — Vblank
# 0x040 = DRM_UT_STATE — Atomic 상태
# 0x080 = DRM_UT_LEASE — DRM 리스
# 0x100 = DRM_UT_DP — DisplayPort
# 0x200 = DRM_UT_DRMRES — 리소스 관리
# 부팅 시 커널 파라미터로 설정
# drm.debug=0x1e (DRIVER+KMS+PRIME+ATOMIC)
# DRM debugfs 정보 확인
ls /sys/kernel/debug/dri/0/
# clients gem_names name state ...
# GEM 객체 목록 (메모리 사용량 확인)
cat /sys/kernel/debug/dri/0/gem_names
# 현재 KMS 상태 (모든 CRTC/Plane/Connector)
cat /sys/kernel/debug/dri/0/state
# GPU 행(hang) 시 ftrace로 추적
echo 1 > /sys/kernel/debug/tracing/events/drm/enable
cat /sys/kernel/debug/tracing/trace_pipe
dmesg에서"GPU HANG"또는"timed out"메시지 확인- i915:
/sys/kernel/debug/dri/0/i915_gpu_info에서 엔진 상태 덤프(Dump) - amdgpu:
/sys/kernel/debug/dri/0/amdgpu_gpu_recover로 수동 GPU 리셋 - GPU coredump: 일부 드라이버는
devcoredump프레임워크로 GPU 상태 덤프 생성 (/sys/class/devcoredump/)
GPU 성능 프로파일링(Profiling)
| 도구 | 대상 GPU | 측정 항목 | 사용 예 |
|---|---|---|---|
intel_gpu_top |
Intel | 엔진 사용률, 주파수, 전력 | intel_gpu_top -l |
radeontop |
AMD | 파이프라인 사용률, VRAM 사용량 | radeontop -d - |
nvtop |
AMD/Intel/NVIDIA | 프로세스별 GPU 사용률 (htop 스타일) | nvtop |
gpu_metrics |
AMD (sysfs) | 온도, 전력, 주파수, 팬 속도 | cat /sys/class/drm/card0/device/gpu_metrics |
| i915 perf | Intel | EU 효율, 메모리 대역폭, 캐시 히트율 | intel_gpu_frequency -g |
| ftrace | 모든 DRM | drm_vblank, atomic_commit 이벤트 추적 | trace-cmd record -e drm |
# 프레임 드롭 디버깅 — vblank 이벤트 추적
echo 1 > /sys/kernel/debug/tracing/events/drm/drm_vblank_event/enable
echo 1 > /sys/kernel/debug/tracing/events/drm/drm_vblank_event_delivered/enable
cat /sys/kernel/debug/tracing/trace_pipe
# 출력: vblank 시퀀스 번호와 타임스탬프 → 누락된 프레임 확인
# Atomic commit 성능 추적
echo 1 > /sys/kernel/debug/tracing/events/drm/drm_atomic_state/enable
# commit 소요 시간, 포함된 CRTC/Plane 수 확인
# GPU 메모리 사용량 상세 (드라이버별 debugfs)
# amdgpu:
cat /sys/kernel/debug/dri/0/amdgpu_gem_info # 프로세스별 GEM 사용량
cat /sys/kernel/debug/dri/0/amdgpu_vram_mm # VRAM 할당 맵
cat /sys/kernel/debug/dri/0/amdgpu_vm_info # GPU 가상 메모리 통계
# i915:
cat /sys/kernel/debug/dri/0/i915_gem_objects # GEM 객체 통계
cat /sys/kernel/debug/dri/0/i915_frequency_info # GPU 주파수 정보
참고 사항
drivers/gpu/drm/drm_gem*.c— GEM 프레임워크drivers/gpu/drm/ttm/— TTM (Translation Table Manager)drivers/dma-buf/— DMA-BUF 프레임워크drivers/gpu/drm/scheduler/— GPU 스케줄러drivers/gpu/drm/drm_gpuvm.c— GPUVMinclude/drm/— DRM 헤더 파일Documentation/gpu/— 커널 공식 GPU 문서
- DRM Memory Management — GEM, PRIME, VRAM helper, TTM, GPUVA
- DMA-BUF Sharing API — GPU 간 버퍼 공유 프레임워크
- DRM Internals — DRM 코어 내부 API
- Linux GPU Driver Developer's Guide — Introduction
- amdgpu Driver — AMD GPU 드라이버 내부 구조, IP 블록, 전원 관리
- i915 Driver — Intel GPU 드라이버, GuC/HuC, Xe 마이그레이션
- xe Driver — Intel Xe GPU 차세대 드라이버 아키텍처
- Mesa 3D Graphics Library — 오픈소스 GPU 유저스페이스 드라이버
- IGT GPU Tools — DRM/KMS 드라이버 테스트 스위트
- Fence 시그널링 규칙 —
dma_fence는 반드시 유한 시간 내에 시그널되어야 합니다. 무한 대기 fence는 시스템 전체를 교착시킬 수 있습니다 - 메모리 매핑 주의 — GPU VRAM을 WC(Write-Combining)로 매핑할 때 캐시 일관성(Cache Coherency)에 주의.
ioremap_wc()사용 - GPU 리셋 격리 — 하나의 컨텍스트 행이 다른 컨텍스트에 영향을 주지 않도록 per-engine 또는 per-context 리셋 구현 권장
관련 문서
이 주제와 관련된 다른 문서를 더 깊이 이해하고 싶다면 다음을 참고하세요.