본문으로 건너뛰기
피드

RK3588 GPU 안에 숨어있는 Cortex-M7 MCU를 뜯어보고 Rust/gdb/MicroPython까지 올려본 이야기

open-source 약 7분

RK3588의 Mali-G610 GPU 내부에 990MHz로 동작하는 Cortex-M7 MCU가 있으며, 이 펌웨어가 커널 대신 GPU 작업을 관리함. 메모리 접근의 3단 계층 구조, 인터럽트 시스템, 펌웨어 이미지 포맷을 분석하고, 실제로 Rust 정적 라이브러리, gdb 디버깅, MicroPython까지 MCU 위에서 구동하는 과정을 상세히 다룸.

  • 1

    GPU 내장 Cortex-M7 MCU가 최대 990MHz로 동작하며 기존 커널의 GPU 관리 역할을 대체함

  • 2

    메모리 접근은 MPU → MCU 매핑 → GPU MMU 3단 계층을 거치며, MCU는 앞 2개만 제어 가능해 보안상 이점이 있음

  • 3

    5가지 인터럽트 경로(커널↔MCU, 유저스페이스→MCU, GPU→MCU, 타이머)로 시스템 간 통신함

  • 4

    mali_csffw.bin은 GPL-2 라이선스의 20바이트 헤더 기반 펌웨어 포맷임

  • 5

    Rust(정적 라이브러리), gdb(MRI 기반 셀프호스트 디버그), MicroPython을 MCU에서 실행하는 데 성공함

펌웨어가 뭐하는 물건인고

  • RK3588의 Mali-G610 GPU 내부에는 Cortex-M7 (r1p2) MCU가 들어있으며, GPU 클럭을 공유해 최대 990MHz로 동작함. FPU, ECC 캐시, TCM은 없는 구성임
  • 이 펌웨어(mali_csffw.bin)는 기존에 커널이 처리하던 GPU 관련 작업들을 MCU가 대신 처리하도록 넘겨받은 것임. 커맨드 스트림 관리, 전력 관리, 컨텍스트 스위칭 등이 포함됨
  • MCU는 32비트인데 GPU는 48비트 가상 주소 공간 8개를 지원함. 해결책은 MCU가 자기 페이지 테이블을 직접 제어하는 것임

메모리 접근의 3단 구조

  • 메모리 접근 시 MPU → MCU 매핑 → GPU MMU 세 계층을 순서대로 통과해야 함. 각 계층의 역할이 다름
  • MPU: 권한과 L1 캐시 동작을 설정하며, 거의 임의 크기의 리전 16개를 지원함. 폴트 시 MCU 예외가 발생함
  • MCU 매핑: 순수 매핑 전용으로 권한 설정은 불가능하며, 128MiB 크기의 리전 8개를 64MiB 정렬로 제공함. 폴트 없음
  • GPU MMU: 권한, 매핑, L2 캐시, 코히런시를 모두 제어하며, 4KB 페이지 단위로 48비트 주소 공간을 관리함. 폴트는 커널이 처리하고, MCU 주소 공간에서 폴트 발생 시 리셋됨
  • 보안 관점에서 MCU가 제어하는 건 앞의 두 계층뿐이라, 익스플로잇으로도 GPU가 매핑하지 않은 메모리에는 접근 불가함

인터럽트 시스템

  • 커널 → MCU: doorbell을 울려 MCU를 깨움. 펌웨어 초기화, 커맨드 스트림 설정, 전력 관리, protected mode 진입 등에 사용됨
  • MCU → 커널: 커널 요청 처리 완료 알림이나 GPU 작업 완료 시 유저스페이스 스레드를 깨우는 데 사용됨. 에러 시그널링도 이 경로임
  • 유저스페이스 → MCU: 매핑된 doorbell 페이지에 쓰기를 하면 MCU 레지스터가 설정되고 인터럽트가 발생함. GPU에 커맨드 스트림 처리 시작을 알리는 용도임
  • GPU → MCU: 커맨드 스트림 처리 완료 시나, "event add" 같은 에뮬레이션이 필요한 인스트럭션 실행 시 발생함
  • MCU 타이머 인터럽트: 일정 시간 후 코드 실행에 활용됨. 예를 들어 fragment job을 soft-stop해서 다른 컨텍스트에 렌더링 기회를 주는 식임

MMIO와 주요 메모리 영역

  • 0x04000000에 64MiB 영역: 커널과 MCU 간 공유 버퍼로, 상태 변경 요청(커맨드 스트림 그룹 온라인, 레지스터 서스펜드 등)과 tracebuffer 디버그 출력에 사용됨
  • 0x40000000에 256KiB MMIO 영역: GPU 하드웨어 제어용으로, 인터럽트 시그널링, MCU 메모리 매핑 설정, GPU 상태 조회, 커맨드 스트림 프로세서 실행 등을 처리함

펌웨어 이미지 포맷

  • mali_csffw.bin은 20바이트 헤더(버전 정보 + 엔트리 크기)로 시작하고, 그 뒤에 다양한 엔트리가 이어지는 구조임
  • Interface 엔트리: 메모리 섹션을 설정하며, GPU 페이지 테이블용 권한을 지정함. 첫 번째 인터페이스에는 "This firmware image is GPL-2"라는 라벨이 붙어 있어 라이선스 확인이 가능함
  • Tracebuffer 엔트리: MCU가 CPU로 트레이스 데이터를 쓰는 버퍼를 설정함. fwlog(로그 메시지), fwin/fwout(gdb용) 등이 있음
  • 그 외에 Configuration 엔트리(sysfs를 통한 설정 변경), Timeline metadata 엔트리(트레이스 이벤트 정보), Build info metadata 엔트리(git SHA 저장) 등이 존재함
  • ELF에서 변환하는 건 간단하지만, 역방향 변환은 Ghidra로 Arm 펌웨어를 로드하고 싶은 유혹 때문에 일부러 구현하지 않았다고 함. GPU 리버스 엔지니어링 윤리를 지키려는 의도임

MCU에서 이것저것 돌려보기

  • Rust: 언어 자체는 괜찮은데 빌드 툴링이 고통스러웠음. 결국 순수 Rust 펌웨어는 포기하고, Meson에서 Cargo를 호출해 C에서 불러오는 정적 라이브러리로 타협함
  • gdb: Adam Green이 만든 MRI(Armv7-M 셀프 호스트 디버그 기반 gdb 서버)를 활용해 SoC 내장 MCU에서도 gdb 디버깅이 가능함. 다만 패치된 커널이 필요하고, debugfs의 fw_io 파일을 통해 tracebuffer로 통신함
  • watchpoint: Cortex-M의 하드웨어 워치포인트가 비동기적으로 동작해서, 실제 접근 시점보다 몇 인스트럭션 뒤에 예외가 발생함. 사실상 쓸모없음. 대안으로 MPU 리전 접근 차단이나 싱글스테핑을 사용해야 함
  • 크리티컬 섹션: 원자적 연산 대신, ISR이 온스택 컨텍스트 연결 리스트를 순회하며 하위 우선순위 컨텍스트의 일관성을 보장하는 방식을 채택함. Linux의 RSEQ(restartable sequences)와 비슷한 아이디어임
  • MicroPython: MCU에서 동작하며, GPU 컨텍스트 메모리의 tracebuffer를 I/O로 사용함. 실제 Python보다 훨씬 빠르게 시작되고, root 권한이나 패치 커널 없이도 접근 가능함. "일단 Python으로 구현하고 나중에 Rust로 재작성" 전략임
  • 전체 코드는 panFWost git 저장소에 공개되어 있으며, Alyssa Rosenzweig의 도구들이 큰 도움이 되었다고 함

GPU 내부 MCU의 동작 원리를 이 정도로 상세하게 공개한 글은 드묾. 특히 MicroPython으로 프로토타이핑 후 Rust로 재작성하는 전략은 임베디드 펌웨어 개발에서 참고할 만한 접근법임.

댓글

댓글

댓글을 불러오는 중...

open-source

뱀부랩, 오픈소스 슬라이서 개발자에게 법적 압박 걸었다가 역풍 맞음

3D 프린터 제조사 뱀부랩이 OrcaSlicer-BambuLab 개발자에게 중단 요구서를 보내면서 오픈소스와 수리권 커뮤니티의 반발을 샀다. GamersNexus와 Louis Rossmann은 개발자의 허락을 받아 소프트웨어를 다시 호스팅하고, 소송이 걸리면 각각 1만 달러씩 법률 지원을 하겠다고 나섰다.

open-source

OrcaSlicer 포크, Bambu Lab 프린터의 인터넷 연결 기능 되살림

FULU Foundation의 OrcaSlicer-bambulab 포크가 Bambu Lab 프린터에서 LAN 전용 제한 없이 BambuNetwork 기반 인터넷 연결을 다시 지원한다고 밝힘. Windows에서는 WSL 2 설정이 필요하고, Linux에서는 일반 설치만으로 충분하다고 안내함.

open-source

코넬대가 공개한 정확히 2,000줄짜리 교육용 운영체제

코넬대 기반 프로젝트인 egos-2000은 학생이 교육용 운영체제 전체 코드를 직접 읽을 수 있게 만드는 걸 목표로 한다. C, 헤더, 어셈블리, make 파일을 합쳐 정확히 2,000줄이며, QEMU와 RISC-V 보드에서 동작하고 9개 코스 프로젝트가 붙어 있다. 운영체제 수업에서 ‘작지만 전체 구조가 보이는 코드베이스’가 필요했던 사람에게 꽤 반가운 자료다.

open-source

이맥스가 Git 대신 Bazaar를 붙잡았던 6년짜리 오픈소스 드라마

이맥스는 2008년 CVS에서 벗어나면서 Git 대신 GNU 프로젝트인 Bazaar를 선택했고, 이 결정은 성능 벤치마크와 개발자 반발을 압도한 정치적 판단에 가까웠다. Bazaar는 느리고 유지보수도 흔들렸지만, GNU 패키지는 GNU 도구를 써야 한다는 원칙 때문에 전환은 2014년까지 미뤄졌다. 결국 ELPA 브랜치 문제와 Bazaar 개발 중단, 변환 스크립트 준비 끝에 이맥스는 Git으로 옮겨갔다.

open-source

현대차·기아, 오픈소스 특허 방어망 넓혀 소프트웨어 중심 차량 전환 준비

현대차·기아가 오픈소스 소프트웨어 특허 분쟁을 줄이기 위해 글로벌 특허 네트워크 OIN 2.0에 가입했다. 소프트웨어 중심 차량, 클라우드, 커넥티드 서비스처럼 오픈소스 의존도가 큰 영역에서 법적 리스크를 미리 관리하려는 움직임이다.