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

misc: finish more TODOs #61

Merged
merged 7 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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