Skip to content

Commit 694e57f

Browse files
fix(nvme): map bar
Signed-off-by: Anhad Singh <[email protected]>
1 parent ea9e66b commit 694e57f

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

src/aero_kernel/src/drivers/block/nvme/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use alloc::vec::Vec;
2929
use bit_field::BitField;
3030

3131
use crate::arch::interrupts::{self, InterruptStack};
32-
use crate::drivers::pci::*;
32+
use crate::drivers::pci::{self, *};
3333
use crate::fs::block::{install_block_device, BlockDevice, BlockDeviceInterface};
3434
use crate::mem::paging::*;
3535

@@ -281,11 +281,13 @@ impl<'a> Controller<'a> {
281281
let bar0 = header.get_bar(0).ok_or(Error::UnknownBar)?;
282282

283283
// All NVMe registers are accessible via BAR0.
284-
let registers_addr = match bar0 {
285-
Bar::Memory64 { address, .. } => PhysAddr::new(address),
284+
let (registers_addr, bar_size) = match bar0 {
285+
Bar::Memory64 { address, size, .. } => (PhysAddr::new(address), size),
286286
_ => return Err(Error::UnknownBar),
287287
};
288288

289+
pci::map_bar(&bar0);
290+
289291
let registers = registers_addr
290292
.as_hhdm_virt()
291293
.read_mut::<Registers>()

src/aero_kernel/src/drivers/pci.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::utils::bitmap::Bitmap;
2323
use crate::utils::sync::Mutex;
2424

2525
use crate::acpi::mcfg;
26-
use crate::mem::paging::OffsetPageTable;
26+
use crate::mem::paging::{OffsetPageTable, PhysAddr};
2727
use crate::utils::VolatileCell;
2828

2929
use crate::arch::{apic, io};
@@ -116,16 +116,18 @@ impl<'a> Msix<'a> {
116116
.get_bar(bar_index)
117117
.expect("msix: table bar not present");
118118

119+
map_bar(&bar);
120+
119121
let bar_address = match bar {
120-
Bar::Memory64 { address, .. } => address,
121-
Bar::Memory32 { address, .. } => address as u64,
122+
Bar::Memory64 { address, .. } => PhysAddr::new(address),
123+
Bar::Memory32 { address, .. } => PhysAddr::new(address as u64),
122124
_ => unreachable!(),
123125
};
124126

125127
// SAFETY: We have exclusive access to the BAR and the slice is in bounds.
126128
let messages = unsafe {
127129
core::slice::from_raw_parts_mut(
128-
(bar_address + bar_offset as u64) as *mut Message,
130+
(bar_address.as_hhdm_virt() + bar_offset as u64).as_mut_ptr::<Message>(),
129131
table_length as usize,
130132
)
131133
};
@@ -788,6 +790,45 @@ impl PciTable {
788790
}
789791
}
790792

793+
pub fn map_bar(bar: &Bar) {
794+
use crate::mem::paging::{Mapper, Page, PageTableFlags, PhysFrame, Size4KiB, UnmapError};
795+
796+
use crate::mem::AddressSpace;
797+
798+
let mut address_space = AddressSpace::this();
799+
let mut offset_table = address_space.offset_page_table();
800+
801+
let (addr, size) = match bar {
802+
Bar::Memory64 { address, size, .. } => (PhysAddr::new(*address), *size),
803+
_ => unreachable!(),
804+
};
805+
806+
for frame in PhysFrame::range(
807+
PhysFrame::<Size4KiB>::from_start_address(addr).unwrap(),
808+
PhysFrame::containing_address(addr + size),
809+
) {
810+
let virt = frame.start_address().as_hhdm_virt();
811+
let page = Page::containing_address(virt);
812+
813+
// Map will fail if the bar was partially mapped.
814+
match offset_table.unmap(page) {
815+
Ok((_, m)) => m.ignore(),
816+
Err(UnmapError::PageNotMapped) => {}
817+
Err(e) => unreachable!("{:?}", e),
818+
}
819+
820+
unsafe {
821+
offset_table.map_to(
822+
page,
823+
frame,
824+
PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE,
825+
)
826+
}
827+
.unwrap()
828+
.flush();
829+
}
830+
}
831+
791832
pub fn register_device_driver(handle: Arc<dyn PciDeviceHandle>) {
792833
PCI_TABLE.lock().inner.push(PciDevice { handle })
793834
}

src/aero_kernel/src/mem/paging/page.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ impl<S: PageSize> PhysFrame<S> {
249249
Ok(PhysFrame::containing_address(address))
250250
}
251251

252+
/// Returns a range of pages, exclusive `end`.
253+
#[inline]
254+
pub const fn range(start: Self, end: Self) -> PhysFrameRange<S> {
255+
PhysFrameRange { start, end }
256+
}
257+
252258
/// Returns the frame that contains the given physical address.
253259
#[inline]
254260
pub fn containing_address(address: PhysAddr) -> Self {

0 commit comments

Comments
 (0)