Skip to content

Commit

Permalink
Merge branch 'main' into ref_fs
Browse files Browse the repository at this point in the history
  • Loading branch information
Lockna authored Jan 22, 2024
2 parents 9b743e9 + d4a645d commit 1dd61ac
Show file tree
Hide file tree
Showing 20 changed files with 271 additions and 87 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Xernel Lint
on: [push, pull_request]
jobs:
xernel-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: sudo apt update && sudo apt install -y mtools
- run: rustup update && rustup toolchain install nightly
- run: rustup component add rust-src rustfmt clippy
- run: cargo kernel build
- run: cargo kernel fmt --check
- run: cargo kernel clippy
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# xernel
A kernel that tries to support multiple architectures/platforms using a hybrid kernel architecture.
It's using the limine protocol.
A kernel for x86-64 (and maybe ARM/RISC-V later on) using the limine boot protocol.
Mostly made for learning purposes, no real-world application.

![xernel](status_quo.png)

## Building
For building, you simply need a working Rust installation with the nightly toolchain installed and the `mtools` package which we use for the generation of the disk image.
For building, you simply need a working Rust installation with the nightly toolchain installed.
We use xtask as our workflow for building and running the kernel.
Therefore, the command `cargo kernel` is used.

Expand All @@ -16,6 +15,9 @@ You can simply use `cargo kernel build` or `cargo kernel run`, it is going to us

## Contact
Feel free to reach out to `lockna` or `mp1310` on Discord
or join our **Offical Discord Server:** https://discord.gg/e3gsmHX4w4

Here you can talk to us in the `xernel-development` category.

## TODO
Things that are still to do:
Expand Down
1 change: 1 addition & 0 deletions build/xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ pico-args = "0.5.0"
anyhow = "1"
wsl = "0.1.0"
dotenv = "0.15.0"
fatfs = "0.3.6"
77 changes: 35 additions & 42 deletions build/xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use anyhow::{bail, Result};
use dotenv::dotenv;
use fatfs::{format_volume, FormatVolumeOptions};
use pico_args::Arguments;
use std::env;
use std::io::{Cursor, Read, Seek, Write};
use std::path::{Path, PathBuf};
use std::{env, fs, vec};
use xshell::{cmd, Shell};

const HELP: &str = "\
Expand Down Expand Up @@ -85,14 +87,7 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> {
.opt_value_from_str::<_, String>("--target")?
.unwrap_or_else(|| "x86_64".to_string());

if !Path::new(
sh.current_dir()
.as_path()
.join("xernel/kernel/limine")
.as_path(),
)
.exists()
{
if !Path::new(sh.current_dir().as_path().join("xernel/kernel/limine").as_path()).exists() {
sh.change_dir(sh.current_dir().as_path().join("xernel/kernel"));
cmd!(
sh,
Expand Down Expand Up @@ -121,34 +116,30 @@ fn build(sh: &Shell, rl: bool, mut args: Arguments) -> Result<()> {
let build_dir = if rl { "release" } else { "debug" };

let diskname = "xernel.hdd";
let disksize = 64.to_string();
let disksize = 64 * 1024 * 1024; // 64 MB

cmd!(
sh,
"dd if=/dev/zero of={diskname} bs=1M count=0 seek={disksize}"
)
.run()?;
let data_vec = vec![0_u8; disksize];
let mut disk = Cursor::new(data_vec);

cmd!(sh, "mformat -i {diskname} -F").run()?;
cmd!(
sh,
"mcopy -i {diskname} ./target/{target}/{build_dir}/xernel ::/xernel"
)
.run()?;
cmd!(
sh,
"mcopy -i {diskname} xernel/kernel/limine.cfg ::/limine.cfg"
)
.run()?;
format_volume(&mut disk, FormatVolumeOptions::new().fat_type(fatfs::FatType::Fat32))?;

cmd!(sh, "mcopy -i {diskname} ./logo.bmp ::/logo.bmp").run()?;
cmd!(sh, "mmd -i {diskname} ::/EFI").run()?;
cmd!(sh, "mmd -i {diskname} ::/EFI/BOOT").run()?;
cmd!(
sh,
"mcopy -i {diskname} xernel/kernel/limine/BOOTX64.EFI ::/EFI/BOOT"
)
.run()?;
let fs = fatfs::FileSystem::new(&mut disk, fatfs::FsOptions::new())?;
{
let root_dir = fs.root_dir();

copy_to_image(&root_dir, &format!("./target/{target}/{build_dir}/xernel"), "xernel")?;

copy_to_image(&root_dir, "./logo.bmp", "logo.bmp")?;

let dir = root_dir.create_dir("EFI")?;
let dir = dir.create_dir("BOOT")?;

copy_to_image(&dir, "./xernel/kernel/limine/BOOTX64.EFI", "BOOTX64.EFI")?;
copy_to_image(&dir, "./xernel/kernel/limine.cfg", "limine.cfg")?;
}
fs.unmount()?;

fs::write(diskname, disk.into_inner())?;

Ok(())
}
Expand All @@ -159,10 +150,7 @@ fn run(sh: &Shell, gdb: bool, mut args: Arguments) -> Result<()> {
let ram = args
.opt_value_from_str::<_, String>("--ram")?
.unwrap_or_else(|| "128M".to_string());
let cpus = args
.opt_value_from_str::<_, u32>("--cpus")?
.unwrap_or(2)
.to_string();
let cpus = args.opt_value_from_str::<_, u32>("--cpus")?.unwrap_or(2).to_string();

let kvm = if args.contains("--kvm") {
&["-enable-kvm"]
Expand All @@ -174,10 +162,7 @@ fn run(sh: &Shell, gdb: bool, mut args: Arguments) -> Result<()> {

let qemu_in_wsl_arg = args.contains("--wsl-qemu");

let qemu_in_wsl_env = env::var("qemu_in_wsl")
.unwrap_or("false".to_string())
.parse()
.unwrap();
let qemu_in_wsl_env = env::var("qemu_in_wsl").unwrap_or("false".to_string()).parse().unwrap();

let qemu_in_wsl = qemu_in_wsl_arg || qemu_in_wsl_env;

Expand Down Expand Up @@ -242,3 +227,11 @@ fn root() -> PathBuf {
path.pop();
path
}

fn copy_to_image<T: Seek + Write + Read>(dir: &fatfs::Dir<T>, src_path: &str, dst_path: &str) -> Result<()> {
let data = fs::read(src_path)?;

dir.create_file(dst_path)?.write_all(&data)?;

Ok(())
}
1 change: 1 addition & 0 deletions crates/libxernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bitflags = "2.4.1"

[features]
kernel = []
8 changes: 8 additions & 0 deletions crates/libxernel/src/sync/spin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ impl<T: ?Sized> Spinlock<T> {
None
}

pub fn with_lock<F, U>(&self, function: F) -> U
where
F: FnOnce(&mut T) -> U,
{
let mut lock = self.lock();
function(&mut *lock)
}

/// Unlocking a spinlock
///
/// With the drop approach the lock only gets released when the [`MutexGuard`] value goes out of scope.
Expand Down
22 changes: 22 additions & 0 deletions crates/libxernel/src/syscall.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// constants for syscall numbers

use bitflags::bitflags;

pub const SYS_READ: usize = 0;
pub const SYS_WRITE: usize = 1;
pub const SYS_OPEN: usize = 2;
pub const SYS_CLOSE: usize = 3;
pub const SYS_MMAP: usize = 4;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[repr(isize)]
Expand All @@ -18,4 +21,23 @@ pub enum SyscallError {
MountPointNotFound = -8,
FileSystemNotFound = -9,
MalformedPath = -10,
InvalidArgument = -11,
}

bitflags! {
#[derive(Clone, Copy)]
pub struct ProtectionFlags: u8 {
const READ = 1 << 0;
const WRITE = 1 << 1;
const EXECUTE = 1 << 2;
}
}

bitflags! {
#[derive(PartialEq, Eq)]
pub struct MapFlags: u8 {
const SHARED = 1 << 0;
const PRIVATE = 1 << 1;
const ANONYMOUS = 1 << 3;
}
}
1 change: 0 additions & 1 deletion xernel/kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ x86_64 = { git = "https://github.com/rust-osdev/x86_64" }
acpi_parsing = { package = "acpi", version = "4.1.1" }
libxernel = { path = "../../crates/libxernel", features = ["kernel"] }
linked_list_allocator = { version = "0.10.3", features = [] }
bitflags = "1.3.2"
paste = "1.0.14"
seq-macro = "0.3.5"
3 changes: 2 additions & 1 deletion xernel/kernel/src/arch/amd64/gdt.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloc::alloc::alloc_zeroed;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::ptr::addr_of;
use libxernel::sync::{Once, TicketMutex};
use x86_64::instructions::segmentation::{Segment, CS, DS, ES, SS};
use x86_64::instructions::tables::load_tss;
Expand Down Expand Up @@ -39,7 +40,7 @@ pub struct Selectors {
pub fn init() {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
let stack_start = VirtAddr::from_ptr(unsafe { &BSP_IST_STACK });
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(BSP_IST_STACK) });
stack_start + IST_STACK_SIZE
};

Expand Down
37 changes: 24 additions & 13 deletions xernel/kernel/src/arch/amd64/idt.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::arch::amd64::ports::outb;
use crate::sched::context::CpuContext;
use crate::{arch::amd64::ports::outb, mem::mmap::handle_page_fault};
use core::arch::asm;
use core::mem::size_of;
use core::ptr::addr_of;
use libxernel::sync::{Spinlock, SpinlockIRQ};
use x86_64::structures::idt::PageFaultErrorCode;

use crate::arch::amd64::read_cr2;
use paste::paste;
Expand Down Expand Up @@ -165,7 +167,7 @@ pub fn init() {

let idtr = Idtr::new(
((IDT.len() * size_of::<IDTEntry>()) - 1) as u16,
(&IDT as *const _) as u64,
(addr_of!(IDT) as *const _) as u64,
);

idtr.load();
Expand Down Expand Up @@ -238,17 +240,26 @@ fn double_fault_handler(frame: CpuContext) {
}

fn page_fault_handler(frame: CpuContext) {
dbg!("EXCEPTION: PAGE FAULT");
dbg!("Accessed Address: {:?}", read_cr2());
dbg!("Error Code: {:?}", frame.error_code);
dbg!("{:#?}", frame);
println!("EXCEPTION: PAGE FAULT");
println!("Accessed Address: {:?}", read_cr2());
println!("Error Code: {:?}", frame.error_code);
println!("{:#?}", frame);
loop {
unsafe {
asm!("hlt");
let addr = read_cr2();
let error_code = PageFaultErrorCode::from_bits_truncate(frame.error_code);

let handled_successfully = handle_page_fault(addr, error_code);

if !handled_successfully {
dbg!("EXCEPTION: PAGE FAULT");
dbg!("Accessed Address: {:?}", read_cr2());
dbg!("Error Code: {:?}", frame.error_code);
dbg!("{:#?}", frame);

error!("EXCEPTION: PAGE FAULT");
error!("Accessed Address: {:?}", read_cr2());
error!("Error Code: {:?}", error_code);
error!("{:#?}", frame);

loop {
unsafe {
asm!("hlt");
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion xernel/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use super::vnode::VNode;

pub struct File {
node: Arc<Spinlock<VNode>>,
offset: usize,
}

impl File {
pub fn new(node: Arc<Spinlock<VNode>>) -> Self {
Self { node }
Self { node, offset: 0 }
}

pub fn get_node(&self) -> Arc<Spinlock<VNode>> {
Expand Down
1 change: 1 addition & 0 deletions xernel/kernel/src/fs/vfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use alloc::{
sync::Arc,
vec::Vec,
};
use libxernel::boot::InitAtBoot;
use libxernel::sync::Spinlock;
use libxernel::boot::InitAtBoot;

Expand Down
6 changes: 2 additions & 4 deletions xernel/kernel/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#![no_std]
#![no_main]
#![feature(abi_x86_interrupt)]
#![feature(core_intrinsics)]
#![feature(pointer_byte_offsets)]
#![feature(naked_functions)]
#![feature(exclusive_range_pattern)]
#![feature(let_chains)]
Expand Down Expand Up @@ -155,13 +153,13 @@ extern "C" fn kernel_main() -> ! {
}
}

KERNEL_PROCESS.set_once(Arc::new(Spinlock::new(Process::new(None, true))));
KERNEL_PROCESS.set_once(Arc::new(Spinlock::new(Process::new(None))));

wait_until_cpus_registered();

scheduler::init();

let process = Arc::new(Spinlock::new(Process::new(Some(KERNEL_PROCESS.clone()), false)));
let process = Arc::new(Spinlock::new(Process::new(Some(KERNEL_PROCESS.clone()))));

let _user_task = Thread::new_user_thread(process.clone(), VirtAddr::new(0x200000));

Expand Down
Loading

0 comments on commit 1dd61ac

Please sign in to comment.