Integration with Operating System
Relevant source files
This page documents how the axptr
library integrates with the underlying operating system components to provide safe user memory access from kernel code. We cover the dependency architecture, memory management integration, error handling, and page fault coordination that enable axptr
to function within a broader OS environment.
For information about the core pointer types and their usage, see User Space Pointers. For details on safety mechanisms, see Safety Mechanisms.
Dependency Architecture
The axptr
library depends on several OS components to provide its functionality:
flowchart TD subgraph subGraph1["OS Integration Points"] axmm["axmm: Memory Management"] axerrno["axerrno: Error Handling"] page_table["page_table_multiarch: Page Tables"] memory_addr["memory_addr: Address Types"] percpu["percpu: Per-CPU Variables"] end subgraph subGraph0["axptr Components"] userptr["UserPtr/UserConstPtr"] addrspace_provider["AddrSpaceProvider trait"] fault_handler["Page Fault Coordination"] end kernel["Kernel Memory Subsystem"] kernel_errors["Kernel Error Handling"] arch_mm["Architecture-specific Memory Management"] kernel_smp["Kernel SMP Support"] addrspace_provider --> axmm axerrno --> kernel_errors axmm --> kernel fault_handler --> percpu page_table --> arch_mm percpu --> kernel_smp userptr --> axerrno userptr --> axmm userptr --> memory_addr userptr --> page_table
The diagram illustrates how axptr
interfaces with various operating system components through its dependencies. These dependencies allow axptr
to leverage the kernel's existing infrastructure for memory management, error handling, and multi-core support.
Sources: Cargo.toml(L7 - L12) src/lib.rs(L4 - L11)
Memory Management Integration
axptr
integrates with the OS memory management system primarily through the axmm
crate, which provides the AddrSpace
abstraction. This integration enables axptr
to:
- Check permissions for memory regions
- Populate page tables as needed
- Enforce proper memory alignment
- Handle page faults gracefully
Address Space Provider Mechanism
The AddrSpaceProvider
trait serves as the primary integration point between axptr
and the OS memory management subsystem:
The trait is designed to be simple enough that OS-specific implementations can easily provide access to the appropriate address space, while still allowing for thread-safety and context-specific behavior.
Sources: src/lib.rs(L119 - L126)
Memory Access Workflow
When kernel code attempts to access user memory through UserPtr
or UserConstPtr
, the following sequence occurs:
sequenceDiagram participant KernelCode as "Kernel Code" participant UserPtrmethods as "UserPtr methods" participant check_regionfunction as "check_region function" participant AddrSpaceProvider as "AddrSpaceProvider" participant AddrSpaceOS as "AddrSpace (OS)" participant PageFaultHandlerOS as "Page Fault Handler (OS)" KernelCode ->> UserPtrmethods: get(aspace) UserPtrmethods ->> check_regionfunction: check_region_with(aspace, addr, layout, flags) check_regionfunction ->> AddrSpaceProvider: with_addr_space(lambda) AddrSpaceProvider ->> AddrSpaceOS: lambda(aspace) AddrSpaceOS ->> AddrSpaceOS: check_region_access(range, flags) AddrSpaceOS ->> AddrSpaceOS: populate_area(page_start, page_end - page_start) AddrSpaceOS -->> check_regionfunction: Result check_regionfunction -->> UserPtrmethods: Result alt Success UserPtrmethods ->> UserPtrmethods: Set ACCESSING_USER_MEM flag UserPtrmethods ->> KernelCode: Return memory reference Note over KernelCode,UserPtrmethods: During access, page fault may occur KernelCode ->> PageFaultHandlerOS: (Page fault in kernel mode) PageFaultHandlerOS ->> PageFaultHandlerOS: Check is_accessing_user_memory() PageFaultHandlerOS ->> KernelCode: Handle fault appropriately UserPtrmethods ->> UserPtrmethods: Clear ACCESSING_USER_MEM flag else Failure UserPtrmethods ->> KernelCode: Return error (EFAULT, etc.) end
This workflow demonstrates how axptr
coordinates with the OS memory management subsystem to safely access user memory, involving permission checks, page table population, and page fault handling.
Sources: src/lib.rs(L31 - L54) src/lib.rs(L175 - L198) src/lib.rs(L258 - L277)
Error Handling Integration
axptr
uses the axerrno
crate for Linux-compatible error codes. This integration ensures that errors from user memory access operations can be properly propagated to OS-specific error handling systems.
The primary error codes used by axptr
include:
Error Code | Description | Usage inaxptr |
---|---|---|
EFAULT | Bad address | Returned for misaligned or inaccessible memory regions |
EILSEQ | Illegal byte sequence | Returned when string conversion fails inget_as_str |
The error handling flow integrates with the OS through the LinuxResult
type, which is a Result<T, LinuxError>
that can be directly used by OS components or converted to OS-specific error types.
Sources: src/lib.rs(L4) src/lib.rs(L36 - L47) src/lib.rs(L301)
Page Fault Coordination
One of the most critical aspects of OS integration is the coordination between axptr
and the OS page fault handler. This is achieved through the ACCESSING_USER_MEM
per-CPU flag:
flowchart TD start["Kernel Code accesses user memory"] access_fn["access_user_memory() function"] set_flag["Set ACCESSING_USER_MEM = true"] memory_op["Perform memory operation"] page_fault["Page fault occurs"] os_handler["OS Page Fault Handler"] check_flag["Check is_accessing_user_memory()"] special_handling["Handle as user memory access"] kernel_crash["Handle as kernel bug"] clear_flag["Set ACCESSING_USER_MEM = false"] end_access["Return result"] access_fn --> set_flag check_flag --> kernel_crash check_flag --> special_handling clear_flag --> end_access memory_op --> clear_flag memory_op --> page_fault os_handler --> check_flag page_fault --> os_handler set_flag --> memory_op special_handling --> memory_op start --> access_fn
This mechanism requires the OS page fault handler to check is_accessing_user_memory()
when a page fault occurs in kernel mode. If true, the fault should be treated as a normal user memory access that may require page table updates or signal delivery. If false, it should be treated as a bug in the kernel.
Sources: src/lib.rs(L11 - L29) src/lib.rs(L73 - L104)
Implementation of AddrSpaceProvider
Operating systems integrating with axptr
must provide an implementation of the AddrSpaceProvider
trait. The library provides a simple implementation for &mut AddrSpace
, but OS-specific implementations might include:
- Process-specific address space providers
- Thread-specific address space providers
- Providers that switch to user address spaces temporarily
The implementation should ensure that:
- The correct address space is used for the current context
- Any necessary locking or synchronization is handled
- The address space remains valid throughout the operation
Example of the default implementation:
#![allow(unused)] fn main() { impl AddrSpaceProvider for &mut AddrSpace { fn with_addr_space<R>(&mut self, f: impl FnOnce(&mut AddrSpace) -> R) -> R { f(self) } } }
Sources: src/lib.rs(L119 - L126)
Dependency Requirements
The operating system must provide or accommodate the following components for proper integration with axptr
:
Dependency | Required Features |
---|---|
axmm | AddrSpace implementation with check_region_access and populate_area methods |
page_table_multiarch | Support for mapping flags (READ, WRITE) |
memory_addr | Address types and manipulation (VirtAddr, VirtAddrRange) |
percpu | Per-CPU variable support for the ACCESSING_USER_MEM flag |
axerrno | Linux-compatible error codes |
Each dependency provides essential functionality that axptr
relies on to safely access user memory. The operating system must ensure these dependencies are properly implemented and available.
Sources: Cargo.toml(L7 - L12) src/lib.rs(L4 - L11)
Integration Example Flow
The complete flow of integration between axptr
and the operating system for a typical user memory access operation:
sequenceDiagram participant KernelCode as "Kernel Code" participant UserPtr as "UserPtr" participant OSAddrSpaceProvider as "OS AddrSpaceProvider" participant OSAddrSpace as "OS AddrSpace" participant OSPageTables as "OS Page Tables" participant OSPageFaultHandler as "OS Page Fault Handler" KernelCode ->> UserPtr: get(os_provider) UserPtr ->> OSAddrSpaceProvider: with_addr_space(lambda) OSAddrSpaceProvider ->> OSAddrSpace: Acquire address space OSAddrSpaceProvider ->> UserPtr: Execute lambda with address space UserPtr ->> OSAddrSpace: check_region_access(range, flags) OSAddrSpace ->> OSAddrSpace: Validate permissions UserPtr ->> OSAddrSpace: populate_area(page_start, size) OSAddrSpace ->> OSPageTables: Ensure pages are populated UserPtr ->> UserPtr: Set ACCESSING_USER_MEM = true UserPtr ->> KernelCode: Return reference to user memory KernelCode ->> KernelCode: Access user memory alt Page Fault Occurs KernelCode -->> OSPageFaultHandler: Page fault exception OSPageFaultHandler ->> OSPageFaultHandler: Call is_accessing_user_memory() OSPageFaultHandler ->> OSPageTables: Handle fault (map page, etc.) OSPageFaultHandler -->> KernelCode: Resume execution end KernelCode ->> UserPtr: Memory access complete UserPtr ->> UserPtr: Set ACCESSING_USER_MEM = false
This diagram illustrates the complete integration flow, showing how various OS components interact with axptr
during a user memory access operation, including the handling of page faults.
Sources: src/lib.rs(L18 - L29) src/lib.rs(L31 - L54) src/lib.rs(L175 - L198)