diff --git a/Changelog.md b/Changelog.md index 8b5db859..dc2e07bb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,8 @@ # Unreleased -# 0.9.26 – 2024-02-16 +- [Fix: unify flags if multiple segments are mapped to same frame with different flags](https://github.com/rust-osdev/bootloader/pull/423) +# 0.9.26 – 2024-02-16 - [Fix map errors during kernel loading](https://github.com/rust-osdev/bootloader/pull/422) - Don't error if a kernel page is already mapped to the correct frame diff --git a/src/page_table.rs b/src/page_table.rs index c666de79..fce0bd22 100644 --- a/src/page_table.rs +++ b/src/page_table.rs @@ -2,9 +2,10 @@ use crate::frame_allocator::FrameAllocator; use bootloader::bootinfo::MemoryRegionType; use bootloader::bootinfo::TlsTemplate; use fixedvec::FixedVec; -use x86_64::structures::paging::mapper::{MapToError, MapperFlush, UnmapError}; +use x86_64::structures::paging::mapper::{MapToError, MapperFlush, TranslateResult, UnmapError}; use x86_64::structures::paging::{ self, Mapper, Page, PageSize, PageTableFlags, PhysFrame, RecursivePageTable, Size4KiB, + Translate, }; use x86_64::{align_up, PhysAddr, VirtAddr}; use xmas_elf::program::{self, ProgramHeader64}; @@ -101,6 +102,18 @@ pub(crate) fn map_segment( } { Ok(flusher) => flusher.flush(), Err(MapToError::PageAlreadyMapped(to)) if to == frame => { + let flags = match page_table.translate(page.start_address()) { + TranslateResult::Mapped { flags, .. } => flags, + _ => unreachable!(), + }; + if flags != page_table_flags { + unsafe { + page_table + .update_flags(page, flags | page_table_flags) + .unwrap() + .flush() + }; + } // nothing to do, page is already mapped to the correct frame } Err(err) => return Err(err),