
Rust로 작성된 RISC-V 에뮬레이터로, ARM64/x86_64에서 JIT로 Linux를 부팅하고 Sv39 가상 메모리를 지원합니다.
Rust로 작성된 RISC-V 에뮬레이터입니다. Linux를 부팅합니다.
이 머신은 RV64IMAFDC, M/S/U 권한 레벨, Sv39 가상 메모리를 구현합니다.
ARM64 및 x86_64 호스트에서 JIT를 실행하며, 필요시 인터프리터로 대체됩니다.
주변장치로는 UART 16550, CLINT, PLIC, SBI 1.0이 있습니다. 외부 의존성은 zstd 하나입니다.
가장 빠른 에뮬레이터는 아닙니다. 인터프리터 모드에서는 QEMU보다 약 3배 느립니다. JIT 모드에서는 약 29배 느립니다. 코드 블록 체이닝은 아직 구현되지 않았습니다. 그것이 도움이 될 것입니다. 어떤 성능을 기대해야 하는지 알 수 있도록 솔직히 말씀드립니다.
잘하는 점: 사용이 간단하고, 머신 제어를 위한 HTTP API를 제공하며, 커널 없이 베어메탈 ELF를 실행할 수 있고, 전체 머신 상태를 저장하고 복원할 수 있습니다. 이는 시스템 작업 및 테스트에 유용합니다.
cargo build --release
바이너리는 target/release/emuko에 생성됩니다. 별칭을 만드십시오.
alias emuko=target/release/emuko
emuko dow
Debian RISC-V netboot 커널과 initrd를 ~/.emuko/에 다운로드합니다.
SHA256이 검증됩니다. 별도의 커널이 필요하지 않습니다.
emuko start
에뮬레이터가 데몬으로 실행됩니다. 콘솔에 연결됩니다. 커널이 부팅되는 것을 볼 수 있습니다. 셸에 접속하게 됩니다.
| 키 | 효과 |
|---|---|
| Ctrl+] | 분리 (데몬은 계속 실행) |
| Ctrl+C | 게스트에서 인터럽트 |
| Ctrl+D | 게스트에서 EOF |
emuko start # 콘솔 재연결
emuko dump # CPU 상태 출력
emuko stop # 실행 일시 정지
emuko con # 계속 실행
emuko step 1000 # N개 명령어 단일 스텝
emuko snap # 스냅샷 생성
emuko kill # 종료
데몬은 http://127.0.0.1:7788/v1/api/에서 수신하며, WebSocket 콘솔 연결을
ws://127.0.0.1:7788/v1/ws/uart에서 수락합니다. 둘 다 스크립트에서 사용할 수 있습니다.
때로는 운영 체제가 필요하지 않을 때가 있습니다. 머신과 바이너리만 있으면 됩니다.
emuko run ./my_program.elf
데몬이 머신을 리셋하고, ELF 세그먼트를 물리 주소에 로드한 후 실행을 시작합니다. 출력은 UART 콘솔을 통해 수신됩니다. 데몬이 이미 실행 중이어야 합니다.
베어메탈에서 콘솔에 출력하려면: 0x1000_0000에 바이트를 저장하세요.
examples/ 디렉터리에는 이 방식으로 실행되는 프로그램이 있습니다.
| 예제 | 설명 |
|---|---|
bare_printf | 1천만 반복마다 메시지를 출력합니다. libc 없음. 직접 UART 쓰기. |
RISC-V 크로스 컴파일러가 필요합니다.
macOS: brew install riscv64-elf-gcc
Linux: apt install gcc-riscv64-linux-gnu
emuko start
cd examples/bare_printf
make run
머신 상태(레지스터, 메모리, 모든 것)를 저장하고 복원할 수 있습니다.
emuko snap # 지금 스냅샷
emuko snap 5000000 # 5M 스텝마다 자동 스냅샷
emuko snap stop # 자동 스냅샷 중지
emuko ls # 스냅샷 목록
emuko restore <snapshot> # 복원
가상 머신은 QEMU RISC-V virt 플랫폼과 호환되는 고정 MMIO 레이아웃을 사용합니다.
| 영역 | 기본주소 | 크기 | 비고 |
|---|---|---|---|
| CLINT | 0x0200_0000 | 64 KiB | 타이머 및 소프트웨어 IRQ |
| PLIC | 0x0C00_0000 | 4 MiB | 32개 인터럽트 소스 |
| UART | 0x1000_0000 | 256 B | NS16550A, IRQ 10 |
| RAM | 0x8000_0000 | 1 GiB | 설정 가능 |
기본 설정(load_addr=0x80200000, 1 GiB RAM) 기준:
0x8000_0000 ── RAM 기본
(간격 — 베어메탈 프로그램에서 사용 가능)
0x8020_0000 ── 커널 이미지
│ .text / .rodata / .data / .bss
└─ 커널 끝
(사용 가능)
── initrd
── DTB
── EFI 영역 (128 KiB, PE/UEFI 커널만)
0xBFFF_FFFF ── RAM 끝
DTB, initrd, EFI는 RAM 상단에서 아래로 배치됩니다. 에뮬레이터는 부팅 시 커널과의 중복을 확인하고, RAM이 너무 작으면 명확한 오류와 함께 중지됩니다.
ELF PT_LOAD 세그먼트는 해당 p_vaddr 주소에 배치됩니다.
bare_printf는 0x8000_0000에 링크됩니다:
0x8000_0000 ── .text
── .rodata
── .data
── .bss (start.S에 의해 0으로 초기화)
── stack (BSS 위 16 KiB)
커널 없음. initrd 없음. DTB 없음. 레지스터는 sp를 제외하고 0에서 시작합니다. sp는 에뮬레이터가 ram_base + 0x100000으로 설정하며, 이후 start.S가 제어를 이어받습니다.
옵션은 명령줄, 환경 변수, 또는 emuko.yml 파일을 통해 전달할 수 있습니다.
| 옵션 | 환경 변수 | 기본값 | 설명 |
|---|---|---|---|
--ram-size | RAM_SIZE | 1 GB | RAM 크기 (바이트) |
--backend | EMUKO_BACKEND | adaptive | adaptive, arm64_jit, amd64_jit, arm64, x86_64 |
--bootargs | BOOTARGS | 직렬 콘솔 | 커널 명령줄 |
일반적으로 사용되는 RISC-V 에뮬레이터와의 직접 비교입니다.
✅ = 지원 및 문서화, — = 내장되지 않음.
| 기능 | emuko | QEMU | Spike | Renode |
|---|---|---|---|---|
| JIT / 동적 변환 | ✅ | ✅ | — | — |
| 스냅샷 저장 및 복원 | ✅ | ✅ | — | ✅ |
| 주기적 자동 스냅샷 | ✅ | — | — | ✅ |
| 머신 제어용 HTTP API | ✅ | — | — | — |
| WebSocket UART 콘솔 | ✅ | — | — | — |
| 스크립트 가능 UART 호스트 브리지 | ✅ | — | — | ✅ |
| 베어메탈 ELF 업로드 (OS 없음) | ✅ | — | — | — |
| 원클릭 커널 다운로드 + SHA256 | ✅ | — | — | — |
| JIT-vs-인터프리터 차등 검사기 | ✅ | — | — | — |
| GDB 디버깅 | — | ✅ | ✅ | ✅ |
| 대규모 장치 생태계 (PCIe, virtio) | — | ✅ | — | — |
| 다중 노드 시뮬레이션 | — | — | — | ✅ |
| 광범위한 ISA 지원 (RVV, 암호화 등) | — | — | ✅ | — |
출처: QEMU virt · Spike · Renode
Apache 2.0. LICENSE 참조.