Hacker News

The Lost Atomic Update on Loongson CPU

Loongson CPU에서 사라지는 원자적 갱신

Loongson LA664 코어에서 벡터 메모리 읽기와 특정 원자 연산이 겹칠 때 갱신이 누락되는 CPU 결함이 발견됐습니다. 이 결함은 Debian 패키지 빌드의 무한 루프와 Rust 프로그램의 메모리 손상으로 이어졌으며, Loongson은 성능 저하가 적은 펌웨어 수정안을 마련했습니다.

AI 요약

Debian용 LoongArch 패키지를 빌드하던 중 수학 소프트웨어 normaliz의 테스트가 무한 루프에 빠졌습니다. 병렬 처리 코드에서는 처리한 항목 수를 OpenMP의 원자적 증가 연산으로 세는데, 실제 처리가 끝나도 두 카운터 값이 서로 달랐습니다. 조사 결과 컴파일러나 소프트웨어가 아니라 Loongson LA664 CPU의 원자 연산이 특정 조건에서 갱신을 놓치는 결함으로 밝혀졌습니다.

원인 추적

처음에는 LoongArch의 약한 메모리 모델에서 생긴 경쟁 상태를 의심했습니다. 하지만 문제 코드가 원자 변수만 읽고 쓰는 구조였고, 디스어셈블리에서도 컴파일러는 예상한 amadd.d 명령을 생성했습니다. 간단한 테스트에서는 문제가 재현되지 않아 원인을 좁히지 못했습니다.

6개월 뒤 조사팀은 AI를 활용해 normaliz 코드를 최소 재현 프로그램으로 줄였습니다. AI는 처리 함수 안의 memcpy에 주목했습니다. glibc는 지원하는 하드웨어 기능에 따라 memcpy 구현을 고르는데, LASX가 켜져 있으면 벡터 명령을 사용합니다. 이 벡터 메모리 읽기가 원자 연산의 갱신 누락을 유발했습니다. 안정적인 재현 프로그램을 얻기까지 약 이틀이 걸렸습니다.

결함이 나타나는 조건과 범위

실험에서 결함 재현에는 세 조건이 필요했습니다. 스레드가 서로 다른 물리 코어에서 실행되고, 같은 주소에 데이터 장벽 없는 원자 연산을 하며, 적어도 한 스레드가 원자 연산 사이에 메모리를 읽어야 합니다. 대개 LASX의 256비트 읽기 명령 xvld가 이 읽기 역할을 했습니다. 다만 원자 변수와 읽기 주소의 배치가 특정 관계를 이루면 일반 스칼라 읽기도 결함을 일으킬 수 있습니다. 반면 LSX의 128비트 읽기는 재현되지 않았습니다.

문제는 덧셈에 그치지 않았습니다. 조사팀은 CAS, 최댓값, 교환 연산에서도 갱신 누락을 확인했습니다. 3C6000/S에서 두 물리 코어를 사용해 시험한 결과, 양쪽 스레드가 LASX 읽기를 할 때 amadd.d는 30회 중 30회, ammax.d와 amswap.d는 각각 30회 중 30회 시험에서 문제가 나타났습니다. 이는 각 시험의 실패 비율이며, amcas_db.d처럼 데이터 장벽을 포함한 명령은 같은 조건에서 실패하지 않았습니다.

소프트웨어 영향과 수정

원자적 증가 연산 amadd는 참조 횟수 관리에 흔히 쓰입니다. 증가가 누락되면 실제 참조보다 카운터가 작아져 객체가 일찍 해제될 수 있습니다. 조사팀은 Rust의 std::sync::Arc와 std::sync::mpsc::Sender에서도 데이터 장벽 없는 amadd 사용을 확인했고, 두 기능을 이용한 안전한 Rust 프로그램에서 SIGABRT나 힙 손상이 발생하는 사례를 만들었습니다. 공격에 악용하려면 같은 프로세스 안에서 두 스레드가 같은 객체의 카운터를 동시에 건드려야 해, 프로세스 격리를 넘는 공격은 어렵다고 설명합니다.

일반 애플리케이션은 컴파일러가 어떤 원자 명령을 내보낼지 직접 제어하기 어렵습니다. 소프트웨어 차원에서는 데이터 장벽을 포함한 명령을 쓰거나 LL/SC 반복문으로 연산을 구현할 수 있지만, 기존 바이너리에는 전체 재컴파일이 필요합니다. Loongson은 2026년 8월 26일 보고를 받은 뒤 9월 9일 시험 펌웨어를 제공했습니다. MCSR24의 13번 비트를 켜면 결함이 사라졌고, 단일 코어 성능 저하는 없으며 멀티코어 성능 저하는 작았습니다. 회사는 10월 1일 전 펌웨어 공개를 예상한다고 밝혔습니다. 펌웨어를 기다리지 않는 사용자는 Linux 커널에서 해당 비트를 직접 설정하는 방법도 있습니다.

Hacker News 반응

  • @TazeTSchnitzel — “MCSR24의 13번 비트를 1로 설정하는 것이 수정 방법입니다. MCSR24는 기능이 매뉴얼에 설명되지 않은 내부 CSR입니다. 이 비트를 설정하면 갱신 누락이 더는 발생하지 않습니다. 시험 결과 성능 저하는 매우 작습니다. 단일 코어 성능에는 영향이 없고 멀티코어 성능만 조금 떨어집니다.” 아마 이른바 ‘치킨 비트(chicken bit)’겠네요.
    • @monocasa — 딱 그런 말의 정의에 가깝네요. 버그가 있는 것으로 드러난 최적화 기능을 끄는 비트가 문서화되지 않은 레지스터에 들어 있는 거죠.
    • @aleph_minus_one — “‘치킨 비트’라는 말을 처음 들으신 분들을 위해: https://lwn.net/Articles/744840/ 를 보세요. https://en.wiktionary.org/wiki/chicken_bit 의 인용문 목록에도 이 용어가 쓰인 과학 문헌이 나옵니다.
    • @oynqr — 차라리 닭장을 벗어난 쪽이겠네요.
    • @jacquesm — 첫 GPS 위성에도 그런 비트가 있었습니다. 아인슈타인이 틀렸을 경우를 대비해서였죠. 틀린 건 아인슈타인이 아니었습니다. https://www.quora.com/Why-did-the-GPS-system-initially-resis...
  • @xyzsparetimexyz — Wang Miao요? 이거 소폰(sophons) 탓인가요?

원문: Hacker News / 번역·요약: Trawling