ARMv9가 바꾼 것을 먼저 한눈에 본다
ARMv9는 ARMv8을 버리고 새로 만든 CPU 언어가 아니다. 기존 AArch64의 EL0~EL3, page table, exception과 memory-ordering 구조를 이어받고, 더 넓은 vector·matrix 계산과 confidential computing, memory·control-flow 보안을 단계적으로 강화했다.
한 번에 더 많은 data
SVE2는 길이가 다른 vector CPU에서 같은 program을 실행하고, SME는 큰 2차원 누적 storage로 matrix 계산을 가속한다.
잘못된 주소와 흐름 검사
MTE는 pointer와 memory tag를, PAC·BTI·GCS는 pointer·branch·return 흐름을 서로 다른 단계에서 검사한다.
관리자도 내용을 못 보는 Realm
RME는 host가 workload를 운영하되 보호된 code·data·register에는 접근하지 못하는 새 World와 memory 소유권 검사를 만든다.
서버와 가상머신의 비용 감소
TLBI, MPAM, PMU·trace, dirty-page 기록과 interrupt·device virtualization을 큰 시스템에 맞게 개선한다.
읽을 때의 기준: ARMv9라는 제품명보다 Armv9.x-A + FEAT_* + CPU revision + Linux HWCAP을 본다. 같은 ARMv9 CPU라도 선택 기능과 vector length, cache·PMU 구현이 다를 수 있기 때문이다.
ARMv9는 Armv8과 겹치며 진화한다
핵심: ARMv9.0-A는 Armv8.5-A의 기능을 바탕으로 ARMv9 전용 요구사항을 더한다. ARMv9.1~v9.4는 각각 Armv8.6~v8.9와 같은 연차의 공통 확장을 공유한다. 따라서 “v9에서 처음 생긴 기능”과 “v8.x에서 먼저 도입돼 v9 기준선에 포함된 기능”을 구분해야 한다.
| ARMv9 버전 | 대응하는 Armv8 확장 | 대표 변화 | 읽을 때 주의할 점 |
|---|---|---|---|
| v9.0 | v8.5 | SVE2 계열, TME와 ARMv9 기준선. PAC·BTI·MTE 등 v8.x에서 도입된 기능도 같은 시대 기반선에 놓인다. | 기능의 최초 도입 버전과 v9.0에서의 필수 여부는 같은 질문이 아니다. |
| v9.1 | v8.6 | RME, BF16, I8MM과 가상화·시스템 기능 확장. | RME가 명세에 있어도 CCA 시스템은 RMM·펌웨어·플랫폼 지원이 모두 필요하다. |
| v9.2 | v8.7 | SME, BRBE, LPA2와 추가 가상화 제어. | SME와 BRBE는 실제 구현 및 OS 노출을 별도로 검사한다. |
| v9.3 | v8.8 | MOPS, NMI, QARMA3, hinted branches, 세분화된 trap 제어. | MOPS가 있으면 라이브러리가 memcpy·memset 경로를 선택할 수 있지만 CPU별 성능은 측정해야 한다. |
| v9.4 | v8.9 | RME 장치 할당과 MEC, SVE2 확장, MTE·PMU·RAS 개선. | Memory Encryption Context는 GPT의 접근 제어와 별개 층이다. |
| v9.5 | 독립 연차 | FP8, Checked Pointer Arithmetic, HDBSS, VM live migration 지원, PAC 개선. | 새 데이터 형식과 가상화 기능은 컴파일러·KVM ABI 지원까지 확인한다. |
| v9.6 | 독립 연차 | SME2 확장, MPAM Domain, GDI, VM용 SPE/TRBE 인터페이스, GPT 확장성. | GDI의 NSP·SA PAS는 RME의 4개 PAS를 단순히 대체하지 않는다. |
| v9.7 | 독립 연차 | TLBI Domain, MPAMv2, FP6, 영상 처리 명령, GICv5, Realm용 LOR. | 아키텍처 발표와 실제 Cortex·Neoverse 제품 구현 시점은 다를 수 있다. |
Mandatory, Optional, 제품 구현을 분리한다
ARMv9.x는 단순한 기능 체크리스트가 아니다. 각 버전에는 필수 기능과 선택 기능이 섞여 있고, 일부 기능은 특정 조건이나 더 높은 Exception Level 구현 여부에 따라 달라진다. 실제 시스템 판단은 다음 네 층을 모두 통과해야 한다.
Armv9.x-A가 허용하거나 요구하는 기능 집합을 DDI 0487에서 확인한다.
해당 Cortex·Neoverse TRM과 feature 표에서 선택 기능, vector length, cache·PMU 구현을 확인한다.
EL3·RMM·hypervisor가 기능을 노출하는지, Linux가 ID register를 수용하고 활성화했는지 확인한다.
AT_HWCAP, AT_HWCAP2, prctl()과 signal ABI로 프로세스가 실제 사용할 수 있는지 확인한다.
예: FEAT_SVE2, FEAT_SME, FEAT_RME, FEAT_MTE, FEAT_GCS라는 이름이 문서에 등장한다고 해서 특정 CPU에 전부 들어 있다는 뜻은 아니다. ID register의 필드, Linux HWCAP, 제품 TRM을 함께 기록해야 재현 가능한 사양이 된다.
Exception Level과 Security state는 서로 다른 축이다
Exception Level은 권한 높이를, Security state 또는 World는 접근 가능한 자원과 신뢰 경계를 나타낸다. “EL2이므로 Secure하다”처럼 두 축을 합쳐 이해하면 Realm과 가상화 구조를 설명할 수 없다.
| 층 | 일반적인 역할 | 가능한 실행 환경 예 |
|---|---|---|
| EL0 | 응용 프로그램과 제한된 guest userspace | NS-EL0, S-EL0, R-EL0 |
| EL1 | 운영체제 kernel 또는 guest kernel | NS-EL1, S-EL1, R-EL1 |
| EL2 | hypervisor와 Realm 관리 monitor | NS-EL2의 KVM/host, R-EL2의 RMM, 구현 시 S-EL2 |
| EL3 | 최상위 firmware와 World 전환 | Root World의 monitor firmware |
PE(Processing Element)는 명령을 실행하는 아키텍처 처리 주체다. 같은 PE가 예외와 monitor 호출을 통해 EL과 World를 바꿀 수 있다. AArch64와 AArch32는 실행 상태이며, EL이나 World 자체가 아니다.
응용 프로그램의 요청이 kernel까지 가는 과정
가장 쉬운 그림부터 보면, EL0는 일반 사용자가 일하는 공간이고 EL1은 운영체제가 하드웨어를 대신 관리하는 공간이다. 응용 프로그램이 파일을 열거나 메모리를 요청하면 EL0에서 직접 장치를 만지지 않고 SVC 명령으로 EL1에 서비스를 요청한다.
SVC #0 실행PSTATE → SPSR_EL1
CPU는 현재 명령 다음 주소를 ELR_EL1에, 이전 실행 상태를 SPSR_EL1에 저장한다. 예외 종류는 ESR_EL1에 기록하고, 주소 fault라면 FAR_EL1에 문제가 된 virtual address도 남긴다. 그 뒤 VBAR_EL1이 가리키는 vector table의 정해진 entry로 이동한다.
kernel은 register에 담긴 system-call 번호와 인자를 검사하고 작업을 수행한다. 끝나면 반환값을 register에 넣고 ERET를 실행한다. CPU는 ELR_EL1과 SPSR_EL1을 이용해 EL0의 다음 명령과 이전 상태를 복원한다.
| 상황 | 어디로 이동하나 | 왜 더 높은 EL이 필요한가 |
|---|---|---|
| EL0 system call | 보통 NS-EL1 Linux kernel | page table, device, scheduler처럼 응용 프로그램에 허용되지 않은 자원을 사용하기 위해. |
| Guest의 민감한 동작 | NS-EL2 KVM | guest가 실제 interrupt controller나 Stage 2 설정을 직접 바꾸지 못하게 하기 위해. |
| Realm 관리 요청 | R-EL2 RMM 또는 Root firmware 경계 | host도 볼 수 없는 Realm 상태와 GPT를 보호하기 위해. |
| SError·IRQ | routing 설정이 정한 EL | 오류나 interrupt를 처리할 책임이 있는 kernel·hypervisor·firmware로 넘기기 위해. |
핵심: EL 숫자가 높아지는 것은 “더 빠른 코드”가 된다는 뜻이 아니다. 더 넓은 제어 권한과 더 큰 책임을 가진 software로 실행 주체가 바뀐다는 뜻이다.
ARMv9의 AArch32는 EL0에서만 선택적이다
ARMv9-A는 privileged level에서 AArch32를 제거하고, AArch32 EL0 지원만 구현 선택으로 남겼다. 32비트 앱을 계속 실행하려면 CPU의 FEAT_AA32EL0, kernel의 compat 지원, 32비트 동적 로더와 라이브러리가 모두 필요하다.
lscpu의 CPU op-mode와/proc/cpuinfo만으로 결론을 내리지 말고 kernel의 compat 설정을 함께 본다.- 혼합 CPU 시스템에서는 모든 online CPU가 안전하게 제공할 수 있는 기능만 kernel ABI로 노출될 수 있다.
- 관련 Linux 동작은 asymmetric 32-bit support 문서와 함께 읽는다.
VA, IPA, PA와 translation regime
translation regime은 어느 EL·World의 주소 변환 규칙과 레지스터 집합을 사용하는지를 뜻한다. 일반 프로세스는 Stage 1에서 VA를 PA로 바꾸고, 가상머신 guest는 Stage 1에서 VA를 IPA로, host가 관리하는 Stage 2에서 IPA를 PA로 바꾼다.
Page와 granule
translation granule은 4KB·16KB·64KB page-table 형식을 정한다. RME의 보호 granule은 소유권 위임 단위라는 다른 의미이므로 문맥을 구분한다.
더 큰 주소
LPA2는 작은 granule에서도 52-bit 주소 공간과 descriptor 변화를 지원한다. CPU·kernel page size·page-table level의 조합을 함께 본다.
주소 뒤의 보안 속성
같은 숫자 PA라도 Physical Address Space 속성이 다르면 접근 결과가 달라질 수 있다. RME에서는 GPC 검사가 translation 이후 별도로 적용된다.
Linux 구현 비교는 page-table format과 address-space switch에서 TTBR, ASID, PTE bit까지 이어진다.
4KB page에서 주소 하나가 번역되는 실제 예
주소 변환표는 거대한 전화번호부를 여러 권으로 나눈 것과 비슷하다. 48-bit virtual address와 4KB translation granule을 사용하는 일반적인 AArch64 구성을 예로 들면, 주소를 9-bit 색인 네 개와 12-bit page 내부 offset으로 나눈다. 각 9-bit 색인은 512개 entry 중 하나를 고른다.
예제 virtual address: 0x0000_1234_5678_9abc
47 39 38 30 29 21 20 12 11 0
+------------------+-----------+-----------+-----------+-----------+
| L0 index = 36 | L1 = 209 | L2 = 179 | L3 = 393 | off=0xabc |
+------------------+-----------+-----------+-----------+-----------+
TTBR0_EL1이 L0 table의 시작 주소를 제공한다. L0[36]이 다음 table을, L1[209]가 그다음 table을 가리키고, L2[179]와 L3[393]를 거쳐 최종 physical page를 얻는다. 마지막으로 page 시작 주소에 0xabc를 더해 실제 byte 위치를 만든다.
| 설정·검사 | 무엇을 결정하나 | 실패하면 |
|---|---|---|
| TCR_EL1 | 주소 크기, 4KB/16KB/64KB granule, cacheability와 shareability | 주소 크기 위반 또는 잘못된 table 해석으로 translation fault. |
| TTBR0/1_EL1 | userspace·kernel 쪽 page-table root와 ASID | 해당 VA를 시작할 table이 없거나 엉뚱한 address space를 참조. |
| Descriptor | 다음 table인지 block/page인지, valid·AF·AP·XN과 output address | translation, access-flag, permission 또는 execute-never fault. |
| MAIR_EL1 | descriptor의 AttrIndx가 의미하는 Normal/Device memory 속성 | 단순 fault보다 더 위험하게, 장치를 일반 RAM처럼 다뤄 ordering이 깨질 수 있음. |
VM 안에서는 이 결과가 바로 DRAM 주소가 아니라 IPA다. 다시 VTTBR_EL2에서 시작하는 Stage 2 walk가 IPA를 PA로 바꾸고, VTCR_EL2와 Stage 2 descriptor가 guest의 read/write/execute 권한을 제한한다. Realm에서는 그 뒤 GPC가 PA의 World 소유권까지 추가로 검사한다.
LPA2가 바꾸는 점: 4KB·16KB granule에서도 52-bit output address를 표현하도록 descriptor와 table walk 규칙을 확장한다. 단순히 주소 register 한 개가 길어지는 기능이 아니라 CPU, page-table 형식, kernel memory layout이 함께 지원해야 한다.
TLB 무효화는 범위와 공유 영역을 지정한다
page table을 고친 것만으로 다른 PE가 새 mapping을 즉시 보는 것은 아니다. 올바른 barrier, TLBI 범위, broadcast와 완료 대기를 결합해야 한다. ARMv9.7의 TLBI Domain은 시스템 전체 broadcast 대신 관련 도메인만 겨냥해 큰 시스템의 비용을 줄이는 방향이다.
shareability 범위와 대상 PE가 누구인지 먼저 정한다.
한 주소, range, address space 전체, Stage 1 또는 Stage 2 중 필요한 범위를 고른다.
page-table write가 보인 뒤 invalidation이 실행되고, 후속 접근 전 완료됐음을 DSB·ISB 경계로 보장한다.
실제 Linux shootdown 흐름은 TLBI와 IPI 비교 문서에 연결했다.
메모리 순서, LSE와 MOPS
| 개념 | 역할 | 실무 판단 |
|---|---|---|
| DMB / DSB / ISB | 메모리 접근 순서, 완료, 명령 실행 context 동기화를 서로 다르게 보장한다. | 세 barrier를 “강한 fence” 하나로 취급하지 않는다. |
| RCpc | release consistency의 일부 경로에서 더 약하고 효율적인 acquire 동작을 제공한다. | 언어 memory model과 kernel primitive가 요구하는 순서를 먼저 본다. |
| LSE / LSE2 | LL/SC retry loop 대신 단일 원자 read-modify-write와 확장된 atomic 동작을 제공한다. | 컴파일 target과 HWCAP, runtime dispatch를 구분한다. |
| LS64 | 64-byte 단위 load/store 계열을 통해 장치·가속기 통신 패턴을 지원한다. | 일반 memcpy 대체로 가정하지 않고 대상 memory type과 protocol을 확인한다. |
| MOPS | 구현 최적화된 memory copy/set 명령군을 제공한다. | 라이브러리와 kernel의 feature dispatch가 선택하는지 측정한다. |
cache/barrier 비교, atomic/locking 비교, Linux MOPS 문서에서 구현과 ABI를 더 깊게 볼 수 있다.
왜 barrier가 필요한지 두 CPU로 이해한다
CPU0이 data를 적고 “준비 완료” flag를 세우며, CPU1이 flag를 본 뒤 data를 읽는 상황을 생각하자. source code 순서만으로는 다른 CPU가 같은 순서로 관찰한다고 보장되지 않는다. store buffer, cache와 interconnect가 서로 다른 시점에 값을 전달할 수 있기 때문이다.
잘못된 게시 순서
// CPU0 // CPU1
data = 42; if (ready == 1)
ready = 1; print(data); // 0을 볼 수도 있음ready가 먼저 보이고 data가 늦게 보일 수 있다. C/C++에서는 data race 자체도 정의되지 않은 동작이므로 architecture assembly뿐 아니라 언어 atomic 계약이 필요하다.
Release / acquire로 만든 전달 관계
// CPU0 // CPU1
data = 42;
store_release(&ready, 1); if (load_acquire(&ready) == 1)
print(data); // 42 보장release는 앞선 data write가 flag 뒤로 밀리지 않게 하고, acquire는 flag를 읽은 뒤의 data read가 앞으로 당겨지지 않게 한다. A64에서는 상황에 따라 STLR/LDAR 또는 barrier를 포함한 sequence로 내려간다.
| 명령 | 쉬운 의미 | 대표 사용 |
|---|---|---|
| DMB | 앞뒤 memory 접근이 다른 관찰자에게 보이는 순서를 정한다. | lock, device descriptor 게시, page-table update ordering. |
| DSB | 선택한 범위의 앞선 작업이 완료될 때까지 다음 단계를 진행하지 않는다. | cache maintenance 완료, TLBI 완료, MMU·power 상태 변경. |
| ISB | 이후 명령을 새 실행 환경에서 다시 가져와 해석하게 한다. | system register나 translation regime을 바꾼 뒤. |
LSE의 CAS·LDADD 계열은 원자 read-modify-write를 한 architecture 명령으로 표현한다. LSE가 없는 CPU에서는 LDXR/STXR exclusive loop로 같은 계약을 구현한다. 둘은 결과의 원자성은 같지만 contention 때 retry·공정성·성능이 다를 수 있다.
MOPS는 큰 memcpy()나 memset()의 준비·주 반복·마무리 단계를 architecture 명령으로 표현해 CPU 구현이 내부 복사 폭과 cache 동작을 최적화하도록 한다. overlap을 허용하는 memmove(), fault 재시작과 userspace 접근 검사는 별도 software 계약이므로 “MOPS가 있으면 모든 복사 함수를 한 명령으로 바꾼다”는 뜻은 아니다.
Coherency와 MPAM은 다른 문제다
cache coherency는 여러 agent가 같은 메모리의 일관된 값을 관찰하게 하는 규칙이다. MPAM은 cache capacity와 memory bandwidth 같은 공유 자원을 partition·monitor하는 제어 체계다. MPAM Domain과 MPAMv2는 시스템 규모와 자원 표현을 확장하지만, coherency를 대신하지 않는다.
CPU와 DMA
CPU coherent domain, non-coherent DMA, cache maintenance와 IOMMU 경계를 따로 기록한다.
Producer / consumer
v9.6 계열의 hint와 outer-cache operation은 데이터 공유 의도를 전달하지만 정합성 계약 자체를 없애지 않는다.
분할과 감시
PARTID·PMG, resource control과 monitor를 통해 workload 간 간섭을 관리한다. 실제 control surface는 platform과 OS 지원에 달린다.
Linux 소스로 내려가기
이 문서의 실행 상태와 주소 변환 개념을 실제 Linux v6.18.37 코드에서 이어서 읽는다. 진입 어셈블리부터 C handler, page fault와 page table 구성까지 호출 흐름을 끊지 않고 추적했다.
Arm 공식 자료
- ArchitectureDDI 0487: A-profile Architecture Reference Manual
- RegistersDDI 0601: A-profile System Registers
- v9.3A-profile architecture developments 2021
- v9.4A-profile architecture developments 2022
- v9.5A-profile architecture developments 2023
- v9.6A-profile architecture developments 2024
- v9.7A-profile architecture developments 2025