mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Format using rustfmt-nightly
This commit is contained in:
@@ -43,12 +43,14 @@ pub fn init(memory_controller: &mut MemoryController) {
|
||||
use x86_64::instructions::tables::load_tss;
|
||||
use x86_64::VirtualAddress;
|
||||
|
||||
let double_fault_stack =
|
||||
memory_controller.alloc_stack(1).expect("could not allocate double fault stack");
|
||||
let double_fault_stack = memory_controller
|
||||
.alloc_stack(1)
|
||||
.expect("could not allocate double fault stack");
|
||||
|
||||
let tss = TSS.call_once(|| {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX] = VirtualAddress(double_fault_stack.top());
|
||||
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX] =
|
||||
VirtualAddress(double_fault_stack.top());
|
||||
tss
|
||||
});
|
||||
|
||||
@@ -78,29 +80,41 @@ extern "x86-interrupt" fn divide_by_zero_handler(stack_frame: &mut ExceptionStac
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStackFrame) {
|
||||
println!("\nEXCEPTION: BREAKPOINT at {:#x}\n{:#?}",
|
||||
println!(
|
||||
"\nEXCEPTION: BREAKPOINT at {:#x}\n{:#?}",
|
||||
stack_frame.instruction_pointer,
|
||||
stack_frame);
|
||||
stack_frame
|
||||
);
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn invalid_opcode_handler(stack_frame: &mut ExceptionStackFrame) {
|
||||
println!("\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
|
||||
println!(
|
||||
"\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
|
||||
stack_frame.instruction_pointer,
|
||||
stack_frame);
|
||||
stack_frame
|
||||
);
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn page_fault_handler(stack_frame: &mut ExceptionStackFrame, error_code: PageFaultErrorCode) {
|
||||
extern "x86-interrupt" fn page_fault_handler(
|
||||
stack_frame: &mut ExceptionStackFrame,
|
||||
error_code: PageFaultErrorCode,
|
||||
) {
|
||||
use x86_64::registers::control_regs;
|
||||
println!("\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
|
||||
println!(
|
||||
"\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
|
||||
{:?}\n{:#?}",
|
||||
control_regs::cr2(),
|
||||
error_code,
|
||||
stack_frame);
|
||||
stack_frame
|
||||
);
|
||||
loop {}
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn double_fault_handler(stack_frame: &mut ExceptionStackFrame, _error_code: u64) {
|
||||
extern "x86-interrupt" fn double_fault_handler(
|
||||
stack_frame: &mut ExceptionStackFrame,
|
||||
_error_code: u64,
|
||||
) {
|
||||
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
|
||||
loop {}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ pub struct AreaFrameAllocator {
|
||||
}
|
||||
|
||||
impl AreaFrameAllocator {
|
||||
pub fn new(kernel_start: usize,
|
||||
pub fn new(
|
||||
kernel_start: usize,
|
||||
kernel_end: usize,
|
||||
multiboot_start: usize,
|
||||
multiboot_end: usize,
|
||||
memory_areas: MemoryAreaIter)
|
||||
-> AreaFrameAllocator {
|
||||
memory_areas: MemoryAreaIter,
|
||||
) -> AreaFrameAllocator {
|
||||
let mut allocator = AreaFrameAllocator {
|
||||
next_free_frame: Frame::containing_address(0),
|
||||
current_area: None,
|
||||
|
||||
@@ -23,31 +23,41 @@ pub fn init(boot_info: &BootInformation) -> MemoryController {
|
||||
assert_has_not_been_called!("memory::init must be called only once");
|
||||
|
||||
let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
|
||||
let elf_sections_tag = boot_info.elf_sections_tag().expect("Elf sections tag required");
|
||||
let elf_sections_tag = boot_info
|
||||
.elf_sections_tag()
|
||||
.expect("Elf sections tag required");
|
||||
|
||||
let kernel_start = elf_sections_tag.sections()
|
||||
let kernel_start = elf_sections_tag
|
||||
.sections()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.addr)
|
||||
.min()
|
||||
.unwrap();
|
||||
let kernel_end = elf_sections_tag.sections()
|
||||
let kernel_end = elf_sections_tag
|
||||
.sections()
|
||||
.filter(|s| s.is_allocated())
|
||||
.map(|s| s.addr + s.size)
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
println!("kernel start: {:#x}, kernel end: {:#x}",
|
||||
println!(
|
||||
"kernel start: {:#x}, kernel end: {:#x}",
|
||||
kernel_start,
|
||||
kernel_end);
|
||||
println!("multiboot start: {:#x}, multiboot end: {:#x}",
|
||||
kernel_end
|
||||
);
|
||||
println!(
|
||||
"multiboot start: {:#x}, multiboot end: {:#x}",
|
||||
boot_info.start_address(),
|
||||
boot_info.end_address());
|
||||
boot_info.end_address()
|
||||
);
|
||||
|
||||
let mut frame_allocator = AreaFrameAllocator::new(kernel_start as usize,
|
||||
let mut frame_allocator = AreaFrameAllocator::new(
|
||||
kernel_start as usize,
|
||||
kernel_end as usize,
|
||||
boot_info.start_address(),
|
||||
boot_info.end_address(),
|
||||
memory_map_tag.memory_areas());
|
||||
memory_map_tag.memory_areas(),
|
||||
);
|
||||
|
||||
let mut active_table = paging::remap_the_kernel(&mut frame_allocator, boot_info);
|
||||
|
||||
@@ -83,9 +93,11 @@ pub struct MemoryController {
|
||||
|
||||
impl MemoryController {
|
||||
pub fn alloc_stack(&mut self, size_in_pages: usize) -> Option<Stack> {
|
||||
let &mut MemoryController { ref mut active_table,
|
||||
let &mut MemoryController {
|
||||
ref mut active_table,
|
||||
ref mut frame_allocator,
|
||||
ref mut stack_allocator } = self;
|
||||
ref mut stack_allocator,
|
||||
} = self;
|
||||
stack_allocator.alloc_stack(active_table, frame_allocator, size_in_pages)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ impl Entry {
|
||||
|
||||
pub fn pointed_frame(&self) -> Option<Frame> {
|
||||
if self.flags().contains(PRESENT) {
|
||||
Some(Frame::containing_address(self.0 as usize & 0x000fffff_fffff000))
|
||||
Some(Frame::containing_address(
|
||||
self.0 as usize & 0x000fffff_fffff000,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -32,11 +32,8 @@ impl Mapper {
|
||||
|
||||
pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
|
||||
let offset = virtual_address % PAGE_SIZE;
|
||||
self.translate_page(Page::containing_address(virtual_address)).map(|frame| {
|
||||
frame.number *
|
||||
PAGE_SIZE +
|
||||
offset
|
||||
})
|
||||
self.translate_page(Page::containing_address(virtual_address))
|
||||
.map(|frame| frame.number * PAGE_SIZE + offset)
|
||||
}
|
||||
|
||||
pub fn translate_page(&self, page: Page) -> Option<Frame> {
|
||||
@@ -78,7 +75,8 @@ impl Mapper {
|
||||
}
|
||||
|
||||
pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
let mut p3 = self.p4_mut().next_table_create(page.p4_index(), allocator);
|
||||
let mut p2 = p3.next_table_create(page.p3_index(), allocator);
|
||||
@@ -89,21 +87,24 @@ impl Mapper {
|
||||
}
|
||||
|
||||
pub fn map<A>(&mut self, page: Page, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
let frame = allocator.allocate_frame().expect("out of memory");
|
||||
self.map_to(page, frame, flags, allocator)
|
||||
}
|
||||
|
||||
pub fn identity_map<A>(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
let page = Page::containing_address(frame.start_address());
|
||||
self.map_to(page, frame, flags, allocator)
|
||||
}
|
||||
|
||||
pub fn unmap<A>(&mut self, page: Page, allocator: &mut A)
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
use x86_64::VirtualAddress;
|
||||
use x86_64::instructions::tlb;
|
||||
|
||||
@@ -31,9 +31,11 @@ pub struct Page {
|
||||
|
||||
impl Page {
|
||||
pub fn containing_address(address: VirtualAddress) -> Page {
|
||||
assert!(address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
|
||||
assert!(
|
||||
address < 0x0000_8000_0000_0000 || address >= 0xffff_8000_0000_0000,
|
||||
"invalid address: 0x{:x}",
|
||||
address);
|
||||
address
|
||||
);
|
||||
Page { number: address / PAGE_SIZE }
|
||||
}
|
||||
|
||||
@@ -113,11 +115,13 @@ impl ActivePageTable {
|
||||
ActivePageTable { mapper: Mapper::new() }
|
||||
}
|
||||
|
||||
pub fn with<F>(&mut self,
|
||||
pub fn with<F>(
|
||||
&mut self,
|
||||
table: &mut InactivePageTable,
|
||||
temporary_page: &mut temporary_page::TemporaryPage, // new
|
||||
f: F)
|
||||
where F: FnOnce(&mut Mapper)
|
||||
f: F,
|
||||
) where
|
||||
F: FnOnce(&mut Mapper),
|
||||
{
|
||||
use x86_64::registers::control_regs;
|
||||
use x86_64::instructions::tlb;
|
||||
@@ -162,10 +166,11 @@ pub struct InactivePageTable {
|
||||
}
|
||||
|
||||
impl InactivePageTable {
|
||||
pub fn new(frame: Frame,
|
||||
pub fn new(
|
||||
frame: Frame,
|
||||
active_table: &mut ActivePageTable,
|
||||
temporary_page: &mut TemporaryPage)
|
||||
-> InactivePageTable {
|
||||
temporary_page: &mut TemporaryPage,
|
||||
) -> InactivePageTable {
|
||||
{
|
||||
let table = temporary_page.map_table_frame(frame.clone(), active_table);
|
||||
table.zero();
|
||||
@@ -178,7 +183,8 @@ impl InactivePageTable {
|
||||
}
|
||||
|
||||
pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> ActivePageTable
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe }, allocator);
|
||||
|
||||
@@ -189,7 +195,9 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> Ac
|
||||
};
|
||||
|
||||
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
||||
let elf_sections_tag = boot_info.elf_sections_tag().expect("Memory map tag required");
|
||||
let elf_sections_tag = boot_info
|
||||
.elf_sections_tag()
|
||||
.expect("Memory map tag required");
|
||||
|
||||
// identity map the allocated kernel sections
|
||||
for section in elf_sections_tag.sections() {
|
||||
@@ -198,11 +206,15 @@ pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> Ac
|
||||
continue;
|
||||
}
|
||||
|
||||
assert!(section.addr as usize % PAGE_SIZE == 0,
|
||||
"sections need to be page aligned");
|
||||
println!("mapping section at addr: {:#x}, size: {:#x}",
|
||||
assert!(
|
||||
section.addr as usize % PAGE_SIZE == 0,
|
||||
"sections need to be page aligned"
|
||||
);
|
||||
println!(
|
||||
"mapping section at addr: {:#x}, size: {:#x}",
|
||||
section.addr,
|
||||
section.size);
|
||||
section.size
|
||||
);
|
||||
|
||||
let flags = EntryFlags::from_elf_section_flags(section);
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ pub struct Table<L: TableLevel> {
|
||||
}
|
||||
|
||||
impl<L> Table<L>
|
||||
where L: TableLevel
|
||||
where
|
||||
L: TableLevel,
|
||||
{
|
||||
pub fn zero(&mut self) {
|
||||
for entry in self.entries.iter_mut() {
|
||||
@@ -31,7 +32,8 @@ impl<L> Table<L>
|
||||
}
|
||||
|
||||
impl<L> Table<L>
|
||||
where L: HierarchicalLevel
|
||||
where
|
||||
L: HierarchicalLevel,
|
||||
{
|
||||
fn next_table_address(&self, index: usize) -> Option<usize> {
|
||||
let entry_flags = self[index].flags();
|
||||
@@ -44,22 +46,28 @@ impl<L> Table<L>
|
||||
}
|
||||
|
||||
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
|
||||
self.next_table_address(index).map(|address| unsafe { &*(address as *const _) })
|
||||
self.next_table_address(index)
|
||||
.map(|address| unsafe { &*(address as *const _) })
|
||||
}
|
||||
|
||||
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
|
||||
self.next_table_address(index).map(|address| unsafe { &mut *(address as *mut _) })
|
||||
self.next_table_address(index)
|
||||
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||
}
|
||||
|
||||
pub fn next_table_create<A>(&mut self,
|
||||
pub fn next_table_create<A>(
|
||||
&mut self,
|
||||
index: usize,
|
||||
allocator: &mut A)
|
||||
-> &mut Table<L::NextLevel>
|
||||
where A: FrameAllocator
|
||||
allocator: &mut A,
|
||||
) -> &mut Table<L::NextLevel>
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
if self.next_table(index).is_none() {
|
||||
assert!(!self.entries[index].flags().contains(HUGE_PAGE),
|
||||
"mapping code does not support huge pages");
|
||||
assert!(
|
||||
!self.entries[index].flags().contains(HUGE_PAGE),
|
||||
"mapping code does not support huge pages"
|
||||
);
|
||||
let frame = allocator.allocate_frame().expect("no frames available");
|
||||
self.entries[index].set(frame, PRESENT | WRITABLE);
|
||||
self.next_table_mut(index).unwrap().zero();
|
||||
@@ -69,7 +77,8 @@ impl<L> Table<L>
|
||||
}
|
||||
|
||||
impl<L> Index<usize> for Table<L>
|
||||
where L: TableLevel
|
||||
where
|
||||
L: TableLevel,
|
||||
{
|
||||
type Output = Entry;
|
||||
|
||||
@@ -79,7 +88,8 @@ impl<L> Index<usize> for Table<L>
|
||||
}
|
||||
|
||||
impl<L> IndexMut<usize> for Table<L>
|
||||
where L: TableLevel
|
||||
where
|
||||
L: TableLevel,
|
||||
{
|
||||
fn index_mut(&mut self, index: usize) -> &mut Entry {
|
||||
&mut self.entries[index]
|
||||
|
||||
@@ -18,7 +18,8 @@ pub struct TemporaryPage {
|
||||
|
||||
impl TemporaryPage {
|
||||
pub fn new<A>(page: Page, allocator: &mut A) -> TemporaryPage
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
TemporaryPage {
|
||||
page: page,
|
||||
@@ -31,18 +32,21 @@ impl TemporaryPage {
|
||||
pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) -> VirtualAddress {
|
||||
use super::entry::WRITABLE;
|
||||
|
||||
assert!(active_table.translate_page(self.page).is_none(),
|
||||
"temporary page is already mapped");
|
||||
assert!(
|
||||
active_table.translate_page(self.page).is_none(),
|
||||
"temporary page is already mapped"
|
||||
);
|
||||
active_table.map_to(self.page, frame, WRITABLE, &mut self.allocator);
|
||||
self.page.start_address()
|
||||
}
|
||||
|
||||
/// Maps the temporary page to the given page table frame in the active table.
|
||||
/// Returns a reference to the now mapped table.
|
||||
pub fn map_table_frame(&mut self,
|
||||
pub fn map_table_frame(
|
||||
&mut self,
|
||||
frame: Frame,
|
||||
active_table: &mut ActivePageTable)
|
||||
-> &mut Table<Level1> {
|
||||
active_table: &mut ActivePageTable,
|
||||
) -> &mut Table<Level1> {
|
||||
unsafe { &mut *(self.map(frame, active_table) as *mut Table<Level1>) }
|
||||
}
|
||||
|
||||
@@ -56,7 +60,8 @@ struct TinyAllocator([Option<Frame>; 3]);
|
||||
|
||||
impl TinyAllocator {
|
||||
fn new<A>(allocator: &mut A) -> TinyAllocator
|
||||
where A: FrameAllocator
|
||||
where
|
||||
A: FrameAllocator,
|
||||
{
|
||||
let mut f = || allocator.allocate_frame();
|
||||
let frames = [f(), f(), f()];
|
||||
|
||||
@@ -12,11 +12,12 @@ impl StackAllocator {
|
||||
}
|
||||
|
||||
impl StackAllocator {
|
||||
pub fn alloc_stack<FA: FrameAllocator>(&mut self,
|
||||
pub fn alloc_stack<FA: FrameAllocator>(
|
||||
&mut self,
|
||||
active_table: &mut ActivePageTable,
|
||||
frame_allocator: &mut FA,
|
||||
size_in_pages: usize)
|
||||
-> Option<Stack> {
|
||||
size_in_pages: usize,
|
||||
) -> Option<Stack> {
|
||||
if size_in_pages == 0 {
|
||||
return None; /* a zero sized stack makes no sense */
|
||||
}
|
||||
|
||||
@@ -17,10 +17,9 @@ const BUFFER_WIDTH: usize = 80;
|
||||
|
||||
pub static WRITER: Mutex<Writer> = Mutex::new(Writer {
|
||||
column_position: 0,
|
||||
color_code: ColorCode::new(Color::LightGreen,
|
||||
Color::Black),
|
||||
color_code: ColorCode::new(Color::LightGreen, Color::Black),
|
||||
buffer: unsafe { Unique::new(0xb8000 as *mut _) },
|
||||
});
|
||||
});
|
||||
|
||||
macro_rules! println {
|
||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||
|
||||
Reference in New Issue
Block a user