kata: add a hello test application wrtten in Rust

This hello app uses the logger crate plumbed to the console. Way
bigger than the C version.

Change-Id: I7bf7e8b559fea8e045123d057412493bf7b71a24
GitOrigin-RevId: 97e12e93cc9ebfb4be021cff506417d7434b27f5
This commit is contained in:
Sam Leffler 2022-08-17 21:03:36 +00:00
parent e95c0bebeb
commit fe24490359
5 changed files with 185 additions and 0 deletions

View File

@ -0,0 +1,38 @@
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[package]
name = "hello"
version = "0.1.0"
edition = "2021"
build = "build.rs"
[build-dependencies]
# build.rs depends on SEL4_OUT_DIR = "${ROOTDIR}/out/kata/kernel"
sel4-config = { path = "../../system/components/kata-os-common/src/sel4-config" }
[features]
default = []
# Used by sel4-config to extract kernel config
CONFIG_PRINTING = []
[lib]
name = "hello"
path = "hello.rs"
crate-type = ["staticlib"]
[dependencies]
cstr_core = { version = "0.2.3", default-features = false }
kata-os-common = { path = "../../system/components/kata-os-common", default-features = false }
log = "0.4"

24
apps/rust/hello/Makefile Normal file
View File

@ -0,0 +1,24 @@
OUT_KATA ?= $(OUT)/kata/riscv32-unknown-elf/release
OUT_HELLO ?= $(OUT_KATA)/apps/hello
CARGO_OPTS ?= --release
# hello app staticlib (location set w/ --out-dir below)
LIB_HELLO := ${OUT_HELLO}/libhello.a
# To satisfy Rust core deps with debug build
LIB_LIBC := ${OUT_KATA}/musllibc/build-temp/stage/lib/libc.a
LD_FLAGS := -march=rv32imac -mabi=ilp32 -static -nostdlib -ftls-model=local-exec
#DBG:=-g
# NB: let cargo handle incremental build steps
${OUT_HELLO}/hello.elf: hello.rs | tmp_check
SEL4_OUT_DIR=${OUT_KATA}/kernel kcargo build ${CARGO_OPTS} --target-dir ${OUT_HELLO} --out-dir ${OUT_HELLO}
riscv32-unknown-elf-gcc ${LD_FLAGS} $(DBG) ${LIB_HELLO} ${LIB_LIBC} -o ${OUT_HELLO}/hello.elf
tmp_check:
mkdir -p $(OUT_HELLO)
clean:
rm -rf ${OUT_HELLO}
PHONY: tmp_check

34
apps/rust/hello/build.rs Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate sel4_config;
use std::env;
fn main() {
// If SEL4_OUT_DIR is not set we expect the kernel build at a fixed
// location relative to the ROOTDIR env variable.
println!("SEL4_OUT_DIR {:?}", env::var("SEL4_OUT_DIR"));
let sel4_out_dir = env::var("SEL4_OUT_DIR")
.unwrap_or_else(|_| format!("{}/out/kata/kernel", env::var("ROOTDIR").unwrap()));
println!("sel4_out_dir {}", sel4_out_dir);
// Dredge seL4 kernel config for settings we need as features to generate
// correct code: e.g. CONFIG_KERNEL_MCS enables MCS support which changes
// the system call numbering.
let features = sel4_config::get_sel4_features(&sel4_out_dir);
println!("features={:?}", features);
for feature in features {
println!("cargo:rustc-cfg=feature=\"{}\"", feature);
}
}

87
apps/rust/hello/hello.rs Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright 2021, Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#![no_std]
#![no_main]
#![feature(asm)]
#![feature(thread_local)]
// TODO(sleffler): plumb logger to SDKRuntime to eliminate seL4_DebugPutChar
// (or provide a logger alternative)
use kata_os_common::logger::KataLogger;
use kata_os_common::sel4_sys;
use sel4_sys::seL4_IPCBuffer;
const PAGE_SIZE: usize = 4096;
#[no_mangle]
#[thread_local]
static mut __sel4_ipc_buffer: *mut seL4_IPCBuffer = 0 as _;
#[repr(align(4096))]
#[allow(dead_code)]
struct PageAlign {
data: [u8; PAGE_SIZE],
}
static mut STATIC_TLS: PageAlign = PageAlign {
data: [0u8; PAGE_SIZE],
};
#[no_mangle]
pub fn _start() {
unsafe {
asm!("
.option push
.option norelax
la gp, __global_pointer$
la tp, {tls}
lui t1,0
add t1,t1,tp
sw a0,0(t1) # __sel4_ipc_buffer>
addi sp,sp,-16
sw a0, 12(sp)
sw a1, 8(sp)
sw a2, 4(sp)
sw a3, 0(sp)
.option pop
j main",
tls = sym STATIC_TLS,
options(noreturn),
)
};
}
// Message output is sent through the kata-os-logger which calls logger_log
// to deliver data to the console. We use seL4_DebugPutChar to write to the
// console which only works if DEBUG_PRINTING is enabled in the kernel.
#[no_mangle]
#[allow(unused_variables)]
pub fn logger_log(_level: u8, msg: *const cstr_core::c_char) {
#[cfg(feature = "CONFIG_PRINTING")]
unsafe {
for c in cstr_core::CStr::from_ptr(msg).to_bytes() {
let _ = sel4_sys::seL4_DebugPutChar(*c);
}
let _ = sel4_sys::seL4_DebugPutChar(b'\n');
}
}
#[no_mangle]
// XXX need SDK specification of main, use hack for now
pub fn main(a0: u32, a1: u32, a2: u32, a3: u32) {
// Setup logger; (XXX belongs in the SDKRuntime)
static KATA_LOGGER: KataLogger = KataLogger;
log::set_logger(&KATA_LOGGER).unwrap();
log::set_max_level(log::LevelFilter::Trace);
// XXX maybe setup a heap (XXX belongs in the SDKRuntime)
log::info!("I am a Rust app, hear me roar!");
log::info!("a0 {:x} a1 {:x} a2 {:x} a3 {:x}", a0, a1, a2, a3);
log::info!("__sel4_ipc_buffer {:p}", unsafe { __sel4_ipc_buffer });
log::info!("Done, wimper ...");
}

View File

@ -246,6 +246,8 @@ impl seL4BundleImpl {
//
// NB: beware the order of this must match *_SLOT above
// TODO(sleffler): maybe construct the vec to avoid mismatches
// TODO(sleffler): the toplevel CNode has a fixed size which
// can overflow when nframes is non-trivial
let dynamic_objs = kata_object_alloc_in_toplevel(vec![
// control/main-thread TCB
ObjDesc::new(seL4_TCBObject, 1, TCB_SLOT),