mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Introduce macros that allow system device driver to remove sensitive ports
test test
This commit is contained in:
parent
a038b8401b
commit
92b7961df1
@ -42,6 +42,14 @@ SECTIONS
|
||||
KEEP(*(SORT(.init_array .init_array.*)))
|
||||
__einit_array = .;
|
||||
}
|
||||
|
||||
# A list of the sensitive IoPort ranges in OSTD which will be used during
|
||||
# the initialization of IoPortAllocator.
|
||||
.sensitive_io_ports : AT(ADDR(.sensitive_io_ports) - KERNEL_VMA_OFFSET) {
|
||||
__sensitive_io_ports_start = .;
|
||||
KEEP(*(.sensitive_io_ports))
|
||||
__sensitive_io_ports_end = .;
|
||||
}
|
||||
|
||||
. = DATA_SEGMENT_RELRO_END(0, .);
|
||||
|
||||
|
@ -113,6 +113,14 @@ SECTIONS
|
||||
__einit_array = .;
|
||||
} : rodata
|
||||
|
||||
# A list of the sensitive IoPort ranges in OSTD which will be used during
|
||||
# the initialization of IoPortAllocator.
|
||||
.sensitive_io_ports : AT(ADDR(.sensitive_io_ports) - KERNEL_VMA) {
|
||||
__sensitive_io_ports_start = .;
|
||||
KEEP(*(.sensitive_io_ports))
|
||||
__sensitive_io_ports_end = .;
|
||||
} : rodata
|
||||
|
||||
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) {
|
||||
*(.rodata .rodata.*)
|
||||
} : rodata
|
||||
|
@ -58,11 +58,34 @@ pub(super) fn construct_io_mem_allocator_builder() -> IoMemAllocatorBuilder {
|
||||
unsafe { IoMemAllocatorBuilder::new(ranges) }
|
||||
}
|
||||
|
||||
/// Initializes the allocatable PIO area based on the x86-64 port distribution map.
|
||||
/// Initializes the allocatable PIO area outside OSTD based on the x86-64 port distribution map.
|
||||
pub(super) fn construct_io_port_allocator_builder() -> IoPortAllocatorBuilder {
|
||||
/// Port I/O definition reference: https://bochs.sourceforge.io/techspec/PORTS.LST
|
||||
const MAX_IO_PORT: u16 = u16::MAX;
|
||||
|
||||
// SAFETY: `MAX_IO_PORT` is guaranteed not to exceed the maximum value specified by x86-64.
|
||||
unsafe { IoPortAllocatorBuilder::new(MAX_IO_PORT) }
|
||||
let mut builder = unsafe { IoPortAllocatorBuilder::new(MAX_IO_PORT) };
|
||||
|
||||
extern "C" {
|
||||
fn __sensitive_io_ports_start();
|
||||
fn __sensitive_io_ports_end();
|
||||
}
|
||||
let start = __sensitive_io_ports_start as usize;
|
||||
let end = __sensitive_io_ports_end as usize;
|
||||
|
||||
// Iterate through the sensitive I/O port ranges and remove them from the allocator.
|
||||
assert!((end - start) % (size_of::<u16>() * 2) == 0);
|
||||
let io_port_ranges = (end - start) / (size_of::<u16>() * 2);
|
||||
for i in 0..io_port_ranges {
|
||||
let range_base_addr = __sensitive_io_ports_start as usize + i * 2 * size_of::<u16>();
|
||||
let (range_start, range_end) = unsafe {
|
||||
(
|
||||
*(range_base_addr as *const u16),
|
||||
*((range_base_addr + size_of::<u16>()) as *const u16),
|
||||
)
|
||||
};
|
||||
builder.remove(range_start..range_end);
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
|
@ -39,6 +39,16 @@ impl<T, A> IoPort<T, A> {
|
||||
.ok_or(Error::AccessDenied)
|
||||
}
|
||||
|
||||
/// Returns the port number.
|
||||
pub const fn port(&self) -> u16 {
|
||||
self.port
|
||||
}
|
||||
|
||||
/// Returns the size of the I/O port.
|
||||
pub const fn size(&self) -> u16 {
|
||||
size_of::<T>() as u16
|
||||
}
|
||||
|
||||
/// Create an I/O port.
|
||||
///
|
||||
/// # Safety
|
||||
@ -81,3 +91,81 @@ impl<T, A> Drop for IoPort<T, A> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserves an I/O port range which may refer to the port I/O range used by the
|
||||
/// system device driver.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// reserve_io_port_range!(0x60..0x64);
|
||||
/// ```
|
||||
macro_rules! reserve_io_port_range {
|
||||
($range:expr) => {
|
||||
crate::const_assert!(
|
||||
$range.start < $range.end,
|
||||
"I/O port range must be valid (start < end)"
|
||||
);
|
||||
|
||||
const _: () = {
|
||||
#[used]
|
||||
#[link_section = ".sensitive_io_ports"]
|
||||
static _RANGE: crate::io::RawIoPortRange = crate::io::RawIoPortRange {
|
||||
begin: $range.start,
|
||||
end: $range.end,
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/// Declares one or multiple sensitive I/O ports.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// User must ensures that:
|
||||
/// - The I/O port is valid and doesn't overlap with other sensitive I/O ports.
|
||||
/// - The I/O port is used by the target system device driver.
|
||||
///
|
||||
/// # Example
|
||||
/// ``` norun
|
||||
/// sensitive_io_port! {
|
||||
/// unsafe {
|
||||
/// /// Master PIC command port
|
||||
/// static MASTER_CMD: IoPort<u8, WriteOnlyAccess> = IoPort::new(0x20);
|
||||
/// /// Master PIC data port
|
||||
/// static MASTER_DATA: IoPort<u8, WriteOnlyAccess> = IoPort::new(0x21);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! sensitive_io_port {
|
||||
(unsafe { $(
|
||||
$(#[$meta:meta])*
|
||||
$vis:vis static $name:ident: IoPort<$size:ty, $access:ty> = IoPort::new($port:expr);
|
||||
)* }) => {
|
||||
$(
|
||||
$(#[$meta])*
|
||||
$vis static $name: IoPort<$size, $access> = {
|
||||
#[used]
|
||||
#[link_section = ".sensitive_io_ports"]
|
||||
static _RESERVED_IO_PORT_RANGE: crate::io::RawIoPortRange = crate::io::RawIoPortRange {
|
||||
begin: $name.port(),
|
||||
end: $name.port() + $name.size(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
IoPort::new($port)
|
||||
}
|
||||
};
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use reserve_io_port_range;
|
||||
pub(crate) use sensitive_io_port;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct RawIoPortRange {
|
||||
pub(crate) begin: u16,
|
||||
pub(crate) end: u16,
|
||||
}
|
||||
|
@ -11,7 +11,10 @@ mod io_mem;
|
||||
mod io_port;
|
||||
|
||||
pub use self::{io_mem::IoMem, io_port::IoPort};
|
||||
pub(crate) use self::{io_mem::IoMemAllocatorBuilder, io_port::IoPortAllocatorBuilder};
|
||||
pub(crate) use self::{
|
||||
io_mem::IoMemAllocatorBuilder,
|
||||
io_port::{reserve_io_port_range, sensitive_io_port, IoPortAllocatorBuilder, RawIoPortRange},
|
||||
};
|
||||
|
||||
/// Initializes the static allocator based on builder.
|
||||
///
|
||||
|
Loading…
x
Reference in New Issue
Block a user