Commit 49d7d45e authored by Nifou's avatar Nifou

Run `rustfmt`

parent cff5f248
Pipeline #165689676 passed with stages
in 9 minutes and 3 seconds
fn_single_line = true
......@@ -18,8 +18,7 @@
#[no_mangle]
/// Copy memory from `src` to `dest` on `n` bytes
pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
let mut i = 0;
while i < n {
*dest.offset(i as isize) = *src.offset(i as isize);
......@@ -30,15 +29,16 @@ pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8,
#[no_mangle]
/// Move memory from `src` to `dest` on `n` bytes
pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
n: usize) -> *mut u8 {
if src < dest as *const u8 { // copy from end
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
if src < dest as *const u8 {
// copy from end
let mut i = n;
while i != 0 {
i -= 1;
*dest.offset(i as isize) = *src.offset(i as isize);
}
} else { // copy from beginning
} else {
// copy from beginning
let mut i = 0;
while i < n {
*dest.offset(i as isize) = *src.offset(i as isize);
......@@ -50,7 +50,7 @@ pub unsafe extern fn memmove(dest: *mut u8, src: *const u8,
#[no_mangle]
/// Set memory started from `s` with the value `c` on `n` bytes
pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
let mut i = 0;
while i < n {
*s.offset(i as isize) = c as u8;
......@@ -61,13 +61,13 @@ pub unsafe extern fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
#[no_mangle]
/// Compare the memory `s1` with the memory `s2` on `n` bytes
pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
let mut i = 0;
while i < n {
let a = *s1.offset(i as isize);
let b = *s2.offset(i as isize);
if a != b {
return a as i32 - b as i32
return a as i32 - b as i32;
}
i += 1;
}
......
......@@ -15,27 +15,21 @@
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! A loader which loads ELF static binaries
use alloc::{
prelude::v1::String,
collections::btree_map::BTreeMap,
};
use alloc::{collections::btree_map::BTreeMap, prelude::v1::String};
use core::ptr::copy_nonoverlapping;
use goblin::elf::{
Elf,
program_header::{PT_LOAD, PT_PHDR},
Elf,
};
use x86_64::structures::paging::page_table::PageTableFlags as Flags;
use crate::memory::{self, PAGE_SIZE};
use crate::tasking::{
process::ProcessBuilder,
info::{
ProcessInfo,
AuxVecItem,
},
info::{AuxVecItem, ProcessInfo},
memory::MemoryArea,
process::ProcessBuilder,
};
#[derive(PartialEq, Debug, Clone, Copy)]
......@@ -70,7 +64,12 @@ static MAGIC: [u8; 4] = [0x7f, 'E' as u8, 'L' as u8, 'F' as u8];
impl<'a> ElfLoader<'a> {
/// Create a new ElfLoader with the specified binary
pub fn new(binary: Elf<'a>, data: &'a [u8], path: String) -> Self {
Self { binary, data, path, process: None }
Self {
binary,
data,
path,
process: None,
}
}
/// Check the binary
......@@ -99,19 +98,40 @@ impl<'a> ElfLoader<'a> {
let envs = vec!["PATH=/bin".into()];
let mut auxv = BTreeMap::new();
if let Some(phdr) = self.binary.program_headers.iter().find(|ph| ph.p_type == PT_PHDR) {
if let Some(phdr) = self
.binary
.program_headers
.iter()
.find(|ph| ph.p_type == PT_PHDR)
{
auxv.insert(AuxVecItem::PHDR as u8, phdr.p_vaddr as usize);
} else if let Some(elf_addr) = self.binary.program_headers.iter().find(|ph| ph.p_type == PT_LOAD && ph.p_offset == 0) {
auxv.insert(AuxVecItem::PHDR as u8, (elf_addr.p_vaddr + self.binary.header.e_phoff) as usize);
} else if let Some(elf_addr) = self
.binary
.program_headers
.iter()
.find(|ph| ph.p_type == PT_LOAD && ph.p_offset == 0)
{
auxv.insert(
AuxVecItem::PHDR as u8,
(elf_addr.p_vaddr + self.binary.header.e_phoff) as usize,
);
} else {
println!("No program header found!");
}
auxv.insert(AuxVecItem::PHENT as u8, self.binary.header.e_phentsize as usize);
auxv.insert(
AuxVecItem::PHENT as u8,
self.binary.header.e_phentsize as usize,
);
auxv.insert(AuxVecItem::PHNUM as u8, self.binary.header.e_phnum as usize);
auxv.insert(AuxVecItem::PAGESZ as u8, PAGE_SIZE);
auxv.insert(AuxVecItem::ENTRY as u8, self.binary.header.e_entry as usize);
ProcessInfo { args, envs, auxv, first_arg_addr: 0 }
ProcessInfo {
args,
envs,
auxv,
first_arg_addr: 0,
}
}
/// Load the binary in memory
......@@ -169,7 +189,7 @@ impl<'a> ElfLoader<'a> {
let mut area = MemoryArea::new(
mappings.first().unwrap().1.start_address().as_u64(),
mappings.last().unwrap().1.start_address().as_u64() + PAGE_SIZE as u64,
flags
flags,
);
area.mappings(mappings.clone());
......@@ -192,7 +212,5 @@ impl<'a> ElfLoader<'a> {
}
/// Add the created process to the list of processes
pub fn add(&self) {
self.process.as_ref().unwrap().build();
}
pub fn add(&self) { self.process.as_ref().unwrap().build(); }
}
......@@ -21,8 +21,8 @@ use goblin::elf::*;
pub mod loader;
use crate::initfs;
use self::loader::ElfLoader;
use crate::initfs;
/// Check, load and run a static linked binary
pub fn load(path: String) {
......@@ -45,6 +45,6 @@ pub fn load(path: String) {
}
Err(e) => {
println!("ELF Error: {}", e);
},
}
}
}
......@@ -17,11 +17,11 @@
//! Global descriptor table segments management and initialization
use core::mem;
use x86::{
segmentation::*,
Ring::Ring0,
current::task::TaskStateSegment,
dtables::{lgdt, DescriptorTablePointer},
segmentation::*,
task::load_tr,
dtables::{DescriptorTablePointer, lgdt},
Ring::Ring0,
};
/// The index of the Double Fault entry in the Interrupt Stack Table (IST)
......@@ -92,7 +92,7 @@ pub struct GdtEntry {
pub flags_limith: u8,
/// The high part of the entry's offset
pub offseth: u8
pub offseth: u8,
}
impl GdtEntry {
......@@ -125,29 +125,35 @@ impl GdtEntry {
/// The pointer to the global GDT
pub static mut GDTR: DescriptorTablePointer<Descriptor> = DescriptorTablePointer {
limit: 0,
base: 0 as *const Descriptor
base: 0 as *const Descriptor,
};
/// The global GDT used by the kernel
pub static mut GDT: [GdtEntry; 7] = [
// Null segment
GdtEntry::new(0, 0),
// Kernel code segment
GdtEntry::new(GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// Kernel data segment
GdtEntry::new(GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
GDT_A_PRESENT | GDT_A_RING_0 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// User code segment
GdtEntry::new(GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_EXECUTABLE | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// User data segment
GdtEntry::new(GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE, GDT_F_LONG_MODE),
GdtEntry::new(
GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_SYSTEM | GDT_A_PRIVILEGE,
GDT_F_LONG_MODE,
),
// TSS segment
GdtEntry::new(GDT_A_PRESENT | GDT_A_RING_3 | GDT_A_TSS_AVAIL, 0),
// TSS must be 16 bytes long, twice the normal size
GdtEntry::new(0, 0),
];
......@@ -161,7 +167,7 @@ pub static mut TSS: TaskStateSegment = TaskStateSegment {
ist: [0; 7],
reserved3: 0,
reserved4: 0,
iomap_base: 0xFFFF
iomap_base: 0xFFFF,
};
/// Initialize GDT
......@@ -193,6 +199,4 @@ pub unsafe fn init() {
}
/// Set the kernel's stack pointer in the TSS
pub unsafe fn set_stack(addr: u64) {
TSS.rsp[0] = addr;
}
pub unsafe fn set_stack(addr: u64) { TSS.rsp[0] = addr; }
......@@ -15,38 +15,22 @@
* along with this program. If not, see https://www.gnu.org/licenses.
*/
//! Functions which are called when an interrupt or an exception happens
use core::{intrinsics::copy_nonoverlapping, sync::atomic::Ordering};
use x86_64::{
VirtAddr,
structures::{
idt::{
InterruptStackFrame,
PageFaultErrorCode
},
paging::{
Page, Size4KiB,
page_table::PageTableFlags as Flags,
FrameAllocator,
Mapper,
},
idt::{InterruptStackFrame, PageFaultErrorCode},
paging::{page_table::PageTableFlags as Flags, FrameAllocator, Mapper, Page, Size4KiB},
},
};
use core::{
sync::atomic::Ordering,
intrinsics::copy_nonoverlapping,
VirtAddr,
};
use super::id::IrqId;
use super::idt::PICS;
use crate::{
memory::{table::TemporaryPage, PAGE_SIZE, TMP_PAGE_ADDR},
tasking::{
memory::MemoryArea,
scheduler::{
FIRST_TIME, SCHEDULER, PROCESSES
},
},
memory::{
TMP_PAGE_ADDR, PAGE_SIZE,
table::TemporaryPage,
scheduler::{FIRST_TIME, PROCESSES, SCHEDULER},
},
};
......@@ -87,7 +71,7 @@ pub extern "x86-interrupt" fn timer_interrupt_handler(_: &mut InterruptStackFram
// Save the current context
if !FIRST_TIME.load(Ordering::Relaxed) {
// Use a closure to avoid messing up the stack (with the stack frame)
let get_kstack = || { SCHEDULER.get().current().unwrap().kstack };
let get_kstack = || SCHEDULER.get().current().unwrap().kstack;
unsafe {
llvm_asm!("
......@@ -128,8 +112,7 @@ pub extern "x86-interrupt" fn timer_interrupt_handler(_: &mut InterruptStackFram
:
: "intel", "volatile");
}
}
else {
} else {
FIRST_TIME.store(false, Ordering::Relaxed);
}
......@@ -254,7 +237,10 @@ pub extern "x86-interrupt" fn general_protection_fault_handler(
///
/// Handler(s):
/// * Copy-on-write
pub extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut InterruptStackFrame, error_code: PageFaultErrorCode) {
pub extern "x86-interrupt" fn page_fault_handler(
stack_frame: &mut InterruptStackFrame,
error_code: PageFaultErrorCode,
) {
use x86_64::registers::control::Cr2;
// Use the kernel's page table
......@@ -266,10 +252,15 @@ pub extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut InterruptStac
let mut processes = PROCESSES.write();
let current_thread = SCHEDULER.get().current().unwrap().clone();
if let Some(area) = processes.get(&current_thread.process).expect("Could not find the current process").memory.get_area(addr.as_u64()) {
if let Some(area) = processes
.get(&current_thread.process)
.expect("Could not find the current process")
.memory
.get_area(addr.as_u64())
{
let mut flags = area.flags;
if flags.contains(Flags::BIT_9)
&& error_code.contains(PageFaultErrorCode::CAUSED_BY_WRITE) {
if flags.contains(Flags::BIT_9) && error_code.contains(PageFaultErrorCode::CAUSED_BY_WRITE)
{
// --- Copy-on-write handler ---
// Allocate a new frame which will be the clone of the frame
......@@ -281,28 +272,43 @@ pub extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut InterruptStac
.unwrap();
// Create a temporary page to copy data between the two frames
let mut tmp = TemporaryPage::new(Page::containing_address(VirtAddr::new(TMP_PAGE_ADDR)));
let mut tmp =
TemporaryPage::new(Page::containing_address(VirtAddr::new(TMP_PAGE_ADDR)));
// TODO: Add the kernel heap in the process' memory to avoid this ugly and slow line
// (because we would be in the process' memory space and not in the kernel's memory space)
let mut dest_frame = None;
processes.get_mut(&current_thread.process).expect("Could not find the current process").memory.table.with(|mapper| {
dest_frame = mapper.translate_page(page).ok();
});
processes
.get_mut(&current_thread.process)
.expect("Could not find the current process")
.memory
.table
.with(|mapper| {
dest_frame = mapper.translate_page(page).ok();
});
unsafe {
crate::memory::KERNEL_MAPPER.r#try().unwrap().lock().map_to(
page,
dest_frame.unwrap(),
Flags::PRESENT | Flags::NO_EXECUTE,
&mut *crate::memory::FRAME_ALLOCATOR.r#try().unwrap().lock()
).unwrap().flush();
crate::memory::KERNEL_MAPPER
.r#try()
.unwrap()
.lock()
.map_to(
page,
dest_frame.unwrap(),
Flags::PRESENT | Flags::NO_EXECUTE,
&mut *crate::memory::FRAME_ALLOCATOR.r#try().unwrap().lock(),
)
.unwrap()
.flush();
}
// ---
{
let src = (addr.as_u64() - (addr.as_u64() % PAGE_SIZE as u64)) as *const u8;
let dest = tmp.map(frame.clone(), Flags::PRESENT | Flags::WRITABLE | Flags::NO_EXECUTE) as *mut u8;
let dest = tmp.map(
frame.clone(),
Flags::PRESENT | Flags::WRITABLE | Flags::NO_EXECUTE,
) as *mut u8;
unsafe { copy_nonoverlapping(src, dest, PAGE_SIZE) };
}
......@@ -310,14 +316,23 @@ pub extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut InterruptStac
// TODO: Add the kernel heap in the process' memory to avoid this ugly and slow line
// (because we would be in the process' memory space and not in the kernel's memory space)
crate::memory::KERNEL_MAPPER.r#try().unwrap().lock().unmap(
page
).unwrap().1.flush();
crate::memory::KERNEL_MAPPER
.r#try()
.unwrap()
.lock()
.unmap(page)
.unwrap()
.1
.flush();
// ---
// Change the page's frame
processes.get_mut(&current_thread.process).expect("Could not find the current process")
.memory.table.unmap(page);
processes
.get_mut(&current_thread.process)
.expect("Could not find the current process")
.memory
.table
.unmap(page);
// Add the WRITABLE flag because the page is now cloned
flags.insert(Flags::WRITABLE);
......@@ -327,23 +342,35 @@ pub extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut InterruptStac
let mut area = MemoryArea::new(
page.start_address().as_u64(),
page.start_address().as_u64() + PAGE_SIZE as u64,
flags
flags,
);
area.mappings(vec![(frame, page)]);
processes.get_mut(&current_thread.process).expect("Could not find the current process")
.memory.map(area);
processes
.get_mut(&current_thread.process)
.expect("Could not find the current process")
.memory
.map(area);
handled = true;
}
}
if handled == false {
println!("@ Error: Page fault at {:#x} | {:?} | -> {:#x}", stack_frame.instruction_pointer.as_u64(), error_code, addr.as_u64());
println!(
"@ Error: Page fault at {:#x} | {:?} | -> {:#x}",
stack_frame.instruction_pointer.as_u64(),
error_code,
addr.as_u64()
);
stop();
}
processes.get(&current_thread.process).expect("Could not find the current process").memory.switch_page_table();
processes
.get(&current_thread.process)
.expect("Could not find the current process")
.memory
.switch_page_table();
drop(processes);
}
......
......@@ -87,6 +87,4 @@ lazy_static! {
}
/// Init the IDT by using the `lidt` instruction
pub fn init() {
IDT.load();
}
pub fn init() { IDT.load(); }
......@@ -25,7 +25,6 @@
#![feature(llvm_asm)]
#![feature(alloc_error_handler)]
#![feature(naked_functions)]
#![warn(deprecated_in_future)]
#![warn(missing_docs)]
......@@ -34,16 +33,16 @@ extern crate alloc;
#[macro_use]
pub mod serial;
pub mod boot_info;
pub mod common;
pub mod elf;
pub mod gdt;
pub mod initfs;
pub mod irq;
pub mod memory;
pub mod sse;
pub mod tasking;
pub mod syscall;
pub mod common;
pub mod boot_info;
pub mod tasking;
use alloc::{alloc::Layout, prelude::v1::String};
use core::panic::PanicInfo;
......@@ -93,24 +92,35 @@ pub fn init() {
println!(" [ OK ]");
println!("Areas detected:");
let areas = boot_info::BOOT_INFO.r#try().unwrap().get().memory_map_tag()
.expect("Memory map tag required")
.memory_areas().clone();
let areas = boot_info::BOOT_INFO
.r#try()
.unwrap()
.get()
.memory_map_tag()
.expect("Memory map tag required")
.memory_areas()
.clone();
let mut total_size = 0;
for area in areas {
println!(" - From {:#x} to {:#x}. Type: {:?}", area.start_address(), area.end_address(), area.typ());
println!(
" - From {:#x} to {:#x}. Type: {:?}",
area.start_address(),
area.end_address(),
area.typ()
);
total_size += area.size();
}
println!("Total size: | {} MiB |", total_size / (1024 * 1024));
}
#[no_mangle]
#[cfg(not(feature = "test"))]
/// The entry point of the kernel
pub extern "C" fn kmain(info_addr: usize) {
let boot_info = unsafe { multiboot2::load((info_addr as u64 + (KERNEL_START_VIRT - KERNEL_START_PHYS)) as usize) };
let boot_info = unsafe {
multiboot2::load((info_addr as u64 + (KERNEL_START_VIRT - KERNEL_START_PHYS)) as usize)
};
boot_info::BOOT_INFO.call_once(|| boot_info::BootInfo(boot_info));
......@@ -134,7 +144,9 @@ pub extern "C" fn kmain(info_addr: usize) {
use memory::map;
let boot_info = unsafe { multiboot2::load((info_addr as u64 + (KERNEL_START_VIRT - KERNEL_START_PHYS)) as usize) };
let boot_info = unsafe {
multiboot2::load((info_addr as u64 + (KERNEL_START_VIRT - KERNEL_START_PHYS)) as usize)
};
BOOT_INFO.call_once(|| BootInfo(boot_info));
......
......@@ -16,14 +16,14 @@
*/
//! Physical memory's frames allocator
use alloc::prelude::v1::Vec;
use multiboot2::{MemoryArea, MemoryAreaIter, MemoryAreaType};
use x86_64::{
structures::paging::{FrameAllocator, FrameDeallocator, PhysFrame, Size4KiB},
PhysAddr,
};
use multiboot2::{MemoryAreaIter, MemoryArea, MemoryAreaType};
use super::heap::{HEAP_SIZE, HEAP_START_PHYS};
use crate::boot_info::BOOT_INFO;
use super::heap::{HEAP_START_PHYS, HEAP_SIZE};
/// An allocator which gives frames of physical memory
pub struct NextFrameAllocator {
......@@ -46,7 +46,11 @@ impl NextFrameAllocator {
/// Create a new FrameAllocator with the given areas
pub fn new() -> Self {
let mut result = Self {
areas: BOOT_INFO.r#try().unwrap().get().memory_map_tag()
areas: BOOT_INFO
.r#try()
.unwrap()
.get()
.memory_map_tag()
.expect("Memory map tag required")
.memory_areas(),