Skip to content

Commit ab8c9c3

Browse files
committed
Step 0-1: add a hello-world hypervisor
1 parent 9739b31 commit ab8c9c3

18 files changed

Lines changed: 808 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Build CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
clippy:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
arch: [x86_64]
12+
steps:
13+
- uses: actions/checkout@v2
14+
- uses: actions-rs/toolchain@v1
15+
with:
16+
profile: minimal
17+
toolchain: nightly-2022-11-03
18+
override: true
19+
components: rust-src, clippy, rustfmt
20+
- name: Clippy
21+
run: make -C hypervisor clippy ARCH=${{ matrix.arch }}
22+
- name: Check code format
23+
run: cd hypervisor && cargo fmt -- --check
24+
25+
build:
26+
runs-on: ${{ matrix.os }}
27+
strategy:
28+
fail-fast: false
29+
matrix:
30+
os: [ubuntu-latest]
31+
arch: [x86_64]
32+
steps:
33+
- uses: actions/checkout@v2
34+
- uses: actions-rs/toolchain@v1
35+
with:
36+
profile: minimal
37+
toolchain: nightly-2022-11-03
38+
components: rust-src, llvm-tools-preview
39+
- uses: actions-rs/install@v0.1
40+
with:
41+
crate: cargo-binutils
42+
version: latest
43+
use-tool-cache: true
44+
- name: Build hypervisor
45+
run: make -C hypervisor ARCH=${{ matrix.arch }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
target
22
.vscode
33
.DS_Store
4+
rvm/Cargo.lock
5+
!hypervisor/Cargo.lock

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
11
# RVM-Tutorial
22

33
Let's write an x86 hypervisor in Rust from scratch!
4+
5+
## Install Build Dependencies
6+
7+
Install [cargo-binutils](https://github.com/rust-embedded/cargo-binutils) to use `rust-objcopy` and `rust-objdump` tools:
8+
9+
```console
10+
$ cargo install cargo-binutils
11+
```
12+
13+
## Build & Run Hypervisor
14+
15+
```console
16+
$ cd hypervisor
17+
$ make run [LOG=warn|info|debug|trace]
18+
......
19+
Booting from ROM..
20+
21+
RRRRRR VV VV MM MM
22+
RR RR VV VV MMM MMM
23+
RRRRRR VV VV MM MM MM
24+
RR RR VV VV MM MM
25+
RR RR VVV MM MM
26+
___ ____ ___ ___
27+
|__ \ / __ \ |__ \ |__ \
28+
__/ / / / / / __/ / __/ /
29+
/ __/ / /_/ / / __/ / __/
30+
/____/ \____/ /____/ /____/
31+
32+
arch = x86_64
33+
build_mode = release
34+
log_level = info
35+
......
36+
```

hypervisor/Cargo.lock

Lines changed: 117 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hypervisor/Cargo.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "rvm-hypervisor"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Yuekai Jia <equation618@gmail.com>"]
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
log = "0.4"
11+
spin = "0.9"
12+
cfg-if = "1.0"
13+
bitflags = "1.3"
14+
15+
[target.'cfg(target_arch = "x86_64")'.dependencies]
16+
x86 = "0.52"
17+
x86_64 = "0.14"

hypervisor/Makefile

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Arguments
2+
ARCH ?= x86_64
3+
MODE ?= release
4+
LOG ?= warn
5+
6+
export ARCH
7+
export MODE
8+
export LOG
9+
10+
# Paths
11+
target_elf := target/$(ARCH)/$(MODE)/rvm-hypervisor
12+
target_bin := $(target_elf).bin
13+
14+
build_args := --target $(ARCH).json -Zbuild-std=core,alloc -Zbuild-std-features=compiler-builtins-mem
15+
ifeq ($(MODE), release)
16+
build_args += --release
17+
endif
18+
19+
# Binutils
20+
OBJDUMP := rust-objdump -d --print-imm-hex --x86-asm-syntax=intel
21+
OBJCOPY := rust-objcopy --binary-architecture=$(ARCH)
22+
GDB := gdb-multiarch
23+
24+
# QEMU
25+
qemu := qemu-system-$(ARCH)
26+
qemu_args := -nographic -m 128M
27+
28+
qemu_args += -cpu host -accel kvm
29+
30+
ifeq ($(ARCH), x86_64)
31+
qemu_args += \
32+
-machine q35 \
33+
-serial mon:stdio \
34+
-kernel $(target_elf)
35+
endif
36+
37+
build: $(target_bin)
38+
39+
$(target_bin): elf
40+
@$(OBJCOPY) $(target_elf) --strip-all -O binary $@
41+
42+
elf:
43+
@echo Arch: $(ARCH)
44+
cargo build $(build_args)
45+
46+
clean:
47+
cargo clean
48+
49+
clippy:
50+
cargo clippy $(build_args)
51+
52+
fmt:
53+
cargo fmt
54+
55+
disasm:
56+
@$(OBJDUMP) $(target_elf) | less
57+
58+
run: build justrun
59+
60+
justrun:
61+
$(qemu) $(qemu_args)
62+
63+
.PHONY: build elf clean clippy disasm run justrun

hypervisor/linker.lds

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
OUTPUT_ARCH(x86_64)
2+
3+
BASE_ADDRESS = 0xffffff8000200000;
4+
5+
ENTRY(_start)
6+
SECTIONS
7+
{
8+
. = BASE_ADDRESS;
9+
skernel = .;
10+
11+
.text : {
12+
stext = .;
13+
*(.text.boot)
14+
*(.text .text.*)
15+
. = ALIGN(4K);
16+
etext = .;
17+
}
18+
19+
.rodata : {
20+
srodata = .;
21+
*(.rodata .rodata.*)
22+
*(.srodata .srodata.*)
23+
. = ALIGN(4K);
24+
erodata = .;
25+
}
26+
27+
.data : {
28+
sdata = .;
29+
*(.data.boot_page_table)
30+
*(.data .data.*)
31+
*(.sdata .sdata.*)
32+
*(.got .got.*)
33+
. = ALIGN(4K);
34+
edata = .;
35+
}
36+
37+
.bss : {
38+
boot_stack = .;
39+
*(.bss.stack)
40+
. = ALIGN(4K);
41+
boot_stack_top = .;
42+
43+
sbss = .;
44+
*(.bss .bss.*)
45+
*(.sbss .sbss.*)
46+
. = ALIGN(4K);
47+
ebss = .;
48+
}
49+
50+
ekernel = .;
51+
52+
/DISCARD/ : {
53+
*(.eh_frame) *(.eh_frame_hdr)
54+
}
55+
}

hypervisor/src/arch/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cfg_if::cfg_if! {
2+
if #[cfg(target_arch = "x86_64")] {
3+
mod x86_64;
4+
pub use self::x86_64::*;
5+
}
6+
}

hypervisor/src/arch/x86_64/boot.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use core::arch::global_asm;
2+
3+
use x86_64::registers::control::{Cr0Flags, Cr4Flags};
4+
use x86_64::registers::model_specific::EferFlags;
5+
6+
use crate::config::{BOOT_KERNEL_STACK_SIZE, PHYS_VIRT_OFFSET};
7+
8+
const CR0: u64 = Cr0Flags::PROTECTED_MODE_ENABLE.bits()
9+
| Cr0Flags::MONITOR_COPROCESSOR.bits()
10+
| Cr0Flags::TASK_SWITCHED.bits()
11+
| Cr0Flags::NUMERIC_ERROR.bits()
12+
| Cr0Flags::WRITE_PROTECT.bits()
13+
| Cr0Flags::PAGING.bits();
14+
const CR4: u64 = Cr4Flags::PHYSICAL_ADDRESS_EXTENSION.bits() | Cr4Flags::PAGE_GLOBAL.bits();
15+
const EFER: u64 = EferFlags::LONG_MODE_ENABLE.bits() | EferFlags::NO_EXECUTE_ENABLE.bits();
16+
17+
global_asm!(
18+
include_str!("multiboot.S"),
19+
main_entry = sym crate::main,
20+
offset = const PHYS_VIRT_OFFSET,
21+
boot_stack_size = const BOOT_KERNEL_STACK_SIZE,
22+
cr0 = const CR0,
23+
cr4 = const CR4,
24+
efer_msr = const x86::msr::IA32_EFER,
25+
efer = const EFER,
26+
);

hypervisor/src/arch/x86_64/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
mod boot;
2+
3+
pub mod uart16550;
4+
5+
pub use uart16550 as uart;
6+
7+
pub fn init_early() {
8+
uart::init();
9+
}

0 commit comments

Comments
 (0)