Compare commits

...

6 Commits

18 changed files with 323 additions and 517 deletions

View File

@ -1,5 +1,2 @@
[alias]
xtask = "run --package xtask --"
[target.'cfg(all(target_arch = "riscv64", target_os = "none"))'] [target.'cfg(all(target_arch = "riscv64", target_os = "none"))']
runner = "qemu-system-riscv64 -nographic -machine virt -serial mon:stdio -smp 1 -kernel " runner = "qemu-system-riscv64 -nographic -machine virt -serial mon:stdio -smp 1 -kernel "

View File

@ -12,30 +12,34 @@ jobs:
matrix: matrix:
include: include:
- arch: riscv64 - arch: riscv64
qemu: qemu-system-misc qemu-pkg: qemu-system-misc
target: riscv64imac-unknown-none-elf rust-target: riscv64imac-unknown-none-elf
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
ARCH: ${{ matrix.arch }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Qemu - name: Install Qemu
uses: ConorMacBride/install-package@v1 uses: ConorMacBride/install-package@v1
with: with:
apt: ${{ matrix.qemu }} apt: ${{ matrix.qemu-pkg }}
- name: Install Rust - name: Install Rust
uses: dtolnay/rust-toolchain@master uses: dtolnay/rust-toolchain@master
with: with:
toolchain: nightly toolchain: nightly
targets: ${{ matrix.target }} targets: ${{ matrix.rust-target }}
components: clippy, rust-src components: clippy, rust-src
- name: Run Clippy - name: Run Clippy
run: cargo xtask clippy run: make clippy ARCH=${{ matrix.arch }}
- name: Build
run: cargo xtask build --arch ${{ matrix.arch }}
- name: Test - name: Test
run: cargo xtask test --arch ${{ matrix.arch }} run: make test ARCH=${{ matrix.arch }}
- name: Build
run: make kernel ARCH=${{ matrix.arch }}

208
Cargo.lock generated
View File

@ -18,60 +18,6 @@ dependencies = [
"vspace", "vspace",
] ]
[[package]]
name = "anstream"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
dependencies = [
"anstyle",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]] [[package]]
name = "api" name = "api"
version = "0.1.0" version = "0.1.0"
@ -110,52 +56,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "cpio" name = "cpio"
version = "0.1.0" version = "0.1.0"
@ -200,12 +100,6 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "kernel" name = "kernel"
version = "0.1.0" version = "0.1.0"
@ -351,12 +245,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.58" version = "2.0.58"
@ -385,12 +273,6 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "utils" name = "utils"
version = "0.1.0" version = "0.1.0"
@ -407,72 +289,6 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]] [[package]]
name = "x86" name = "x86"
version = "0.52.0" version = "0.52.0"
@ -483,27 +299,3 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"raw-cpuid", "raw-cpuid",
] ]
[[package]]
name = "xshell"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437"
dependencies = [
"xshell-macros",
]
[[package]]
name = "xshell-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852"
[[package]]
name = "xtask"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
"xshell",
]

View File

@ -1,6 +1,6 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = ["api", "kernel", "lib/*", "xtask"] members = ["api", "kernel", "lib/*"]
[profile.dev] [profile.dev]
panic = "abort" panic = "abort"

44
Makefile Normal file
View File

@ -0,0 +1,44 @@
ARCH ?= riscv64
ifeq ($(ARCH), riscv64)
BUILD_TARGET := riscv64imac-unknown-none-elf
LINKER_LDS := kernel/src/arch/riscv/linker64.ld
else
$(error Invalid TARGET: $(ARCH))
endif
RUSTFLAGS += -Crelocation-model=static
RUSTFLAGS += -Ccode-model=medium
RUSTFLAGS += -Ctarget-feature=+relax
RUSTFLAGS += -Cforce-frame-pointers=yes
RUSTFLAGS += -Clink-arg=-T$(LINKER_LDS)
CARGO_TARGET_ARGS := --target=$(BUILD_TARGET)
CARGO_BUILD_ARGS += -Zbuild-std=core,compiler_builtins,alloc
CARGO_BUILD_ARGS += -Zbuild-std-features=compiler-builtins-mem
CARGO_BUILD_ARGS += $(CARGO_TARGET_ARGS)
kernel:
env RUSTFLAGS="$(RUSTFLAGS)" cargo build --bin kernel $(CARGO_BUILD_ARGS)
clippy:
cargo clippy -p allocator
cargo clippy -p utils
cargo clippy --no-deps $(CARGO_TARGET_ARGS) --manifest-path=kernel/Cargo.toml
test:
cargo test -p allocator
cargo test -p utils
env RUSTFLAGS="$(RUSTFLAGS)" cargo test $(CARGO_TARGET_ARGS) --bin=kernel
clean:
cargo clean
qemu: kernel
qemu-system-$(ARCH) -nographic -machine virt -serial mon:stdio -smp 1 -kernel target/$(BUILD_TARGET)/debug/kernel
qemu-gdb: kernel
qemu-system-$(ARCH) -nographic -machine virt -serial mon:stdio -smp 1 -kernel target/$(BUILD_TARGET)/debug/kernel -s -S
.PHONY: kernel clippy test clean qemu

View File

@ -1,6 +1,10 @@
use crate::objects::null::NullCap; use crate::objects::null::NullCap;
use api::cap::ObjectType; use api::cap::ObjectType;
use core::{cell::Cell, ptr::NonNull}; use core::cell::Cell;
use utils::{
linked_list::{Link, LinkHelper},
LinkHelperImpl,
};
use vspace::addr::PhysAddr; use vspace::addr::PhysAddr;
/// RawCap is the specific implementation of capability which stores in CNode /// RawCap is the specific implementation of capability which stores in CNode
@ -31,47 +35,34 @@ impl RawCap {
} }
} }
#[derive(Copy, Clone, Default)]
pub struct Link {
pub prev: Option<NonNull<CapEntry>>,
pub next: Option<NonNull<CapEntry>>,
}
#[derive(Clone)]
pub struct CapEntry { pub struct CapEntry {
pub cap: Cell<RawCap>, pub cap: Cell<RawCap>,
pub link: Cell<Link>, pub link: Link<Self>,
} }
LinkHelperImpl!(CapEntry: link);
const_assert_eq!(core::mem::size_of::<CapEntry>(), ObjectType::CNode.size(0)); const_assert_eq!(core::mem::size_of::<CapEntry>(), ObjectType::CNode.size(0));
impl CapEntry { impl CapEntry {
pub fn new(cap: RawCap) -> Self { pub fn new(cap: RawCap) -> Self {
Self { Self {
cap: Cell::new(cap), cap: Cell::new(cap),
link: Cell::new(Link::default()), link: Link::default(),
} }
} }
pub fn init(&mut self) { pub fn init(&mut self) {
self.cap = Cell::new(NullCap::mint()); self.cap = Cell::new(NullCap::mint());
self.link = Cell::new(Link::default()); self.link = Link::default();
}
} }
pub fn prev(&self) -> Option<NonNull<CapEntry>> { impl Clone for CapEntry {
self.link.get().prev fn clone(&self) -> Self {
} let mut cte = Self::new(self.cap.get());
cte.link = self.link.clone();
pub fn next(&self) -> Option<NonNull<CapEntry>> { cte
self.link.get().next
}
pub fn set_prev(&mut self, prev: Option<NonNull<CapEntry>>) {
self.link.get_mut().prev = prev;
}
pub fn set_next(&mut self, next: Option<NonNull<CapEntry>>) {
self.link.get_mut().next = next;
} }
} }

View File

@ -51,25 +51,22 @@ impl<'a, T: KernelObject + ?Sized> TryFrom<&'a CapEntry> for Cap<'a, T> {
impl<'a, T: KernelObject + ?Sized> Cap<'a, T> { impl<'a, T: KernelObject + ?Sized> Cap<'a, T> {
pub fn append(&mut self, new: &mut CapEntry) { pub fn append(&mut self, new: &mut CapEntry) {
let next = self.cte.next(); let next = self.cte.link.next();
// update new cap's link // update new cap's link
new.set_prev(Some(NonNull::from(self.cte))); new.link.set_prev(Some(NonNull::from(self.cte)));
new.set_next(next); new.link.set_next(next);
// record new cap's addr // record new cap's addr
let new_addr = Some(NonNull::from(new)); let new_addr = Some(NonNull::from(new));
// update next cap's link.prev // update next cap's link.prev
if let Some(mut next) = next { if let Some(mut next) = next {
unsafe { next.as_mut().set_prev(new_addr) }; unsafe { next.as_mut().link.set_prev(new_addr) };
} }
// update self's link.next // update self's link.next
self.cte.link.update(|mut link| { self.cte.link.next.set(new_addr);
link.next = new_addr;
link
});
} }
} }

View File

@ -22,6 +22,6 @@ impl<T> AtomicConstPtr<T> {
} }
pub fn store(&self, ptr: *mut T, order: Ordering) { pub fn store(&self, ptr: *mut T, order: Ordering) {
self.0.store(ptr as *mut T, order) self.0.store(ptr, order)
} }
} }

View File

@ -3,6 +3,20 @@
#[macro_export] #[macro_export]
macro_rules! container_of { macro_rules! container_of {
($ptr:expr, $type:ty, $field:ident) => { ($ptr:expr, $type:ty, $field:ident) => {
($ptr as *const u8).sub(core::mem::offset_of!($type, $field) as usize) as *const $type ($ptr as *const _ as *const u8).sub(core::mem::offset_of!($type, $field) as usize) as *const $type
};
}
#[macro_export]
macro_rules! container_of_offset {
($ptr:expr, $type:ty, $offset:expr) => {
($ptr as *const _ as *const u8).sub($offset) as *const $type
};
}
#[macro_export]
macro_rules! to_field_offset {
($ptr:expr, $type:ty, $offset:expr) => {
($ptr as *const _ as *const u8).add($offset) as *const $type
}; };
} }

View File

@ -7,5 +7,11 @@ pub mod bin;
pub mod container_of; pub mod container_of;
pub mod extern_addr; pub mod extern_addr;
pub mod function_name; pub mod function_name;
pub mod linked_list;
pub mod size; pub mod size;
pub mod then; pub mod then;
pub mod warn;
#[cfg(test)]
#[macro_use]
extern crate std;

View File

@ -0,0 +1,207 @@
use crate::{container_of_offset, to_field_offset};
use core::{cell::Cell, ptr::NonNull};
#[macro_export]
macro_rules! LinkHelperImpl {
($type:ty : $field:ident) => {
impl LinkHelper for $type {
const LINK_OFFSET: usize = core::mem::offset_of!($type, $field) as usize;
}
};
}
pub trait LinkHelper: Sized {
const LINK_OFFSET: usize;
/// # Safety
/// LINK_OFFSET must be a valid field offset of Self
unsafe fn get_link(&self) -> &Link<Self> {
&*(to_field_offset!(self, Link<Self>, Self::LINK_OFFSET))
}
}
pub struct Link<T: LinkHelper> {
pub prev: Cell<Option<NonNull<T>>>,
pub next: Cell<Option<NonNull<T>>>,
}
impl<T: LinkHelper> Default for Link<T> {
fn default() -> Self {
Self {
prev: Cell::new(None),
next: Cell::new(None),
}
}
}
impl<T: LinkHelper> Clone for Link<T> {
fn clone(&self) -> Self {
Self {
prev: Cell::new(self.prev.get()),
next: Cell::new(self.next.get()),
}
}
}
impl<T: LinkHelper> Link<T> {
/// # Safety
/// LINK_OFFSET must be a valid field offset of T
pub unsafe fn object(&self) -> &T {
&*(container_of_offset!(self, T, T::LINK_OFFSET))
}
pub fn prev(&self) -> Option<NonNull<T>> {
self.prev.get()
}
pub fn next(&self) -> Option<NonNull<T>> {
self.next.get()
}
pub fn set_prev(&self, prev: Option<NonNull<T>>) {
self.prev.set(prev);
}
pub fn set_next(&self, next: Option<NonNull<T>>) {
self.next.set(next);
}
pub fn prepend(&self, new: &T) {
unsafe {
// setup new's link
new.get_link().set_prev(self.prev());
new.get_link().set_next(Some(NonNull::from(self.object())));
// setup prev's link
if let Some(prev) = self.prev() {
prev.as_ref().get_link().set_next(Some(NonNull::from(new)))
}
// setup self's link
self.set_prev(Some(NonNull::from(new)));
}
}
pub fn append(&self, new: &T) {
unsafe {
// setup new's link
new.get_link().set_prev(Some(NonNull::from(self.object())));
new.get_link().set_next(self.next());
// setup next's link
if let Some(next) = self.next() {
next.as_ref().get_link().set_prev(Some(NonNull::from(new)))
}
// setup self's link
self.set_next(Some(NonNull::from(new)));
}
}
pub fn detach(&self) {
unsafe {
// setup prev's link
if let Some(prev) = self.prev() {
prev.as_ref().get_link().set_next(self.next())
}
// setup next's link
if let Some(next) = self.next() {
next.as_ref().get_link().set_prev(self.prev())
}
// setup self's link
self.set_prev(None);
self.set_next(None);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
struct Node {
link: Link<Node>,
value: i32,
}
LinkHelperImpl!(Node: link);
macro_rules! as_mut_ptr {
($ref:expr => $type:ty) => {
$ref as *const _ as *mut $type
};
($ref:expr) => {
$ref as *const _ as *mut _
};
}
#[test]
fn test_linked_list() {
let node1 = Node {
link: Link::default(),
value: 1,
};
let node2 = Node {
link: Link::default(),
value: 2,
};
let node3 = Node {
link: Link::default(),
value: 3,
};
node1.link.append(&node2);
node2.link.append(&node3);
unsafe {
// check object
assert_eq!(as_mut_ptr!(node1.link.object() => Node), as_mut_ptr!(&node1 => Node));
assert_eq!(node1.link.object().value, 1);
assert_eq!(as_mut_ptr!(node2.link.object() => Node), as_mut_ptr!(&node2 => Node));
assert_eq!(node2.link.object().value, 2);
assert_eq!(as_mut_ptr!(node3.link.object() => Node), as_mut_ptr!(&node3 => Node));
assert_eq!(node3.link.object().value, 3);
}
unsafe {
// check get_link
assert_eq!(as_mut_ptr!(node1.get_link() => Link<Node>), as_mut_ptr!(&node1.link));
assert_eq!(as_mut_ptr!(node2.get_link() => Link<Node>), as_mut_ptr!(&node2.link));
assert_eq!(as_mut_ptr!(node3.get_link() => Link<Node>), as_mut_ptr!(&node3.link));
}
{
// check next link
assert!(node1.link.next().is_some());
assert_eq!(node1.link.next().unwrap().as_ptr(), as_mut_ptr!(&node2));
assert!(node2.link.next().is_some());
assert_eq!(node2.link.next().unwrap().as_ptr(), as_mut_ptr!(&node3));
assert!(node3.link.next().is_none());
}
{
// check prev link
assert!(node1.link.prev().is_none());
assert!(node2.link.prev().is_some());
assert_eq!(node2.link.prev().unwrap().as_ptr(), as_mut_ptr!(&node1));
assert!(node3.link.prev().is_some());
assert_eq!(node3.link.prev().unwrap().as_ptr(), as_mut_ptr!(&node2));
}
{
// check detach
node2.link.detach();
assert!(node2.link.next().is_none());
assert!(node2.link.prev().is_none());
assert!(node1.link.next().is_some());
assert_eq!(node1.link.next().unwrap().as_ptr(), as_mut_ptr!(&node3));
assert!(node3.link.prev().is_some());
assert_eq!(node3.link.prev().unwrap().as_ptr(), as_mut_ptr!(&node1));
}
}
}

15
lib/utils/src/warn.rs Normal file
View File

@ -0,0 +1,15 @@
// Taken from https://internals.rust-lang.org/t/pre-rfc-add-compile-warning-macro/9370/7
#[macro_export]
macro_rules! compile_warning {
($name:ident, $message:expr $(,)*) => {
mod $name {
#[must_use = $message]
struct compile_warning;
#[allow(dead_code)]
fn trigger_warning() {
compile_warning;
}
}
};
}

View File

@ -1,9 +0,0 @@
[package]
name = "xtask"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0"
clap = { version = "4.5", features = ["derive"] }
xshell = "0.2"

View File

@ -1,129 +0,0 @@
use anyhow::Result;
use clap::{Args, ValueEnum};
#[derive(ValueEnum, Copy, Clone)]
#[value(rename_all = "snake_case")]
pub enum Profile {
Debug,
Release,
}
#[derive(ValueEnum, Copy, Clone)]
#[value(rename_all = "snake_case")]
pub enum Arch {
RISCV64,
}
impl Arch {
const ARGS_BUILD_STD: [&'static str; 2] = [
"-Zbuild-std=core,compiler_builtins,alloc",
"-Zbuild-std-features=compiler-builtins-mem",
];
const FLAGS_RELOCATION: [&'static str; 4] = [
"-Crelocation-model=static",
"-Ccode-model=medium",
"-Ctarget-feature=+relax",
"-Cforce-frame-pointers=yes",
];
pub fn cargo_args(&self, test: bool) -> Vec<String> {
let mut args: Vec<String> = Vec::new();
if !test {
args.extend(Self::ARGS_BUILD_STD.iter().map(|s| s.to_string()).collect::<Vec<_>>());
}
args.push(format!("--target={}", self.triple()));
args
}
pub fn rust_flags(&self) -> Vec<String> {
let mut flags = Self::FLAGS_RELOCATION.iter().map(|s| s.to_string()).collect::<Vec<_>>();
match self {
Arch::RISCV64 => {
flags.push("-Clink-arg=-Tkernel/src/arch/riscv/linker64.ld".to_string());
flags
},
}
}
pub fn triple(&self) -> String {
match self {
Arch::RISCV64 => "riscv64imac-unknown-none-elf".to_string(),
}
}
pub fn board_arch_name(&self) -> String {
"riscv".to_string()
}
}
#[derive(ValueEnum, Copy, Clone)]
#[value(rename_all = "snake_case")]
pub enum Board {
Default,
Virt,
}
impl Board {
pub fn cargo_args(&self, arch: &Arch) -> Result<String> {
match self {
Board::Default => Ok(arch.board_arch_name().to_string() + ".board.default"),
Board::Virt => Ok(arch.board_arch_name().to_string() + ".board.virt"),
}
}
}
#[derive(Args)]
pub struct Artifact {
#[arg(long)]
pub arch: Arch,
#[arg(long)]
pub profile: Option<Profile>,
#[arg(long)]
pub board: Option<Board>,
#[arg(long)]
pub features: Vec<String>,
}
impl Artifact {
pub fn cargo_args(&self, test: bool) -> Result<Vec<String>> {
let mut args: Vec<String> = Vec::new();
let mut features: Vec<String> = Vec::new();
// profile
if let Some(Profile::Release) = self.profile {
args.push("--release".to_string());
}
// arch
args.extend(self.arch.cargo_args(test).iter().map(|s| s.to_string()));
// board
if let Some(board) = self.board {
features.push(board.cargo_args(&self.arch)?);
}
// features
features.extend(self.features.iter().map(|s| s.to_string()));
if !features.is_empty() {
args.push("--no-default-features".to_string());
args.push(format!("--features={}", features.join(",")));
}
Ok(args)
}
pub fn rust_flags(&self) -> Result<Vec<String>> {
let mut flags: Vec<String>;
let existing = std::env::var("CARGO_ENCODED_RUSTFLAGS").unwrap_or_default();
if !existing.is_empty() {
flags = existing.split('\x1f').map(|s| s.to_string()).collect::<Vec<_>>();
} else {
flags = Vec::new();
}
flags.extend(self.arch.rust_flags().iter().map(|s| s.to_string()));
Ok(flags)
}
}

View File

@ -1,24 +0,0 @@
use crate::artifact::Artifact;
use anyhow::Result;
use clap::Args;
use xshell::cmd;
#[derive(Args)]
pub struct Build {
#[command(flatten)]
pub artifact: Artifact,
}
impl Build {
pub fn run(&self) -> Result<()> {
let sh = crate::shell()?;
cmd!(sh, "cargo build")
.env("CARGO_ENCODED_RUSTFLAGS", self.artifact.rust_flags()?.join("\x1f"))
.args(["--bin", "kernel"])
.args(self.artifact.cargo_args(false)?)
.run()?;
Ok(())
}
}

View File

@ -1,24 +0,0 @@
use crate::artifact::Arch;
use anyhow::Result;
use clap::Args;
use xshell::cmd;
#[derive(Args)]
pub struct Clippy;
impl Clippy {
pub fn run(&self) -> Result<()> {
let sh = crate::shell()?;
{
let target = Arch::RISCV64;
cmd!(sh, "cargo clippy")
.arg("--target")
.arg(target.triple())
.args(["--no-deps", "--manifest-path", "kernel/Cargo.toml"])
.run()?;
}
Ok(())
}
}

View File

@ -1,36 +0,0 @@
mod artifact;
mod build;
mod clippy;
mod test;
use anyhow::Result;
use clap::Parser;
use std::path::Path;
use xshell::Shell;
#[derive(Parser)]
enum Cli {
Build(build::Build),
Clippy(clippy::Clippy),
Test(test::Test),
}
impl Cli {
fn run(&self) -> Result<()> {
match self {
Cli::Build(build) => build.run(),
Cli::Clippy(clippy) => clippy.run(),
Cli::Test(ci) => ci.run(),
}
}
}
fn main() -> Result<()> {
Cli::parse().run()
}
pub fn shell() -> Result<Shell> {
let sh = Shell::new()?;
sh.change_dir(Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap());
Ok(sh)
}

View File

@ -1,39 +0,0 @@
use crate::artifact::Artifact;
use clap::Args;
use xshell::cmd;
#[derive(Args)]
pub struct Test {
#[command(flatten)]
pub artifact: Artifact,
#[arg(long, default_value_t = false)]
pub debug: bool,
#[arg(long, default_value_t = false)]
pub dump: bool,
}
impl Test {
pub fn run(&self) -> anyhow::Result<()> {
let sh = crate::shell()?;
let mut extra_args: Vec<&str> = Vec::new();
if self.debug && !self.dump {
extra_args.push("--");
extra_args.push("-s");
extra_args.push("-S");
}
if self.dump {
extra_args.push("--no-run");
extra_args.push("--message-format=json")
}
cmd!(sh, "cargo test")
.env("CARGO_ENCODED_RUSTFLAGS", self.artifact.rust_flags()?.join("\x1f"))
.args(["--bin", "kernel"])
.args(self.artifact.cargo_args(true)?)
.args(extra_args)
.run()?;
Ok(())
}
}