diff --git a/kernel/comps/framebuffer/src/framebuffer.rs b/kernel/comps/framebuffer/src/framebuffer.rs index 913c3c822..197e54dbd 100644 --- a/kernel/comps/framebuffer/src/framebuffer.rs +++ b/kernel/comps/framebuffer/src/framebuffer.rs @@ -5,7 +5,7 @@ use alloc::{sync::Arc, vec::Vec}; use ostd::{ boot::boot_info, io::IoMem, - mm::{HasSize, VmIo}, + mm::{CachePolicy, HasSize, VmIo}, sync::Mutex, Error, Result, }; @@ -96,7 +96,14 @@ pub(crate) fn init() { let fb_size = framebuffer_arg.height.checked_mul(line_size).unwrap(); let fb_base = framebuffer_arg.address; - let io_mem = IoMem::acquire(fb_base..fb_base.checked_add(fb_size).unwrap()).unwrap(); + // Use write-combining for framebuffer to enable faster write operations. + // Write-combining allows the CPU to combine multiple writes into fewer bus transactions, + // which is ideal for framebuffer access patterns (sequential writes). + let io_mem = IoMem::acquire_with_cache_policy( + fb_base..fb_base.checked_add(fb_size).unwrap(), + CachePolicy::WriteCombining, + ) + .unwrap(); let default_cmap = FbCmap { entries: Vec::new(), diff --git a/kernel/comps/pci/src/cfg_space.rs b/kernel/comps/pci/src/cfg_space.rs index be8214ab5..36ad87526 100644 --- a/kernel/comps/pci/src/cfg_space.rs +++ b/kernel/comps/pci/src/cfg_space.rs @@ -229,6 +229,8 @@ impl MemoryBar { /// Grants I/O memory access pub fn io_mem(&self) -> &IoMem { self.io_memory.call_once(|| { + // Use the `Uncacheable` cache policy for PCI device BARs by default. + // Device-specific drivers may remap with different cache policies if needed. IoMem::acquire((self.base as usize)..((self.base + self.size) as usize)).unwrap() }) } diff --git a/ostd/src/arch/riscv/irq/chip/plic.rs b/ostd/src/arch/riscv/irq/chip/plic.rs index fe46ac45a..91aaf7bdc 100644 --- a/ostd/src/arch/riscv/irq/chip/plic.rs +++ b/ostd/src/arch/riscv/irq/chip/plic.rs @@ -319,7 +319,7 @@ impl Plic { Self { phandle, - io_mem: io_mem_builder.reserve(range), + io_mem: io_mem_builder.reserve(range, crate::mm::CachePolicy::Uncacheable), hart_to_target_mapping, interrupt_number_mappings: (0..num_interrupt_sources) .map(|_| None) diff --git a/ostd/src/arch/x86/irq/chip/ioapic.rs b/ostd/src/arch/x86/irq/chip/ioapic.rs index b4ca5586a..77cc929e3 100644 --- a/ostd/src/arch/x86/irq/chip/ioapic.rs +++ b/ostd/src/arch/x86/irq/chip/ioapic.rs @@ -178,7 +178,10 @@ impl IoApicAccess { /// /// The caller must ensure that the base address is a valid I/O APIC base address. pub(self) unsafe fn new(base_address: usize, io_mem_builder: &IoMemAllocatorBuilder) -> Self { - let io_mem = io_mem_builder.reserve(base_address..(base_address + Self::MMIO_SIZE)); + let io_mem = io_mem_builder.reserve( + base_address..(base_address + Self::MMIO_SIZE), + crate::mm::CachePolicy::Uncacheable, + ); if_tdx_enabled!({ assert_eq!( diff --git a/ostd/src/arch/x86/kernel/apic/mod.rs b/ostd/src/arch/x86/kernel/apic/mod.rs index 44e1fbb69..19bad86fb 100644 --- a/ostd/src/arch/x86/kernel/apic/mod.rs +++ b/ostd/src/arch/x86/kernel/apic/mod.rs @@ -359,7 +359,10 @@ pub fn init(io_mem_builder: &IoMemAllocatorBuilder) -> Result<(), ApicInitError> log::info!("xAPIC found!"); // SAFETY: xAPIC is present. let base_address = unsafe { xapic::read_xapic_base_address() }; - let io_mem = io_mem_builder.reserve(base_address..(base_address + xapic::XAPIC_MMIO_SIZE)); + let io_mem = io_mem_builder.reserve( + base_address..(base_address + xapic::XAPIC_MMIO_SIZE), + crate::mm::CachePolicy::Uncacheable, + ); APIC_TYPE.call_once(|| ApicType::XApic(io_mem)); Ok(()) } else { diff --git a/ostd/src/io/io_mem/allocator.rs b/ostd/src/io/io_mem/allocator.rs index 192156802..874e0a63c 100644 --- a/ostd/src/io/io_mem/allocator.rs +++ b/ostd/src/io/io_mem/allocator.rs @@ -179,7 +179,10 @@ mod test { use alloc::vec; use super::{IoMemAllocator, IoMemAllocatorBuilder}; - use crate::{mm::PAGE_SIZE, prelude::ktest}; + use crate::{ + mm::{CachePolicy, PAGE_SIZE}, + prelude::ktest, + }; #[expect(clippy::reversed_empty_ranges)] #[expect(clippy::single_range_in_vec_init)] @@ -189,18 +192,36 @@ mod test { let allocator = unsafe { IoMemAllocator::new(IoMemAllocatorBuilder::new(range).allocators) }; - assert!(allocator.acquire(0..0).is_none()); - assert!(allocator.acquire(usize::MAX..0).is_none()); + assert!(allocator.acquire(0..0, CachePolicy::Uncacheable).is_none()); + assert!(allocator + .acquire(usize::MAX..0, CachePolicy::Uncacheable) + .is_none()); - assert!(allocator.acquire(0x4000_0000..0x4000_0000).is_none()); - assert!(allocator.acquire(0x4000_1000..0x4000_1000).is_none()); - assert!(allocator.acquire(0x41ff_0000..0x41ff_0000).is_none()); - assert!(allocator.acquire(0x4200_0000..0x4200_0000).is_none()); + assert!(allocator + .acquire(0x4000_0000..0x4000_0000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x4000_1000..0x4000_1000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x41ff_0000..0x41ff_0000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x4200_0000..0x4200_0000, CachePolicy::Uncacheable) + .is_none()); - assert!(allocator.acquire(0x4000_1000..0x4000_0000).is_none()); - assert!(allocator.acquire(0x4000_2000..0x4000_1000).is_none()); - assert!(allocator.acquire(0x41ff_f000..0x41ff_e000).is_none()); - assert!(allocator.acquire(0x4200_0000..0x41ff_f000).is_none()); + assert!(allocator + .acquire(0x4000_1000..0x4000_0000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x4000_2000..0x4000_1000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x41ff_f000..0x41ff_e000, CachePolicy::Uncacheable) + .is_none()); + assert!(allocator + .acquire(0x4200_0000..0x41ff_f000, CachePolicy::Uncacheable) + .is_none()); } #[ktest] @@ -216,24 +237,42 @@ mod test { unsafe { IoMemAllocator::new(IoMemAllocatorBuilder::new(range).allocators) }; assert!(allocator - .acquire((io_mem_region_a.start - 1)..io_mem_region_a.start) + .acquire( + (io_mem_region_a.start - 1)..io_mem_region_a.start, + CachePolicy::Uncacheable + ) .is_none()); assert!(allocator - .acquire(io_mem_region_a.start..(io_mem_region_a.start + 1)) + .acquire( + io_mem_region_a.start..(io_mem_region_a.start + 1), + CachePolicy::Uncacheable + ) .is_some()); assert!(allocator - .acquire((io_mem_region_a.end + 1)..(io_mem_region_b.start - 1)) + .acquire( + (io_mem_region_a.end + 1)..(io_mem_region_b.start - 1), + CachePolicy::Uncacheable + ) .is_none()); assert!(allocator - .acquire((io_mem_region_a.end - 1)..(io_mem_region_b.start + 1)) + .acquire( + (io_mem_region_a.end - 1)..(io_mem_region_b.start + 1), + CachePolicy::Uncacheable + ) .is_none()); assert!(allocator - .acquire((io_mem_region_a.end - 1)..io_mem_region_a.end) + .acquire( + (io_mem_region_a.end - 1)..io_mem_region_a.end, + CachePolicy::Uncacheable + ) .is_some()); assert!(allocator - .acquire(io_mem_region_a.end..(io_mem_region_a.end + 1)) + .acquire( + io_mem_region_a.end..(io_mem_region_a.end + 1), + CachePolicy::Uncacheable + ) .is_none()); } }