Skip to content

Commit

Permalink
misc: finish more TODOs (#61)
Browse files Browse the repository at this point in the history
* use proper Cargo aliases
* update docs further
* add command to view code documentation
* bump Rust toolchain and crate version
* add HART to startup & misc
* added dynamic memory support
  • Loading branch information
georglauterbach authored Nov 14, 2023
1 parent 9ece62e commit 7884c26
Show file tree
Hide file tree
Showing 29 changed files with 458 additions and 126 deletions.
16 changes: 16 additions & 0 deletions code/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# For a reference to this file, see
# https://doc.rust-lang.org/cargo/reference/config.html

# ! Only use this file for aliases! Do not provide target information or
# ! any other form of information in this file. This is because
# ! configuration in this file are inflexible, see
# ! https://georglauterbach.github.io/uncore/development/#about-the-workspace

[alias]
_help = ["run", "-q", "--", "help"]
_run = ["run", "-q", "--", "run"]
_debug = ["run", "-q", "--", "run", "--debug"]
_check = ["run", "-q", "--", "check"]
_doc = ["run", "-q", "--", "doc", "--open"]
_utest = ["run", "-q", "--", "u-test"]
_itest = ["run", "-q", "--", "i-test"]
2 changes: 1 addition & 1 deletion code/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "uncore-helper"
version = "1.0.0-alpha1"
version = "1.0.1"
edition = "2021"

description = """
Expand Down
6 changes: 3 additions & 3 deletions code/rust-toolchain.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
# General information about the keys below can be found under
# https://rust-lang.github.io/rustup/concepts/index.html
[toolchain]
channel = "nightly-2023-11-10"
components = [ "cargo", "rustc", 'rust-std', "clippy", "rustfmt" ]
targets = ["riscv64gc-unknown-none-elf"]
channel = 'nightly-2023-11-10'
components = [ 'cargo', 'rustc', 'rust-std', 'clippy', 'rustfmt' ]
targets = ['riscv64gc-unknown-none-elf']
128 changes: 120 additions & 8 deletions code/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,23 @@ pub enum Command {
ITest {
/// Specify whether you want to debug a test (only works when a specific test is
/// supplied)
#[clap(short, long)]
#[clap(short, long, requires = "test")]
debug: bool,
/// Specify which test to run
#[clap(short, long)]
test: Option<String>,
},
/// Check the code (e.g. with `clippy`)
Check,
/// Work with `unCORE`'s documentation
Doc {
/// Whether to open the documentation immediately
#[clap(short, long)]
open: bool,
/// Whether to watch for changes (requires 'cargo-watch)
#[clap(short, long)]
watch: bool,
},
}

impl Command {
Expand Down Expand Up @@ -64,6 +73,9 @@ impl Command {
Self::Check => {
check(architecture_specification)?;
},
Self::Doc { open, watch } => {
documentation(architecture_specification, *open, *watch)?;
},
}
Ok(())
}
Expand All @@ -77,14 +89,24 @@ impl std::fmt::Display for Command {

use anyhow::Context;

/// Short-hand for calling [`which`].
/// Short-hand for calling [`which`]. When only one argument is given, the command name
/// and the package name are equal on Ubuntu. When two arguments are given, the first one
/// is the command name to check, the second one is the package name on Ubuntu. When using
/// "cargo" in the beginning, the command has to be installed via `cargo install`.
macro_rules! check_bin {
($command:tt) => {
which::which($command).context(format!("Package '{}' seems to be missing", $command))?;
which::which($command).context(format!("Package '{}' seems to be missing", $command))
};

($command:expr, $package:expr) => {
which::which($command).context(format!("Package '{}' seems to be missing", $package))?;
which::which($command).context(format!("Package '{}' seems to be missing", $package))
};

(cargo $command:expr) => {
which::which($command).context(format!(
"Package '{0}' seems to be missing (install with 'cargo install {0}')",
$command
))
};
}

Expand All @@ -101,14 +123,14 @@ fn check_build_time_dependencies(_architecture: arguments::Architecture) -> anyh
fn check_run_time_dependencies(architecture: arguments::Architecture, is_debug: bool) -> anyhow::Result<()> {
log::debug!("Checking run-time dependencies");

check_bin!("jq");
check_bin!("jq")?;

match architecture {
arguments::Architecture::Riscv64 => {
check_bin!("qemu-system-riscv64");
check_bin!("qemu-system-riscv64")?;
if is_debug {
log::trace!("Checking run-time dependencies required for debugging");
check_bin!("gdb-multiarch");
check_bin!("gdb-multiarch")?;
}
},
}
Expand Down Expand Up @@ -209,7 +231,7 @@ fn run(arch_specification: &arguments::ArchitectureSpecification, is_debug: bool
let mut arguments = arch_specification.qemu_arguments_with_kernel();
if is_debug {
log::info!("Debugging unCORE");
log::debug!("You may use 'gdb-multiarch -q -x misc/gdb/init.txt' to attach now");
log::debug!("You may use 'gdb-multiarch -q -x ../misc/gdb/init.txt' to attach now");
log::trace!("Remember: 'Ctrl-A x' will exit QEMU");
arguments.append(&mut vec!["-s", "-S"]);
} else {
Expand Down Expand Up @@ -488,3 +510,93 @@ fn check(arch_specification: &arguments::ArchitectureSpecification) -> anyhow::R
log::debug!("Linting completed successfully");
Ok(())
}

/// This function handles working with the code documentation, written in doc comments.
fn documentation(
arch_specification: &arguments::ArchitectureSpecification,
open: bool,
watch: bool,
) -> anyhow::Result<()> {
log::info!("Building documentation now");
if watch {
log::debug!("Changes to the documentation are watched");

check_bin!(cargo "cargo-watch")?;
check_bin!("xdg-open", "xdg-utils")?;

let mut arguments = vec!["watch", "-w", "uncore/src", "-s"]
.into_iter()
.map(std::string::ToString::to_string)
.collect::<Vec<String>>();

arguments.push(format!(
"cargo doc --package uncore --document-private-items --lib --target {}",
arch_specification.target
));

if open {
log::trace!("Opening the documentation in the process");
let mut cargo_watch = std::process::Command::new(env!("CARGO"))
.args(arguments)
.stderr(std::process::Stdio::null())
.spawn()?;

let browser = std::process::Command::new("xdg-open")
.arg("target/riscv64gc-unknown-none-elf/doc/uncore/index.html")
.spawn();
if browser.is_err() {
cargo_watch.kill()?;
} else {
let browser = browser?.wait();
if browser.is_err() {
cargo_watch.kill()?;
}

if !browser?.success() {
cargo_watch.kill()?;
}
}

// A somewhat complicated piece of code that ensure we always call `cargo_watch.kill()` in
// case something went wrong.
let browser = std::process::Command::new("xdg-open")
.arg("target/riscv64gc-unknown-none-elf/doc/uncore/index.html")
.spawn();
if browser.is_err() {
cargo_watch.kill()?;
} else {
let browser = browser?.wait();
if browser.is_err() {
cargo_watch.kill()?;
}

if !browser?.success() {
cargo_watch.kill()?;
}
}

cargo_watch.wait()?;
Ok(())
} else {
log::debug!("Just watching changes, not opening");
run_command_and_check!(env!("CARGO"), arguments)
}
} else {
let mut arguments = vec![
"doc",
"--package",
"uncore",
"--document-private-items",
"--lib",
"--target",
arch_specification.target,
];

if open {
log::debug!("Opening the documentation");
arguments.push("--open");
}

run_command_and_check!(env!("CARGO"), arguments)
}
}
6 changes: 1 addition & 5 deletions code/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@

//! This module provides logging functionality.

/// ## The Global Test Runner Logger
///
/// This static variable is used by the [`log`] crate for
/// logging kernel-wide. Shamelessly copied from the kernel code.
/// logging kernel-wide.
static LOGGER: Logger = Logger;

/// ### The Main Test Runner Logger
///
/// This structure holds associated function that provide logging. The
/// [`log::Log`] trait is implemented for this structure.
#[derive(Debug)]
Expand Down
3 changes: 2 additions & 1 deletion code/uncore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cargo-features = ["per-package-target"]

[package]
name = "uncore"
version = "1.0.0-alpha2"
version = "1.0.0-alpha3"
edition = "2021"
workspace = "../"

Expand Down Expand Up @@ -58,6 +58,7 @@ autotests = false
[build-dependencies]

[dependencies]
linked_list_allocator = "0.10.5"
log = "0.4.20"
owo-colors = "3.5.0"
riscv-rt = { git = "https://github.com/rust-embedded/riscv-rt.git", rev = "28b916d", features = ["s-mode"] }
Expand Down
17 changes: 13 additions & 4 deletions code/uncore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
// ? MODULES and GLOBAL / CRATE-LEVEL FUNCTIONS
// ? ---------------------------------------------------------------------

// extern crate alloc;
/// Lol
extern crate alloc;

/// ### The Core Library
///
Expand All @@ -75,7 +76,15 @@ pub use library::{

/// This function can be described as the kernel's "main" function. It usually runs after
/// architecture-specific setup functions have run.
pub fn setup_kernel() {
library::log::initialize();
library::log::display_initial_information();
pub fn setup_kernel(hart: usize) {
if hart == 0 {
library::log::initialize();
library::log::display_initial_information();
}

log::info!("Running on HART {}", hart);

if hart == 0 {
library::mem::heap::Heap::initialize();
}
}
5 changes: 5 additions & 0 deletions code/uncore/src/library/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
//! "riscv64`) so that only one architecture is enabled at any given time.

/// Re-exported intra-kernel API that any implementation of an architecture must satisfy.
///
/// #### Attention
///
/// Initialization functionality may not have a working logger available when the
/// functions are called at run-time.
pub use architecture::{
drivers,
heap,
Expand Down
6 changes: 5 additions & 1 deletion code/uncore/src/library/arch/risc_v/drivers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ static mut INIT_WAS_CALLED: bool = false;
///
/// If this function is called more than once, it panics, because initializing certain
/// drivers more than once is undefined behavior.
pub(super) fn initialize() {
pub(super) fn initialize(hart: usize) {
if hart != 0 {
return;
}

assert!(
unsafe { !INIT_WAS_CALLED },
"called library/arch/risc_v/drivers/mod.rs:initialize more than once"
Expand Down
4 changes: 2 additions & 2 deletions code/uncore/src/library/arch/risc_v/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
//! address and its size.

extern "C" {
static __heap__start: u8;
static mut __heap__start: u8;
static __heap__size: u8;
}

/// Returns the starting address of the kernel heap.
#[must_use]
pub fn get_start() -> *const u8 { crate::transform_linker_symbol_to_value!(__heap__start) }
pub fn get_start() -> *mut u8 { crate::transform_linker_symbol_to_value!(mut __heap__start) }

/// Returns the size of the kernel heap.
#[must_use]
Expand Down
59 changes: 56 additions & 3 deletions code/uncore/src/library/arch/risc_v/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,65 @@
/// handler reports the interrupt and exists the kernel.
#[export_name = "DefaultHandler"]
pub fn default_handler() {
log::error!("Interrupt without defined interrupt handler occurred");
crate::arch::exit_kernel(crate::UncoreResult::Err);
todo!("Default Interrupt handler is todo");
}

/// todo
#[export_name = "UserSoft"]
pub fn user_software() {
todo!("User Software Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "SupervisorSoft"]
pub fn supervisor_software() {
todo!("Supervisor Software Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "MachineSoft"]
pub fn machine_software() {
todo!("Machine Software Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "UserTimer"]
pub fn user_timer() {
todo!("User Timer Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "SupervisorTimer"]
pub fn supervisor_timer() {
todo!("User Timer Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "MachineTimer"]
pub fn machine_timer() {
todo!("User Timer Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "UserExternal"]
pub fn user_external() {
todo!("User External Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "SupervisorExternal"]
pub fn supervisor_external() {
todo!("Supervisor External Interrupt triggered but interrupt handler is todo");
}

/// todo
#[export_name = "MachineExternal"]
pub fn machine_external() {
todo!("Machine External Interrupt triggered but interrupt handler is todo");
}

/// This function is used by [`riscv-rt`] to provide an exception handler.
#[export_name = "ExceptionHandler"]
fn exception_handler(_trap_frame: &riscv_rt::TrapFrame) -> ! {
panic!("Exception occurred but handler has not been written");
todo!("Exception occurred but handler has not been written");
}
Loading

0 comments on commit 7884c26

Please sign in to comment.