Skip to content

Conversation

@alarmfox
Copy link
Collaborator

@alarmfox alarmfox commented Mar 8, 2025

Firmware init

This PR starts creating the firmware. The main idea is to use OpenSBI to avoid rewriting initialization code for platform and focusing our firmware in tsm_driver part. OpenSBI allows also to create domains using a device tree.

I found this closed issues on opensbi. Leaving there for reference:

OpenSBI can launch firmware in 3 ways, but they cannot be used in our use case because they are executed with S or HS priviledge mode. According to CoVE specification, Shadowfax must run in M mode to be a compliant tsm_driver.

Fortunately, OpenSBI can be used from an external firmware (shadowfax itself) and linked as a static library. According to the documentation, we need to initialize harts using sbi_init() and setup trap handler with sbi_trap_handler() with the following requirements:

  1. The RISC-V MSCRATCH CSR must point to a valid OpenSBI scratch space
    (i.e. a struct sbi_scratch instance).
  2. The RISC-V SP register (i.e. the stack pointer) must be set per-HART
    pointing to distinct non-overlapping stacks.
    The most important functions from an external firmware or bootloader
    perspective are sbi_init() and sbi_trap_handler().

In addition to the above constraints, the external firmware or bootloader must
ensure that interrupts are disabled in the MSTATUS and MIE CSRs when calling
the functions sbi_init() and sbi_trap_handler().

external firmwares or bootloaders can be more conservative by
forwarding all traps and interrupts to sbi_trap_handler().

We can start working from here with some assumptions (ie. only 1 hart with id 0). We can take as reference the file firmware/fw_base.S in OpenSBI source code in which hart and the platform are initialized.

Platform vs non platform library

OpenSBI exposes 2 different static library:

  • libsbi.a: platform agnostic library which must be integrated with specific initialization hooks. In this case, we should provide our custom device tree;
  • libplatsbi.a: which performs also init hooks for specific platform (the ones supported by the opensbi spec). The library will be different based on the PLATFORM flag specified when compiling.

In our case, we could use the generic platform which can be used to test against the virt machine in QEMU.

Linkerscript

src/init.ld provides a basic linkerscript taken from examples/helloworld. We need to evaluate if other sections are needed and to need to parametrize some variables like start address and end address to make it compatible with the target platform.

Running the example

For simplicity, the example is in assembly. The goal is to setup the platform in a minimal way:

  • sbi_init for hart 0
  • setup sbi_trap_handler
  • jump to an helloworld function

First, clone the repository and checkout the branch:

git clone --depth 1 -b feature/opensbi_integration git@github.com:Granp4sso/shadowfax.git

Now, get OpenSBI:

curl -fsSLO https://github.com/riscv-software-src/opensbi/archive/refs/tags/v1.6.tar.gz
tar xvf v1.6.tar.gz
cd opensbi-1.6

Compile and install OpenSBI using the cross-compile toolchain (substitute the riscv if needed and the path to shadowfax accordingly) for the generic platform:

make -j`nproc` PLATFORM=generic CROSS_COMPILE=riscv64-linux-gnu-
make I=../shadowfax install

Run "shadowfax firmware" using:

cd ../shadowfax/
make CROSS_COMPILE=riscv64-linux-gnu- run

The output should be:

> make CROSS_COMPILE=riscv64-linux-gnu- run
riscv64-linux-musl-gcc -Wall -Wextra -march=rv64gh -mabi=lp64 -Iinclude/ -c -o init.o init.S
riscv64-linux-musl-ld  -static -o shadowfax -T init.ld init.o ../lib64/lp64/libsbi.a
Press (ctrl + a) and then x to quit
qemu-system-riscv64 -nographic -machine virt -bios shadowfax
hello

@alarmfox alarmfox self-assigned this Mar 8, 2025
@Granp4sso Granp4sso merged commit db5e5b2 into main Apr 15, 2025
1 check passed
@Granp4sso Granp4sso deleted the feature/opensbi_integration branch May 6, 2025 07:43
alarmfox added a commit that referenced this pull request Aug 2, 2025
# This is the 1st commit message:

Adding examples

# This is the commit message #2:

Added config.mk for general configuration

# This is the commit message #3:

Removed -c

# This is the commit message #4:

Formatting

# This is the commit message #5:

Working C example

# This is the commit message #6:

New demo

# This is the commit message #7:

Added details

# This is the commit message #8:

Added folders
alarmfox added a commit that referenced this pull request Aug 2, 2025
# This is the 1st commit message:

Adding examples

# This is the commit message #2:

Added config.mk for general configuration

# This is the commit message #3:

Removed -c

# This is the commit message #4:

Formatting

# This is the commit message #5:

Working C example

# This is the commit message #6:

New demo

# This is the commit message #7:

Added details

# This is the commit message #8:

Added folders

# This is the commit message #9:

Simple README.md

# This is the commit message #10:

Added pre-commit basic configuration

# This is the commit message #11:

Updated default hooks

# This is the commit message #12:

Rename: src -> tsm-driver

# This is the commit message #13:

Added author name and changed PREFIX to CROSS_COMPILE

# This is the commit message #14:

More standard way of passing CROSS_COMPILE: now includes -

# This is the commit message #15:

Using native toolchain if CROSS_COMPILE is not defined

# This is the commit message #16:

Fix usage section

# This is the commit message #17:

Added static and nostdlib to helloworld

# This is the commit message #18:

More parameters from config.mk
alarmfox added a commit that referenced this pull request Nov 17, 2025
…col (#35)

* Fix commit

* # This is a combination of 8 commits.
# This is the 1st commit message:

Adding examples

# This is the commit message #2:

Added config.mk for general configuration

# This is the commit message #3:

Removed -c

# This is the commit message #4:

Formatting

# This is the commit message #5:

Working C example

# This is the commit message #6:

New demo

# This is the commit message #7:

Added details

# This is the commit message #8:

Added folders

* Repository setup

* # This is a combination of 18 commits.
# This is the 1st commit message:

Adding examples

# This is the commit message #2:

Added config.mk for general configuration

# This is the commit message #3:

Removed -c

# This is the commit message #4:

Formatting

# This is the commit message #5:

Working C example

# This is the commit message #6:

New demo

# This is the commit message #7:

Added details

# This is the commit message #8:

Added folders

# This is the commit message #9:

Simple README.md

# This is the commit message #10:

Added pre-commit basic configuration

# This is the commit message #11:

Updated default hooks

# This is the commit message #12:

Rename: src -> tsm-driver

# This is the commit message #13:

Added author name and changed PREFIX to CROSS_COMPILE

# This is the commit message #14:

More standard way of passing CROSS_COMPILE: now includes -

# This is the commit message #15:

Using native toolchain if CROSS_COMPILE is not defined

# This is the commit message #16:

Fix usage section

# This is the commit message #17:

Added static and nostdlib to helloworld

# This is the commit message #18:

More parameters from config.mk

* Basic repository setup

* This patch contains:
 - rust project initializtion for bare metal riscv programming integrating
 - integration with opensbi using bindgen
 - setup Docker environment

* This patch contains:
 - working OpenSBI integration
 - scripts refactoring
 - adding devcontainer
 - cove extension scratch

* Cleanup repository

* Refactored code with pure (almost) Rust
fix: aligning 4 byte the trap handler
Refactored trap.rs
working hypervisor with shadowfax
Moved SBI extensions in sbi/
refactor: added build time jump address, debug! macro, embed-elf

* feature: moving to HS-mode TSM deployment

* refactor: fix gitignore and remove build files

* feat: added pmp entry to enable communication for host-tsm

* Moved handlers to naked_asm! to avoid improper stack manipulation by LLVM

* feature: prevented TEECALL towards non confidential domain

* fix: restricting permission to write only to TSM in sbi_covh_get_tsm_info

* refactor: removed extra align statement

* fix: overwriting a0 register in sp setting

* fix: t0 restoring; moving to TOR instead of NAPOT

* feature: handling supervisor domain extension from CoVE without opensbi

* Bump rust version. Previous one contained a rust-analyzer catastrophic bug

* fix: alignement according new rust features

* removed extra pmp registers and extra fence

* feat: added trustmap for each supervisor domain

* refactor: tee trap handler in cove.rs. Moved state.rs and domain.rs in src/

* fix: saving csr for supd

* refactor: small refactor

* adpated: scripts/gdb to new function name

* reduces scratch stack to 8k

* moved binary to bin directory

* added extra check for trust

* Added comments to state and cove

* splitted Context in context.rs file

* Removed old linker.ld

* Modern devcontainer environment

* added missing device tree compiler

* better .gitignore

* fix: missing entries in .gitignore

* fixed .devcontainer

* fixed setup scripts and reduced Docker image size

* fix Cargo.lock

* fix opensbi build

* fix Cargo.lock

* fixed scripts llvm-config.sh

* adjusted README.md

* fix/workaround: LLVM bug not producing code without explicit
architecture.

* Added gdb multiarch

* sticking to ISA v1.10 for now

* print all export

* removed logging

* fix Dockerfile comments

* removed linker adjustment in README.md

* Specified target information

* copied entrypoint.sh in shell profile to be sourced

* lint

* lint

* added comment in build.rs

* fix: non executable entrypoint.sh for Dockerfile shell

* fix: Dockerfile entrypoint

* Added reference to development workspaces

* removed rust-toolchain.toml from TSM

* removed bottom_stack

* This commit migrates to a workspace structure:
- shadowfax_core: secure firmware
- payload/tsm: the TEE security module
- payload/hypervisor: mini-hypervisor to run simple guests
- tests: integration tests.

* Added Makefile to automate build and test process.

* fix: CI

* fix: missing bin/

* maybe fix

* fix: generating keys before running tests

* fix: prevent qemu raw stdin to break terminal after test

* fix: detecting host platform for bindgen in Cargo.toml automatically

* fix: detecting host platform for bindgen in Cargo.toml automatically

* split TSM building in separated steps

* repo: better makefile for guests

* repo: better makefile for guests

* fix: build system and linker problems

* CI: exported shadowfax jump address

* Update rust.yml

* CI runner broken for some reason (after the recent runner update).
Thanks Microsft. Will fix in another PR. Squashing all of this together.

* feat: preparing for TVM Create

* scripts to reproduce create_tvm_steps

* repo: dropped empty payload

* repo: dropped empty payload

* feat: first untrusted supervisor domain is marked as active instead of hardcoding the root ID

* fix: test needs device tree

* repo: dropped empty payload

* repo: dropped empty payload

* small changes to Makefile

* returning SbiRet structure from ECALL

* structured assert after each ECALL

* feat: simpler context switch -> handling just TSM

* dropped hypervisor for now

* Moved to TSM elf directly from target directly

* added simple script to test simple TEECALL/TEERET

* fix: specified arch in build.rs as bindgen does not recognize it sometimes

* refactor: initialized TSM state in TSM-Driver, moved workspaces to reasonable name

* feat: handling global state

* feat: moved common structures in the common crate

* better testing infrastructure

* Added allocator for TSM

* feat: introduced convert_pages

* excluding pycache

* feat: complete TSM State assert

* feat: added qemu reset macro

* feat: removed old memory reads

* feat: added instructions to run example on QEMU

* moved to unix socket for monitor

* Fix:
 - invalid PMP entry masking on TEERET
 - missing root supervisor domain in SUPD_GET_ACTIVE_DOMAINS
 - invalid a6 register masking when inverting the caller id

* print step name

* feat: added enum supervisor domains in test

* feat: added better linkerscript definition and debug print of symbol even before OpenSBI definition

* refactor: changed shadowfax_tsm -> tsm

* feat: cleared API for TVM

* feat: working create TVM

* feat: made padding explicit int TsmInfo

* feat: made ebreak optional

* feat: made padding explicit int TsmInfo

* fix: next addres when EBREAK is optional

* fix: missing feature h

* feat: working create TVM

* fix: missing OPENSBI_PATH CI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request help wanted Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants