Skip to content

Commit

Permalink
Merge pull request #1611 from hermit-os/uefi-paging
Browse files Browse the repository at this point in the history
fix: VIRTIO on UEFI
  • Loading branch information
mkroening authored Feb 23, 2025
2 parents dcaa3d4 + addb804 commit 162fc78
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ jobs:
if: matrix.arch != 'riscv64'
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci --no-default-virtio-features
if: matrix.arch != 'riscv64'
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4 qemu ${{ matrix.flags }} --netdev virtio-net-pci --uefi
if: matrix.arch == 'x86_64'
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --no-default-features --features ci,hermit/dhcpv4,hermit/tcp qemu ${{ matrix.flags }} --microvm --netdev virtio-net-mmio
if: matrix.arch == 'x86_64'
- run: cargo xtask ci rs --arch ${{ matrix.arch }} --profile ${{ matrix.profile }} --package httpd --features ci,hermit/dhcpv4,hermit/rtl8139 qemu ${{ matrix.flags }} --netdev rtl8139
Expand Down
50 changes: 29 additions & 21 deletions src/arch/x86_64/mm/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,15 @@ pub unsafe fn identity_mapped_page_table() -> OffsetPageTable<'static> {

/// Translate a virtual memory address to a physical one.
pub fn virtual_to_physical(virtual_address: VirtAddr) -> Option<PhysAddr> {
let page_table = unsafe { recursive_page_table() };
let translate = page_table.translate(virtual_address.into());
let addr = x86_64::VirtAddr::from(virtual_address);

match translate {
let translate_result = if env::is_uefi() {
unsafe { identity_mapped_page_table() }.translate(addr)
} else {
unsafe { recursive_page_table() }.translate(addr)
};

match translate_result {
TranslateResult::NotMapped | TranslateResult::InvalidFrameAddress(_) => {
trace!(
"Uable to determine the physical address of 0x{:X}",
Expand Down Expand Up @@ -152,8 +157,8 @@ pub fn map<S>(
flags: PageTableEntryFlags,
) where
S: PageSize + Debug,
RecursivePageTable<'static>: Mapper<S>,
OffsetPageTable<'static>: Mapper<S>,
for<'a> RecursivePageTable<'a>: Mapper<S>,
for<'a> OffsetPageTable<'a>: Mapper<S>,
{
let pages = {
let start = Page::<S>::containing_address(virtual_address.into());
Expand Down Expand Up @@ -214,8 +219,8 @@ pub fn map<S>(
pub fn map_heap<S>(virt_addr: VirtAddr, count: usize) -> Result<(), usize>
where
S: PageSize + Debug,
RecursivePageTable<'static>: Mapper<S>,
OffsetPageTable<'static>: Mapper<S>,
for<'a> RecursivePageTable<'a>: Mapper<S>,
for<'a> OffsetPageTable<'a>: Mapper<S>,
{
let flags = {
let mut flags = PageTableEntryFlags::empty();
Expand All @@ -238,31 +243,30 @@ where
pub fn identity_map<S>(frame: PhysFrame<S>)
where
S: PageSize + Debug,
RecursivePageTable<'static>: Mapper<S>,
for<'a> RecursivePageTable<'a>: Mapper<S>,
for<'a> OffsetPageTable<'a>: Mapper<S>,
{
assert!(
frame.start_address().as_u64() < mm::kernel_start_address().as_u64(),
"Address {:p} to be identity-mapped is not below Kernel start address",
frame.start_address()
);

let flags = PageTableEntryFlags::PRESENT | PageTableEntryFlags::NO_EXECUTE;
let mut frame_allocator = physicalmem::PHYSICAL_FREE_LIST.lock();
unsafe {
recursive_page_table()
.identity_map(
frame,
PageTableEntryFlags::PRESENT | PageTableEntryFlags::NO_EXECUTE,
&mut *frame_allocator,
)
.unwrap()
.flush();
}
let mapper_result = if env::is_uefi() {
unsafe { identity_mapped_page_table().identity_map(frame, flags, &mut *frame_allocator) }
} else {
unsafe { recursive_page_table().identity_map(frame, flags, &mut *frame_allocator) }
};
mapper_result.unwrap().flush();
}

pub fn unmap<S>(virtual_address: VirtAddr, count: usize)
where
S: PageSize + Debug,
RecursivePageTable<'static>: Mapper<S>,
for<'a> RecursivePageTable<'a>: Mapper<S>,
for<'a> OffsetPageTable<'a>: Mapper<S>,
{
trace!(
"Unmapping virtual address {:p} ({} pages)",
Expand All @@ -274,8 +278,12 @@ where
let range = Page::range(first_page, last_page);

for page in range {
let mut page_table = unsafe { recursive_page_table() };
match page_table.unmap(page) {
let unmap_result = if env::is_uefi() {
unsafe { identity_mapped_page_table() }.unmap(page)
} else {
unsafe { recursive_page_table() }.unmap(page)
};
match unmap_result {
Ok((_frame, flush)) => flush.flush(),
// FIXME: Some sentinel pages around stacks are supposed to be unmapped.
// We should handle this case there instead of here.
Expand Down
15 changes: 10 additions & 5 deletions src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,10 @@ pub(crate) fn allocate(size: usize, no_execution: bool) -> VirtAddr {
if no_execution {
flags.execute_disable();
}
arch::mm::paging::map::<BasePageSize>(virtual_address, physical_address, count, flags);

if !env::is_uefi() {
arch::mm::paging::map::<BasePageSize>(virtual_address, physical_address, count, flags);
}

virtual_address
}
Expand All @@ -269,10 +272,12 @@ pub(crate) fn deallocate(virtual_address: VirtAddr, size: usize) {
let size = size.align_up(BasePageSize::SIZE as usize);

if let Some(phys_addr) = arch::mm::paging::virtual_to_physical(virtual_address) {
arch::mm::paging::unmap::<BasePageSize>(
virtual_address,
size / BasePageSize::SIZE as usize,
);
if !env::is_uefi() {
arch::mm::paging::unmap::<BasePageSize>(
virtual_address,
size / BasePageSize::SIZE as usize,
);
}
arch::mm::virtualmem::deallocate(virtual_address, size);
arch::mm::physicalmem::deallocate(phys_addr, size);
} else {
Expand Down

0 comments on commit 162fc78

Please sign in to comment.