mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Add unsafe
for acquring I/O memory/port
This commit is contained in:
parent
e1e5f9f575
commit
31dbae5330
@ -34,23 +34,20 @@ impl SerialPort {
|
|||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// User must ensure the `port` is valid serial port.
|
/// The caller must ensure that the base port is a valid serial base port and that it has
|
||||||
|
/// exclusive ownership of the serial ports.
|
||||||
pub const unsafe fn new(port: u16) -> Self {
|
pub const unsafe fn new(port: u16) -> Self {
|
||||||
let data = IoPort::new(port);
|
// SAFETY: The safety is upheld by the caller.
|
||||||
let int_en = IoPort::new(port + 1);
|
unsafe {
|
||||||
let fifo_ctrl = IoPort::new(port + 2);
|
Self {
|
||||||
let line_ctrl = IoPort::new(port + 3);
|
data: IoPort::new(port),
|
||||||
let modem_ctrl = IoPort::new(port + 4);
|
int_en: IoPort::new(port + 1),
|
||||||
let line_status = IoPort::new(port + 5);
|
fifo_ctrl: IoPort::new(port + 2),
|
||||||
let modem_status = IoPort::new(port + 6);
|
line_ctrl: IoPort::new(port + 3),
|
||||||
Self {
|
modem_ctrl: IoPort::new(port + 4),
|
||||||
data,
|
line_status: IoPort::new(port + 5),
|
||||||
int_en,
|
modem_status: IoPort::new(port + 6),
|
||||||
fifo_ctrl,
|
}
|
||||||
line_ctrl,
|
|
||||||
modem_ctrl,
|
|
||||||
line_status,
|
|
||||||
modem_status,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +32,14 @@ impl FaultEventRegisters {
|
|||||||
FaultStatus::from_bits_truncate(self.status.as_ptr().read())
|
FaultStatus::from_bits_truncate(self.status.as_ptr().read())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an instance from base address.
|
/// Creates an instance from the IOMMU base address.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// User must ensure the base_register_vaddr is read from DRHD
|
/// The caller must ensure that the base address is a valid IOMMU base address and that it has
|
||||||
|
/// exclusive ownership of the IOMMU fault event registers.
|
||||||
unsafe fn new(base_register_vaddr: NonNull<u8>) -> Self {
|
unsafe fn new(base_register_vaddr: NonNull<u8>) -> Self {
|
||||||
|
// SAFETY: The safety is upheld by the caller.
|
||||||
let (capability, status, mut control, mut data, mut address, upper_address) = unsafe {
|
let (capability, status, mut control, mut data, mut address, upper_address) = unsafe {
|
||||||
let base = base_register_vaddr;
|
let base = base_register_vaddr;
|
||||||
(
|
(
|
||||||
@ -231,9 +233,12 @@ pub(super) static FAULT_EVENT_REGS: Once<SpinLock<FaultEventRegisters, LocalIrqD
|
|||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// User must ensure the base_register_vaddr is read from DRHD
|
/// The caller must ensure that the base address is a valid IOMMU base address and that it has
|
||||||
|
/// exclusive ownership of the IOMMU fault event registers.
|
||||||
pub(super) unsafe fn init(base_register_vaddr: NonNull<u8>) {
|
pub(super) unsafe fn init(base_register_vaddr: NonNull<u8>) {
|
||||||
FAULT_EVENT_REGS.call_once(|| SpinLock::new(FaultEventRegisters::new(base_register_vaddr)));
|
FAULT_EVENT_REGS
|
||||||
|
// SAFETY: The safety is upheld by the caller.
|
||||||
|
.call_once(|| SpinLock::new(unsafe { FaultEventRegisters::new(base_register_vaddr) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iommu_fault_handler(_frame: &TrapFrame) {
|
fn iommu_fault_handler(_frame: &TrapFrame) {
|
||||||
|
@ -30,11 +30,12 @@ pub struct InvalidationRegisters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InvalidationRegisters {
|
impl InvalidationRegisters {
|
||||||
/// Creates an instance from IOMMU base address.
|
/// Creates an instance from the IOMMU base address.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// User must ensure the address is valid.
|
/// The caller must ensure that the base address is a valid IOMMU base address and that it has
|
||||||
|
/// exclusive ownership of the IOMMU invalidation registers.
|
||||||
pub(super) unsafe fn new(base: NonNull<u8>) -> Self {
|
pub(super) unsafe fn new(base: NonNull<u8>) -> Self {
|
||||||
let offset = {
|
let offset = {
|
||||||
// SAFETY: The safety is upheld by the caller.
|
// SAFETY: The safety is upheld by the caller.
|
||||||
|
@ -278,8 +278,11 @@ impl IommuRegisters {
|
|||||||
io_mem_builder.remove(base_address as usize..(base_address as usize + PAGE_SIZE));
|
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:
|
||||||
// address is obtained from DRHD.
|
// - We trust the ACPI tables (as well as the DRHD in them), from which the base address is
|
||||||
|
// obtained, so it is a valid IOMMU base address.
|
||||||
|
// - `io_mem_builder.remove()` guarantees that we have exclusive ownership of all the IOMMU
|
||||||
|
// registers.
|
||||||
let iommu_regs = unsafe {
|
let iommu_regs = unsafe {
|
||||||
fault::init(base);
|
fault::init(base);
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ impl IoApicAccess {
|
|||||||
/// The caller must ensure that the base address is a valid I/O APIC base address.
|
/// The caller must ensure that the base address is a valid I/O APIC base address.
|
||||||
unsafe fn new(base_address: usize, io_mem_builder: &IoMemAllocatorBuilder) -> Self {
|
unsafe fn new(base_address: usize, io_mem_builder: &IoMemAllocatorBuilder) -> Self {
|
||||||
io_mem_builder.remove(base_address..(base_address + 0x20));
|
io_mem_builder.remove(base_address..(base_address + 0x20));
|
||||||
|
|
||||||
if_tdx_enabled!({
|
if_tdx_enabled!({
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
base_address % crate::mm::PAGE_SIZE,
|
base_address % crate::mm::PAGE_SIZE,
|
||||||
@ -156,9 +157,18 @@ impl IoApicAccess {
|
|||||||
unsafe { tdx_guest::unprotect_gpa_range(base_address, 1).unwrap() };
|
unsafe { tdx_guest::unprotect_gpa_range(base_address, 1).unwrap() };
|
||||||
});
|
});
|
||||||
|
|
||||||
let base = NonNull::new(paddr_to_vaddr(base_address) as *mut u8).unwrap();
|
let register_addr = NonNull::new(paddr_to_vaddr(base_address) as *mut u32).unwrap();
|
||||||
let register = VolatileRef::new_restricted(WriteOnly, base.cast::<u32>());
|
// SAFETY:
|
||||||
let data = VolatileRef::new(base.add(0x10).cast::<u32>());
|
// - The caller guarantees that the memory is an I/O ACPI register.
|
||||||
|
// - `io_mem_builder.remove()` guarantees that we have exclusive ownership of the register.
|
||||||
|
let register = unsafe { VolatileRef::new_restricted(WriteOnly, register_addr) };
|
||||||
|
|
||||||
|
let data_addr = NonNull::new(paddr_to_vaddr(base_address + 0x10) as *mut u32).unwrap();
|
||||||
|
// SAFETY:
|
||||||
|
// - The caller guarantees that the memory is an I/O ACPI register.
|
||||||
|
// - `io_mem_builder.remove()` guarantees that we have exclusive ownership of the register.
|
||||||
|
let data = unsafe { VolatileRef::new(data_addr) };
|
||||||
|
|
||||||
Self { register, data }
|
Self { register, data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user