← ARMv9 길잡이DUJINLABS.COM

SVE2 · SME2 · BF16/FP8/FP6 · MTE · PAC · BTI · GCS

ARMv9 Vector·AI와 메모리·제어 흐름 보안

가변 길이 vector와 matrix 상태가 명령·ABI·context switch를 어떻게 바꾸는지, 메모리 tag와 return-address 보호가 서로 어떤 공격을 막는지 기능 이름보다 경계 중심으로 읽는다.

Vector
SVE · SVE2 · SVE2.1
Matrix
SME · SME2 · SME2.1
Security
MTE · PAC · BTI · GCS
Checked
2026-08-07 KST

먼저 이해할 두 가지

Vector·matrix 기능

숫자 하나씩 계산하는 대신 같은 종류의 숫자 여러 개를 한꺼번에 처리한다. 사진의 pixel, audio sample, AI tensor와 과학 계산에서 같은 명령을 반복하는 비용을 줄인다.

Memory·control-flow 보안

프로그램이 잘못된 memory를 읽거나 공격자가 함수의 돌아갈 주소를 바꾸는 순간을 hardware가 검사한다. 버그를 없애는 마법이 아니라, 버그가 공격으로 이어지기 어렵게 만드는 여러 겹의 검사다.

ARMv9의 특징은 이 둘을 한 architecture 안에서 확장했다는 점이다. SVE2·SME는 더 많은 데이터를 효율적으로 처리하고, MTE·PAC·BTI·GCS는 그 큰 software가 memory와 실행 흐름을 잘못 다룰 때 피해를 줄인다.

SVE와 SVE2의 차이

SVE는 128~2048 bit의 구현 선택 vector length를 같은 binary가 활용하도록 vector-length-agnostic(VLA) programming model을 도입했다. SVE2는 그 predication과 scalable register model을 유지하면서 DSP·multimedia·computer vision·암호 등 정수 중심 workload에 필요한 연산을 크게 넓힌다.

기능핵심 목적명령 수준 차이확인점
Neon고정 128-bit SIMDlane 수가 compile time에 고정기존 ABI와 library 최적화가 매우 넓다.
SVEHPC와 VLA vectorizationpredicate register, while-loop, gather/scatter와 scalable Z registerHWCAP_SVE와 vector length를 검사한다.
SVE2범용 DSP·media·crypto 확대narrowing, widening, complex integer, bit permutation과 domain-specific 연산 확대HWCAP2_SVE2 및 세부 extension을 확인한다.
SVE2.1+명령군과 predication의 연차 개선새 load/store·permutation·arithmetic 기능이 추가됨architecture revision만 보지 말고 개별 FEAT_*를 본다.

VLA 규칙: loop가 처리할 element 수를 svcnt*로 얻고, whilelt 계열 predicate로 tail을 처리해야 한다. 256-bit라고 가정해 상수를 넣으면 더 짧거나 긴 CPU에서 이식성이 깨진다.

길이가 10인 배열을 SVE가 처리하는 방법

예를 들어 CPU의 vector length가 256 bit라면 32-bit 정수 8개를 한 번에 담을 수 있다. 원소 10개를 더할 때 첫 회에는 8개, 두 번째 회에는 남은 2개만 활성화한다. 같은 binary가 128-bit CPU에서는 4+4+2개, 512-bit CPU에서는 10개를 한 번에 처리한다.

Predicate가 마지막 2개만 켜는 과정

배열 index:       0 1 2 3 4 5 6 7 | 8 9
첫 반복 predicate: 1 1 1 1 1 1 1 1
둘째 predicate:    1 1 0 0 0 0 0 0

whilelt p0.s, xIndex, xCount   // index < count인 lane만 1
ld1w    z0.s, p0/z, [xBase, xIndex, lsl #2]
add     zAcc.s, p0/m, zAcc.s, z0.s
incw    xIndex                 // 현재 VL에 들어가는 32-bit 원소 수만큼 증가

p0/z는 꺼진 lane을 0으로 만들고, p0/m은 꺼진 lane의 기존 목적지 값을 유지한다. 이 차이를 모르면 마지막 반복에서 이전 값이 섞이거나 합계가 틀릴 수 있다.

SVE2는 이 가변 길이·predicate 구조를 유지하면서 saturating arithmetic, widening/narrowing, bit permutation, complex arithmetic와 암호 명령을 보강한다. 따라서 “SVE2는 SVE보다 register가 더 넓다”가 아니라 “같은 scalable 실행 틀로 다룰 수 있는 정수·DSP 작업이 넓어졌다”가 정확하다.

SME는 SVE에 matrix storage를 더한다

Scalable Matrix Extension은 Streaming SVE mode와 2차원 ZA storage를 도입한다. streaming mode의 vector length는 일반 SVE vector length와 독립적으로 관리될 수 있고, 함수가 streaming 상태나 ZA를 공유·보존하는 방식은 호출 ABI에 영향을 준다.

SM

Streaming SVE mode

긴 matrix loop에 맞춘 실행 mode다. mode 전환과 streaming-compatible 함수 속성을 compiler ABI가 추적한다.

ZA

Scalable matrix storage

vector length의 제곱에 비례하는 큰 상태다. context switch와 signal frame 비용을 지배할 수 있다.

ZT0

추가 tile storage

일부 SME2 연산이 사용하는 별도 상태이며 ABI에서 live·preserve 계약을 명시한다.

FA64

Full A64 in streaming mode

streaming mode에서 사용할 수 있는 명령 범위를 확장한다. 구현 feature를 별도로 확인한다.

SME2

Multi-vector와 outer product

여러 Z register를 묶는 연산과 tile 처리로 matrix kernel의 instruction overhead를 줄인다.

SME2.1+

Quarter-tile·sparsity

더 작은 tile 조작과 structured sparsity 등 AI workload의 data movement를 줄이는 방향으로 확장된다.

SME가 matrix 곱을 계산하는 원리

matrix 곱 C = A × B는 A의 column 방향 값과 B의 row 방향 값을 곱해 C의 여러 칸에 누적하는 작업이다. SME는 두 vector의 outer product를 한 번에 계산하고 결과를 2차원 ZA storage에 계속 더한다.

두 vector의 outer product가 ZA tile을 채우는 방식
A vector[a0, a1, a2, …]
×
B vector[b0, b1, b2, …]
FMOPAai × bj를 병렬 계산
ZA tileC[i][j]에 누적

개념적인 SME 실행 순서

SMSTART ZA              // Streaming mode와 ZA 접근 시작
ZERO    {ZA}            // 누적 matrix를 0으로 초기화

loop_k:
    load zA, pA, [A]    // A의 한 방향 vector
    load zB, pB, [B]    // B의 한 방향 vector
    FMOPA za0.s, pA/m, pB/m, zA.s, zB.s
    ...                 // K 방향을 반복하며 같은 ZA tile에 누적

store ZA rows to C
SMSTOP                  // mode와 ZA 사용 종료

실제 instruction과 tile element type은 data 형식에 따라 달라진다. predicate 두 개는 A와 B 양쪽의 유효 원소를 제한해 matrix 가장자리의 불완전한 tile도 같은 loop로 처리한다.

공식 Arm SME 설명에 따르면 ZA는 SVL 바이트 × SVL 바이트의 정사각 byte array다. SVL이 256 bit, 즉 32 byte면 ZA는 32×32 = 1,024 byte다. SVL이 512 bit면 64×64 = 4,096 byte가 된다. vector length가 두 배가 되면 ZA 저장량은 네 배가 되므로 context switch 비용도 빠르게 커진다.

Streaming mode는 PSTATE.SM, ZA 접근은 PSTATE.ZA가 제어한다. SMSTART/SMSTOP은 이 bit를 바꾸는 명령 alias다. mode 전환 시 streaming과 non-streaming vector 상태 규칙이 달라지므로 compiler의 __arm_streaming·ZA 공유 attribute가 함수 경계에서 중요하다.

BF16, I8MM, FP8과 FP6는 연산 계약이 다르다

형식·기능주요 용도누산·정확도 관점
BF16학습·추론의 넓은 exponent 범위입력 저장량을 줄이고 더 넓은 형식으로 누산하는 사용이 일반적이다.
I8MM8-bit integer matrix multiply작은 정수 입력을 더 넓은 accumulator로 모은다.
F32MM / F64MMSVE matrix multiplyfloat32·float64 workload의 multiply-accumulate throughput을 높인다.
FP8AI model의 저정밀 저장·연산여러 FP8 encoding, scaling과 exception 처리 계약을 함께 봐야 한다.
FP6v9.7 세대의 더 압축된 AI 데이터정밀도·동적 범위 손실을 software quantization 정책과 함께 관리한다.

“지원한다”는 말은 register가 그 형식을 직접 담는지, 변환 명령이 있는지, dot-product 또는 matrix 명령이 있는지를 구분해야 한다. compiler intrinsic과 library kernel이 같은 encoding·accumulator 규칙을 택하는지도 확인한다.

Vector length가 Linux ABI 크기를 바꾼다

SVE·SME register state는 구현 vector length에 따라 커진다. Linux는 프로세스별 vector length와 기능 opt-in을 관리하고, signal frame·ptrace regset·core dump에 가변 크기 record를 사용한다.

prctl()

SVE·SME vector length를 조회·설정하고 exec 이후 상속 정책을 지정한다. 요청값이 그대로 보장된다고 가정하지 말고 반환값을 사용한다.

Signal frame

FPSIMD, SVE, ZA, ZT record를 header와 size로 순회한다. 고정 offset으로 casting하면 새 extension에서 깨진다.

ptrace()

debugger는 NT_ARM_SVE·SME 계열 regset의 크기와 flags를 먼저 읽고 상태 형식을 해석한다.

Context switch

kernel은 사용 여부와 ownership을 추적해 큰 상태를 필요할 때 저장한다. ZA는 VL 제곱에 비례해 특히 비싸다.

구체적인 kernel 저장·복원은 SVE/SME extended state 비교Linux SVE ABI, Linux SME ABI에서 이어진다.

Vector length가 상태 저장량을 얼마나 키우는가

Linux 문서에서 VL은 Z register의 크기를 byte로 나타낸다. 각 Z register는 VL byte, 각 predicate와 FFR은 VL/8 byte다. scalable 부분만 단순 계산하면 다음과 같다.

상태계산식VL=32B (256-bit)VL=256B (2048-bit)
Z0..Z3132 × VL1,024B8,192B
P0..P1516 × VL/864B512B
FFRVL/84B32B
ZASVL × SVL1,024B65,536B

여기에 FPSIMD state, header, alignment와 ZT 등 추가 record가 붙는다. 그래서 kernel은 모든 task마다 최대 크기를 무조건 복사하지 않고 실제 사용 여부를 추적한다. signal frame은 sve_context.vl과 record size를 포함하고, debugger는 NT_ARM_SVE·NT_ARM_ZA regset의 header를 먼저 읽는다.

실무 오류: signal frame에서 register offset을 고정 숫자로 계산하면 다른 VL이나 SME 추가 state에서 깨진다. Linux UAPI의 SVE_SIG_*·ZA_SIG_* macro와 record header를 사용해야 한다.

ACLE intrinsic과 compile target

ACLE은 C/C++에서 architecture feature와 vector type을 사용하는 표준 interface다. SVE intrinsic은 보통 arm_sve.h를, SME는 compiler가 제공하는 SME attribute와 intrinsic을 사용한다.

Vector length를 고정하지 않는 SVE 합산 골격

#include <arm_sve.h>

float sum_sve(const float *p, size_t n) {
    svfloat32_t acc = svdup_f32(0.0f);
    for (size_t i = 0; i < n; i += svcntw()) {
        svbool_t pg = svwhilelt_b32(i, n);
        acc = svadd_m(pg, acc, svld1(pg, p + i));
    }
    return svaddv(svptrue_b32(), acc);
}

-march=armv9-a+sve2 같은 compile target은 그 명령을 실행할 CPU가 보장될 때 사용한다. 범용 binary는 별도 object 또는 function multiversioning과 HWCAP dispatch를 사용한다.

MTE는 allocation tag와 pointer tag를 비교한다

Memory Tagging Extension은 memory granule에 allocation tag를, pointer 상위 bit에 logical tag를 두고 접근 때 비교한다. use-after-free와 일부 out-of-bounds를 탐지하지만, tag 충돌 확률과 allocator 정책 때문에 완전한 memory safety 증명은 아니다.

Fault mode관찰 시점장단점
Synchronous문제가 된 접근에서 정확히 faultdebugging과 원인 추적에 좋지만 실행 비용이 더 클 수 있다.
Asynchronous오류를 기록하고 나중에 전달성능은 유리할 수 있으나 faulting instruction을 정확히 특정하기 어렵다.
Asymmetricload와 store에 서로 다른 정책 적용 가능workload별 성능·탐지 절충을 세밀하게 조정한다.

세대별 MTE 확장은 tag storage·fault control·virtualization을 개선한다. 실제 process는 tagged address ABI, allocator와 prctl() 설정이 모두 맞아야 한다. Linux MTE 문서에 userspace 계약을 연결했다.

MTE가 use-after-free를 찾는 예

MTE는 memory의 16-byte granule마다 4-bit allocation tag를 두고 pointer의 logical tag와 비교한다. 자물쇠와 열쇠 번호가 같은지를 매 load/store 때 확인한다고 생각하면 된다.

해제된 pointer를 다시 사용할 때

1. malloc()이 0x...1000 영역에 allocation tag 5를 지정
2. application pointer의 상위 tag도 5 → 접근 성공
3. free() 후 allocator가 같은 영역을 tag 9로 변경
4. 오래된 pointer는 여전히 tag 5
5. pointer tag 5 != memory tag 9 → Tag Check Fault

공간 오류도 pointer가 다른 tag의 16-byte granule로 넘어가면 잡을 수 있다. 다만 우연히 같은 4-bit tag가 재사용되거나 한 granule 안에서 벗어나면 탐지하지 못할 수 있다.

SCTLR_ELx.TCF 계열 설정은 mismatch를 무시할지, 정확한 instruction에서 synchronous fault로 보고할지, 비동기적으로 모아 나중에 알릴지 정한다. 개발 환경은 정확한 위치가 필요한 synchronous mode가 유리하고, 운영 환경은 비용과 진단 정확도를 절충한다.

Arm의 PAC·BTI·MTE 입문 문서는 logical tag가 4-bit이며 mismatch 처리 방식을 system register로 선택한다고 설명한다.

PAC는 pointer와 context를 인증한다

Pointer Authentication은 pointer의 사용되지 않는 상위 bit에 인증 code를 넣고, secret key와 modifier를 사용해 변조를 탐지한다. instruction·data pointer용 key가 분리되며 EL별 key 관리와 context switch가 필요하다.

Key

APIAKey, APIBKey, APDAKey, APDBKey와 generic key는 용도를 분리한다. kernel·hypervisor가 context 전환 때 올바르게 관리한다.

Modifier

stack pointer, program counter 또는 별도 context 값을 섞어 같은 pointer의 재사용 공격 범위를 줄인다.

Algorithm

implementation과 architecture feature에 따라 QARMA 계열 지원이 진화한다. v9.3의 QARMA3는 지연과 보안 특성의 새 선택지를 제공한다.

Failure

인증 실패 pointer는 후속 사용에서 fault하도록 손상된다. PAC 자체가 bounds check나 memory encryption을 제공하지는 않는다.

Linux pointer authentication ABI에서 HWCAP, key와 virtualization 노출을 확인한다.

BTI와 GCS는 서로 다른 제어 흐름을 막는다

기능보호 대상방법남는 공격면
BTI간접 branch의 목적지허용된 landing pad에서만 특정 간접 branch가 도착하도록 검사허용된 target 내부의 논리 공격과 return chain은 별도 보호가 필요하다.
PACpointer와 return address 무결성key·modifier 기반 인증 code 검사올바르게 서명된 pointer의 오용과 data corruption은 남는다.
GCSreturn address 흐름일반 stack과 별도 보호 stack에 return state를 기록·대조forward-edge 간접 branch는 BTI 등 별도 보호가 필요하다.

GCS는 hardware, ELF property, loader, kernel의 prctl()·signal 처리와 compiler가 함께 작동해야 한다. 자세한 ABI는 Linux GCS 문서에서 본다.

함수 반환 주소를 세 겹으로 보호하는 과정

함수 호출 명령 BL은 돌아갈 주소를 LR에 넣는다. 함수가 LR을 stack에 저장한 뒤 buffer overflow가 stack을 덮으면 공격자는 return 주소를 자신이 원하는 code로 바꿀 수 있다.

보호함수 호출 때 하는 일공격된 return 때 결과
PACPACIASP가 LR, instruction key와 현재 SP로 서명을 만들어 pointer 상위 bit에 넣는다.AUTIASP 인증이 실패해 유효한 return address를 얻지 못한다.
GCS일반 data stack과 별도의 보호된 Guarded Control Stack에도 예상 return state를 기록한다.일반 stack의 return address와 보호 copy가 다르면 예외가 발생한다.
BTI간접 호출이 도착해도 되는 함수 entry에 BTI c 같은 landing pad를 둔다.공격자가 함수 중간 instruction으로 간접 branch하면 landing-pad 검사가 막는다.

PAC를 사용한 전형적 함수 골격

function:
    paciasp                 // LR을 key IA + SP context로 서명
    stp x29, x30, [sp, #-16]!
    ...                     // 함수 본문
    ldp x29, x30, [sp], #16
    autiasp                 // LR 서명 확인
    ret

modifier에 SP를 쓰면 다른 stack frame에서 가져온 서명된 return address를 그대로 재사용하기 어렵다. 하지만 올바른 key와 context로 이미 서명된 pointer의 논리적 오용까지 막는 것은 아니다.

Checked Pointer Arithmetic

v9.5 계열의 Checked Pointer Arithmetic은 pointer 계산에서 address space 범위를 벗어나거나 예상하지 못한 wrap이 생기는 것을 검사하도록 돕는다. MTE가 접근 시 tag를 검사하고 PAC가 pointer 무결성을 검사한다면, CPA는 pointer를 만드는 산술 단계의 오류를 겨냥한다.

서로 대체하지 않는다: CPA, MTE, PAC, BTI와 GCS는 각각 arithmetic, memory temporal/spatial bug 탐지, pointer 인증, indirect branch, return 흐름을 담당한다. threat model에 맞춰 compiler·OS·loader까지 함께 켜야 한다.

실제 Linux에서 확인할 것

  1. getauxval(AT_HWCAP)AT_HWCAP2로 SVE2·SME·MTE·PAC·BTI·GCS 세부 bit를 확인한다.
  2. prctl() 반환값으로 SVE/SME VL과 MTE fault mode, GCS process policy를 확인한다.
  3. signal handler와 debugger가 가변 크기 context record를 안전하게 순회하는지 검사한다.
  4. compile option만 보고 배포하지 말고 illegal instruction fallback과 runtime dispatch를 시험한다.
  5. dmesg에서 feature 비활성화, 이질 CPU 제약과 erratum workaround를 확인한다.

Linux가 큰 CPU 상태를 관리하는 방법

명령 설명에서 멈추지 않고 task 전환, signal frame, vector length 설정과 MTE fault 처리로 이어진다.

공식 자료