Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stage1: Rustify stage1 and update IGVM VTOM on TDP platforms #517

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
12 changes: 9 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
# ld to work, so build all the objects without performing the
# final linking step.
- name: Build
run: make FEATURES="default,enable-gdb" bin/svsm-kernel.elf stage1/stage1.o stage1/reset.o
run: make FEATURES="default,enable-gdb" STAGE1_RUSTC_ARGS="--emit=obj -C linker=/usr/bin/true" stage1_elf_full stage1_elf_trampoline

- name: Run tests
run: make test
Expand All @@ -56,13 +56,19 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --exclude igvmbuilder --exclude igvmmeasure --exclude svsm-fuzz --exclude packit --all-features -- -D warnings
args: --workspace --exclude igvmbuilder --exclude igvmmeasure --exclude svsm-fuzz --exclude packit --exclude stage1 --all-features -- -D warnings

- name: Clippy on std x86_64-unknown-linux-gnu
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-features --exclude svsm --exclude svsm-fuzz --exclude packit --target=x86_64-unknown-linux-gnu -- -D warnings
args: --workspace --all-features --exclude svsm --exclude svsm-fuzz --exclude packit --exclude stage1 --target=x86_64-unknown-linux-gnu -- -D warnings

- name: Clippy on stage1
uses: actions-rs/cargo@v1
with:
command: clippy
args: --package stage1 --all-features --target=x86_64-unknown-linux-gnu -- -D warnings -C panic=abort

- name: Clippy on svsm-fuzz
uses: actions-rs/cargo@v1
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"igvmbuilder",
"igvmmeasure",
# binary targets
"stage1",
"kernel",
# fuzzing
"fuzz",
Expand Down Expand Up @@ -50,7 +51,7 @@ p384 = { version = "0.13.0" }
sha2 = "0.10.8"
uuid = "1.6.1"
# Add the derive feature by default because all crates use it.
zerocopy = { version = "0.8.2", features = ["alloc", "derive"] }
zerocopy = { version = "0.8.2", features = ["derive"] }

# Verus repos
builtin = { git = "https://github.com/verus-lang/verus", rev ="943ba63", default-features = false }
Expand Down
45 changes: 22 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ else ifeq ($(V), 2)
CARGO_ARGS += -vv
endif

STAGE1_RUSTC_ARGS += -C panic=abort

STAGE1_ELF = "target/x86_64-unknown-none/${TARGET_PATH}/stage1"
STAGE2_ELF = "target/x86_64-unknown-none/${TARGET_PATH}/stage2"
SVSM_KERNEL_ELF = "target/x86_64-unknown-none/${TARGET_PATH}/svsm"
TEST_KERNEL_ELF = target/x86_64-unknown-none/${TARGET_PATH}/svsm-test
Expand All @@ -36,9 +39,6 @@ endif

C_BIT_POS ?= 51

STAGE1_OBJS = stage1/stage1.o stage1/reset.o
STAGE1_TEST_OBJS = stage1/stage1-test.o stage1/reset.o
STAGE1_TRAMPOLINE_OBJS = stage1/stage1-trampoline.o stage1/reset.o
IGVM_FILES = bin/coconut-qemu.igvm bin/coconut-hyperv.igvm bin/coconut-vanadium.igvm
IGVMBUILDER = "target/x86_64-unknown-linux-gnu/${TARGET_PATH}/igvmbuilder"
IGVMBIN = bin/igvmbld
Expand Down Expand Up @@ -141,42 +141,41 @@ ifneq ($(FS_FILE), none)
endif
touch ${FS_BIN}

stage1/stage1.o: stage1/stage1.S bin/stage2.bin bin/svsm-fs.bin bin/svsm-kernel.elf bin
stage1_elf_full: bin/stage2.bin bin/svsm-fs.bin bin/svsm-kernel.elf bin/meta.bin
ln -sf svsm-kernel.elf bin/kernel.elf
cc -c -DLOAD_STAGE2 -o $@ $<
cargo rustc --manifest-path stage1/Cargo.toml ${CARGO_ARGS} --features load-stage2 --bin stage1 -- ${STAGE1_RUSTC_ARGS}
rm -f bin/kernel.elf

stage1/stage1-test.o: stage1/stage1.S bin/stage2.bin bin/svsm-fs.bin bin/test-kernel.elf bin
stage1_elf_trampoline: bin/meta.bin
cargo rustc --manifest-path stage1/Cargo.toml ${CARGO_ARGS} --bin stage1 -- ${STAGE1_RUSTC_ARGS}

stage1_elf_test: bin/stage2.bin bin/svsm-fs.bin bin/test-kernel.elf bin/meta.bin
ln -sf test-kernel.elf bin/kernel.elf
cc -c -DLOAD_STAGE2 -o $@ $<
cargo rustc --manifest-path stage1/Cargo.toml ${CARGO_ARGS} --features load-stage2 --bin stage1 -- ${STAGE1_RUSTC_ARGS}
rm -f bin/kernel.elf

stage1/stage1-trampoline.o: stage1/stage1.S
cc -c -o $@ $<

stage1/reset.o: stage1/reset.S bin/meta.bin

bin/stage1: ${STAGE1_OBJS}
$(CC) -o $@ $(STAGE1_OBJS) -nostdlib -Wl,--build-id=none -Wl,-Tstage1/stage1.lds -no-pie
bin/svsm: stage1_elf_full
cp -f $(STAGE1_ELF) $@

bin/stage1-test: ${STAGE1_TEST_OBJS}
$(CC) -o $@ $(STAGE1_TEST_OBJS) -nostdlib -Wl,--build-id=none -Wl,-Tstage1/stage1.lds -no-pie
bin/stage1-trampoline: stage1_elf_trampoline
cp -f $(STAGE1_ELF) $@

bin/stage1-trampoline: ${STAGE1_TRAMPOLINE_OBJS}
$(CC) -o $@ $(STAGE1_TRAMPOLINE_OBJS) -nostdlib -Wl,--build-id=none -Wl,-Tstage1/stage1.lds -no-pie
bin/svsm-test: stage1_elf_test
cp -f $(STAGE1_ELF) $@

bin/svsm.bin: bin/stage1
bin/svsm.bin: bin/svsm
objcopy -O binary $< $@

bin/stage1-trampoline.bin: bin/stage1-trampoline
objcopy -O binary $< $@

bin/svsm-test.bin: bin/stage1-test
bin/svsm-test.bin: bin/svsm-test
objcopy -O binary $< $@

clippy:
cargo clippy --workspace --all-features --exclude packit --exclude svsm-fuzz --exclude igvmbuilder --exclude igvmmeasure -- -D warnings
cargo clippy --workspace --all-features --exclude packit --exclude svsm-fuzz --exclude svsm --target=x86_64-unknown-linux-gnu -- -D warnings
cargo clippy --workspace --all-features --exclude packit --exclude svsm-fuzz --exclude igvmbuilder --exclude igvmmeasure --exclude stage1 -- -D warnings
cargo clippy --workspace --all-features --exclude packit --exclude svsm-fuzz --exclude svsm --exclude stage1 --target=x86_64-unknown-linux-gnu -- -D warnings
cargo clippy -p stage1 --all-features --target=x86_64-unknown-linux-gnu -- -D warnings ${STAGE1_RUSTC_ARGS}
RUSTFLAGS="--cfg fuzzing" cargo clippy --package svsm-fuzz --all-features --target=x86_64-unknown-linux-gnu -- -D warnings
cargo clippy --workspace --all-features --exclude packit --tests --target=x86_64-unknown-linux-gnu -- -D warnings

Expand All @@ -189,4 +188,4 @@ clean:
distclean: clean
$(MAKE) -C libtcgtpm $@

.PHONY: test clean clippy bin/stage2.bin bin/svsm-kernel.elf bin/test-kernel.elf distclean
.PHONY: test clean clippy bin/stage2.bin bin/svsm-kernel.elf bin/test-kernel.elf stage1_elf_full stage1_elf_trampoline stage1_elf_test distclean
13 changes: 11 additions & 2 deletions bootlib/src/kernel_launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@
// Author: Joerg Roedel <[email protected]>

use crate::platform::SvsmPlatformType;

use core::mem::size_of;
use zerocopy::{Immutable, IntoBytes};

pub const STAGE2_STACK_END: u32 = 0x805000;
pub const STAGE2_INFO_SZ: u32 = size_of::<Stage2LaunchInfo>() as u32;
pub const STAGE2_STACK: u32 = STAGE2_STACK_END + 0x1000 - STAGE2_INFO_SZ;
pub const SECRETS_PAGE: u32 = 0x806000;
pub const CPUID_PAGE: u32 = 0x807000;
// Stage2 is loaded at 8 MB + 32 KB
pub const STAGE2_START: u32 = 0x808000;
pub const STAGE2_MAXLEN: u32 = 0x8D0000 - STAGE2_START;

#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct KernelLaunchInfo {
Expand Down Expand Up @@ -45,7 +54,7 @@ impl KernelLaunchInfo {

// Stage 2 launch info from stage1
// The layout has to match the order in which the parts are pushed to the stack
// in stage1/stage1.S
// in stage1.rs
#[derive(IntoBytes, Immutable, Default, Debug, Clone, Copy)]
#[repr(C, packed)]
pub struct Stage2LaunchInfo {
Expand Down
9 changes: 5 additions & 4 deletions igvmbuilder/src/gpa_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use std::error::Error;
use std::fs::metadata;

use bootlib::kernel_launch::{CPUID_PAGE, SECRETS_PAGE, STAGE2_STACK_END, STAGE2_START};
use igvm_defs::PAGE_SIZE_4K;

use crate::cmd_options::{CmdOptions, Hypervisor};
Expand Down Expand Up @@ -105,7 +106,7 @@ impl GpaMap {
0
};

let stage2_image = GpaRange::new(0x808000, stage2_len as u64)?;
let stage2_image = GpaRange::new(STAGE2_START.into(), stage2_len as u64)?;

// The kernel image is loaded beyond the end of the stage2 image,
// rounded up to a 4 KB boundary.
Expand Down Expand Up @@ -154,10 +155,10 @@ impl GpaMap {
let gpa_map = Self {
base_addr: 0x800000,
stage1_image,
stage2_stack: GpaRange::new_page(0x805000)?,
stage2_stack: GpaRange::new_page(STAGE2_STACK_END.into())?,
stage2_image,
secrets_page: GpaRange::new_page(0x806000)?,
cpuid_page: GpaRange::new_page(0x807000)?,
secrets_page: GpaRange::new_page(SECRETS_PAGE.into())?,
cpuid_page: GpaRange::new_page(CPUID_PAGE.into())?,
kernel_elf,
kernel_fs,
igvm_param_block,
Expand Down
2 changes: 1 addition & 1 deletion igvmbuilder/src/stage2_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const _: () = assert!((size_of::<Stage2Stack>() as u64) <= PAGE_SIZE_4K);
impl Stage2Stack {
pub fn new(gpa_map: &GpaMap, vtom: u64) -> Self {
let stage2_stack = Stage2LaunchInfo {
stage2_end: gpa_map.kernel_elf.get_start() as u32,
stage2_end: gpa_map.stage2_image.get_end() as u32,
kernel_elf_start: gpa_map.kernel_elf.get_start() as u32,
kernel_elf_end: (gpa_map.kernel_elf.get_start() + gpa_map.kernel_elf.get_size()) as u32,
kernel_fs_start: gpa_map.kernel_fs.get_start() as u32,
Expand Down
2 changes: 1 addition & 1 deletion kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ intrusive-collections.workspace = true
log = { workspace = true, features = ["max_level_info", "release_max_level_info"] }
packit.workspace = true
libtcgtpm = { workspace = true, optional = true }
zerocopy.workspace = true
zerocopy = { workspace = true, features = ["alloc", "derive"] }

builtin = { workspace = true, optional = true }
builtin_macros = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions kernel/src/platform/tdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ impl SvsmPlatform for TdpPlatform {
}

fn env_setup(&mut self, debug_serial_port: u16, vtom: usize) -> Result<(), SvsmError> {
assert_ne!(vtom, 0);
VTOM.init(&vtom).map_err(|_| SvsmError::PlatformInit)?;
// Serial console device can be initialized immediately
init_svsm_console(&GHCI_IO_DRIVER, debug_serial_port)
Expand Down
8 changes: 4 additions & 4 deletions kernel/src/stage2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

pub mod boot_stage2;

use bootlib::kernel_launch::{KernelLaunchInfo, Stage2LaunchInfo};
use bootlib::kernel_launch::{KernelLaunchInfo, Stage2LaunchInfo, STAGE2_START};
use bootlib::platform::SvsmPlatformType;
use core::arch::asm;
use core::panic::PanicInfo;
Expand Down Expand Up @@ -94,9 +94,9 @@ fn setup_env(
.expect("Early environment setup failed");

let kernel_mapping = FixedAddressMappingRange::new(
VirtAddr::from(0x808000u64),
VirtAddr::from(launch_info.stage2_end as u64),
PhysAddr::from(0x808000u64),
VirtAddr::from(u64::from(STAGE2_START)),
VirtAddr::from(u64::from(launch_info.stage2_end)),
PhysAddr::from(u64::from(STAGE2_START)),
);

// Use the low 640 KB of memory as the heap.
Expand Down
2 changes: 2 additions & 0 deletions scripts/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ def make_build(package, config, args):
"""
if config["file"]:
command = ["make", config["file"]]
if args.release:
command.append("RELEASE=1")
if args.verbose:
command.append("V=2")
print(command)
Expand Down
17 changes: 17 additions & 0 deletions stage1/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "stage1"
version = "0.1.0"
edition = "2021"
rust-version = "1.82.0"

[[bin]]
name = "stage1"
path = "src/stage1.rs"
test = false

[features]
default = []
load-stage2 = []

[dependencies]
bootlib.workspace = true
15 changes: 15 additions & 0 deletions stage1/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (C) 2024 Intel Corporation
//
// Author: Peter Fang <[email protected]>

fn main() {
println!("cargo:rustc-link-arg-bin=stage1=-nostdlib");
println!("cargo:rustc-link-arg-bin=stage1=--build-id=none");
println!("cargo:rustc-link-arg-bin=stage1=-Tstage1/stage1.lds");
println!("cargo:rustc-link-arg-bin=stage1=-no-pie");
println!("cargo:rustc-link-arg-bin=stage1=-no-gc-sections");

println!("cargo:rerun-if-changed=stage1.lds");
}
11 changes: 4 additions & 7 deletions stage1/reset.S → stage1/src/reset.S
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@
* Author: Joerg Roedel <[email protected]>
*/

#define ENTRY(name) \
.globl name; \
name:
#define END(name) ENTRY(end_##name)

.code16gcc
.section .init
/* to_pm_mode must be at 0xfffffe00 */
ENTRY(to_pm_mode)
.globl to_pm_mode
to_pm_mode:
xor %bx, %bx
mov %bx, %ds
mov %bx, %es
Expand Down Expand Up @@ -56,7 +52,8 @@ gdt32_descr:
.word gdt32_end - gdt32 - 1
.long gdt32

END(to_pm_mode)
.globl end_to_pm_mode
end_to_pm_mode:

.section .sevmeta
.incbin "bin/meta.bin"
Expand Down
Loading
Loading