Compare commits
No commits in common. "c54cb174deb20cc91aa92672d8a27f58a72e16a6" and "6944f2203f285425c49d29ae3e368f6294ee040b" have entirely different histories.
c54cb174de
...
6944f2203f
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -8,12 +8,6 @@ version = "0.10.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -25,7 +19,6 @@ name = "julios"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"multiboot2",
|
|
||||||
"pc-keyboard",
|
"pc-keyboard",
|
||||||
"pic8259",
|
"pic8259",
|
||||||
"spin",
|
"spin",
|
||||||
@ -42,15 +35,6 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "multiboot2"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b209a4456a3cc81fb69ad318ed6d47af81a90b829701f151354e3994d8b216d4"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 0.4.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pc-keyboard"
|
name = "pc-keyboard"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@ -91,6 +75,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "bbc6ed1ed2cd4536b083c34041aff7b84448ee25ac4aa5e9d54802ce226f9815"
|
checksum = "bbc6ed1ed2cd4536b083c34041aff7b84448ee25ac4aa5e9d54802ce226f9815"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"bitflags 1.3.2",
|
"bitflags",
|
||||||
"volatile 0.4.4",
|
"volatile 0.4.4",
|
||||||
]
|
]
|
||||||
|
@ -14,7 +14,6 @@ spin = "0.5.2"
|
|||||||
x86_64 = "0.14.2"
|
x86_64 = "0.14.2"
|
||||||
pic8259 = "0.10.1"
|
pic8259 = "0.10.1"
|
||||||
pc-keyboard = "0.5.0"
|
pc-keyboard = "0.5.0"
|
||||||
multiboot2 = "0.1.0"
|
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
2
Makefile
2
Makefile
@ -12,7 +12,7 @@ GRUB_CFG = grub/grub.cfg
|
|||||||
all: $(ISO)
|
all: $(ISO)
|
||||||
|
|
||||||
run: $(ISO)
|
run: $(ISO)
|
||||||
qemu-system-x86_64 -cdrom $< -serial stdio -m 8G
|
qemu-system-x86_64 -cdrom $< -serial stdio
|
||||||
|
|
||||||
debug: $(ISO)
|
debug: $(ISO)
|
||||||
bochs -q
|
bochs -q
|
||||||
|
@ -15,7 +15,6 @@ bits 32
|
|||||||
|
|
||||||
_start:
|
_start:
|
||||||
mov esp, stack_top
|
mov esp, stack_top
|
||||||
mov edi, ebx
|
|
||||||
|
|
||||||
call check_multiboot
|
call check_multiboot
|
||||||
call check_cpuid
|
call check_cpuid
|
||||||
@ -28,11 +27,6 @@ _start:
|
|||||||
jmp gdt64.code:long_mode_start
|
jmp gdt64.code:long_mode_start
|
||||||
|
|
||||||
set_up_page_tables:
|
set_up_page_tables:
|
||||||
; recursively map p4
|
|
||||||
mov eax, p4_table
|
|
||||||
or eax, 0b11 ; present + writeable
|
|
||||||
mov [p4_table + 511 * 8], eax
|
|
||||||
|
|
||||||
; map first P4 entry to P3 table
|
; map first P4 entry to P3 table
|
||||||
mov eax, p3_table
|
mov eax, p3_table
|
||||||
or eax, 0b11 ; present + writable
|
or eax, 0b11 ; present + writable
|
||||||
@ -169,8 +163,9 @@ p3_table:
|
|||||||
p2_table:
|
p2_table:
|
||||||
resb 4096
|
resb 4096
|
||||||
|
|
||||||
|
section .stack
|
||||||
stack_bottom:
|
stack_bottom:
|
||||||
resb 4 * 4096
|
resb 0x800000
|
||||||
stack_top:
|
stack_top:
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::gdt;
|
use crate::gdt;
|
||||||
use crate::hlt_loop;
|
|
||||||
use crate::vga::{self, Color, ColorCode};
|
use crate::vga::{self, Color, ColorCode};
|
||||||
use crate::{print, println};
|
use crate::{print, println};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -7,7 +6,6 @@ use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
|||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
use spin::{self, Mutex};
|
use spin::{self, Mutex};
|
||||||
use x86_64::instructions::port::Port;
|
use x86_64::instructions::port::Port;
|
||||||
use x86_64::structures::idt::PageFaultErrorCode;
|
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||||
|
|
||||||
pub const PIC_1_OFFSET: u8 = 32;
|
pub const PIC_1_OFFSET: u8 = 32;
|
||||||
@ -39,7 +37,6 @@ lazy_static! {
|
|||||||
static ref IDT: InterruptDescriptorTable = {
|
static ref IDT: InterruptDescriptorTable = {
|
||||||
let mut idt = InterruptDescriptorTable::new();
|
let mut idt = InterruptDescriptorTable::new();
|
||||||
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
idt.breakpoint.set_handler_fn(breakpoint_handler);
|
||||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
idt.double_fault
|
idt.double_fault
|
||||||
.set_handler_fn(double_fault_handler)
|
.set_handler_fn(double_fault_handler)
|
||||||
@ -69,22 +66,6 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
|
|||||||
vga::change_color(color);
|
vga::change_color(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn page_fault_handler(
|
|
||||||
stack_frame: InterruptStackFrame,
|
|
||||||
error_code: PageFaultErrorCode,
|
|
||||||
) {
|
|
||||||
let color: vga::ColorCode = vga::get_color();
|
|
||||||
vga::change_color(ColorCode::new(Color::LightRed, Color::Black));
|
|
||||||
use x86_64::registers::control::Cr2;
|
|
||||||
|
|
||||||
println!("EXCEPTION: PAGE FAULT");
|
|
||||||
println!("Accessed Address: {:?}", Cr2::read());
|
|
||||||
println!("Error Code: {:?}", error_code);
|
|
||||||
println!("{:#?}", stack_frame);
|
|
||||||
vga::change_color(color);
|
|
||||||
hlt_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "x86-interrupt" fn double_fault_handler(
|
extern "x86-interrupt" fn double_fault_handler(
|
||||||
stack_frame: InterruptStackFrame,
|
stack_frame: InterruptStackFrame,
|
||||||
_error_code: u64,
|
_error_code: u64,
|
||||||
@ -93,7 +74,7 @@ extern "x86-interrupt" fn double_fault_handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
// print!(".");
|
print!(".");
|
||||||
unsafe {
|
unsafe {
|
||||||
PICS.lock()
|
PICS.lock()
|
||||||
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
|
||||||
@ -102,8 +83,9 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr
|
|||||||
|
|
||||||
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = Mutex::new(
|
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
|
||||||
Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore)
|
Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1,
|
||||||
|
HandleControl::Ignore)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
src/lib.rs
35
src/lib.rs
@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
mod gdt;
|
mod gdt;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
mod memory;
|
|
||||||
mod serial;
|
mod serial;
|
||||||
mod vga;
|
mod vga;
|
||||||
|
|
||||||
extern crate multiboot2;
|
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use vga::{Color, ColorCode};
|
use vga::{Color, ColorCode};
|
||||||
|
|
||||||
@ -34,39 +31,11 @@ pub fn init() {
|
|||||||
vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
|
vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_frame_allocator(multiboot_info_addr: usize) -> memory::AreaFrameAllocator {
|
|
||||||
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
|
||||||
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 kernel_start: u64 = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
|
|
||||||
let kernel_end: u64 = elf_sections_tag
|
|
||||||
.sections()
|
|
||||||
.map(|s| s.addr + s.size)
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let multiboot_start: u64 = multiboot_info_addr as u64;
|
|
||||||
let multiboot_end: u64 = multiboot_start + (boot_info.total_size as u64);
|
|
||||||
|
|
||||||
memory::AreaFrameAllocator::new( kernel_start, kernel_end, multiboot_start,
|
|
||||||
multiboot_end, memory_map_tag.memory_areas())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn julios_main(multiboot_info_addr: usize) -> ! {
|
pub extern "C" fn julios_main() -> ! {
|
||||||
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
|
||||||
|
|
||||||
let mut frame_allocator = get_frame_allocator(multiboot_info_addr);
|
|
||||||
|
|
||||||
memory::kernel_remap(&mut frame_allocator, boot_info);
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
println!("***JuliOS V0.1.0***");
|
println!("***JuliOS V0.1.0***");
|
||||||
serial_println!("Hello serial");
|
serial_println!("Hello serial");
|
||||||
memory::paging::test_paging(&mut frame_allocator);
|
|
||||||
panic!("Kernel end of flow");
|
panic!("Kernel end of flow");
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,26 @@
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 1M;
|
. = 1M;
|
||||||
|
|
||||||
.rodata :
|
.boot :
|
||||||
{
|
{
|
||||||
/* ensure that the multiboot header is at the beginning */
|
/* ensure that the multiboot header is at the beginning */
|
||||||
KEEP(*(.multiboot_header))
|
*(.multiboot_header)
|
||||||
*(.rodata .rodata.*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text :
|
.stack :
|
||||||
{
|
{
|
||||||
*(.text .text.*)
|
*(.stack)
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
*(.data .data.*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
*(.bss .bss.*)
|
*(.bss)
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.got :
|
.text :
|
||||||
{
|
{
|
||||||
*(.got)
|
*(.text)
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.got.plt :
|
|
||||||
{
|
|
||||||
*(.got.plt)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.data.rel.ro : ALIGN(4K) {
|
|
||||||
*(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gcc_except_table : ALIGN(4K) {
|
|
||||||
*(.gcc_except_table)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
pub use super::PAGE_SIZE;
|
|
||||||
use multiboot2::{MemoryArea, MemoryAreaIter};
|
|
||||||
pub use x86_64::structures::paging::{
|
|
||||||
frame::PhysFrame as Frame, FrameAllocator, FrameDeallocator, Size4KiB,
|
|
||||||
};
|
|
||||||
use x86_64::PhysAddr;
|
|
||||||
|
|
||||||
pub struct AreaFrameAllocator {
|
|
||||||
next_free_frame: Frame,
|
|
||||||
current_area: Option<&'static MemoryArea>,
|
|
||||||
areas: MemoryAreaIter,
|
|
||||||
kernel_start: Frame,
|
|
||||||
kernel_end: Frame,
|
|
||||||
multiboot_start: Frame,
|
|
||||||
multiboot_end: Frame,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AreaFrameAllocator {
|
|
||||||
pub fn new(kernel_start: u64, kernel_end: u64, multiboot_start: u64, multiboot_end: u64, memory_areas: MemoryAreaIter) -> AreaFrameAllocator {
|
|
||||||
let mut allocator = AreaFrameAllocator {
|
|
||||||
next_free_frame: Frame::containing_address(PhysAddr::new(0)),
|
|
||||||
current_area: None,
|
|
||||||
areas: memory_areas,
|
|
||||||
kernel_start: Frame::containing_address(PhysAddr::new(kernel_start)),
|
|
||||||
kernel_end: Frame::containing_address(PhysAddr::new(kernel_end)),
|
|
||||||
multiboot_start: Frame::containing_address(PhysAddr::new(multiboot_start)),
|
|
||||||
multiboot_end: Frame::containing_address(PhysAddr::new(multiboot_end)),
|
|
||||||
};
|
|
||||||
allocator.choose_next_area();
|
|
||||||
allocator
|
|
||||||
}
|
|
||||||
|
|
||||||
fn choose_next_area(&mut self) {
|
|
||||||
self.current_area = self
|
|
||||||
.areas
|
|
||||||
.clone()
|
|
||||||
.filter(|area| {
|
|
||||||
let address = area.base_addr + area.length - 1;
|
|
||||||
Frame::containing_address(PhysAddr::new(address)) >= self.next_free_frame
|
|
||||||
})
|
|
||||||
.min_by_key(|area| area.base_addr);
|
|
||||||
|
|
||||||
if let Some(area) = self.current_area {
|
|
||||||
let start_frame = Frame::containing_address(PhysAddr::new(area.base_addr));
|
|
||||||
if self.next_free_frame < start_frame {
|
|
||||||
self.next_free_frame = start_frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl FrameAllocator<Size4KiB> for AreaFrameAllocator {
|
|
||||||
fn allocate_frame(&mut self) -> Option<Frame> {
|
|
||||||
if let Some(area) = self.current_area {
|
|
||||||
// "Clone" the frame to return it if it's free. Frame doesn't
|
|
||||||
// implement Clone, but we can construct an identical frame.
|
|
||||||
let frame = Frame::containing_address(self.next_free_frame.start_address());
|
|
||||||
|
|
||||||
// the last frame of the current area
|
|
||||||
let current_area_last_frame = {
|
|
||||||
let address = area.base_addr + area.length - 1;
|
|
||||||
Frame::containing_address(PhysAddr::new(address))
|
|
||||||
};
|
|
||||||
|
|
||||||
if frame > current_area_last_frame {
|
|
||||||
// all frames of current area are used, switch to next area
|
|
||||||
self.choose_next_area();
|
|
||||||
} else if frame >= self.kernel_start && frame <= self.kernel_end {
|
|
||||||
// `frame` is used by the kernel
|
|
||||||
self.next_free_frame =
|
|
||||||
Frame::containing_address(self.kernel_end.start_address() + PAGE_SIZE);
|
|
||||||
} else if frame >= self.multiboot_start && frame <= self.multiboot_end {
|
|
||||||
// `frame` is used by the multiboot information structure
|
|
||||||
self.next_free_frame =
|
|
||||||
Frame::containing_address(self.multiboot_end.start_address() + PAGE_SIZE);
|
|
||||||
} else {
|
|
||||||
// frame is unused, increment `next_free_frame` and return it
|
|
||||||
self.next_free_frame =
|
|
||||||
Frame::containing_address(self.next_free_frame.start_address() + PAGE_SIZE);
|
|
||||||
return Some(frame);
|
|
||||||
}
|
|
||||||
// `frame` was not valid, try it again with the updated `next_free_frame`
|
|
||||||
self.allocate_frame()
|
|
||||||
} else {
|
|
||||||
None // no free frames left
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FrameDeallocator<Size4KiB> for AreaFrameAllocator {
|
|
||||||
unsafe fn deallocate_frame(&mut self, _frame: Frame) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
pub use self::frame_allocator::AreaFrameAllocator;
|
|
||||||
pub use paging::kernel_remap;
|
|
||||||
|
|
||||||
pub mod frame_allocator;
|
|
||||||
pub mod paging;
|
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
|
@ -1,33 +0,0 @@
|
|||||||
use multiboot2::BootInformation;
|
|
||||||
use x86_64::structures::paging::{FrameAllocator, Size4KiB, PageTable, RecursivePageTable, Page, PageTableFlags as Flags, Mapper};
|
|
||||||
use crate::println;
|
|
||||||
use x86_64::VirtAddr;
|
|
||||||
|
|
||||||
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
|
|
||||||
|
|
||||||
pub fn kernel_remap<A>(_allocator: &mut A, _boot_info: &BootInformation)
|
|
||||||
where A: FrameAllocator<Size4KiB>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn test_paging<A>(allocator: &mut A)
|
|
||||||
where A: FrameAllocator<Size4KiB>
|
|
||||||
{
|
|
||||||
let mut page_table = unsafe { RecursivePageTable::new(&mut *P4).expect("Could not create Page Table") };
|
|
||||||
|
|
||||||
let addr = 42 * 512 * 512 * 4096; // 42th P3 entry
|
|
||||||
let page = Page::containing_address(VirtAddr::new(addr));
|
|
||||||
let frame = allocator.allocate_frame().expect("no more frames");
|
|
||||||
println!("None = , map to {:?}", frame);
|
|
||||||
unsafe { page_table.map_to(page, frame, Flags::PRESENT, allocator).expect("Could not map").flush() };
|
|
||||||
println!("next free frame: {:?}", allocator.allocate_frame());
|
|
||||||
|
|
||||||
let page_ptr: *mut u8 = page.start_address().as_mut_ptr();
|
|
||||||
let frame_ptr: *mut u8 = frame.start_address().as_u64() as *mut u8;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
println!("Page: {:#?}, Frame: {:#?}", *page_ptr, *frame_ptr);
|
|
||||||
*frame_ptr = 42;
|
|
||||||
println!("Page: {:#?}, Frame: {:#?}", *page_ptr, *frame_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user