Skip to content

Commit

Permalink
Fix page fault on accessing xhc_mmio_base
Browse files Browse the repository at this point in the history
map xhc MMIO region as identity map
  • Loading branch information
gifnksm committed May 12, 2021
1 parent 4778f8c commit c5a89b7
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 55 deletions.
30 changes: 30 additions & 0 deletions src/error.rs
@@ -1,5 +1,9 @@
use core::fmt;

use x86_64::structures::paging::{
mapper::MapToError, page::AddressNotAligned, PhysFrame, Size4KiB,
};

pub(crate) type Result<T> = core::result::Result<T, Error>;

#[derive(Debug)]
Expand Down Expand Up @@ -41,6 +45,10 @@ pub(crate) enum ErrorKind {
NotEnoughMemory,
XhcNotFound,
IndexOutOfRange,
AddressNotAligned,
FrameAllocationFailed,
ParentEntryHugePage,
PageAlreadyMapped(PhysFrame<Size4KiB>),
}

impl fmt::Display for ErrorKind {
Expand All @@ -56,6 +64,28 @@ impl fmt::Display for ErrorKind {
}
}

impl From<AddressNotAligned> for Error {
#[track_caller]
fn from(_: AddressNotAligned) -> Self {
crate::make_error!(ErrorKind::AddressNotAligned)
}
}

impl From<MapToError<Size4KiB>> for Error {
#[track_caller]
fn from(err: MapToError<Size4KiB>) -> Self {
match err {
MapToError::FrameAllocationFailed => {
crate::make_error!(ErrorKind::FrameAllocationFailed)
}
MapToError::ParentEntryHugePage => crate::make_error!(ErrorKind::ParentEntryHugePage),
MapToError::PageAlreadyMapped(frame) => {
crate::make_error!(ErrorKind::PageAlreadyMapped(frame))
}
}
}
}

#[macro_export]
macro_rules! make_error {
($kind:expr $(,)?) => {
Expand Down
51 changes: 7 additions & 44 deletions src/main.rs
Expand Up @@ -10,7 +10,7 @@ use bootloader::{
entry_point, BootInfo,
};
use core::mem;
use x86_64::{structures::paging::Translate, VirtAddr};
use x86_64::VirtAddr;

mod console;
mod desktop;
Expand Down Expand Up @@ -73,61 +73,24 @@ fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
.as_ref()
.copied()
.expect("physical memory is not mapped");
let physical_memory_offset = VirtAddr::new(physical_memory_offset);

let mapper = unsafe { paging::init(physical_memory_offset) };
let physical_memory_offset = VirtAddr::new(physical_memory_offset);
let mut mapper = unsafe { paging::init(physical_memory_offset) };

desktop::draw().expect("failed to draw desktop");

let addresses = &[
0xb8000,
0x201008,
0x0100_0020_1a10,
physical_memory_offset.as_u64(),
];

for &address in addresses {
let virt = VirtAddr::new(address);
let phys = mapper.translate(virt);
println!("{:?} -> {:?}", virt, phys);
}

println!("Welcome to sabios!");

let mut allocator = memory::lock_memory_manager();
allocator
memory::lock_memory_manager()
.init(MemoryRegions::new(&*boot_info.memory_regions))
.expect("failed to initialize bitmap memory manager");

for region in MemoryRegions::new(&*boot_info.memory_regions) {
println!(
"addr={:08x}-{:08x}, pages = {:08x}, kind = {:?}",
region.start,
region.end,
(region.end - region.start) / 4096,
region.kind,
);
}

{
let frames1 = allocator.allocate(3).expect("failed to allocate");
println!("allocated: {:?}", frames1);
let frames2 = allocator.allocate(5).expect("failed to allocate");
println!("allocated: {:?}", frames2);
allocator.free(frames1);
let frames3 = allocator.allocate(4).expect("failed to allocate");
println!("allocated: {:?}", frames3);
let frames4 = allocator.allocate(3).expect("failed to allocate");
println!("allocated: {:?}", frames4);
}

mouse::draw_cursor().expect("failed to draw mouse cursor");

let devices = pci::scan_all_bus().expect("failed to scan PCI devices");
for device in &devices {
debug!("{}", device);
}
xhc::init(&devices).expect("failed to initialize xHC");
xhc::init(&devices, &mut mapper).expect("failed to initialize xHC");

mouse::draw_cursor().expect("failed to draw mouse cursor");

hlt_loop();
}
Expand Down
18 changes: 9 additions & 9 deletions src/memory.rs
@@ -1,11 +1,8 @@
use crate::{
bail,
error::{ErrorKind, Result},
};
use crate::prelude::*;
use bootloader::boot_info::{MemoryRegion, MemoryRegionKind};
use core::cmp;
use x86_64::{
structures::paging::{frame::PhysFrameRange, page::AddressNotAligned, PhysFrame},
structures::paging::{frame::PhysFrameRange, FrameAllocator, PhysFrame, Size4KiB},
PhysAddr,
};

Expand Down Expand Up @@ -49,10 +46,7 @@ pub(crate) fn lock_memory_manager() -> spin::MutexGuard<'static, BitmapMemoryMan
}

impl BitmapMemoryManager {
pub(crate) fn init(
&mut self,
regions: impl IntoIterator<Item = MemoryRegion>,
) -> core::result::Result<(), AddressNotAligned> {
pub(crate) fn init(&mut self, regions: impl IntoIterator<Item = MemoryRegion>) -> Result<()> {
let mut available_start = self.range.start;
let mut available_end = self.range.end;
for region in regions {
Expand Down Expand Up @@ -124,3 +118,9 @@ impl BitmapMemoryManager {
}
}
}

unsafe impl FrameAllocator<Size4KiB> for BitmapMemoryManager {
fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> {
self.allocate(1).map(|range| range.start).ok()
}
}
22 changes: 20 additions & 2 deletions src/xhc.rs
@@ -1,10 +1,15 @@
use crate::{
memory,
pci::{self, Device},
prelude::*,
};
use mikanos_usb as usb;
use x86_64::{
structures::paging::{Mapper, OffsetPageTable, Page, PhysFrame},
PhysAddr, VirtAddr,
};

pub(crate) fn init(devices: &[Device]) -> Result<()> {
pub(crate) fn init(devices: &[Device], mapper: &mut OffsetPageTable) -> Result<()> {
let mut xhc_dev = None;
for dev in devices {
// is the device is xHC?
Expand All @@ -26,8 +31,21 @@ pub(crate) fn init(devices: &[Device]) -> Result<()> {
let xhc_mmio_base = xhc_bar & !0xf;
debug!("xHC mmio_base = {:08x}", xhc_mmio_base);

{
// Map [xhc_mmio_base..(xhc_mmio_base+64kib)] as identity map
use x86_64::structures::paging::PageTableFlags as Flags;
let base_page = Page::from_start_address(VirtAddr::new(xhc_mmio_base))?;
let base_frame = PhysFrame::from_start_address(PhysAddr::new(xhc_mmio_base))?;
let flags = Flags::PRESENT | Flags::WRITABLE;
let mut allocator = memory::lock_memory_manager();
for i in 0..16 {
let page = base_page + i;
let frame = base_frame + i;
unsafe { mapper.map_to(page, frame, flags, &mut *allocator) }?.flush();
}
}

unsafe {
// page fault occurs... xhc_mmio_base is not mapped to virtual memory
let _xhc = usb::xhc_controller_new(xhc_mmio_base);
//xhc.init();
}
Expand Down

0 comments on commit c5a89b7

Please sign in to comment.