Remove the system device's IO memory access

This commit is contained in:
Yuke Peng
2024-10-31 08:43:52 +08:00
committed by Tate, Hongliang Tian
parent 8a26b785a4
commit 05ec50def3
7 changed files with 32 additions and 24 deletions

View File

@ -11,7 +11,7 @@ mod registers;
pub(crate) use dma_remapping::{has_dma_remapping, map, unmap}; pub(crate) use dma_remapping::{has_dma_remapping, map, unmap};
pub(crate) use interrupt_remapping::{alloc_irt_entry, has_interrupt_remapping, IrtEntryHandle}; pub(crate) use interrupt_remapping::{alloc_irt_entry, has_interrupt_remapping, IrtEntryHandle};
use crate::mm::page_table::PageTableError; use crate::{io::IoMemAllocatorBuilder, mm::page_table::PageTableError};
/// An enumeration representing possible errors related to IOMMU. /// An enumeration representing possible errors related to IOMMU.
#[derive(Debug)] #[derive(Debug)]
@ -22,8 +22,8 @@ pub enum IommuError {
ModificationError(PageTableError), ModificationError(PageTableError),
} }
pub(crate) fn init() -> Result<(), IommuError> { pub(crate) fn init(io_mem_builder: &IoMemAllocatorBuilder) -> Result<(), IommuError> {
registers::init()?; registers::init(io_mem_builder)?;
invalidate::init(); invalidate::init();
dma_remapping::init(); dma_remapping::init();
interrupt_remapping::init(); interrupt_remapping::init();

View File

@ -39,7 +39,8 @@ use crate::{
}, },
x86::kernel::acpi::dmar::{Dmar, Remapping}, x86::kernel::acpi::dmar::{Dmar, Remapping},
}, },
mm::paddr_to_vaddr, io::IoMemAllocatorBuilder,
mm::{paddr_to_vaddr, PAGE_SIZE},
sync::{LocalIrqDisabled, SpinLock}, sync::{LocalIrqDisabled, SpinLock},
}; };
@ -251,7 +252,7 @@ impl IommuRegisters {
} }
/// Creates an instance from base address /// Creates an instance from base address
fn new() -> Option<Self> { fn new(io_mem_builder: &IoMemAllocatorBuilder) -> Option<Self> {
let dmar = Dmar::new()?; let dmar = Dmar::new()?;
debug!("DMAR: {:#x?}", dmar); debug!("DMAR: {:#x?}", dmar);
@ -265,6 +266,7 @@ impl IommuRegisters {
assert_ne!(base_address, 0, "IOMMU address should not be zero"); assert_ne!(base_address, 0, "IOMMU address should not be zero");
debug!("IOMMU base address: {:#x?}", base_address); debug!("IOMMU base address: {:#x?}", base_address);
io_mem_builder.remove(base_address as usize..(base_address as usize + PAGE_SIZE));
let base = NonNull::new(paddr_to_vaddr(base_address as usize) as *mut u8).unwrap(); let base = NonNull::new(paddr_to_vaddr(base_address as usize) as *mut u8).unwrap();
// SAFETY: All offsets and sizes are strictly adhered to in the manual, and the base // SAFETY: All offsets and sizes are strictly adhered to in the manual, and the base
@ -303,8 +305,8 @@ impl IommuRegisters {
pub(super) static IOMMU_REGS: Once<SpinLock<IommuRegisters, LocalIrqDisabled>> = Once::new(); pub(super) static IOMMU_REGS: Once<SpinLock<IommuRegisters, LocalIrqDisabled>> = Once::new();
pub(super) fn init() -> Result<(), IommuError> { pub(super) fn init(io_mem_builder: &IoMemAllocatorBuilder) -> Result<(), IommuError> {
let iommu_regs = IommuRegisters::new().ok_or(IommuError::NoIommu)?; let iommu_regs = IommuRegisters::new(io_mem_builder).ok_or(IommuError::NoIommu)?;
IOMMU_REGS.call_once(|| SpinLock::new(iommu_regs)); IOMMU_REGS.call_once(|| SpinLock::new(iommu_regs));
Ok(()) Ok(())
} }

View File

@ -17,6 +17,7 @@ use volatile::{
use crate::{ use crate::{
arch::{iommu::has_interrupt_remapping, x86::kernel::acpi::get_platform_info}, arch::{iommu::has_interrupt_remapping, x86::kernel::acpi::get_platform_info},
if_tdx_enabled, if_tdx_enabled,
io::IoMemAllocatorBuilder,
mm::paddr_to_vaddr, mm::paddr_to_vaddr,
sync::SpinLock, sync::SpinLock,
trap::IrqLine, trap::IrqLine,
@ -142,7 +143,8 @@ impl IoApicAccess {
/// # Safety /// # Safety
/// ///
/// User must ensure the base address is valid. /// User must ensure the base address is valid.
unsafe fn new(base_address: usize) -> Self { unsafe fn new(base_address: usize, io_mem_builder: &IoMemAllocatorBuilder) -> Self {
io_mem_builder.remove(base_address..(base_address + 0x20));
let base = NonNull::new(paddr_to_vaddr(base_address) as *mut u8).unwrap(); let base = NonNull::new(paddr_to_vaddr(base_address) as *mut u8).unwrap();
let register = VolatileRef::new_restricted(WriteOnly, base.cast::<u32>()); let register = VolatileRef::new_restricted(WriteOnly, base.cast::<u32>());
let data = VolatileRef::new(base.add(0x10).cast::<u32>()); let data = VolatileRef::new(base.add(0x10).cast::<u32>());
@ -178,7 +180,7 @@ impl IoApicAccess {
pub static IO_APIC: Once<Vec<SpinLock<IoApic>>> = Once::new(); pub static IO_APIC: Once<Vec<SpinLock<IoApic>>> = Once::new();
pub fn init() { pub fn init(io_mem_builder: &IoMemAllocatorBuilder) {
let Some(platform_info) = get_platform_info() else { let Some(platform_info) = get_platform_info() else {
IO_APIC.call_once(|| { IO_APIC.call_once(|| {
// FIXME: Is it possible to have an address that is not the default 0xFEC0_0000? // FIXME: Is it possible to have an address that is not the default 0xFEC0_0000?
@ -193,7 +195,7 @@ pub fn init() {
tdx_guest::unprotect_gpa_range(IO_APIC_DEFAULT_ADDRESS, 1).unwrap(); tdx_guest::unprotect_gpa_range(IO_APIC_DEFAULT_ADDRESS, 1).unwrap();
} }
}); });
let mut io_apic = unsafe { IoApicAccess::new(IO_APIC_DEFAULT_ADDRESS) }; let mut io_apic = unsafe { IoApicAccess::new(IO_APIC_DEFAULT_ADDRESS, io_mem_builder) };
io_apic.set_id(0); io_apic.set_id(0);
let id = io_apic.id(); let id = io_apic.id();
let version = io_apic.version(); let version = io_apic.version();
@ -225,7 +227,8 @@ pub fn init() {
} }
}); });
let interrupt_base = io_apic.global_system_interrupt_base; let interrupt_base = io_apic.global_system_interrupt_base;
let mut io_apic = unsafe { IoApicAccess::new(io_apic.address as usize) }; let mut io_apic =
unsafe { IoApicAccess::new(io_apic.address as usize, io_mem_builder) };
io_apic.set_id(id as u8); io_apic.set_id(id as u8);
let id = io_apic.id(); let id = io_apic.id();
let version = io_apic.version(); let version = io_apic.version();

View File

@ -8,8 +8,9 @@ use core::{
use bit_field::BitField; use bit_field::BitField;
use spin::Once; use spin::Once;
use xapic::get_xapic_base_address;
use crate::{cpu::PinCurrentCpu, cpu_local}; use crate::{cpu::PinCurrentCpu, cpu_local, io::IoMemAllocatorBuilder};
pub mod ioapic; pub mod ioapic;
pub mod x2apic; pub mod x2apic;
@ -346,7 +347,7 @@ pub enum DivideConfig {
Divide128 = 0b1010, Divide128 = 0b1010,
} }
pub fn init() -> Result<(), ApicInitError> { pub fn init(io_mem_builder: &IoMemAllocatorBuilder) -> Result<(), ApicInitError> {
crate::arch::x86::kernel::pic::disable_temp(); crate::arch::x86::kernel::pic::disable_temp();
if x2apic::X2Apic::has_x2apic() { if x2apic::X2Apic::has_x2apic() {
log::info!("x2APIC found!"); log::info!("x2APIC found!");
@ -354,6 +355,8 @@ pub fn init() -> Result<(), ApicInitError> {
Ok(()) Ok(())
} else if xapic::XApic::has_xapic() { } else if xapic::XApic::has_xapic() {
log::info!("xAPIC found!"); log::info!("xAPIC found!");
let base_address = get_xapic_base_address();
io_mem_builder.remove(base_address..(base_address + size_of::<[u32; 256]>()));
APIC_TYPE.call_once(|| ApicType::XApic); APIC_TYPE.call_once(|| ApicType::XApic);
Ok(()) Ok(())
} else { } else {

View File

@ -23,7 +23,7 @@ impl XApic {
if !Self::has_xapic() { if !Self::has_xapic() {
return None; return None;
} }
let address = mm::paddr_to_vaddr(get_apic_base_address()); let address = mm::paddr_to_vaddr(get_xapic_base_address());
Some(Self { Some(Self {
mmio_start: address as *mut u32, mmio_start: address as *mut u32,
}) })
@ -47,7 +47,7 @@ impl XApic {
pub fn enable(&mut self) { pub fn enable(&mut self) {
// Enable xAPIC // Enable xAPIC
set_apic_base_address(get_apic_base_address()); set_apic_base_address(get_xapic_base_address());
// Set SVR, Enable APIC and set Spurious Vector to 15 (Reserved irq number) // Set SVR, Enable APIC and set Spurious Vector to 15 (Reserved irq number)
let svr: u32 = (1 << 8) | 15; let svr: u32 = (1 << 8) | 15;
@ -119,8 +119,8 @@ fn set_apic_base_address(address: usize) {
} }
} }
/// Gets APIC base address /// Gets xAPIC base address
fn get_apic_base_address() -> usize { pub(super) fn get_xapic_base_address() -> usize {
unsafe { unsafe {
(x86_64::registers::model_specific::Msr::new(IA32_APIC_BASE_MSR).read() & 0xf_ffff_f000) (x86_64::registers::model_specific::Msr::new(IA32_APIC_BASE_MSR).read() & 0xf_ffff_f000)
as usize as usize

View File

@ -80,11 +80,11 @@ pub(crate) unsafe fn late_init_on_bsp() {
kernel::acpi::init(); kernel::acpi::init();
let builder = construct_io_mem_allocator_builder(); let io_mem_builder = construct_io_mem_allocator_builder();
match kernel::apic::init() { match kernel::apic::init(&io_mem_builder) {
Ok(_) => { Ok(_) => {
ioapic::init(); ioapic::init(&io_mem_builder);
} }
Err(err) => { Err(err) => {
info!("APIC init error:{:?}", err); info!("APIC init error:{:?}", err);
@ -99,7 +99,7 @@ pub(crate) unsafe fn late_init_on_bsp() {
if_tdx_enabled!({ if_tdx_enabled!({
} else { } else {
match iommu::init() { match iommu::init(&io_mem_builder) {
Ok(_) => {} Ok(_) => {}
Err(err) => warn!("IOMMU initialization error:{:?}", err), Err(err) => warn!("IOMMU initialization error:{:?}", err),
} }
@ -110,7 +110,7 @@ pub(crate) unsafe fn late_init_on_bsp() {
// SAFETY: All the system device memory I/Os have been removed from the builder. // SAFETY: All the system device memory I/Os have been removed from the builder.
unsafe { unsafe {
crate::io::init(builder); crate::io::init(io_mem_builder);
} }
} }

View File

@ -113,8 +113,8 @@ pub static IO_MEM_ALLOCATOR: Once<IoMemAllocator> = Once::new();
/// ///
/// User must ensure all the memory I/O regions that belong to the system device have been removed by calling the /// User must ensure all the memory I/O regions that belong to the system device have been removed by calling the
/// `remove` function. /// `remove` function.
pub(crate) unsafe fn init(builder: IoMemAllocatorBuilder) { pub(crate) unsafe fn init(io_mem_builder: IoMemAllocatorBuilder) {
IO_MEM_ALLOCATOR.call_once(|| IoMemAllocator::new(builder.allocators)); IO_MEM_ALLOCATOR.call_once(|| IoMemAllocator::new(io_mem_builder.allocators));
} }
fn find_allocator<'a>( fn find_allocator<'a>(