refactoring
This commit is contained in:
parent
d609af0b6e
commit
ecf8cf9fa5
@ -1,12 +1,23 @@
|
||||
use alloc::alloc::{GlobalAlloc, Layout};
|
||||
use core::ptr::null_mut;
|
||||
use fixed_size_block::FixedSizeBlockAllocator;
|
||||
use x86_64::{
|
||||
structures::paging::{
|
||||
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
||||
},
|
||||
VirtAddr,
|
||||
};
|
||||
use linked_list_allocator::LockedHeap;
|
||||
|
||||
pub mod bump;
|
||||
pub mod linked_list;
|
||||
pub mod fixed_size_block;
|
||||
|
||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||
pub const HEAP_SIZE: usize = 100 * 1024;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: Locked<FixedSizeBlockAllocator> = Locked::new(
|
||||
FixedSizeBlockAllocator::new());
|
||||
|
||||
pub fn init_heap(
|
||||
mapper: &mut impl Mapper<Size4KiB>,
|
||||
@ -36,23 +47,7 @@ pub fn init_heap(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub mod bump;
|
||||
use bump::BumpAllocator;
|
||||
|
||||
pub mod linked_list;
|
||||
use linked_list::LinkedListAllocator;
|
||||
|
||||
pub mod fixed_size_block;
|
||||
use fixed_size_block::FixedSizeBlockAllocator;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: Locked<FixedSizeBlockAllocator> = Locked::new(
|
||||
FixedSizeBlockAllocator::new());
|
||||
|
||||
pub struct Dummy;
|
||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||
pub const HEAP_SIZE: usize = 100 * 1024;
|
||||
|
||||
unsafe impl GlobalAlloc for Dummy {
|
||||
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||
@ -64,11 +59,6 @@ unsafe impl GlobalAlloc for Dummy {
|
||||
}
|
||||
}
|
||||
|
||||
/// Align the given address `addr` upwards to alignment `align`.
|
||||
fn align_up(addr: usize, align: usize) -> usize {
|
||||
(addr + align - 1) & !(align - 1)
|
||||
}
|
||||
|
||||
pub struct Locked<A> {
|
||||
inner: spin::Mutex<A>,
|
||||
}
|
||||
@ -79,8 +69,13 @@ impl<A> Locked<A> {
|
||||
inner: spin::Mutex::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn lock(&self) -> spin::MutexGuard<A> {
|
||||
self.inner.lock()
|
||||
}
|
||||
}
|
||||
|
||||
/// Align the given address `addr` upwards to alignment `align`.
|
||||
fn align_up(addr: usize, align: usize) -> usize {
|
||||
(addr + align - 1) & !(align - 1)
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
use x86_64::VirtAddr;
|
||||
use x86_64::structures::tss::TaskStateSegment;
|
||||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor};
|
||||
use x86_64::structures::gdt::SegmentSelector;
|
||||
use lazy_static::lazy_static;
|
||||
use x86_64::structures::gdt::{GlobalDescriptorTable, Descriptor, SegmentSelector};
|
||||
use x86_64::structures::tss::TaskStateSegment;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
|
||||
|
||||
|
||||
@ -1,35 +1,53 @@
|
||||
use x86_64::structures::idt::{PageFaultErrorCode, InterruptDescriptorTable, InterruptStackFrame};
|
||||
use pic8259::ChainedPics;
|
||||
|
||||
use crate::{gdt, hlt_loop, print, println};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::println;
|
||||
use crate::print;
|
||||
use crate::gdt;
|
||||
use crate::hlt_loop;
|
||||
|
||||
use pic8259::ChainedPics;
|
||||
use spin;
|
||||
use x86_64::structures::idt::{PageFaultErrorCode, InterruptDescriptorTable, InterruptStackFrame};
|
||||
|
||||
pub const PIC_1_OFFSET: u8 = 32;
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum InterruptIndex {
|
||||
Timer = PIC_1_OFFSET,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
impl InterruptIndex {
|
||||
fn as_u8(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
|
||||
fn as_usize(self) -> usize {
|
||||
usize::from(self.as_u8())
|
||||
}
|
||||
}
|
||||
|
||||
pub static PICS: spin::Mutex<ChainedPics> =
|
||||
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
|
||||
lazy_static! {
|
||||
static ref IDT: InterruptDescriptorTable = {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||
unsafe {
|
||||
idt.double_fault.set_handler_fn(double_fault_handler)
|
||||
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
.set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
idt[InterruptIndex::Timer.as_usize()]
|
||||
.set_handler_fn(timer_interrupt_handler);
|
||||
.set_handler_fn(timer_interrupt_handler);
|
||||
idt[InterruptIndex::Keyboard.as_usize()]
|
||||
.set_handler_fn(keyboard_interrupt_handler);
|
||||
.set_handler_fn(keyboard_interrupt_handler);
|
||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||
idt
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init_idt() {
|
||||
IDT.load();
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: InterruptStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
@ -80,31 +98,6 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn init_idt() {
|
||||
IDT.load();
|
||||
}
|
||||
|
||||
pub static PICS: spin::Mutex<ChainedPics> =
|
||||
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
pub enum InterruptIndex {
|
||||
Timer = PIC_1_OFFSET,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
impl InterruptIndex {
|
||||
fn as_u8(self) -> u8 {
|
||||
self as u8
|
||||
}
|
||||
|
||||
fn as_usize(self) -> usize {
|
||||
usize::from(self.as_u8())
|
||||
}
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn test_breakpoint_exception() {
|
||||
x86_64::instructions::interrupts::int3();
|
||||
|
||||
67
src/lib.rs
67
src/lib.rs
@ -3,10 +3,11 @@
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(alloc_error_handler)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
|
||||
extern crate alloc;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
pub mod serial;
|
||||
@ -17,13 +18,12 @@ pub mod memory;
|
||||
pub mod allocator;
|
||||
pub mod task;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(test)]
|
||||
use bootloader::{entry_point, BootInfo};
|
||||
|
||||
#[cfg(test)]
|
||||
entry_point!(test_kernel_main);
|
||||
pub fn init() {
|
||||
gdt::init();
|
||||
interrupts::init_idt();
|
||||
unsafe { interrupts::PICS.lock().initialize() };
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
pub trait Testable {
|
||||
fn run(&self) -> ();
|
||||
@ -31,7 +31,7 @@ pub trait Testable {
|
||||
|
||||
impl<T> Testable for T
|
||||
where
|
||||
T: Fn(),
|
||||
T: Fn(),
|
||||
{
|
||||
fn run(&self) {
|
||||
serial_print!("{}...\t", core::any::type_name::<T>());
|
||||
@ -55,31 +55,6 @@ pub fn test_panic_handler(info: &PanicInfo) -> ! {
|
||||
hlt_loop();
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
gdt::init();
|
||||
interrupts::init_idt();
|
||||
unsafe { interrupts::PICS.lock().initialize() };
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_kernel_main(_boot_info: &'static BootInfo) -> ! {
|
||||
init();
|
||||
test_main();
|
||||
hlt_loop();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
test_panic_handler(info)
|
||||
}
|
||||
|
||||
#[alloc_error_handler]
|
||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||
panic!("allocation error: {:?}", layout)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
pub enum QemuExitCode {
|
||||
@ -100,4 +75,28 @@ pub fn hlt_loop() -> ! {
|
||||
loop {
|
||||
x86_64::instructions::hlt();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use bootloader::{entry_point, BootInfo};
|
||||
|
||||
#[cfg(test)]
|
||||
entry_point!(test_kernel_main);
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_kernel_main(_boot_info: &'static BootInfo) -> ! {
|
||||
init();
|
||||
test_main();
|
||||
hlt_loop();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
test_panic_handler(info)
|
||||
}
|
||||
|
||||
#[alloc_error_handler]
|
||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||
panic!("allocation error: {:?}", layout)
|
||||
}
|
||||
@ -1,13 +1,28 @@
|
||||
use bootloader::bootinfo::{MemoryMap, MemoryRegionType};
|
||||
use x86_64::{
|
||||
structures::paging::{OffsetPageTable,
|
||||
Page, PhysFrame,
|
||||
Mapper, Size4KiB,
|
||||
PageTable, FrameAllocator},
|
||||
PhysAddr,
|
||||
VirtAddr
|
||||
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
|
||||
PhysAddr, VirtAddr,
|
||||
};
|
||||
use bootloader::bootinfo::MemoryMap;
|
||||
use bootloader::bootinfo::MemoryRegionType;
|
||||
|
||||
pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> {
|
||||
let level_4_table = active_level_4_table(physical_memory_offset);
|
||||
OffsetPageTable::new(level_4_table, physical_memory_offset)
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the active level 4 table.
|
||||
unsafe fn active_level_4_table(physical_memory_offset: VirtAddr)
|
||||
-> &'static mut PageTable
|
||||
{
|
||||
use x86_64::registers::control::Cr3;
|
||||
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let phys = level_4_table_frame.start_address();
|
||||
let virt = physical_memory_offset + phys.as_u64();
|
||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||
|
||||
&mut *page_table_ptr // unsafe
|
||||
}
|
||||
|
||||
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
|
||||
pub struct BootInfoFrameAllocator {
|
||||
@ -27,7 +42,7 @@ impl BootInfoFrameAllocator {
|
||||
next: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
|
||||
// get usable regions from memory map
|
||||
let regions = self.memory_map.iter();
|
||||
@ -49,24 +64,4 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||
self.next += 1;
|
||||
frame
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> {
|
||||
let level_4_table = active_level_4_table(physical_memory_offset);
|
||||
OffsetPageTable::new(level_4_table, physical_memory_offset)
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the active level 4 table.
|
||||
unsafe fn active_level_4_table(physical_memory_offset: VirtAddr)
|
||||
-> &'static mut PageTable
|
||||
{
|
||||
use x86_64::registers::control::Cr3;
|
||||
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let phys = level_4_table_frame.start_address();
|
||||
let virt = physical_memory_offset + phys.as_u64();
|
||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||
|
||||
&mut *page_table_ptr // unsafe
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
use uart_16550::SerialPort;
|
||||
use spin::Mutex;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
use uart_16550::SerialPort;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SERIAL1: Mutex<SerialPort> = {
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
use super::{Task, TaskId};
|
||||
use alloc::{collections::BTreeMap, sync::Arc};
|
||||
use core::task::Waker;
|
||||
use alloc::{collections::BTreeMap, sync::Arc, task::Wake};
|
||||
use core::task::{Context, Poll, Waker};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
use core::task::{Context, Poll};
|
||||
use alloc::task::Wake;
|
||||
|
||||
pub struct Executor {
|
||||
tasks: BTreeMap<TaskId, Task>,
|
||||
@ -11,11 +9,6 @@ pub struct Executor {
|
||||
waker_cache: BTreeMap<TaskId, Waker>,
|
||||
}
|
||||
|
||||
struct TaskWaker {
|
||||
task_id: TaskId,
|
||||
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
pub fn new() -> Self {
|
||||
Executor {
|
||||
@ -24,7 +17,7 @@ impl Executor {
|
||||
waker_cache: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn spawn(&mut self, task: Task) {
|
||||
let task_id = task.id;
|
||||
if self.tasks.insert(task.id, task).is_some() {
|
||||
@ -32,7 +25,7 @@ impl Executor {
|
||||
}
|
||||
self.task_queue.push(task_id).expect("queue full");
|
||||
}
|
||||
|
||||
|
||||
fn run_ready_tasks(&mut self) {
|
||||
// destructure `self` to avoid borrow checker errors
|
||||
let Self {
|
||||
@ -40,15 +33,15 @@ impl Executor {
|
||||
task_queue,
|
||||
waker_cache,
|
||||
} = self;
|
||||
|
||||
|
||||
while let Ok(task_id) = task_queue.pop() {
|
||||
let task = match tasks.get_mut(&task_id) {
|
||||
Some(task) => task,
|
||||
None => continue, // task no longer exists
|
||||
};
|
||||
let waker = waker_cache
|
||||
.entry(task_id)
|
||||
.or_insert_with(|| TaskWaker::new(task_id, task_queue.clone()));
|
||||
.entry(task_id)
|
||||
.or_insert_with(|| TaskWaker::new(task_id, task_queue.clone()));
|
||||
let mut context = Context::from_waker(waker);
|
||||
match task.poll(&mut context) {
|
||||
Poll::Ready(()) => {
|
||||
@ -60,17 +53,17 @@ impl Executor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn run(&mut self) -> ! {
|
||||
loop {
|
||||
self.run_ready_tasks();
|
||||
self.sleep_if_idle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn sleep_if_idle(&self) {
|
||||
use x86_64::instructions::interrupts::{self, enable_and_hlt};
|
||||
|
||||
|
||||
interrupts::disable();
|
||||
if self.task_queue.is_empty() {
|
||||
enable_and_hlt();
|
||||
@ -80,11 +73,16 @@ impl Executor {
|
||||
}
|
||||
}
|
||||
|
||||
struct TaskWaker {
|
||||
task_id: TaskId,
|
||||
task_queue: Arc<ArrayQueue<TaskId>>,
|
||||
}
|
||||
|
||||
impl TaskWaker {
|
||||
fn wake_task(&self) {
|
||||
self.task_queue.push(self.task_id).expect("task_queue full");
|
||||
}
|
||||
|
||||
|
||||
fn new(task_id: TaskId, task_queue: Arc<ArrayQueue<TaskId>>) -> Waker {
|
||||
Waker::from(Arc::new(TaskWaker {
|
||||
task_id,
|
||||
|
||||
@ -1,32 +1,18 @@
|
||||
use crate::{print, println};
|
||||
use conquer_once::spin::OnceCell;
|
||||
use core::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
use crate::println;
|
||||
use core::{pin::Pin, task::{Poll, Context}};
|
||||
use futures_util::stream::Stream;
|
||||
use futures_util::task::AtomicWaker;
|
||||
use futures_util::stream::StreamExt;
|
||||
use futures_util::{
|
||||
stream::{Stream, StreamExt},
|
||||
task::AtomicWaker,
|
||||
};
|
||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||
use crate::print;
|
||||
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
|
||||
|
||||
pub async fn print_keypresses() {
|
||||
let mut scancodes = ScancodeStream::new();
|
||||
let mut keyboard = Keyboard::new(layouts::Us104Key, ScancodeSet1,
|
||||
HandleControl::Ignore);
|
||||
|
||||
while let Some(scancode) = scancodes.next().await {
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||
match key {
|
||||
DecodedKey::Unicode(character) => print!("{}", character),
|
||||
DecodedKey::RawKey(key) => print!("{:?}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
|
||||
pub(crate) fn add_scancode(scancode: u8) {
|
||||
if let Ok(queue) = SCANCODE_QUEUE.try_get() {
|
||||
@ -74,4 +60,21 @@ impl Stream for ScancodeStream {
|
||||
Err(crossbeam_queue::PopError) => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn print_keypresses() {
|
||||
let mut scancodes = ScancodeStream::new();
|
||||
let mut keyboard = Keyboard::new(layouts::Us104Key, ScancodeSet1,
|
||||
HandleControl::Ignore);
|
||||
|
||||
while let Some(scancode) = scancodes.next().await {
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||
match key {
|
||||
DecodedKey::Unicode(character) => print!("{}", character),
|
||||
DecodedKey::RawKey(key) => print!("{:?}", key),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,14 @@
|
||||
use core::{future::Future, pin::Pin};
|
||||
use alloc::boxed::Box;
|
||||
use core::task::{Context, Poll};
|
||||
use core::sync::atomic::{AtomicU64, Ordering};
|
||||
use core::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
pub mod simple_executor;
|
||||
pub mod keyboard;
|
||||
pub mod executor;
|
||||
pub mod keyboard;
|
||||
pub mod simple_executor;
|
||||
|
||||
pub struct Task {
|
||||
id: TaskId,
|
||||
|
||||
@ -1,5 +1,16 @@
|
||||
use core::fmt;
|
||||
use lazy_static::lazy_static;
|
||||
use spin::Mutex;
|
||||
use volatile::Volatile;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
|
||||
column_position: 0,
|
||||
color_code: ColorCode::new(Color::Yellow, Color::Black),
|
||||
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
||||
});
|
||||
}
|
||||
|
||||
const BUFFER_HEIGHT: usize = 25;
|
||||
const BUFFER_WIDTH: usize = 80;
|
||||
|
||||
@ -29,6 +40,12 @@ pub enum Color {
|
||||
#[repr(transparent)]
|
||||
struct ColorCode(u8);
|
||||
|
||||
impl ColorCode {
|
||||
fn new(foreground: Color, background: Color) -> ColorCode {
|
||||
ColorCode((background as u8) << 4 | (foreground as u8))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
struct ScreenChar {
|
||||
@ -47,11 +64,6 @@ pub struct Writer {
|
||||
buffer: &'static mut Buffer,
|
||||
}
|
||||
|
||||
impl ColorCode {
|
||||
fn new(foreground: Color, background: Color) -> ColorCode {
|
||||
ColorCode((background as u8) << 4 | (foreground as u8))
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
pub fn write_byte(&mut self, byte: u8) {
|
||||
@ -109,18 +121,6 @@ impl Writer {
|
||||
}
|
||||
}
|
||||
|
||||
use spin::Mutex;
|
||||
use lazy_static::lazy_static;
|
||||
lazy_static! {
|
||||
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer {
|
||||
column_position: 0,
|
||||
color_code: ColorCode::new(Color::Yellow, Color::Black),
|
||||
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
|
||||
});
|
||||
}
|
||||
|
||||
use core::fmt;
|
||||
|
||||
impl fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.write_string(s);
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![test_runner(rust_os::test_runner)]
|
||||
|
||||
use rust_os::println;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[no_mangle]
|
||||
@ -18,8 +19,6 @@ fn panic(info: &PanicInfo) -> ! {
|
||||
rust_os::test_panic_handler(info)
|
||||
}
|
||||
|
||||
use rust_os::println;
|
||||
|
||||
#[test_case]
|
||||
fn test_println() {
|
||||
println!("test_println output");
|
||||
|
||||
@ -6,10 +6,9 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use bootloader::{entry_point, BootInfo};
|
||||
use core::panic::PanicInfo;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use rust_os::allocator::HEAP_SIZE;
|
||||
|
||||
entry_point!(main);
|
||||
@ -32,11 +31,6 @@ fn main(boot_info: &'static BootInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
rust_os::test_panic_handler(info)
|
||||
}
|
||||
|
||||
#[test_case]
|
||||
fn simple_allocation() {
|
||||
let heap_value_1 = Box::new(41);
|
||||
@ -71,4 +65,9 @@ fn many_boxes_long_lived() {
|
||||
assert_eq!(*x, i);
|
||||
}
|
||||
assert_eq!(*long_lived, 1);
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
rust_os::test_panic_handler(info)
|
||||
}
|
||||
@ -3,11 +3,9 @@
|
||||
#![feature(abi_x86_interrupt)]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
use rust_os::serial_print;
|
||||
use lazy_static::lazy_static;
|
||||
use x86_64::structures::idt::InterruptDescriptorTable;
|
||||
use rust_os::{exit_qemu, QemuExitCode, serial_println};
|
||||
use x86_64::structures::idt::InterruptStackFrame;
|
||||
use rust_os::{exit_qemu, QemuExitCode, serial_print, serial_println};
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _start() -> ! {
|
||||
@ -28,20 +26,15 @@ fn stack_overflow() {
|
||||
volatile::Volatile::new(0).read(); // prevent tail recursion optimizations
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
rust_os::test_panic_handler(info)
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref TEST_IDT: InterruptDescriptorTable = {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(test_double_fault_handler)
|
||||
.set_stack_index(rust_os::gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
.set_handler_fn(test_double_fault_handler)
|
||||
.set_stack_index(rust_os::gdt::DOUBLE_FAULT_IST_INDEX);
|
||||
}
|
||||
|
||||
|
||||
idt
|
||||
};
|
||||
}
|
||||
@ -57,4 +50,9 @@ extern "x86-interrupt" fn test_double_fault_handler(
|
||||
serial_println!("[ok]");
|
||||
exit_qemu(QemuExitCode::Success);
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
rust_os::test_panic_handler(info)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user