Skip to content

Commit

Permalink
Merge pull request #90 from roblabla/fix-docs
Browse files Browse the repository at this point in the history
Fix docs
  • Loading branch information
Orycterope authored Dec 22, 2018
2 parents 23e7e03 + adee472 commit b7fb726
Show file tree
Hide file tree
Showing 46 changed files with 1,268 additions and 329 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ script:
- cargo make iso
- cargo make iso-release
- cargo make test
- cargo make doc-full

cache: cargo
1 change: 1 addition & 0 deletions bootstrap/src/bootstrap_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use address::VirtualAddress;

/// The size of a kernel stack, not accounting for the page guard
pub const STACK_SIZE: usize = 4;
/// The size of the kernel stack, with the page guard.
pub const STACK_SIZE_WITH_GUARD: usize = STACK_SIZE + 1;

/// The alignment of the stack. ceil(log2(STACK_SIZE_WITH_GUARD * PAGE_SIZE))
Expand Down
1 change: 1 addition & 0 deletions bootstrap/src/gdt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! our case though, we don't really care about that.
#![allow(dead_code)]
#![allow(missing_docs)]

pub mod segment_selector;
pub mod i386;
Expand Down
6 changes: 6 additions & 0 deletions bootstrap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#![cfg_attr(target_os = "none", no_main)]
#![allow(unused)]
#![warn(missing_docs)]
#![deny(intra_doc_link_resolution_failure)]
#[cfg(not(target_os = "none"))]
use std as core;

Expand Down Expand Up @@ -189,6 +190,9 @@ pub extern "C" fn do_bootstrap(multiboot_info_addr: usize) -> ! {
unreachable!()
}

/// The exception handling personality function for use in the bootstrap.
///
/// We have no exception handling in bootstrap, so make it do nothing.
#[cfg(target_os = "none")]
#[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {}

Expand All @@ -212,6 +216,7 @@ pub extern fn panic_fmt(p: &::core::panic::PanicInfo) -> ! {
macro_rules! multiboot_header {
//($($expr:tt)*) => {
($($name:ident: $tagty:ident :: $method:ident($($args:expr),*)),*) => {
/// The multiboot header structure of our binary.
#[repr(C)]
#[allow(dead_code)]
pub struct MultiBootHeader {
Expand All @@ -222,6 +227,7 @@ macro_rules! multiboot_header {
$($name: $tagty),*
}

/// The multiboot header of our binary.
#[used]
#[cfg_attr(target_os = "none", link_section = ".multiboot_header")]
pub static MULTIBOOT_HEADER: MultiBootHeader = MultiBootHeader {
Expand Down
7 changes: 7 additions & 0 deletions bootstrap/src/paging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ use ::core::ops::Deref;
use core;
use bootstrap_logging::Serial;

/// The size of a single page.
pub const PAGE_SIZE: usize = 4096;

const ENTRY_COUNT: usize = PAGE_SIZE / ::core::mem::size_of::<Entry>();

/// Currently active page tables.
pub static ACTIVE_PAGE_TABLES: Mutex<ActivePageTables> = Mutex::new(ActivePageTables());

/// Check if the paging is currently active.
Expand Down Expand Up @@ -126,7 +128,10 @@ pub unsafe fn map_bootstrap(boot_info : &BootInformation) -> PagingOffPageSet {
/// A trait describing the splitting of virtual memory between Kernel and User.
/// Implemented by UserLand and KernelLand
pub trait VirtualSpaceLand {
/// The first address in this land.
fn start_addr() -> VirtualAddress;

/// The last address in this land.
fn end_addr() -> VirtualAddress;

/// The index in page directory of the first table of this land
Expand All @@ -140,7 +145,9 @@ pub trait VirtualSpaceLand {
}
}

/// The virtual memory belonging to kernel.
pub struct KernelLand;
/// The virtual memory belonging to user.
pub struct UserLand;

impl KernelLand {
Expand Down
2 changes: 2 additions & 0 deletions bootstrap/src/paging/table.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! i386 page table / directory
#![allow(missing_docs)]

use core::ops::{Index, IndexMut, Bound, RangeBounds};

// Yeah, I'm ugly. Screw you.
Expand Down
16 changes: 12 additions & 4 deletions clock/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
#![feature(alloc, used)]
//! Clock applet
//!
//! Show the current time in the bottom left corner of the screen.
#![feature(alloc)]
#![no_std]

#![warn(missing_docs)]
#![deny(intra_doc_link_resolution_failure)]

extern crate kfs_libuser;
#[macro_use]
extern crate alloc;

use kfs_libuser::terminal::{Terminal, WindowSize};
use kfs_libuser::vi;
use kfs_libuser::io::{self, Io};
use kfs_libuser::syscalls;
use core::fmt::Write;
Expand Down Expand Up @@ -106,6 +112,7 @@ fn main() {
let mut month = rtc.read_reg(8);
let mut year = rtc.read_reg(9);

// IBM sometimes uses BCD. Why? God knows.
if !rtc.is_12hr_clock() {
seconds = (seconds & 0x0F) + ((seconds / 16) * 10);
minutes = (minutes & 0x0F) + ((minutes / 16) * 10);
Expand All @@ -116,12 +123,13 @@ fn main() {
year = (year & 0x0F) + ((year / 16) * 10);
}

syscalls::output_debug_string(&format!("{:02}:{:02}:{:02} {} {:02} {} {}", hours, minutes, seconds, get_day_of_week(dayofweek), day, get_month(month), year));
write!(&mut logger, "\n{:02}:{:02}:{:02} {} {:02} {} {}", hours, minutes, seconds, get_day_of_week(dayofweek), day, get_month(month), year);
let _ = syscalls::output_debug_string(&format!("{:02}:{:02}:{:02} {} {:02} {} {}", hours, minutes, seconds, get_day_of_week(dayofweek), day, get_month(month), year));
let _ = write!(&mut logger, "\n{:02}:{:02}:{:02} {} {:02} {} {}", hours, minutes, seconds, get_day_of_week(dayofweek), day, get_month(month), year);
}
}
}

/// Array of IO port this process is allowed to access.
#[cfg_attr(not(test), link_section = ".kernel_ioports")]
#[used]
pub static IOPORTS_PERMS: [u16; 2] = [0x70, 0x71];
2 changes: 1 addition & 1 deletion kernel/src/elf_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn load_segment(process_memory: &mut ProcessMemory, segment: &ProgramHeader, elf
SegmentData::Undefined(elf_data) =>
{
let dest_ptr = kernel_addr.addr() as *mut u8;
let mut dest = unsafe { slice::from_raw_parts_mut(dest_ptr, mem_size_total) };
let dest = unsafe { slice::from_raw_parts_mut(dest_ptr, mem_size_total) };
let (dest_data, dest_pad) = dest.split_at_mut(segment.file_size() as usize);

// Copy elf data
Expand Down
16 changes: 14 additions & 2 deletions kernel/src/heap_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use paging::{PAGE_SIZE, MappingFlags, kernel_memory::get_kernel_memory};
use frame_allocator::{FrameAllocator, FrameAllocatorTrait};
use mem::VirtualAddress;

/// Simple wrapper around linked_list_allocator, growing heap by allocating pages
/// with the frame allocator as necessary.
pub struct Allocator(Once<SpinLock<Heap>>);

// 512MB. Should be a multiple of PAGE_SIZE.
Expand Down Expand Up @@ -103,8 +105,18 @@ unsafe impl<'a> GlobalAlloc for Allocator {
}
}

// required: define how Out Of Memory (OOM) conditions should be handled
// *if* no other crate has already defined `oom`
// TODO: Kernel heap memory management
// BODY: Currently, if the kernel ever OOMs, this will lead to a panic. This is
// BODY: really not ideal. Unfortunately, we depend on a lot of Rust structures
// BODY: that make use of allocation (Arc, Vec, String...). Some of those have
// BODY: methods to customize OOM behavior (Vec and String have try_reserve), but
// BODY: some structures (like Arc) seem to be devoid of any function to avoid
// BODY: OOM.
// BODY:
// BODY: Maybe we should approach the rust developers, see if they would accept
// BODY: a try_new function on Arc/Rc that would return an AllocErr if it fails.
// BODY:
// BODY: Alternatively, we could start using our own Arc/Rc forks.
/// Called when the kernel heap allocator detects Out Of Memory (OOM) condition.
///
/// It simply panics.
Expand Down
53 changes: 39 additions & 14 deletions kernel/src/i386/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ static GDT: Once<SpinLock<GdtManager>> = Once::new();
/// The global LDT used by all the processes.
static GLOBAL_LDT: Once<DescriptorTable> = Once::new();

/// Initializes the GDT.
///
/// Creates a GDT with a flat memory segmentation model. It will create 3 kernel
/// segments (code, data, stack), three user segments (code, data, stack), an
/// LDT, and a TSS for the main task.
///
/// This function should only be called once. Further calls will be silently
/// ignored.
pub fn init_gdt() {
use i386::instructions::tables::{lldt, ltr};

Expand Down Expand Up @@ -91,15 +99,18 @@ pub fn init_gdt() {
gdt.push(DescriptorTableEntry::new_tss(main_task, PrivilegeLevel::Ring0, 0x2001));

info!("Loading GDT");
SpinLock::new(GdtManager::load(gdt, 0x8, 0x10, 0x18))
});
let gdt = SpinLock::new(GdtManager::load(gdt, 0x8, 0x10, 0x18));

unsafe {
info!("Loading LDT");
lldt(SegmentSelector(7 << 3));
info!("Loading Task");
ltr(SegmentSelector(8 << 3));
}

unsafe {
info!("Loading LDT");
lldt(SegmentSelector(7 << 3));
info!("Loading Task");
ltr(SegmentSelector(8 << 3));
}

gdt
});
}

struct GdtManager {
Expand Down Expand Up @@ -147,7 +158,7 @@ impl DerefMut for GdtManager {
}
}

// Push a task segment.
/// Push a task segment.
pub fn push_task_segment(task: &'static TssStruct) -> u16 {
info!("Pushing TSS: {:#?}", task);
let mut gdt = GDT.try().unwrap().lock();
Expand All @@ -157,6 +168,8 @@ pub fn push_task_segment(task: &'static TssStruct) -> u16 {
}

lazy_static! {
/// VirtualAddress of the TSS structure of the main task. Has 0x2001 bytes
/// available after the TssStruct to encode the IOPB of the current process.
pub static ref MAIN_TASK: VirtualAddress = {
// We need TssStruct + 0x2001 bytes of IOPB.
let pregion = FrameAllocator::allocate_region(align_up(size_of::<TssStruct>() + 0x2001, PAGE_SIZE))
Expand All @@ -173,9 +186,19 @@ lazy_static! {
};
}

// TODO: There's currently no guarantee that we don't create multiple &mut pointer to the IOPB.
// In practice, it should only be used by i386::process_switch, and as such, observed only there.
// TODO: Find a way to restrict usage there.
// TODO: gdt::get_main_iopb does not prevent creation of multiple mut ref.
// BODY: There's currently no guarantee that we don't create multiple &mut
// BODY: pointer to the IOPB region, which would cause undefined behavior. In
// BODY: practice, it should only be used by `i386::process_switch`, and as such,
// BODY: there is never actually two main_iopb active at the same time. Still,
// BODY: it'd be nicer to have safe functions to access the IOPB.
/// Get the IOPB of the Main Task.
///
/// # Safety
///
/// This function can be used to create multiple mut references to the same
/// region, which is very UB. Care should be taken to make sure any old mut slice
/// acquired through this method is dropped before it is called again.
pub unsafe fn get_main_iopb() -> &'static mut [u8] {
slice::from_raw_parts_mut((MAIN_TASK.addr() as *mut TssStruct).offset(1) as *mut u8, 0x2001)
}
Expand All @@ -187,12 +210,15 @@ struct DescriptorTable {
}

impl DescriptorTable {
/// Create an empty GDT. This will **not** include the null entry, so make
/// sure you add it!
pub fn new() -> DescriptorTable {
DescriptorTable {
table: Vec::new()
}
}

/// Fill the current DescriptorTable with a copy of the currently loaded entries.
pub fn set_from_loaded(&mut self) {
use core::slice;

Expand All @@ -205,6 +231,7 @@ impl DescriptorTable {
self.table.extend_from_slice(loaded_table);
}

/// Push a new entry to the table, returning a segment selector to it.
pub fn push(&mut self, entry: DescriptorTableEntry) -> u16 {
let ret = self.table.len() << 3;
self.table.push(entry);
Expand Down Expand Up @@ -258,8 +285,6 @@ enum SystemDescriptorTypes {
TrapGate32 = 15
}

// TODO: make this an enum based on a bit? But then it's not repr(transparent)
// :(
#[repr(transparent)]
#[derive(Clone, Copy)]
struct DescriptorTableEntry(u64);
Expand Down
18 changes: 17 additions & 1 deletion kernel/src/i386/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ use core::ops::{Deref, DerefMut};
#[macro_use]
pub mod registers;
pub mod stack;
pub mod pio;
pub mod multiboot;
pub mod structures;
pub mod process_switch;
pub mod gdt;

pub mod pio {
//! Port IO
//!
//! Look at libutils::io for more documentation.
pub use utils::io::Pio;
}

pub mod instructions {
//! Low level functions for special i386 instructions.
pub mod tables {
Expand Down Expand Up @@ -371,10 +378,19 @@ impl TssStruct {
}
}

/// Set the stack pointer used to handle interrupts occuring while running
/// in Ring3.
///
/// If an interrupt occurs while running in Ring3, it would be a security
/// problem to use the user-controlled stack to handle the interrupt. To
/// avoid this, we can tell the CPU to instead run the interrupt handler in
/// a separate stack.
pub fn set_esp0_stack(&mut self, esp: u32) {
self.esp0 = esp;
}

/// Set the IP of the current task struct. When we hardware task switch to
/// this TSS, we will resume running at the given instruction.
pub fn set_ip(&mut self, eip: u32) {
self.eip = eip;
}
Expand Down
4 changes: 4 additions & 0 deletions kernel/src/i386/multiboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub fn try_get_boot_information() -> Option<&'static BootInformation> {
BOOT_INFO.try()
}

/// Initializes the boot information module, allowing the `get_boot_information`
/// functions to operate properly.
///
/// Should only be called once. Further calls will be ignored silently.
pub fn init(boot_information: BootInformation) {
BOOT_INFO.call_once(|| {
boot_information
Expand Down
Loading

0 comments on commit b7fb726

Please sign in to comment.