
QRV는 최신 64비트 하드웨어를 위해 QNX Neutrino 6.4 운영체제를 처음부터 다시 적응시키고 재구현한 것입니다. 주요 아키텍처는 **RISC-V(rv64g)**이며, x86-64는 보조 대상입니다. 이 프로젝트는 2020년 크리스마스 이브에 시작되었습니다. QRV라는 이름은 QNX 상표와의 연관성을 의도적으로 피한 것입니다.
QRV는 단순한 커널이 아니라 전체 운영체제입니다. 마이크로커널은 그 핵심이지만, 작업의 더 큰 부분은 그 주변을 둘러싼 모든 것에 투입되었습니다. 가장 주목할 만한 것은 taskman으로, QNX의 procnto에 해당하는 사용자 모드 프로세스/메모리/경로 관리자입니다. taskman은 깊이 재작업되어 커널 밖으로 끌어내져 사용자 공간으로 옮겨졌습니다. 그와 함께 C 라이브러리, 장치 드라이버, 파일시스템, 동적 로더, 시스템 서버도 모두 포팅되고 64비트에 맞게 정리되었으며, 많은 부분이 실질적으로 다시 작성되었습니다. 마이크로커널은 의도적으로 작게 유지되며, QRV의 대부분은 그 주변의 운영체제에 존재합니다.
이것은 새 컴파일러에서 옛 코드를 컴파일하는 단순한 포크가 아닙니다. 독점적인 procnto 경계를 해체하고, IFS/startup 메커니즘을 교체하며, 가장 최근 릴리스부터는 커널의 Big Kernel Lock을 완전히 제거하고 프로세스/메모리/경로 관리자를 커널 밖의 사용자 모드 서버로 옮긴, 진정한 LP64 모델로의 신중한 모듈별 포팅입니다.
이 README는 QRV v0.43을 설명합니다.
개발 블로그에는 포팅의 전체 이야기가 있습니다: https://r-tty.blogspot.com. 책 한 권 분량의 서사 QRV 포팅 이야기는 소스 트리의 doc/tex/PortingStory/에 있습니다.
QRV는 Claude Code(Anthropic의 에이전틱 코딩 도구)와 긴밀히 협력하여 개발되었습니다. 포팅, SMP 디버깅, 문서화(이 README 포함)의 상당 부분이 저자와 함께하는 인간-AI 페어 프로그래밍 작업으로 수행되었습니다.
obtain_proj.sh 및 os/ 트리TM_PRIV 특권 시스템 콜devb-nvme 및 fs-qrvQNX는 마이크로커널 실시간 운영체제로, 그 핵심 개념은 동기식 메시지 전달입니다. QNX에서 커널 자체는 아주 작습니다. 스레드를 스케줄링하고, 메시지를 전달하고, 시그널을 전달하고, 타이머와 인터럽트를 처리하는 방법 정도만 알 뿐입니다. 모놀리식 OS가 커널 내부에 두는 모든 것, 즉 프로세스 관리자, 메모리 관리자, 파일시스템, 장치 드라이버, 네트워크 스택은 리소스 관리자라는 일반 사용자 프로세스로 실행되며, 서로 및 클라이언트와 동일한 send / receive / reply IPC 프리미티브를 통해 통신합니다.
이 아키텍처가 QNX를 우아하게 만드는 이유이며, QRV가 정확히 보존하는 부분입니다. 파일을 열려는 프로그램은 메시지를 보냅니다. 파일시스템 서버가 그 메시지를 수신하고 작업을 수행한 후 응답합니다. 커널은 단지 그 만남을 중개할 뿐입니다. 그 결과는 드라이버가 커널을 무너뜨리지 않고 충돌 후 재시작될 수 있고, 신뢰할 수 있는 컴퓨팅 베이스가 수십 킬로바이트 단위로 측정되며, "커널"과 "애플리케이션" 사이의 경계가 시스템 콜로 가득 찬 권한 벽이 아니라 메시지 하나가 되는 시스템입니다.
QRV는 2009년 시대의 QNX Neutrino 6.4 커뮤니티 소스를 가져와 그 설계를 앞으로 끌어옵니다.
int/uint32_t/pid_t로 취급해 발생하는 절단 문제를 찾아 수정합니다.qemu-system-riscv64(virt 머신)와 SiFive Unmatched(FU740) 개발 보드입니다. x86-64는 이식성 확인용으로 계속 빌드됩니다.mkifs도 없습니다(QRV는 대신 표준 CPIO 형식을 사용합니다). 분리된 startup/커널 분할도 없습니다(startup은 커널에 직접 링크됩니다). callout도 미니 드라이버도 없습니다.Kconfig 구성, 증분 커널 링크(모듈을 32→64 모놀리스로 링커에 한꺼번에 던지는 것이 아니라 하나씩 추가하고 테스트), 크로스 컴파일러 툴체인(riscv64-linux-gnu-gcc).procnto는 전체에서 taskman(태스크 관리자)으로 불립니다. "Neutrino" 참조는 모두 제거되었습니다.QRV는 fork()를 구현하지 않습니다(프로그램은 posix_spawn()으로 시작합니다). 또한 demand paging과 swap이 없습니다 — 이는 QNX 자체가 8.0 세대에서 선택한 것과 같은 결정입니다.
QRV는 동시에 두 가지 라이선스의 적용을 받습니다. 무엇을 빌드하거나 재배포하기 전에 둘 사이의 관계를 이해하는 것이 필수적입니다.
QRV 고유 코드는 Apache License 2.0입니다. 이 프로젝트를 위해 처음부터 작성된 모든 것, 즉 RISC-V 포트, 새 빌드 시스템, 사용자 모드 taskman 분할, 잠금 없는 커널 재작업, 우리가 작성한 드라이버와 도구는 Apache 2.0입니다. 전문은 **LICENSE.txt**에 있습니다.
QNX 파생 코드는 BlackBerry QNX Community License(QCL) 2.0입니다. 2009년 QNX Neutrino 커뮤니티 소스에서 파생된 QRV의 부분은 QCL 아래에 남아 있으며, QCL은 파생 소스의 비상업적 및 학술적 사용을 허용합니다. QRV는 QNX의 코드를 재라이선스하지 않으며, 할 수도 없습니다.
이 이중 라이선스 현실이 바로 이 저장소에 바로 빌드 가능한 소스 트리가 포함되지 않은 이유입니다. 우리는 QNX 파생 소스를 재배포할 수 없습니다. 따라서 코드를 제공하는 대신, 이 저장소는 레시피(다음 절 참조)를 제공합니다. 즉, 각 QNX 파일이 어디로 가야 하는지에 대한 지도와, 그 파일을 변환하는 QRV 패치입니다. 업스트림 QNX 커뮤니티 소스는 공개 미러에서 직접 구해야 하며, 레시피가 사용자 머신에서 QRV 트리를 재구성합니다. 여러분의 사본은 여러분의 것입니다. 우리는 우리 자신의 Apache 라이선스 패치와 메타데이터만 재배포합니다.
QRV는 또한 다른 허용적 라이선스의 코드도 포함합니다. 예를 들어 FreeBSD에서 채택한 BSD 라이선스 구성 요소(노후화된 QNX 모듈을 대체), xv6 계열의 MIT 라이선스 virtio 블록 드라이버, 시스템 셸로 사용되는 MirBSD Korn shell(mksh) 등이 있습니다. WHAT_IS_WHAT.md는 어떤 구성 요소가 어떤 라이선스 아래에 있고 어디서 왔는지에 대한 권위 있는 구성 요소별 분석입니다. 특정 파일이나 하위 시스템이 확실하지 않을 때마다 이 문서를 참조하십시오.
마지막으로, 저장소에는 **PETITION.md**가 포함되어 있습니다. 이는 QNX Software Systems와 BlackBerry에 2007~2009년의 역사적 Neutrino 소스를 허용적 OSI 승인 라이선스로 재라이선스해 달라는 공개 요청입니다. 이 작업의 기반이 언젠가 완전히 자유로워지기를 바란다면, 그 문서에 이름을 추가하면 됩니다.
obtain_proj.sh 및 os/ 트리QNX 파생 소스는 여기에서 재배포할 수 없으므로, 이 저장소는 소스 재구성 배포판입니다. 다음을 포함합니다.
$ ./obtain_proj.sh
1. **업스트림 QNX 커뮤니티 미러를 클론합니다** (`github.com/vocho/openqnx`,
얕은 클론).
2. **파일을 배치합니다** — `placement.txt`에 따라 각 업스트림
파일을 `os/` 아래의 QRV 위치로 복사합니다. 배치된 파일 수,
이미 있는 파일 수, 누락된 파일 수를 보고합니다.
3. **배치가 끝나면 클론을 제거합니다.**
4. **QRV 패치 시리즈를 적용합니다** — `patches/series`에서 순서대로. 각
패치는 LZ4 압축(`*.patch.lz4`)이며 `lz4cat … | patch -p1`로
적용됩니다. 패치에는 현재 릴리스의 버전이 포함되어 있습니다.
5. **실행 권한이 필요한 몇몇 스크립트에 실행 권한을 설정합니다**
(예: `emu.sh`, `host_tools/mkgpt.py`).
필요한 도구는 `git`, `patch`, `lz4cat`(`lz4` 패키지)입니다.
스크립트는 이를 먼저 확인하고 누락된 것이 있으면 설치 방법을 알려줍니다.
최종 산출물은 **`os/`** — 완전하고 빌드 가능한 QRV 소스 트리입니다:```
os/
├── kernel/ Everything linked into the qrv-kernel binary
│ ├── arch/riscv/ RISC-V port: vectors, traps, SBI, context switch,
│ │ ├── startup/ arch-specific startup (head.S, mmu.c, …)
│ │ ├── platform/ qemu_virt/, unmatched/
│ │ └── include/ context.h, cpu_paging.h, sbi.h, …
│ ├── startup/ arch-independent startup (hardware_init, smp, …)
│ ├── nano/ core nanokernel: messaging, scheduling, sync, xfer
│ ├── kext/ kernel extensions (kerexts)
│ └── include/ kernel-internal headers
├── taskman/ The Task Manager (QNX's "procnto"), a user-mode server
│ ├── sys/ system manager: main, ELF loader, support
│ ├── proc/ process manager: spawn, wait, …
│ ├── mem/ memory manager: page tables, physical allocator
│ │ └── pageman/ page-granularity virtual-memory operations
│ └── path/ path manager: namespace, /dev/*, /proc/*
├── lib/ C library and runtime
├── include/ User-space-visible headers (the public ABI)
├── userland/ Shell, utilities, drivers, servers (resource managers)
├── servers/ pci, slogger
├── dev/ Device drivers (virtio block, 8250 UART, …)
├── boot/ Boot artifacts and deploy helpers
├── host_tools/ Host-side tooling (mkgpt.py, …)
├── doc/ Documentation, incl. The QRV Porting Story (LaTeX)
├── Kconfig, Makefile, def.mk, common.mk, emu.sh
거기서 cd os && make를 실행하면 시스템이 빌드됩니다(§9 참조).
QRV는 진정한 마이크로커널 시스템입니다. 하드웨어부터 위로 올라가는 권한 스택은 RISC-V에서 다음과 같습니다:``` ┌───────────────────────────────────────────────────────────────────────┐ │ User space (U-mode) │ │ │ │ sh pidin lspci sloginfo login ... │ │ │ │ │ │ │ │ │ devb-nvme fs-qrv devc-ser* pci slogger ← resource managers │ │ │ │ │ │ │ │ │ │ └──────┴───────┴────────┴─────────┴───────┘ │ │ │ libc (send / receive / reply stubs) │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ taskman — process · memory · path manager │ │ │ │ a U-mode server, privileged via TM_PRIV │ │ │ └─────────────────────────────────────────────────────────────────┘ │ └────────────────────────────────────│──────────────────────────────────┘ │ ecall (syscall / message) ┌───────────────────────────────────────────────────────────────────────┐ │ QRV microkernel (S-mode) │ │ │ │ message passing · channels & connections · scheduling · │ │ threads · synchronization · signals · timers & clocks · │ │ interrupts · syscall dispatch · TM_PRIV kernel extensions │ └───────────────────────────────────────│───────────────────────────────┘ │ SBI ecall ┌───────────────────────────────────────────────────────────────────────┐ │ OpenSBI firmware (M-mode) │ └───────────────────────────────────────│───────────────────────────────┘ │ ┌───────────────────────────────────────────────────────────────────────┐ │ RISC-V 64-bit hardware — QEMU virt · SiFive Unmatched U740 │ └───────────────────────────────────────────────────────────────────────┘
**커널(S-모드)**은 고전적인 의미에서 특권 모드로 실행되는 유일한 구성 요소입니다.
하위 시스템은 작고 집중되어 있습니다:
- **메시지 전달** — `ker_message.c`, `ker_fastmsg.c`, `nano_message.c`
- **채널 및 연결** — `ker_channel.c`, `ker_connect.c`
- **스레드 및 스케줄링** — `ker_thread.c`, `ker_sched.c`, `nano_sched.c`
- **동기화** — `ker_sync.c`, `nano_sync.c`
- **시그널** — `ker_signal.c`
- **타이머 및 클록** — `ker_timer.c`, `ker_clock.c`
- **인터럽트** — `ker_interrupt.c`
- **시스템 콜 디스패치** — `ker_call_table.c`
- **데이터 전송** — `nano_xfer*.c` 패밀리(주소 공간 간
복사 엔진으로, 프로세스 간에 메시지 페이로드를 안전하게 옮깁니다)
부트스트래퍼와 커널 사이의 인터페이스는 **syspage**이며
(`include/sys/syspage.h`), CPU별 상태는 **cpupage**에 있고, 전체
레지스터 컨텍스트는 `RISCV_CPU_REGISTERS`입니다. RISC-V에서 각 "CPU"는
모든 곳에서 **hart ID**로 식별됩니다 — 단일 CPU 명명
네임스페이스가 끝에서 끝까지 존재합니다.
**그 외의 모든 것은 사용자 프로세스입니다.** 프로세스/메모리/경로 관리자,
블록 및 직렬 드라이버, 파일시스템, PCI 서버, 시스템
로거 — 모두 메시지를 보내 접근하는 리소스 관리자입니다.
커널에는 파일시스템이 포함되어 있지 않습니다. 커널이 가진 것은 한
프로세스가 다른 프로세스에게 *파일시스템이 되어 달라고* 요청할 수 있는 능력뿐입니다.
---
## 5. Taskman 및 특권 시스템 콜 `TM_PRIV`
**`taskman`**은 QNX가 `procnto`라고 부르던 것, 즉
**프로세스 관리자, 메모리 관리자, 경로(네임스페이스) 관리자**가 결합된 QRV의 이름입니다. 고전적인
QNX 시스템에서 이 코드는 커널 이미지에 융합되어 있습니다. QRV의
더 큰 구조적 성과 중 하나는 **taskman이 이제 사용자 모드에서 실행된다**는 것입니다 —
즉, 특권 커널의 일부가 아닌 일반 U-모드 프로세스입니다.
그렇다면 분명한 질문이 생깁니다: taskman이 사용자 공간에 있다면, 어떻게
프로세스 및 메모리 관리자가 반드시 해야 하는 깊이 특권화된 작업들 —
페이지 테이블 조작, 물리 RAM 할당, 주소 공간 생성 및 파괴,
시그널과 펄스 전달, 프로세스 종료 — 을 수행할 수 있을까요?
그 답은 단일하고 엄격하게 통제된 게이트웨이인 **`__KER_TM_PRIV`**
(시스템 콜 슬롯 2)입니다. 그것은 taskman이 커널 특권 작업에 도달하는 *유일한* 문이며,
그 하나의 슬롯 뒤에는 — 각각 하나의 명확히 정의된 특권 작업을 수행하고 반환하는
작은 **커널 확장**("kerexts") — **약 98개의 하위 작업**으로 구성된 디스패치 테이블이 있습니다.
몇 가지 대표적인
계열은 다음과 같습니다:
- **프로세스 수명 주기** — `PROCESS_CREATE`, `PROCESS_EXEC`,
`PROCESS_DESTROY`, `PROCESS_STARTUP`, `PROCESS_SHUTDOWN`, `REPARENT`
- **물리 및 가상 메모리** — `PA_ALLOC`, `PA_FREE`,
`PA_QUANTUM_TO_PADDR`, `PAGE_CONT`, `STACK_CONT`, `ASPACE_MEMCPY`
- **자격 증명 및 제한** — `CRED_GET`, `CRED_SET`, `LIMITS_GET/SET`
- **전달 및 객체** — `PULSE_DELIVER`, `SIGNAL_DELIVER`,
`QUERY_OBJECT`, `CHANNEL_DESTROY`, `CONNECT_DETACH`
- **SMP 및 플랫폼** — `SMP_BRINGUP`, `LEGAL_CPU_MASK`, `GET_KERN_PGDIR`,
`ICACHE_SYNC` (RISC-V 명령어 캐시 일관성 연산으로,
v0.43에서 새로 추가됨)
이 설계는 **신뢰 컴퓨팅 기반을 작게** 유지합니다 — 실제 커널은
최소한으로 유지되면서 — taskman에게 필요한 특권 프리미티브만 정확히,
**그 이상도 아니게** 제공합니다. 결정적으로, 커널 힙 및 기타 커널
내부는 U-모드에서 접근할 수 없습니다(커널 페이지는 `PTE_U=0` 유지).
taskman은 복사-입력/복사-출력 kerext를 통해 작업을 수행하며,
원시 커널 포인터를 넘겨받지 않습니다. 이 enum은
`kernel/include/ker+tm/tm_kercalls.h`에 있고, 디스패치 테이블은
`kernel/ker_tm_priv.c`에 있습니다.
---
## 6. 빅 커널 락 — 그리고 그 제거
초기 QRV — 다중 프로세서 시스템에서 비롯된 QNX 세대처럼 —
단일 **빅 커널 락(BKL)**으로 커널을 보호했습니다: 전역
`inkernel` 워드로, 한 번에 정확히 하나의 hart만 커널에 들어올 수 있었습니다.
CPU가 몇 개든 실행 중이든, 모든 시스템 콜과 모든 taskman
메시지는 그 하나의 락을 통해 직렬화되었습니다. 정확하고 단순하지만 —
SMP 확장성에는 단단한 상한선이었습니다.
**v0.42부터 BKL은 제거되었습니다.** 이것은 긴 일련의
릴리스 후보의 헤드라인이었으며 *The QRV Porting
Story*의 9~14장의 주제였습니다. 시스템 콜과 taskman 메시지는 이제
세분화된 객체별 락을 사용하여 **hart들에 걸쳐 동시에** 실행됩니다:
- **객체별 락킹.** `tChannel`별 락과 `tConnect`별 락이
메시지 큐를 보호하고, 프로세스별 `vec_slock`이 스레드 벡터를 보호하며,
디스패치별 `sched_slock`이 실행 큐를 보호하고, `alloc_slock`이
커널 힙을 보호합니다.
- **락-프리 메시지 전달.** `MsgSend` / `MsgReceive` / `MsgReply` 및
`Sync*` 계열은 **전역 락을 전혀 사용하지 않습니다.** hart 간 랑데부는
상호 배제가 아니라 스레드별 브리지 비트와 하드웨어 메모리 펜스로
조정됩니다.
- **SMR(RCU에 해당) 재활용.** 스레드, 연결, 채널은
안전 메모리 재활용(safe-memory-reclamation)을 통해 은퇴되므로 락-프리 조회가
해제된 객체를 역참조하지 않습니다.
QEMU `virt`에서 `-smp 8`로 커널은 `login:` 프롬프트까지
안정적으로 부팅되며 멈춤 없이 300회 반복 `pidin` 스트레스 루프를 견뎌냅니다.
---
## 7. 저장소: `devb-nvme` 및 `fs-qrv`
마이크로커널 모델에 충실하게, QRV의 저장소는 커널 하위 시스템이 아니라
**협력하는 두 개의 사용자 프로세스**입니다:
- **`devb-nvme`** — 블록 디바이스 드라이버. PCIe를 통해 NVMe를 사용하며(
GPT 파티션 파싱 내장), PCI 서버를 통해 컨트롤러를 발견하고
`/dev/nvme0n1` 및 해당 파티션과 같은 블록 디바이스를
제공합니다. (`devb-virtio` 형제 드라이버는 에뮬레이션된 타깃을 위해
QEMU virtio-blk 디바이스를 구동합니다.)
- **`fs-qrv`** — 파일시스템 리소스 관리자. 파티션을 마운트하고
메시지 전달을 통해 POSIX 파일시스템 네임스페이스를 제공합니다:
애플리케이션의 `open`/`read`/`write`/`close`는 `fs-qrv`가
응답하는 메시지가 됩니다.
일반적인 부팅 과정은 실제 NVMe 파티션을 마운트하고 그 파티션에서 프로그램을 실행합니다:```
mount -t qrv /dev/nvme0n1p5 /disk2
이 경로(블록 드라이버, 파티셔닝, 파일시스템 서버, 그리고 그들 사이의 모든 메시지를 중개하는 커널)는 QEMU와 SiFive Unmatched의 NVMe 드라이브에서 모두 엔드투엔드로 실행된다.
QRV는 sysinit/init으로 부팅하며 직렬 콘솔 드라이버
(QEMU에서는 devc-ser8250, FU740에서는 devc-sersifive), PCI 서버,
스토리지 스택, getty/login을 기동한 다음 셸 프롬프트에 도달시킨다.
주요 사용자 공간 프로그램:
sh — mksh, MirBSD Korn 셸. 실제로 스크립트 가능한 POSIX 셸이
시스템 셸이며, 부트 스크립트(level1.sh, …)는 일반적인 셸
스크립트다.pidin — 고전적인 QNX "프로세스 정보" 도구: 프로세스,
스레드, 상태, 메모리 등을 나열한다. QRV의 주요 "시스템이
살아 있고 정상인가?" 프로브이자 표준 스트레스 테스트 워크로드다.lspci — PCI 서버를 통해 PCI/PCIe 버스를 열거한다.sloginfo — slogger 서버가 수집한 시스템 로그를 덤프한다.이와 함께 사용 가능한 다중 사용자 시스템의 기본 구성 요소가 있다:
getty와 login (자격 증명/인증 지원 포함), mount, shutdown,
pipe, 그리고 핵심 유틸리티(ls, cat, …)가 있다. 모든 QRV 프로그램은
다중 스레드 — 최소한 메인 스레드와 시스템 스레드를 가지며 — 이는
올바른 SMP 동기화(§6 참조)가
그토록 중요한 바로 그 이유다.
Cross-compiler : riscv64-linux-gnu-gcc CPU flags : -march=rv64g -mcmodel=medany -mno-relax Build style : -nostdinc -nostdlib -ffreestanding
### 일반적인 명령 (`os/` 내에서 실행)```bash
make # Build everything: startup + kernel + module package
make -Bj # Force a full parallel rebuild (do this after header changes)
make startup # Build startup only
make kernel # Build kernel only
make modpkg # Create the module package (CPIO)
make qemu # Build and run in QEMU
./emu.sh # Run in QEMU (4 CPUs, 256M RAM, virt machine)
./emu.sh -P 1 # Run with a single hart
./emu.sh -gdb # Run with the GDB remote stub (port 1234)
The primary test platform is qemu-system-riscv64 on the virt
machine. Configuration is Kconfig-based.
QRV의 부차적이면서도 진지한 목표는 SiFive Unmatched (FU740) — 실제 RISC-V 워크스테이션 보드 — 입니다. QEMU에서 깔끔하게 부팅되는 마이크로커널이 실제 실리콘에서도 깔끔하게 부팅되도록 만드는 과정에서 에뮬레이션에서는 전혀 나타나지 않는 부류의 버그들이 드러났으며, 그 버그들을 추적하는 것이 최근 릴리스가 주로 하는 일입니다.
이를 보여주는 대표 사례는 v0.43에서 수정되었습니다. 두 달 동안 QRV는 QEMU에서 완벽하게 실행되었고 실제 하드웨어에서는 오류를 일으켰습니다. FU740에서는 어떤 프로그램 — pidin, lspci, 무엇이든 — 이 몇 번의 스폰 후 크래시가 났으며, 크래시마다 그 양상이 달랐고 프로그램 카운터는 쓰레기값으로 흘러갔습니다. 원인은 메모리 손상이 전혀 아니라 명령어 캐시 불일치였습니다. RISC-V는 데이터 저장과 명령어 인출 사이의 일관성을 보장하지 않으므로, 갓 로드된 프로그램 코드는 해당 hart가 fence.i를 실행할 때까지 hart의 인출 유닛에 보이지 않습니다. 그리고 코드를 로드한 hart가 아닌 다른 hart에서 실행될 코드는 그 hart에서 원격 fence.i가 필요합니다. QRV의 로더는 둘 다 수행하지 않았습니다 (심지어 "I-캐시 무효화" 플래그를 계산한 후 그대로 버렸습니다). QEMU는 명령어 캐시를 모델링하지 않으므로 그 버그는 QEMU에서는 보이지 않았고 U74에서는 결정적으로 발생했습니다.
수정 — 페이지가 실행 가능해질 때마다 로컬 및 SBI 브로드캐스트 fence.i (cpu_icache_sync_all())를 수행하는 것 — 은 FU740에서 몇 번 실행할 때마다 오류가 나던 스폰 루프를 600회 연속 스폰을 깨끗하게 통과하는 루프로 바꾸어 놓았습니다. 처음에 만들었던 잘못된 가설과 그 가설을 뒤집은 진단을 포함한 전체 조사 과정은 The QRV Porting Story 14장의 마지막 절에 있습니다.
지금까지 달성한 하드웨어 이정표에는 FU740의 사용자 모드 taskman에서 login: 프롬프트까지 부팅하는 것과 실제 NVMe 파티션에서 테스트 프로그램을 마운트하고 실행하는 것이 포함됩니다.
QNX는 지금까지 출시된 마이크로커널 설계 중 가장 영향력 있는 것 중 하나입니다. 그 send/receive/reply 모델은 여러 세대의 시스템 엔지니어에게 깔끔한 OS 아키텍처가 어떤 모습인지 가르쳐 주었습니다. 그런데도 그것을 구현한 코드는 10년 넘게 특이한 애매한 상태에 머물러 있었습니다. 커뮤니티 라이선스로 연구할 수 있을 만큼은 공개되어 있었지만, 재배포하거나 진화시키거나 그 주변에 살아있는 생태계를 구축할 만큼 자유롭지는 않았습니다. 이렇게 좋은 설계는 읽기 전용 유물로만 보존되기에는 아깝습니다.
이 작업이 존재하는 이유가 바로 그것입니다. QRV는, 솔직히 말하면, 과도기적 수단입니다 — 포팅을 통해 아키텍처를 깊이 배우고, 분해하고 새 하드웨어에서 다시 조립하며, 커널 락을 제거하고 프로세스 매니저를 사용자 공간으로 끌어올려 정확히 어떤 가정이 하중을 견디는 것인지 발견하는 방법 말입니다. 실제 실리콘에서 추적해낸 모든 버그, 64비트에 맞게 다시 작성된 모든 서브시스템, 해체된 모든 독점 경계는 진정한 자유 구현이 필요로 하는 지식입니다.
장기적 목표는 남의 소스에 패치한 복사본을 영원히 유지하는 것이 아니기 때문입니다. 그것은 QNX의 인터페이스와 호환되고 그 마이크로커널 철학에 충실하면서도 독점 코드에 전혀 빚지지 않는, 완전히 자유롭고 처음부터 새로 만든 운영체제입니다 — 누구의 허락도 없이 사용하고, 가르치고, 배포하고, 개선할 수 있는 운영체제 말입니다. QRV는 그러한 시스템이 가능할 뿐만 아니라 실용적임을 증명하는 방법이자, 그것을 제대로 구축할 경험을 쌓는 방법입니다.
역사적 기반 자체가 자유로워지기를 바란다면 **PETITION.md**에 이름을 추가하세요. 그리고 현대적이고 정직하게 엔지니어링된 마이크로커널의 내부가 어떤 모습인지 보고 싶다면 — 레시피를 클론하고, obtain_proj.sh를 실행하고, 코드를 읽어보세요.
QRV — 64비트 하드웨어를 위한 QNX Neutrino 6.4의 적응 및 재구현. 2020년 크리스마스 이브에 시작. Apache 2.0 (QRV 자체 코드) + BlackBerry QCL 2.0 (QNX 파생 소스). 구성 요소별 분석은 WHAT_IS_WHAT.md를 참조하세요.
| 파일 / 디렉터리 | 용도 |
|---|
obtain_proj.sh | 재구성 스크립트 — 실행하세요. |
placement.txt | 각 업스트림 QNX 경로를 QRV 경로에 매핑합니다(≈680개 항목). |
patches/ | LZ4로 압축된 QRV 패치 시리즈와 series 순서 파일. |
LICENSE.txt | Apache License 2.0. |
WHAT_IS_WHAT.md | 구성 요소별 라이선스 및 출처. |
PETITION.md | 재라이선스 청원. |