mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06: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.*)))
|
KEEP(*(SORT(.init_array .init_array.*)))
|
||||||
__einit_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, .);
|
. = DATA_SEGMENT_RELRO_END(0, .);
|
||||||
|
|
||||||
|
@ -113,6 +113,14 @@ SECTIONS
|
|||||||
__einit_array = .;
|
__einit_array = .;
|
||||||
} : rodata
|
} : 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 : AT(ADDR(.rodata) - KERNEL_VMA) {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
} : rodata
|
} : rodata
|
||||||
|
@ -58,11 +58,34 @@ pub(super) fn construct_io_mem_allocator_builder() -> IoMemAllocatorBuilder {
|
|||||||
unsafe { IoMemAllocatorBuilder::new(ranges) }
|
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 {
|
pub(super) fn construct_io_port_allocator_builder() -> IoPortAllocatorBuilder {
|
||||||
/// Port I/O definition reference: https://bochs.sourceforge.io/techspec/PORTS.LST
|
/// Port I/O definition reference: https://bochs.sourceforge.io/techspec/PORTS.LST
|
||||||
const MAX_IO_PORT: u16 = u16::MAX;
|
const MAX_IO_PORT: u16 = u16::MAX;
|
||||||
|
|
||||||
// SAFETY: `MAX_IO_PORT` is guaranteed not to exceed the maximum value specified by x86-64.
|
// 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)
|
.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.
|
/// Create an I/O port.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # 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;
|
mod io_port;
|
||||||
|
|
||||||
pub use self::{io_mem::IoMem, io_port::IoPort};
|
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.
|
/// Initializes the static allocator based on builder.
|
||||||
///
|
///
|
||||||
|
Loading…
x
Reference in New Issue
Block a user