kernel/object/handle/
syscall.rs

1//! Handle introspection system call
2//!
3//! Provides sys_handle_query for KernelObject type and capability discovery
4
5use crate::{
6    arch::Trapframe,
7    object::{
8        handle::HandleMetadata, handle::HandleType, handle::StandardInputOutput,
9        introspection::KernelObjectInfo,
10    },
11    task::mytask,
12};
13
14/// sys_handle_query - Get information about a KernelObject handle
15///
16/// This system call allows user space to discover the type and capabilities
17/// of a KernelObject, enabling type-safe wrapper implementations.
18///
19/// # Arguments
20/// - handle: The handle to query
21/// - info_ptr: Pointer to KernelObjectInfo structure to fill
22///
23/// # Returns
24/// - 0 on success
25/// - usize::MAX on error
26pub fn sys_handle_query(trapframe: &mut Trapframe) -> usize {
27    let task = match mytask() {
28        Some(task) => task,
29        None => return usize::MAX,
30    };
31
32    let handle = trapframe.get_arg(0) as u32;
33    let info_ptr = trapframe.get_arg(1);
34
35    // Increment PC to avoid infinite loop
36    trapframe.increment_pc_next(task);
37
38    // Translate the pointer to get access to the info structure
39    let info_vaddr = match task.vm_manager.translate_vaddr(info_ptr) {
40        Some(addr) => addr as *mut KernelObjectInfo,
41        None => return usize::MAX, // Invalid pointer
42    };
43
44    // Get object information
45    match task.handle_table.get_object_info(handle) {
46        Some(info) => {
47            // Write the information to user space
48            unsafe {
49                *info_vaddr = info;
50            }
51            0 // Success
52        }
53        None => usize::MAX, // Invalid handle
54    }
55}
56
57/// Change handle role after creation
58///
59/// Arguments:
60/// - handle: Handle to modify
61/// - new_role: New HandleType role
62/// - flags: Additional flags
63///
64/// Returns:
65/// - 0 on success
66/// - usize::MAX on error
67pub fn sys_handle_set_role(trapframe: &mut Trapframe) -> usize {
68    let task = match mytask() {
69        Some(task) => task,
70        None => return usize::MAX,
71    };
72
73    let handle = trapframe.get_arg(0) as u32;
74    let new_role_raw = trapframe.get_arg(1);
75    let _flags = trapframe.get_arg(2);
76
77    trapframe.increment_pc_next(task);
78
79    // Decode new role from raw value
80    let new_role = match decode_handle_type(new_role_raw) {
81        Some(role) => role,
82        None => return usize::MAX, // Invalid role
83    };
84
85    // Get current metadata and verify handle exists
86    let current_metadata = match task.handle_table.get_metadata(handle) {
87        Some(meta) => meta.clone(),
88        None => return usize::MAX, // Invalid handle
89    };
90
91    // Create new metadata with updated role
92    let new_metadata = HandleMetadata {
93        handle_type: new_role,
94        access_mode: current_metadata.access_mode,
95        special_semantics: current_metadata.special_semantics,
96    };
97
98    // Update metadata in handle table
99    if let Err(_) = task.handle_table.update_metadata(handle, new_metadata) {
100        return usize::MAX; // Update failed
101    }
102
103    0 // Success
104}
105
106/// Close a handle (sys_handle_close)
107///
108/// This system call closes a handle and removes it from the handle table.
109///
110/// # Arguments
111/// - handle: The handle to close
112///
113/// # Returns
114/// - 0 on success
115/// - usize::MAX on error (invalid handle)
116pub fn sys_handle_close(trapframe: &mut Trapframe) -> usize {
117    let task = match mytask() {
118        Some(task) => task,
119        None => return usize::MAX,
120    };
121
122    let handle = trapframe.get_arg(0) as u32;
123    trapframe.increment_pc_next(task);
124
125    if task.handle_table.remove(handle).is_some() {
126        0 // Success
127    } else {
128        usize::MAX // Invalid handle
129    }
130}
131
132/// Duplicate a handle (sys_handle_duplicate)
133///
134/// This system call creates a new handle that refers to the same kernel object
135/// as the original handle.
136///
137/// # Arguments
138/// - handle: The handle to duplicate
139///
140/// # Returns
141/// - New handle number on success
142/// - usize::MAX on error (invalid handle, handle table full)
143pub fn sys_handle_duplicate(trapframe: &mut Trapframe) -> usize {
144    let task = match mytask() {
145        Some(task) => task,
146        None => return usize::MAX,
147    };
148
149    let handle = trapframe.get_arg(0) as u32;
150    trapframe.increment_pc_next(task);
151
152    // Check if the handle exists and get the kernel object
153    if let Some(kernel_obj) = task.handle_table.get(handle) {
154        // Insert a new handle for the same object
155        match task.handle_table.insert(kernel_obj.clone()) {
156            Ok(new_handle) => new_handle as usize,
157            Err(_) => usize::MAX, // Handle table full
158        }
159    } else {
160        usize::MAX // Invalid handle
161    }
162}
163
164/// Decode HandleType from raw value
165fn decode_handle_type(raw: usize) -> Option<HandleType> {
166    match raw {
167        0 => Some(HandleType::Regular),
168        1 => Some(HandleType::IpcChannel),
169        2 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stdin)),
170        3 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stdout)),
171        4 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stderr)),
172        5 => Some(HandleType::EventChannel),
173        6 => Some(HandleType::EventSubscription),
174        _ => None,
175    }
176}
177
178/// Encode HandleType to raw value for user space
179pub fn encode_handle_type(handle_type: &HandleType) -> usize {
180    match handle_type {
181        HandleType::Regular => 0,
182        HandleType::IpcChannel => 1,
183        HandleType::StandardInputOutput(StandardInputOutput::Stdin) => 2,
184        HandleType::StandardInputOutput(StandardInputOutput::Stdout) => 3,
185        HandleType::StandardInputOutput(StandardInputOutput::Stderr) => 4,
186        HandleType::EventChannel => 5,
187        HandleType::EventSubscription => 6,
188    }
189}
190
191/// sys_handle_control - Perform control operations on a handle
192///
193/// This system call allows user space to perform device-specific control
194/// operations on a handle, similar to ioctl operations in POSIX systems.
195///
196/// # Arguments
197/// - handle: The handle to perform the control operation on
198/// - command: The control command identifier
199/// - arg: Command-specific argument (often a pointer to data)
200///
201/// # Returns
202/// - i32 value on success (command-specific)
203/// - usize::MAX on error
204pub fn sys_handle_control(trapframe: &mut Trapframe) -> usize {
205    let task = match mytask() {
206        Some(task) => task,
207        None => return usize::MAX,
208    };
209
210    let handle = trapframe.get_arg(0) as u32;
211    let command = trapframe.get_arg(1) as u32;
212    let arg = trapframe.get_arg(2);
213
214    // Increment PC to avoid infinite loop
215    trapframe.increment_pc_next(task);
216
217    // Get the kernel object from the handle table (without clone)
218    let kernel_object = match task.handle_table.get(handle) {
219        Some(obj) => obj,
220        None => return usize::MAX,
221    };
222
223    // Perform the control operation using the ControlOps capability
224    let result = match kernel_object.as_control() {
225        Some(control_ops) => control_ops.control(command, arg),
226        None => Err("Control operations not supported on this object"),
227    };
228
229    // Convert result to usize for system call return value
230    match result {
231        Ok(value) => value as usize,
232        Err(_) => usize::MAX,
233    }
234}