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

Implement initial userspace support #467

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: --workspace --all-features --exclude svsm --exclude svsm-fuzz --target=x86_64-unknown-linux-gnu -- -D warnings
args: --workspace --all-features --exclude svsm --exclude svsm-fuzz --exclude init --exclude dm --target=x86_64-unknown-linux-gnu -- -D warnings

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

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

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ members = [
"libmstpm",
# syscall interface definitions
"syscall",
# init process
"init",
# device model application
"dm",
]


Expand Down Expand Up @@ -46,6 +50,7 @@ tdx-tdcall = "0.2.1"
uuid = "1.6.1"
# Add the derive feature by default because all crates use it.
zerocopy = { version = "0.8.2", features = ["alloc", "derive"] }
buddy_system_allocator = "0.10.0"

# other repos
packit = { git = "https://github.com/coconut-svsm/packit", version = "0.1.1" }
Expand Down
16 changes: 14 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ IGVMBUILDER = "target/x86_64-unknown-linux-gnu/${TARGET_PATH}/igvmbuilder"
IGVMBIN = bin/igvmbld
IGVMMEASURE = "target/x86_64-unknown-linux-gnu/${TARGET_PATH}/igvmmeasure"
IGVMMEASUREBIN = bin/igvmmeasure
INITELF = "target/x86_64-unknown-none/${TARGET_PATH}/init"
DMELF = "target/x86_64-unknown-none/${TARGET_PATH}/dm"

RUSTDOC_OUTPUT = target/x86_64-unknown-none/doc
DOC_SITE = target/x86_64-unknown-none/site
Expand Down Expand Up @@ -135,6 +137,16 @@ bin/test-kernel.elf: bin
LINK_TEST=1 cargo +nightly test ${CARGO_ARGS} ${SVSM_ARGS_TEST} -p svsm --config 'target.x86_64-unknown-none.runner=["sh", "-c", "cp $$0 ../${TEST_KERNEL_ELF}"]'
objcopy -O elf64-x86-64 --strip-unneeded ${TEST_KERNEL_ELF} bin/test-kernel.elf

bin/init: bin
cargo build --manifest-path init/Cargo.toml ${CARGO_ARGS} --bin init
objcopy -O elf64-x86-64 --strip-unneeded ${INITELF} $@

bin/dm: bin
cargo build --manifest-path dm/Cargo.toml ${CARGO_ARGS} --bin dm
objcopy -O elf64-x86-64 --strip-unneeded ${DMELF} $@

user: bin/init bin/dm

${FS_BIN}: bin
ifneq ($(FS_FILE), none)
cp -f $(FS_FILE) ${FS_BIN}
Expand Down Expand Up @@ -176,7 +188,7 @@ bin/svsm-test.bin: bin/stage1-test

clippy:
cargo clippy --workspace --all-features --exclude svsm-fuzz --exclude igvmbuilder --exclude igvmmeasure -- -D warnings
cargo clippy --workspace --all-features --exclude svsm-fuzz --exclude svsm --target=x86_64-unknown-linux-gnu -- -D warnings
cargo clippy --workspace --all-features --exclude svsm-fuzz --exclude svsm --exclude init --exclude dm --target=x86_64-unknown-linux-gnu -- -D warnings
vijaydhanraj marked this conversation as resolved.
Show resolved Hide resolved
RUSTFLAGS="--cfg fuzzing" cargo clippy --package svsm-fuzz --all-features --target=x86_64-unknown-linux-gnu -- -D warnings
cargo clippy --workspace --all-features --tests --target=x86_64-unknown-linux-gnu -- -D warnings

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

.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 distclean user
15 changes: 15 additions & 0 deletions dm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "dm"
version = "0.1.0"
edition = "2021"

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

[dependencies]
syscall = { path = "../syscall" }

[lints]
workspace = true
6 changes: 6 additions & 0 deletions dm/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
fn main() {
println!("cargo:rustc-link-arg-bin=dm=-nostdlib");
println!("cargo:rustc-link-arg-bin=dm=-no-pie");
println!("cargo:rustc-link-arg-bin=dm=-Tdm/dm.lds");
}
37 changes: 37 additions & 0 deletions dm/dm.lds
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* Temporary WA until p_vaddr alignment issue is fixed in our ELF parser */

OUTPUT_ARCH(i386:x86-64)

PHDRS
{
text PT_LOAD FLAGS(5); /* Read + Execute */
rodata PT_LOAD FLAGS(4); /* Read-only */
data PT_LOAD FLAGS(6); /* Read + Write */
bss PT_LOAD FLAGS(6); /* Read + Write */
}

SECTIONS
{
.text : {
*(.text)
*(.text.*)
} :text
. = ALIGN(4096);
.rodata : {
*(.rodata)
*(.rodata.*)
} :rodata
. = ALIGN(4096);
.data : {
*(.data)
*(.data.*)
} :data
. = ALIGN(4096);
.bss : {
*(.bss) *(.bss.*)
. = ALIGN(4096);
} :bss
. = ALIGN(4096);
}

ENTRY(dm_start)
25 changes: 25 additions & 0 deletions dm/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Intel Corporation.
//
// Author: Chuanxiao Dong <[email protected]>

#![no_std]
#![no_main]

use core::panic::PanicInfo;
use syscall::exit;

fn dm_exit() -> ! {
exit(0);
}

#[no_mangle]
pub extern "C" fn dm_start() -> ! {
dm_exit();
}

#[panic_handler]
fn panic(_info: &PanicInfo<'_>) -> ! {
dm_exit();
}
3 changes: 3 additions & 0 deletions elf/src/program_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ impl Elf64Phdr {
if !self.p_align.is_power_of_two() {
return Err(ElfError::InvalidAddressAlignment);
}
// TODO: Due to a bug in the ELF parser, this function returns an error when p_vaddr is not
// aligned. But since spec doesn't guarantee that p_vaddr must be aligned, our ELF parser
// needs to be fixed. Current WA is to use a custom linker script to align p_vaddr.
if self.p_vaddr & (self.p_align - 1) != 0 {
return Err(ElfError::UnalignedSegmentAddress);
}
Expand Down
16 changes: 16 additions & 0 deletions init/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "init"
version = "0.1.0"
edition = "2021"

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

[dependencies]
syscall = { path = "../syscall" }
buddy_system_allocator = { workspace = true }

[lints]
workspace = true
6 changes: 6 additions & 0 deletions init/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
fn main() {
println!("cargo:rustc-link-arg-bin=init=-nostdlib");
println!("cargo:rustc-link-arg-bin=init=-no-pie");
println!("cargo:rustc-link-arg-bin=init=-Tinit/init.lds");
}
37 changes: 37 additions & 0 deletions init/init.lds
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* Temporary WA until p_vaddr alignment issue is fixed in our ELF parser */

OUTPUT_ARCH(i386:x86-64)

PHDRS
{
text PT_LOAD FLAGS(5); /* Read + Execute */
rodata PT_LOAD FLAGS(4); /* Read-only */
data PT_LOAD FLAGS(6); /* Read + Write */
bss PT_LOAD FLAGS(6); /* Read + Write */
}

SECTIONS
{
.text : {
*(.text)
*(.text.*)
} :text
. = ALIGN(4096);
.rodata : {
*(.rodata)
*(.rodata.*)
} : rodata
. = ALIGN(4096);
.data : {
*(.data)
*(.data.*)
} :data
. = ALIGN(4096);
.bss : {
*(.bss) *(.bss.*)
. = ALIGN(4096);
} :bss
. = ALIGN(4096);
}

ENTRY(init_start)
73 changes: 73 additions & 0 deletions init/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Intel Corporation.
//
// Author: Peter Fang <[email protected]>

#![no_std]
#![no_main]

extern crate alloc;
use alloc::ffi::CString;
use alloc::string::String;
use buddy_system_allocator::*;
use core::ffi::CStr;
use core::panic::PanicInfo;
use syscall::{exec, exit, opendir, readdir, DirEnt, FileType, SysCallError};

const HEAP_SIZE: usize = 64 * 1024;
static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];

#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();

#[no_mangle]
pub extern "C" fn init_start() -> ! {
unsafe {
HEAP_ALLOCATOR
.lock()
.init(core::ptr::addr_of!(HEAP) as usize, HEAP_SIZE);
}

let bin = CString::new("/bin/").unwrap();
let Ok(obj) = opendir(&bin) else {
exit(0);
};
let mut dirents: [DirEnt; 8] = Default::default();
let mut binfile: Option<CString> = None;

loop {
let n = readdir(&obj, &mut dirents).unwrap();
if let Some(d) = dirents
.iter()
.take(n)
.find(|d| d.file_type == FileType::File)
{
binfile = Some(CString::from(
CStr::from_bytes_until_nul(&d.file_name).unwrap(),
));
break;
}
if n < dirents.len() {
break;
}
}
let binfile = binfile.unwrap_or_else(|| exit(0));

let mut file = String::from(bin.as_c_str().to_str().unwrap());
file.push_str(binfile.as_c_str().to_str().unwrap());

let file = CString::new(file).unwrap();
let root = CString::new("/").unwrap();

match exec(&file, &root, 0) {
Ok(_) => exit(0),
Err(SysCallError::ENOTFOUND) => exit(1),
_ => panic!("{} launch failed", file.to_str().unwrap()),
};
}

#[panic_handler]
fn panic(_info: &PanicInfo<'_>) -> ! {
exit(u32::MAX);
}
12 changes: 8 additions & 4 deletions kernel/src/cpu/idt/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,14 @@ extern "C" fn ex_handler_system_call(
};

ctxt.regs.rax = match input {
SYS_HELLO => sys_hello(),
SYS_EXIT => sys_exit(),
_ => !0,
};
SYS_EXIT => sys_exit(ctxt.regs.rdi as u32),
SYS_EXEC => sys_exec(ctxt.regs.rdi, ctxt.regs.rsi, ctxt.regs.r8),
SYS_CLOSE => sys_close(ctxt.regs.rdi as u32),
SYS_OPENDIR => sys_opendir(ctxt.regs.rdi),
SYS_READDIR => sys_readdir(ctxt.regs.rdi as u32, ctxt.regs.rsi, ctxt.regs.r8),
_ => Err(SysCallError::EINVAL),
}
.map_or_else(|e| e as usize, |v| v as usize);
}

#[no_mangle]
Expand Down
Loading
Loading