Chapter 23

프로파일: RVA23과 호환성

RISC-V에는 비준된 확장만 해도 수십 개가 있다. 칩마다 고른 조합이 다르면 운영체제 배포판은 어느 조합에 맞춰 바이너리를 만들어야 할지 알 수 없다. 프로파일은 “이 이름을 단 하드웨어라면 이 확장들은 반드시 있다”고 약속하는 묶음이다. 이 장에서는 RVI20·RVA20·RVA22·RVA23·RVB23 프로파일이 무엇을 필수로 정했는지 규격 원문 그대로 정리하고, 소프트웨어가 실행 중에 기능을 알아내는 방법과 배포판이 프로파일을 받아들이는 현황까지 살펴본다.

왜 프로파일이 필요한가: 조합 폭발

2장에서 본 것처럼 RISC-V는 작은 베이스 위에 확장을 골라 얹는 모듈식 ISA다. 마이크로컨트롤러는 RV32IMC만으로 충분하고, 서버 칩은 벡터와 하이퍼바이저까지 갖춘다. 필요한 것만 고를 수 있다는 점은 하드웨어 입장에서는 큰 장점이다. 그런데 소프트웨어 입장에서는 골칫거리가 된다.

확장이 N개 있으면 가능한 조합은 대략 2N가지다. 확장 40개면 조합은 1조 개를 넘는다. 리눅스 배포판은 패키지 수만 개를 미리 컴파일해서 나눠 주는데, 어느 조합을 가정하고 컴파일해야 할까? 너무 적게 가정하면(예: RV64I만) 곱셈 명령조차 못 쓰는 느린 바이너리가 되고, 너무 많이 가정하면 그 확장이 없는 칩에서 잘못된 명령 예외로 죽는다.

프로파일이 없다면 칩 Arv64imac_zba 칩 Brv64gc_zbb_zicond 칩 Crv64gcv_zfh 배포판 빌드 담당자 “어느 조합에 맞춰 컴파일하지?” ? 확장 N개 → 조합 약 2ᴺ 가지 최소 공통분모(RV64I)로 가면 느리고, 욕심내면 죽는다 프로파일이 있다면 칩 XRVA23 ✓ 칩 YRVA23 ✓ 칩 ZRVA23 ✓ RVA23U64 필수 확장 목록이라는 약속 바이너리 한 벌 세 칩 모두에서 그대로 돈다
그림 23-1. 프로파일이 푸는 문제. 왼쪽처럼 칩마다 확장 조합이 제각각이면 미리 컴파일된 바이너리를 나눠 주는 배포판은 기준을 잡을 수 없다. 오른쪽처럼 하드웨어가 “RVA23을 만족한다”고 약속하면 소프트웨어는 그 목록만 믿고 한 벌의 바이너리를 만든다.

그래서 RISC-V International은 프로파일(profile)을 정했다. 프로파일은 새 명령어를 만들지 않는다. 이미 비준된 확장 중에서 무엇이 반드시 있어야 하는지(필수), 무엇은 있을 수도 있어 소프트웨어가 대비해야 하는지(선택)를 이름 하나로 묶을 뿐이다. 길고 다루기 힘든 ISA 문자열(예: rv64imafdcv_zicsr_zifencei_zba_zbb_…)을 짧은 이름 하나로 줄여 주는 효과도 있다.

규격 원문에서
“This flexibility can be used to highly optimize a specialized design by including only the exact set of ISA features required for an application, but the same flexibility also leads to a combinatorial explosion in possible ISA choices. Profiles specify a much smaller common set of ISA choices that capture the most value for most users …”

RISC-V Profiles v1.0, Introduction — 유연함이 곧 조합 폭발로 이어진다는 점을 규격 스스로 인정하고, 그 해법으로 프로파일을 내놓는다.

프로파일은 금지 목록이 아니다

프로파일은 확장을 마음대로 조합하거나 사용자 정의 확장을 넣는 것을 막지 않는다. 다만 그런 조합에는 “널리 퍼진 소프트웨어 지원과 하드웨어 사이의 이식성”을 기대하지 말라는 것이다. 딥 임베디드처럼 소프트웨어를 한 회사가 전부 직접 빌드하는 시장에서는 여전히 자유로운 조합이 맞다.

프로파일 이름 읽기

프로파일 이름은 정해진 순서로 이어 붙인 문자열이다. 규격은 RV 접두어, 계열(family) 이름, 연도, 특권 모드, XLEN의 다섯 부분으로 정의한다.

RV A 23 U 64 접두어RISC-VISA 문자열과 같은RV로 시작한다 계열I 범용 비특권A 응용 프로세서B 맞춤형 응용계열은 1년에 최대 한 번 연도2000년 이후 햇수2019년 비준 규격 기반→ 20발표 연도가 아님! 특권 모드U 사용자S 슈퍼바이저M 머신가장 높은 모드 XLEN32 또는 64베이스 RV32I /RV64I 를 가리킨다
그림 23-2. 프로파일 이름 RVA23U64의 구조. 연도 자리는 그 프로파일이 바탕으로 삼은 규격이 비준된 해를 기준으로 한다. 규격은 “2019년에 비준된 규격에 기반한 프로파일은 20”이라고 예를 든다. 하이퍼바이저 지원은 특권 모드 글자로 표시하지 않고 확장(옵션 또는 필수)으로 다룬다.
계열규격이 밝힌 대상정의된 프로파일
I범용 비특권 명령어(generic unprivileged instructions). 툴체인의 최소 공통 목표RVI20U32, RVI20U64
A리치 OS를 돌리는 64비트 응용 프로세서(application processors running rich OS stacks). 바이너리 배포 시장RVA20U64/S64, RVA22U64/S64, RVA23U64/S64
B리치 OS를 돌리되 보통 표준 OS 소스를 직접 맞춤 빌드해 쓰는 맞춤형 64비트 응용 프로세서(customized application processors)RVB23U64/S64
B는 무엇의 약자인가?

RVB23 규격은 B라는 글자를 따로 풀어 쓰지 않는다. 규격 본문은 RVB를 “리치 OS를 돌리지만 대개 표준 OS 소스를 맞춤 빌드해서 쓰는 맞춤형 응용 프로세서”용이라고 설명하고, docs.riscv.org 목록은 “임베디드·엣지(Embedded and edge)” 프로파일이라고 소개한다. 비트 조작 확장 B(14장)와는 아무 관계가 없다. 또 처음 정의된 이름 규칙 문서는 계열 글자의 예로 I·M·A를 들지만, 2026년 현재 비준된 계열은 I·A·B뿐이다.

U 프로파일과 S 프로파일

특권 모드 글자는 “그 실행 환경에서 가장 높은 특권 모드”를 뜻한다. U64 프로파일은 응용 프로그램이 보는 세계, S64 프로파일은 운영체제 커널이 보는 세계다. S 프로파일은 U 모드도 포함하므로 U 모드에서 ecall을 하면 S 모드 처리기로 가는 contained 트랩이 되고, S 모드에서 ecall을 하면 바깥 실행 환경(펌웨어, 22장의 SBI)으로 나가는 requested 트랩이 된다(1장의 트랩 분류).

RVA23U64 가 묘사하는 세계 응용 프로그램 (U 모드) ecall requested 트랩 실행 환경 (리눅스 사용자 ABI 등) 프로파일이 정하지 않는 바깥 RVA23S64 가 묘사하는 세계 응용 (U 모드) ecall contained 트랩 커널 (S 모드) — ecall requested 트랩 실행 환경 (SBI · M 모드 펌웨어) 어떤 ecall 이 있는지는 프로파일 밖
그림 23-3. U 프로파일과 S 프로파일. 점선 테두리 안이 프로파일이 정하는 범위다. 프로파일은 바깥 실행 환경이 어떤 ecall 서비스를 주는지는 정하지 않고, 그것은 리눅스 사용자 ABI나 SBI 같은 별도 인터페이스의 몫으로 남긴다.
U 프로파일은 S 프로파일의 부분 집합이 아니다

규격은 “U 모드 프로파일의 명령은 모두 사용자 모드에서 실행되지만, S 모드 프로파일 안의 사용자 모드 명령과 동작이 다를 수 있으므로 U 모드 프로파일을 S 모드 프로파일의 부분 집합으로 볼 수 없다”고 못 박는다. 예를 들어 같은 ecall이라도 어느 쪽 환경이냐에 따라 트랩이 가는 곳이 다르다. 대신 더 높은 특권의 프로파일을 갖춘 플랫폼은 그 위에 OS를 올려 같은 계열의 낮은 특권 프로파일 환경을 언제나 만들어 줄 수 있다.

ISA 문자열과의 관계

프로파일 이름은 ISA 이름 문자열 안에 그대로 넣을 수 있게 설계되었다. 그래서 규격은 “프로파일 이름 규칙과 겹치는 이름의 표준 확장은 만들지 않는다”고 약속한다. 실제로 최근 Clang과 GCC는 -march=rva23u64처럼 프로파일 이름을 아키텍처 값으로 받는다. 한편 프로파일과 함께 등장한 Ziccif, Za64rs, Svade 같은 이름은 새 기능이 아니라 원래 규격에 있던 성질에 이름만 붙인 “프로파일 정의 확장(profile-defined extensions)”이다. 이름이 있어야 필수 목록에 적을 수 있기 때문이다.

필수와 선택: 네 종류의 옵션

모든 프로파일은 비준된 베이스 ISA(지금은 RV32I 또는 RV64I) 하나와, 비준된 확장들을 두 범주로 나눠 담는다.

목록에 없는 확장은 비프로파일 확장이다. 프로파일과 충돌하지 않는 비프로파일 확장(예: 사용자 정의 X 확장 일부)을 더 넣어도 여전히 그 프로파일과 호환이지만, 필수 확장의 동작을 바꾸거나 충돌하는 확장을 넣으면 호환이 아니다. 대표적인 예가 Zfinx 계열이다. 부동소수점 값을 정수 레지스터에 두는 이 확장(12장)은 F·D를 필수로 하는 RVA 프로파일과 함께 쓸 수 없다고 규격에 적혀 있다.

RVA23 규격의 근거(rationale) 절은 선택 확장을 성격에 따라 네 종류로 나눈다. RVA23U64는 실제 옵션 목록을 이 네 제목 아래 적어 두었다.

🌐 지역 옵션 (localized)

지정학·관할 지역에 따라 쓰임이 반드시 달라지는 것. 대표가 암호다. 앞으로도 늘 선택으로 남는다. RVA23U64: Zvkng, Zvksg

🛠️ 개발 옵션 (development)

지금은 수명 초기라 선택이지만 다음 세대 RVA에서 필수가 될 확장. “우선 개발하라”는 신호다. RVA23U64: Zabha, Zacas, Ziccamoc, Zvbc, Zama16b

📦 확장 옵션 (expansion)

구현 비용이 크지만 모든 플랫폼에 필요하지는 않고, 탐지로 쉽게 다룰 수 있는 것. 계속 옵션으로 남는다. RVA23U64: Zfh, Zbc, Zicfilp, Zicfiss, Zvfh, Zfbfmin, Zvfbfmin, Zvfbfwma / RVA23S64: Sv48, Sv57, Zkr, Svadu, Sdtrig, Ssstrict, Svvptc, Sspm

⏳ 과도기 옵션 (transitory)

필수·지역·확장 중 어디로 갈지, 아예 빠질지 아직 모르는 것. 언젠가 빠질 수 있다는 신호다. 규격은 벡터 암호가 준비되기 전까지 스칼라 암호를 이 방식으로 허용했다고 설명한다. RVA23에는 과도기 옵션이 없다.

비프로파일 확장 — 사용자 정의 X 확장, 프로파일 이후에 나온 확장 … 충돌 → 호환 아님Zfinx · Zdinx · Zhinx 프로파일 RVA23U64 필수 (profile mandates) 베이스 RV64I M A F D C B V Zicsr … Zicond Zfa Zcb Zawrs Supm … 소프트웨어가 늘 있다고 가정 지역 옵션Zvkng · Zvksg늘 선택으로 남음 개발 옵션Zacas · Zabha · Zvbc …→ 다음 RVA에서 필수 예정 확장 옵션Zfh · Zicfilp · Zvfh …탐지해서 쓰는 큰 기능 과도기 옵션RVA23 에는 없음언젠가 빠질 수 있음 다음 세대에서 필수로 승격
그림 23-4. 한 프로파일 안의 구조. 필수(파랑) 바깥에 성격이 다른 네 종류의 옵션이 있고, 그 밖은 비프로파일 확장이다. 금색 점선은 개발 옵션이 다음 세대에서 필수로 옮겨 가는 길이다. 실제로 RVA22에서 옵션이던 V가 RVA23에서 필수가 되었다.
옵션은 묶음 단위다

여러 확장으로 이루어진 옵션은 구성 확장이 전부 있어야 그 옵션을 갖춘 것으로 본다. RVA22 규격의 예로, Zbkb는 Zkn 옵션의 구성 요소이지만 그것만 따로는 프로파일 옵션이 아니다. 옵션의 단위를 크게 잡는 것은 소프트웨어가 대비해야 할 조합의 수를 줄이기 위해서다.

RVI20 → RVA20 → RVA22 → RVA23

지금까지 비준된 프로파일 문서는 두 묶음이다. 2023년 4월 2일 날짜의 RISC-V Profiles v1.0이 RVI20·RVA20·RVA22를, 2024년 10월 17일 날짜의 RVA23 v1.0과 RVB23 v1.0이 각각 RVA23과 RVB23을 정의한다. 아래 표는 사용자 모드(U64) 프로파일의 필수·선택 확장을 규격 원문 그대로 옮긴 것이다.

확장RVI20U64RVA20U64RVA22U64RVA23U64RVB23U64
RV64I (베이스)필수필수필수필수필수
M · A · F · D · C선택필수필수필수필수
Zicsr · Zicntr선택¹필수필수필수필수
Zihpm선택선택필수필수필수
Zifencei선택—²—²—²—²
Ziccif · Ziccrse · Ziccamoa · Zicclsm—필수필수필수필수
Za128rs → Za64rs—Za128rsZa64rsZa64rsZa64rs
Zihintpause——필수필수필수
Zba · Zbb · Zbs (= B)——필수필수필수
Zic64b · Zicbom · Zicbop · Zicboz——필수필수필수
Zkt——필수필수필수
Zfhmin——필수필수선택
Zfh——선택선택선택
V——선택필수 (신규)선택
Zvfhmin · Zvbb · Zvkt———필수 (신규)선택
Zihintntl · Zicond · Zimop · Zcmop———필수 (신규)필수
Zcb · Zfa · Zawrs———필수 (신규)필수
Supm———필수 (신규)선택
Zkn · Zks (스칼라 암호)——선택—선택
Zvkng · Zvksg (벡터 암호)———선택선택
Zacas · Zabha · Zvbc———선택선택
Zicfilp · Zicfiss (CFI)———선택선택

¹ RVI20에서 Zicsr는 단독으로는 지원되지 않고 Zicntr나 F와 함께 들어온다. ² Zifencei는 U64 프로파일의 옵션이 아니다. 여러 하트가 도는 환경에서는 fence.i 하나로 명령어 캐시를 맞출 수 없으므로 OS 호출(리눅스의 __riscv_flush_icache)을 쓰라는 이유다. 대신 모든 S64 프로파일에서는 필수다. 이 밖에 RVI20·RVA 모든 프로파일에서 fence.tso는 베이스의 일부로 필수다.

EXPLORER

프로파일 상위 집합 탐색기

단계
자동 재생
이 단계의 필수 확장 수0
이전 단계보다 늘어난 수0
단계를 RVI20U64부터 차례로 눌러 보자. 안쪽 상자가 바깥 상자에 그대로 들어 있다는 것은 “RVA23U64를 만족하는 하드웨어는 RVA22U64·RVA20U64·RVI20U64용 바이너리도 실행한다”는 뜻이다. B는 Zba·Zbb·Zbs 세 개로 풀어서 셌다.
2019베이스·IMAFDQC 비준→ 이름의 “20” 2023.04Profiles v1.0RVI20 · RVA20 · RVA22 2024.04Ubuntu 24.04 LTSRVA20 하드웨어 대상 2024.10RVA23 · RVB23 v1.0V·H 필수화(RVA23) 2025.08Debian 13 riscv64공식 아키텍처, RV64GC 기준 2025.10Ubuntu 25.10RVA23 기준으로 상향 2026RVA23 SoC 출하SpacemiT K3 · Linux 7.0
그림 23-5. 프로파일 규격과 생태계의 연표. 규격 날짜는 docs.riscv.org 문서 머리말 기준이고, 배포판·하드웨어 항목은 각 프로젝트의 발표를 따랐다(자세한 내용과 주의점은 이 장 끝의 생태계 현황 절).

RVA23 자세히 보기

RVA23은 지금까지의 프로파일 중 가장 큰 도약이다. 규격은 목표를 분명히 적는다. 바이너리 소프트웨어 생태계가 넓은 필수 집합과 소수의 굵직한 옵션에 기댈 수 있게 하는 것이며, “최소 기능만 두고 잘게 쪼갠 확장을 많이 허용해 하드웨어 자유도를 높이는 것은 명시적으로 목표가 아니다”라고 한다.

RVA23U64에서 새로 필수가 된 것

확장내용이 책
V벡터 확장. RVA22U64에서는 옵션이었다15장
Zvfhmin벡터 반정밀도(FP16) 최소 지원 — 변환 위주15장
Zvbb · Zvkt벡터 기본 비트 조작 · 벡터 데이터 독립 실행 시간14장
Zihintntl비시간적(non-temporal) 지역성 힌트16장
Zicond정수 조건 연산 czero.eqz · czero.nez16장
Zimop · Zcmopmay-be-operations: 나중 확장을 위해 예약된, 지금은 무해한 명령16장
Zcb추가 압축 명령어13장
Zfa추가 부동소수점 명령어12장
Zawrs예약 집합 대기(wait-on-reservation-set) 명령10장
Supm포인터 마스킹 — 실행 환경이 최소 PMLEN=0과 PMLEN=7을 고를 수단을 제공20장

RVA23S64: 하이퍼바이저가 필수

RVA23S64는 특권 규격 1.13(Ss1p13)을 바탕으로 하고, RVA23U64의 모든 필수 확장에 Zifencei와 다음 특권 확장을 더한다. RVA22S64에서 이어진 것은 Svbare, Sv39, Svade, Ssccptr, Sstvecd, Sstvala, Sscounterenw, Svpbmt, Svinval이고, 새로 필수가 된 것은 다음과 같다.

규격 원문에서
“The RVA23 profiles are intended to align implementations of RISC-V 64-bit application processors to allow binary software ecosystems to rely on a large set of guaranteed extensions and a small number of discoverable coarse-grain options.”

RVA23 Profile v1.0, RVA23 Profiles — “넓은 필수, 적고 굵은 옵션”이 RVA23 설계의 한 줄 요약이다.

Ssstrict와 게스트 가상 머신

RVA23S64의 확장 옵션 Ssstrict는 “표준·예약 인코딩 공간의 미구현 opcode나 CSR에 접근하면 반드시 S 모드로 가는 잘못된 명령 예외가 된다”는 성질에 붙인 이름이다(사용자 정의 공간은 해당하지 않는다). 규격은 RVA23의 필수·옵션이 하이퍼바이저 위의 게스트 VM에는 적용되지 않는다고도 밝힌다. RVA23 하이퍼바이저는 RVA23 호환 게스트를 줄 수도, H가 없거나 RVA20 수준인 게스트를 줄 수도 있다.

RVB23: 같은 뼈대, 더 많은 옵션

RVB23은 RVA23과 같은 날 비준되었다. 목표가 다르다. RVA는 여러 회사의 칩에서 같은 바이너리 커널과 응용을 돌리는 것이 목표지만, RVB는 “다양한 바이너리 배포판을 지원하는 단일 표준 인터페이스를 제공하는 것이 명시적으로 목표가 아니다”. 그래서 비용이 큰 기능은 옵션으로 돌린다.

RVA23U64 필수 RVB23U64 필수 RV64I M A F D C B Zicsr Zicntr Zihpm Ziccif Ziccrse Ziccamoa Zicclsm Za64rs Zihintpause Zic64b Zicbom Zicbop Zicboz Zkt Zihintntl Zicond Zimop Zcmop Zcb Zfa Zawrs RVA23U64 의 부분 집합 RVA23 에만 필수 (RVB23 에서는 확장 옵션) V Zfhmin Zvfhmin Zvbb Zvkt Supm S64: Ssnpm · Sha(H) 도 RVB 에선 옵션 RVB23 에만 있는 옵션 지역(localized) 옵션 Zvkg Zvknc · Zvksc Zkn · Zks 벡터가 옵션이라 스칼라 암호를 남겼고, 값싼 carry-less 곱셈판 벡터 암호도 허용한다
그림 23-6. RVB23U64와 RVA23U64. RVB23U64의 필수 집합은 RVA23U64 필수 집합에서 벡터 확장 네 개(V, Zvfhmin, Zvbb, Zvkt), 스칼라 Zfhmin, 포인터 마스킹 Supm을 뺀 것이다. 그것들은 RVB23에서 확장 옵션이 된다. S 모드에서는 Svnapot처럼 값싼 것은 RVB23S64에서도 필수이지만 Sha(하이퍼바이저)와 Ssnpm은 옵션이다.
RVA22U64 ⊄ RVB23U64

RVB23U64는 RVA23U64의 부분 집합이지만, RVA22U64를 포함하지는 않는다. RVA22U64에서 필수였던 Zfhmin이 RVB23U64에서는 옵션이기 때문이다. 이름의 숫자가 크다고 늘 상위 집합인 것은 아니며, 같은 계열(A면 A) 안에서만 상위 집합 관계가 유지된다.

내 CPU는 어느 프로파일을 만족할까

아래 검사기에서 CPU가 지원하는 확장을 눌러 켜고 끄면, 여섯 프로파일 각각에 대해 필수 확장을 얼마나 갖췄는지와 빠진 것이 무엇인지 바로 보여 준다. 판정 기준은 위 표와 같은 규격 원문의 필수 목록이다. 프리셋 버튼으로 대표적인 하드웨어 수준을 불러올 수도 있다.

SIMULATOR

프로파일 호환성 검사기

프리셋
베이스
rv64i
켠 확장 수0
만족하는 프로파일—
“RV64GC만”을 누르면 RVA20U64조차 만족하지 못한다. 빠진 것은 Zicntr와 메모리 속성 이름들이다. 실제 RV64GC 리눅스 보드는 대부분 이 성질을 이미 갖고 있어서, 규격이 RVA20을 만들 때 이름만 새로 붙였다. 그다음 “RVA22급”에서 V 하나만 켜 보고, RVA23U64까지 무엇이 더 필요한지 세어 보자. 점선 테두리는 다른 확장 때문에 저절로 충족된 항목이다(Za64rs를 켜면 더 느슨한 Za128rs도 만족).

실행 중에 기능 알아내기

프로파일은 “최소한 이것은 있다”는 바닥을 정할 뿐이다. 옵션 확장을 쓰려면 프로그램이 실행 중에 하드웨어가 무엇을 갖췄는지 알아내야 한다. RISC-V에서 이 정보가 흘러가는 길은 다음과 같다.

하트 (하드웨어) misa · mvendorid · marchid M 모드 펌웨어 · 부트로더 장치 트리 riscv,isa-extensions / ACPI RHCT 리눅스 커널 (S 모드) 하트별 확장 비트맵을 만든다 /proc/cpuinfo riscv_hwprobe 사용자 프로그램 (U 모드) IFUNC 해석기 (FMV) “V 비트가 켜져 있나?” 질의 비트마스크 foo_default RV64GC 경로 foo_arch_v 벡터 경로 프로그램 시작 때 한 번 고르고 이후에는 고른 함수를 바로 부른다
그림 23-7. 확장 정보가 흐르는 길. 펌웨어가 장치 트리(riscv,isa-extensions)나 ACPI 표로 커널에 알려 주고, 커널은 그것을 /proc/cpuinfo와 riscv_hwprobe 시스템 호출로 사용자 공간에 내보낸다. 함수 다중 버전(FMV)으로 만든 프로그램은 시작할 때 이 값을 보고 함수 하나를 고른다.

misa만으로는 왜 부족한가

misa CSR(17장)은 A부터 Z까지 한 글자 확장마다 비트 하나를 둔다. 그래서 Zba, Zicond 같은 수많은 Z 확장은 표현할 수 없다. 게다가 misa는 M 모드 CSR이라 S 모드 커널이나 U 모드 프로그램은 직접 읽을 수 없다. 그래서 확장 목록은 펌웨어가 장치 트리나 ACPI(RISC-V의 RHCT 표)에 적어 커널에 넘기는 방식을 쓴다.

리눅스: /proc/cpuinfo와 hwprobe

processor : 0 hart : 0 isa : rv64imafdcv_zicbom_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zba_zbb_zbs mmu : sv39

사람이 읽기에는 좋지만 문자열을 파싱하는 것은 느리고 틀리기 쉽다. 그래서 리눅스 6.4부터는 riscv_hwprobe 시스템 호출이 있다. 키-값 쌍 배열을 넘기면 커널이 값을 채워 준다. 예를 들어 키 RISCV_HWPROBE_KEY_IMA_EXT_0의 값은 RISCV_HWPROBE_IMA_FD, RISCV_HWPROBE_IMA_C, RISCV_HWPROBE_IMA_V, RISCV_HWPROBE_EXT_ZBA … 같은 비트로 이루어진 비트마스크다. 여러 CPU를 묻는 경우 불리언 성격의 키는 모든 CPU의 논리곱(AND)으로 답한다. 이기종 코어가 섞인 칩에서도 “모든 코어가 가진 것”만 믿게 하려는 것이다.

// <asm/hwprobe.h> 의 구조체와 상수를 쓴다 struct riscv_hwprobe pairs[] = { { .key = RISCV_HWPROBE_KEY_IMA_EXT_0 }, }; // cpusetsize = 0, cpus = NULL 이면 온라인 CPU 전체를 뜻한다 long result = syscall(__NR_riscv_hwprobe, pairs, 1, 0, NULL, 0); if (result == 0 && (pairs[0].value & RISCV_HWPROBE_IMA_V)) { // 벡터 경로를 고른다 }

함수 다중 버전(FMV)

매번 이런 코드를 손으로 쓰기는 번거롭다. RISC-V C API 규격은 target_clones·target_version 속성을 정의하고, 이를 지원하는 컴파일러는 한 함수를 여러 버전으로 컴파일한 뒤 IFUNC 해석기가 실행 시점에 (리눅스에서는 hwprobe로) 알맞은 버전을 고르게 만든다. default 버전이 반드시 있어야 해서, 기준 프로파일(예: RVA20)만 갖춘 칩에서도 프로그램이 돈다.

__attribute__((target_clones("default", "arch=+v"))) void add_arrays(float *destination, const float *source, size_t count) { for (size_t index = 0; index < count; index++) destination[index] += source[index]; // "arch=+v" 판은 자동 벡터화된다 }
ANIMATION

바이너리 이식성: 어디서 돌고 어디서 죽나

컴파일 대상
재생
RVA23 CPU—
RVA22 CPU—
RV64GC CPU—
컴파일 대상을 바꿔 가며 세 CPU의 결과를 비교하자. rva23u64로 빌드한 바이너리는 RVA22 CPU에서 czero.eqz(Zicond)를 만나는 순간 잘못된 명령 예외가 나고, 리눅스는 프로세스에 SIGILL을 보낸다. FMV 빌드는 공통 부분을 RVA20으로 만들고 뜨거운 함수만 여러 판으로 두어, 모든 CPU에서 돌면서도 RVA23 CPU에서는 벡터 경로를 탄다.

배포판과 하드웨어 현황

프로파일이 의미를 가지려면 운영체제 배포판이 “우리는 이 프로파일을 기준으로 빌드한다”고 선언해야 한다. 2026년 10월 현재 확인한 공개 자료를 정리하면 다음과 같다. 이 분야는 빠르게 바뀌므로 아래 내용은 날짜와 함께 읽고, 실제로 쓰기 전에는 각 프로젝트의 공식 공지를 다시 확인하자.

프로젝트RISC-V 기준근거와 시점
DebianRV64GC, lp64d ABIDebian 13 “trixie”(2025-08-09 발표)에서 riscv64가 처음으로 공식 아키텍처가 되었다. Debian 위키는 하드웨어 기준을 RV64GC로 밝힌다.
Ubuntu 24.04 LTSRVA20Canonical 블로그: 초기 RISC-V 사용자를 위해 RVA20 프로파일을 요구하는 24.04 LTS를 계속 제공한다.
Ubuntu 25.10 이후RVA23 (사용자 공간은 RVA23U64)2025년 계획 공지와 버그 트래커에 따르면 25.10부터 RVA23을 요구하고, 업그레이드 도구는 RVA23U64를 지원하지 않는 하드웨어에서 24.04 이후로의 업그레이드를 막는다. 2026년 2월에는 SpacemiT K3에서 26.04 LTS를 제공한다는 발표가 있었다.
FedoraRV64GC (RVA23 이전 논의 중)공개 발표와 토론에 따르면 현재 기준은 RV64GC이고, RVA23 하드웨어가 널리 보급되면 옮겨 갈 의사를 밝혀 왔다. 공식 결정 문서는 확인하지 못했다.
하드웨어는 소프트웨어보다 늦게 온다

Ubuntu가 RVA23 기준을 발표한 2025년 중반에는 RVA23을 만족하는 상용 칩이 사실상 없었다. 2026년 들어 SpacemiT K3가 “RVA23을 지원하는 첫 상용 SoC 가운데 하나”로 양산에 들어갔고, 리눅스 7.0에 초기 메인라인 지원이 들어갔으며, 이를 쓴 보드가 2026년 5월부터 판매되기 시작했다. “최초”라는 표현은 주로 제조사와 언론 보도에 근거하므로 조심해서 받아들이자. 그 사이 RVA22급 보드(벡터 1.0을 갖춘 것 포함)를 가진 사용자는 24.04 LTS나 RV64GC 기준 배포판에 머물러야 한다.

왜 RVA22를 건너뛰었나

배포판은 기준을 한 번 올리면 수년간 유지해야 한다. RVA22는 벡터와 하이퍼바이저가 옵션이라, RVA22를 기준으로 잡아도 고성능 코드는 여전히 탐지와 분기가 필요하다. RVA23은 이 둘을 필수로 만들어 “한 번 올릴 가치가 있는” 기준이 되었다. RVA 규격의 근거 절이 말하듯, 배포 생태계는 실제 출하된 기기에서 관찰한 최소 공통분모를 고르기 마련이고, RISC-V International은 세대마다 하드웨어 업체들이 같은 기능 집합에 맞추도록 이끄는 역할을 한다.

핵심 정리

  1. 프로파일은 새 명령어를 만들지 않는다. 비준된 확장 가운데 필수와 선택을 정해, 조합 폭발을 이름 하나로 줄인다.
  2. 이름은 RV + 계열(I·A·B) + 연도(바탕 규격의 비준 연도 기준) + 최고 특권 모드(U·S) + XLEN이다. 예: RVA23U64.
  3. RVA23의 옵션은 지역(암호), 개발(다음에 필수), 확장(비싸고 탐지 가능), 과도기(빠질 수 있음) 네 종류로 나뉜다.
  4. RVA20U64는 RV64GC급(+Zicntr, 메모리 속성 이름), RVA22U64는 B(Zba·Zbb·Zbs)·CMO·Zfhmin·Zkt 등을 더했고, RVA23U64는 V, Zicond, Zfa, Zcb, Zawrs, Supm 등을 필수로 만들었다. RVA23S64는 H(Sha)를 필수로 한다.
  5. RVB23은 같은 뼈대에서 벡터·하이퍼바이저 등을 옵션으로 돌린 맞춤형 응용 프로세서용 프로파일이다.
  6. 옵션은 실행 중에 탐지한다. 리눅스는 /proc/cpuinfo와 riscv_hwprobe로 알려 주고, FMV는 이를 써서 함수 버전을 고른다. 2025–2026년 Ubuntu는 RVA23을 기준으로 올렸고 Debian·Fedora는 RV64GC 기준이다.

확인 퀴즈

프로파일이 하는 일로 가장 알맞은 것은?

프로파일의 구성 요소는 모두 비준된 확장이어야 한다. 부팅·펌웨어 같은 실행 환경 전체는 플랫폼 규격의 몫이다.

RVA20U64의 “20”은 무엇을 뜻하나?

규격은 “2019년 비준 규격에 기반한 프로파일은 20”이라고 예를 든다. RVI20·RVA20·RVA22 를 정의한 문서 자체는 2023년 4월 날짜다.

RVA22U64에서는 옵션이었다가 RVA23U64에서 필수가 된 확장은?

V는 RVA22U64의 옵션이었고 RVA23U64에서 필수가 되었다. Zba는 RVA22U64부터 필수, Zkn은 RVA23에서 옵션에서도 빠졌고, Zfh는 여전히 확장 옵션이다.

RVA23S64에서 하이퍼바이저 확장 H가 필수라는 사실을 프로파일 규격은 어떤 이름으로 적는가?

Sha는 H와 그에 딸린 Ssstateen, Shcounterenw, Shvstvala, Shtvala, Shvstvecd, Shvsatpa, Shgatpa를 묶은 프로파일 정의 확장이다.

“다음 세대 RVA에서 필수가 될 예정”이라는 뜻의 옵션 종류는?

RVA23U64의 개발 옵션은 Zabha, Zacas, Ziccamoc, Zvbc, Zama16b다.

RVB23U64와 RVA23U64의 관계로 옳은 것은?

RVB23U64는 V, Zvfhmin, Zvbb, Zvkt, Zfhmin, Supm을 확장 옵션으로 돌렸다. 나머지 필수 확장은 RVA23U64와 같다.

사용자 프로그램이 Zba 지원 여부를 알아내는 방법으로 알맞지 않은 것은?

misa는 M 모드 CSR이고, 한 글자 확장만 비트로 표시하므로 Z 확장 정보가 없다.

RVA23U64용으로 빌드한 바이너리를 RVA22U64만 만족하는 CPU에서 실행하면?

새 명령을 실행하는 순간 illegal-instruction 예외가 나고, 리눅스는 SIGILL로 프로세스를 끝낸다. 그래서 Ubuntu는 업그레이드 단계에서 하드웨어를 미리 검사한다.

더 읽을거리