1use ax_alloc::AllocError;
2use ax_cgroup::CgroupError;
3use ax_fs_ng::BlockError;
4use ax_hal::{cache::TlbShootdownError, paging::PagingError};
5use ax_io::IoError;
6use ax_memory_set::MappingError;
7use ax_mm::MmError;
8use ax_net::NetError;
9use ax_runtime::{RuntimeError, serial::ConfigError, task::thread::TaskError};
10use axfs_ng_vfs::VfsError;
11use dma_api::DmaError;
12#[cfg(all(test, not(axtest)))]
13use rdif_block::{BlkError, RequestOp};
14#[cfg(feature = "sg2002")]
15use sg2002_tpu::{ion::IonError, tpu::error::TpuError};
16use starry_signal::SignalError;
17use starry_vm::VmError;
18use syscalls::Errno;
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub enum DmaOperation {
23 BufferAllocation,
25 DeviceIo,
27}
28
29#[derive(Debug, thiserror::Error)]
31pub enum StarryError {
32 #[error("Linux ABI operation failed: {0}")]
33 Errno(Errno),
34 #[error(transparent)]
35 Vm(#[from] VmError),
36 #[error(transparent)]
37 Signal(#[from] SignalError),
38 #[error(transparent)]
39 Mm(#[from] MmError),
40 #[error(transparent)]
41 Vfs(#[from] VfsError),
42 #[error(transparent)]
43 Mapping(#[from] MappingError),
44 #[error(transparent)]
45 Paging(#[from] PagingError),
46 #[error("pending address-space TLB quarantine blocked the operation: {0}")]
49 TlbShootdown(#[from] TlbShootdownError),
50 #[error(transparent)]
51 Alloc(#[from] AllocError),
52 #[error(transparent)]
53 Cgroup(#[from] CgroupError),
54 #[error(transparent)]
55 IoDomain(#[from] IoError),
56 #[error(transparent)]
57 Net(#[from] NetError),
58 #[error(transparent)]
59 Task(#[from] TaskError),
60 #[error(transparent)]
61 Runtime(#[from] RuntimeError),
62 #[error(transparent)]
63 Block(#[from] BlockError),
64 #[error(transparent)]
65 Driver(#[from] ax_driver::Error),
66 #[cfg(feature = "sg2002")]
67 #[error(transparent)]
68 Ion(#[from] IonError),
69 #[cfg(feature = "sg2002")]
70 #[error(transparent)]
71 Tpu(#[from] TpuError),
72 #[error(transparent)]
73 Format(#[from] core::fmt::Error),
74 #[error("DMA {operation:?} failed: {source}")]
75 Dma {
76 operation: DmaOperation,
77 #[source]
78 source: DmaError,
79 },
80 #[error("kernel object already exists")]
81 AlreadyExists,
82 #[error("argument list is too long")]
83 ArgumentListTooLong,
84 #[error("bad address")]
85 BadAddress,
86 #[error("bad file descriptor")]
87 BadFileDescriptor,
88 #[error("kernel object is in an invalid state")]
89 BadState,
90 #[error("broken pipe")]
91 BrokenPipe,
92 #[error("operation crosses devices")]
93 CrossesDevices,
94 #[error("filesystem traversal loop detected")]
95 FilesystemLoop,
96 #[error("illegal byte sequence")]
97 IllegalBytes,
98 #[error("operation is in progress")]
99 InProgress,
100 #[error("operation was interrupted")]
101 Interrupted,
102 #[error("operation was interrupted without restart")]
105 InterruptedNoRestart,
106 #[error("invalid kernel data")]
107 InvalidData,
108 #[error("invalid executable image")]
109 InvalidExecutable,
110 #[error("malformed executable image")]
111 MalformedExecutable,
112 #[error("invalid kernel input")]
113 InvalidInput,
114 #[error("kernel I/O failed")]
115 Io,
116 #[error("object is a directory")]
117 IsADirectory,
118 #[error("name is too long")]
119 NameTooLong,
120 #[error("kernel allocation failed")]
121 NoMemory,
122 #[error("device does not exist")]
123 NoSuchDevice,
124 #[error("device or address does not exist")]
125 NoSuchDeviceOrAddress,
126 #[error("process does not exist")]
127 NoSuchProcess,
128 #[error("object is not a directory")]
129 NotADirectory,
130 #[error("object is not a socket")]
131 NotASocket,
132 #[error("object is not a tty")]
133 NotATty,
134 #[error("object was not found")]
135 NotFound,
136 #[error("operation is not permitted")]
137 OperationNotPermitted,
138 #[error("operation is not supported by this object")]
139 OperationNotSupported,
140 #[error("result is out of range")]
141 OutOfRange,
142 #[error("permission denied")]
143 PermissionDenied,
144 #[error("filesystem is read-only")]
145 ReadOnlyFilesystem,
146 #[error("kernel resource is busy")]
147 ResourceBusy,
148 #[error("storage is full")]
149 StorageFull,
150 #[error("operation timed out")]
151 TimedOut,
152 #[error("too many files are open")]
153 TooManyOpenFiles,
154 #[error("unexpected end of input")]
155 UnexpectedEof,
156 #[error("kernel capability is unavailable")]
157 Unsupported,
158 #[error("operation would block")]
159 WouldBlock,
160 #[error("write made no progress")]
161 WriteZero,
162}
163
164impl From<Errno> for StarryError {
165 fn from(errno: Errno) -> Self {
166 Self::Errno(errno)
167 }
168}
169
170impl From<StarryError> for VfsError {
171 fn from(error: StarryError) -> Self {
172 match error {
173 StarryError::Vfs(error) => error,
174 StarryError::BadState => Self::BadState,
175 StarryError::InvalidData => Self::InvalidData,
176 error => vfs_error_from_errno(error.linux_errno()),
177 }
178 }
179}
180
181impl StarryError {
182 pub(crate) const fn is_would_block(&self) -> bool {
189 matches!(
190 self,
191 Self::WouldBlock
192 | Self::Vfs(VfsError::WouldBlock)
193 | Self::IoDomain(IoError::WouldBlock)
194 )
195 }
196
197 pub fn linux_errno(&self) -> Errno {
199 match self {
200 Self::Errno(errno) => *errno,
201 Self::Vm(error) => vm_errno(*error),
202 Self::Signal(SignalError::UserMemory(error)) => vm_errno(*error),
203 Self::Signal(SignalError::NoMemory) => Errno::ENOMEM,
204 Self::Mm(error) => mm_errno(*error),
205 Self::Vfs(error) => vfs_errno(*error),
206 Self::Mapping(error) => mapping_errno(error),
207 Self::Paging(error) => match error {
208 PagingError::NoMemory => Errno::ENOMEM,
209 _ => Errno::EINVAL,
210 },
211 Self::TlbShootdown(error) => tlb_errno(*error),
212 Self::Alloc(error) => alloc_errno(*error),
213 Self::Cgroup(error) => cgroup_errno(*error),
214 Self::IoDomain(error) => io_errno(*error),
215 Self::Net(error) => io_errno((*error).into()),
216 Self::Task(error) => task_errno(*error),
217 Self::Runtime(error) => runtime_errno(error),
218 Self::Block(error) => block_errno(error),
219 Self::Driver(_) => Errno::EIO,
220 #[cfg(feature = "sg2002")]
221 Self::Ion(error) => ion_errno(*error),
222 #[cfg(feature = "sg2002")]
223 Self::Tpu(error) => tpu_errno(*error),
224 Self::Format(_) => Errno::EINVAL,
225 Self::Dma { operation, source } => dma_errno(*operation, source),
226 Self::AlreadyExists => Errno::EEXIST,
227 Self::ArgumentListTooLong => Errno::E2BIG,
228 Self::BadAddress | Self::BadState => Errno::EFAULT,
229 Self::BadFileDescriptor => Errno::EBADF,
230 Self::BrokenPipe => Errno::EPIPE,
231 Self::CrossesDevices => Errno::EXDEV,
232 Self::FilesystemLoop => Errno::ELOOP,
233 Self::IllegalBytes => Errno::EILSEQ,
234 Self::InProgress => Errno::EINPROGRESS,
235 Self::Interrupted | Self::InterruptedNoRestart => Errno::EINTR,
236 Self::InvalidData | Self::InvalidInput => Errno::EINVAL,
237 Self::InvalidExecutable | Self::MalformedExecutable => Errno::ENOEXEC,
238 Self::Io | Self::UnexpectedEof | Self::WriteZero => Errno::EIO,
239 Self::IsADirectory => Errno::EISDIR,
240 Self::NameTooLong => Errno::ENAMETOOLONG,
241 Self::NoMemory => Errno::ENOMEM,
242 Self::NoSuchDevice => Errno::ENODEV,
243 Self::NoSuchDeviceOrAddress => Errno::ENXIO,
244 Self::NoSuchProcess => Errno::ESRCH,
245 Self::NotADirectory => Errno::ENOTDIR,
246 Self::NotASocket => Errno::ENOTSOCK,
247 Self::NotATty => Errno::ENOTTY,
248 Self::NotFound => Errno::ENOENT,
249 Self::OperationNotPermitted => Errno::EPERM,
250 Self::OperationNotSupported => Errno::EOPNOTSUPP,
251 Self::OutOfRange => Errno::ERANGE,
252 Self::PermissionDenied => Errno::EACCES,
253 Self::ReadOnlyFilesystem => Errno::EROFS,
254 Self::ResourceBusy => Errno::EBUSY,
255 Self::StorageFull => Errno::ENOSPC,
256 Self::TimedOut => Errno::ETIMEDOUT,
257 Self::TooManyOpenFiles => Errno::EMFILE,
258 Self::Unsupported => Errno::ENOSYS,
259 Self::WouldBlock => Errno::EAGAIN,
260 }
261 }
262}
263
264fn vm_errno(error: VmError) -> Errno {
265 match error {
266 VmError::BadAddress | VmError::AccessDenied => Errno::EFAULT,
267 VmError::TooLong => Errno::ENAMETOOLONG,
268 }
269}
270
271fn mm_errno(error: MmError) -> Errno {
272 match error {
273 MmError::InvalidInput(_) => Errno::EINVAL,
274 MmError::NoMemory => Errno::ENOMEM,
275 MmError::AlreadyExists => Errno::EEXIST,
276 MmError::BadAddress | MmError::BadState(_) => Errno::EFAULT,
277 MmError::Unsupported => Errno::ENOSYS,
278 MmError::TlbShootdown(error) => tlb_errno(error),
279 }
280}
281
282fn mapping_errno(error: &MappingError) -> Errno {
283 match error {
284 MappingError::InvalidParam => Errno::EINVAL,
285 MappingError::AlreadyExists => Errno::EEXIST,
286 MappingError::BadState | MappingError::NeedsRepair => Errno::EFAULT,
287 }
288}
289
290fn tlb_errno(error: TlbShootdownError) -> Errno {
291 match error {
292 TlbShootdownError::CpuOffline | TlbShootdownError::Unsupported => Errno::ENOSYS,
293 TlbShootdownError::Timeout => Errno::ETIMEDOUT,
294 TlbShootdownError::GenerationExhausted => Errno::EOVERFLOW,
295 TlbShootdownError::Platform => Errno::EIO,
296 }
297}
298
299fn alloc_errno(error: AllocError) -> Errno {
300 match error {
301 AllocError::NoMemory => Errno::ENOMEM,
302 AllocError::NotFound => Errno::ENOENT,
303 AllocError::NotInitialized | AllocError::AlreadyInitialized => Errno::EFAULT,
304 AllocError::MemoryOverlap => Errno::EEXIST,
305 AllocError::InvalidParam | AllocError::NotAllocated => Errno::EINVAL,
306 }
307}
308
309fn cgroup_errno(error: CgroupError) -> Errno {
310 match error {
311 CgroupError::NotInitialized | CgroupError::InvalidInput => Errno::EINVAL,
312 CgroupError::NotFound => Errno::ENOENT,
313 CgroupError::AlreadyExists => Errno::EEXIST,
314 CgroupError::ResourceBusy => Errno::EBUSY,
315 CgroupError::LimitExceeded => Errno::EAGAIN,
316 CgroupError::NoSuchProcess => Errno::ESRCH,
317 CgroupError::DirectoryNotEmpty => Errno::ENOTEMPTY,
318 }
319}
320
321fn task_errno(error: TaskError) -> Errno {
322 match error {
323 TaskError::InvalidConfiguration
324 | TaskError::InvalidCpuCount(_)
325 | TaskError::InvalidCpu(_)
326 | TaskError::InvalidNice(_)
327 | TaskError::InvalidRtPriority(_)
328 | TaskError::InvalidRoundRobinQuantum
329 | TaskError::InvalidDeadline { .. }
330 | TaskError::UnsupportedDeadlineFlags(_) => Errno::EINVAL,
331 TaskError::DeadlineAdmission
332 | TaskError::DeadlineAffinity
333 | TaskError::ActiveTimerAffinity
334 | TaskError::ThreadBusy => Errno::EBUSY,
335 TaskError::StaleThreadId => Errno::ESRCH,
336 TaskError::TimerCapacity => Errno::ENOMEM,
337 TaskError::RuntimeFailure(status)
338 if status == ax_runtime::task::runtime::RuntimeStatus::NoMemory as u32 =>
339 {
340 Errno::ENOMEM
341 }
342 TaskError::UnsafeContext => Errno::EPERM,
343 TaskError::CpuOwnerMismatch { .. }
344 | TaskError::CpuOwnerBorrowed
345 | TaskError::CpuAlreadyOnline(_)
346 | TaskError::CpuOffline(_)
347 | TaskError::CpuNotQuiescent(_)
348 | TaskError::LastOnlineCpu(_)
349 | TaskError::ExecutorOwnerMismatch { .. }
350 | TaskError::InvalidTransition { .. }
351 | TaskError::AlreadyQueued
352 | TaskError::NotReady
353 | TaskError::NotExited
354 | TaskError::NoRunnableThread
355 | TaskError::ThreadCapacity
356 | TaskError::NotInitialized
357 | TaskError::InvalidRuntimeHandle
358 | TaskError::InvalidPiState
359 | TaskError::InvalidPiWaitState(_)
360 | TaskError::PiCycle
361 | TaskError::PiChainLimit { .. }
362 | TaskError::RuntimeFailure(_) => Errno::EFAULT,
363 }
364}
365
366fn vfs_error_from_errno(errno: Errno) -> VfsError {
367 match errno {
368 Errno::EEXIST => VfsError::AlreadyExists,
369 Errno::EFAULT => VfsError::BadAddress,
370 Errno::EBADF => VfsError::BadFileDescriptor,
371 Errno::EXDEV => VfsError::CrossesDevices,
372 Errno::ENODATA => VfsError::DataMissing,
373 Errno::ENOTEMPTY => VfsError::DirectoryNotEmpty,
374 Errno::EUCLEAN => VfsError::FilesystemCorrupted,
375 Errno::ELOOP => VfsError::FilesystemLoop,
376 Errno::EFBIG => VfsError::FileTooLarge,
377 Errno::EINVAL => VfsError::InvalidInput,
378 Errno::EINTR => VfsError::Interrupted,
379 Errno::EIO => VfsError::Io,
380 Errno::EISDIR => VfsError::IsADirectory,
381 Errno::ENAMETOOLONG => VfsError::NameTooLong,
382 Errno::ENOMEM => VfsError::NoMemory,
383 Errno::ENODEV => VfsError::NoSuchDevice,
384 Errno::ENXIO => VfsError::NoSuchDeviceOrAddress,
385 Errno::ENOTDIR => VfsError::NotADirectory,
386 Errno::ENOTTY => VfsError::NotATty,
387 Errno::ENOENT => VfsError::NotFound,
388 Errno::EPERM => VfsError::OperationNotPermitted,
389 Errno::EOPNOTSUPP => VfsError::OperationNotSupported,
390 Errno::EACCES => VfsError::PermissionDenied,
391 Errno::EDQUOT => VfsError::QuotaExceeded,
392 Errno::EROFS => VfsError::ReadOnlyFilesystem,
393 Errno::ETXTBSY => VfsError::TextFileBusy,
394 Errno::EBUSY => VfsError::ResourceBusy,
395 Errno::ENOSPC => VfsError::StorageFull,
396 Errno::ETIMEDOUT => VfsError::TimedOut,
397 Errno::EMLINK => VfsError::TooManyLinks,
398 Errno::ENOSYS => VfsError::Unsupported,
399 Errno::EOVERFLOW => VfsError::ValueOverflow,
400 Errno::EAGAIN => VfsError::WouldBlock,
401 _ => VfsError::Io,
402 }
403}
404
405fn runtime_errno(error: &RuntimeError) -> Errno {
406 match error {
407 RuntimeError::SerialConfig(error) => match error {
408 ConfigError::InvalidBaudrate
409 | ConfigError::UnsupportedDataBits
410 | ConfigError::UnsupportedStopBits
411 | ConfigError::UnsupportedParity => Errno::EINVAL,
412 ConfigError::Timeout => Errno::ETIMEDOUT,
413 ConfigError::RegisterError => Errno::EIO,
414 },
415 RuntimeError::SerialNotStarted => Errno::EFAULT,
416 RuntimeError::SerialControlBusy => Errno::EBUSY,
417 RuntimeError::Task(error) => task_errno(*error),
418 RuntimeError::WouldBlock => Errno::EAGAIN,
419 RuntimeError::OperationNotSupported => Errno::EOPNOTSUPP,
420 RuntimeError::InvalidCpu { .. } => Errno::EINVAL,
421 _ => Errno::EIO,
422 }
423}
424
425fn block_errno(error: &BlockError) -> Errno {
426 match error {
427 BlockError::InvalidRequest => Errno::EINVAL,
428 BlockError::InvalidState | BlockError::RuntimeUnavailable => Errno::EFAULT,
429 BlockError::WouldBlock => Errno::EAGAIN,
430 BlockError::NoMemory => Errno::ENOMEM,
431 BlockError::Unsupported => Errno::ENOSYS,
432 BlockError::TimedOut => Errno::ETIMEDOUT,
433 BlockError::ResourceBusy => Errno::EBUSY,
434 BlockError::NotFound => Errno::ENOENT,
435 BlockError::Io | BlockError::Irq(_) => Errno::EIO,
436 BlockError::Device { source, .. } => block_errno(&BlockError::from(*source)),
437 }
438}
439
440#[cfg(feature = "sg2002")]
441fn ion_errno(error: IonError) -> Errno {
442 match error {
443 IonError::InvalidArg => Errno::EINVAL,
444 IonError::NoMemory => Errno::ENOMEM,
445 IonError::InvalidBuffer | IonError::BufferNotFound => Errno::ENOENT,
446 IonError::BufferExists => Errno::EEXIST,
447 IonError::InvalidHeap | IonError::NotSupported => Errno::ENOSYS,
448 IonError::Internal => Errno::EINTR,
449 }
450}
451
452#[cfg(feature = "sg2002")]
453fn tpu_errno(error: TpuError) -> Errno {
454 match error {
455 TpuError::Timeout => Errno::ETIMEDOUT,
456 TpuError::InvalidDmabuf | TpuError::PmuBufferNotAligned | TpuError::DmabufNotAligned => {
457 Errno::EINVAL
458 }
459 TpuError::TdmaError(_) | TpuError::TiuError(_) => Errno::EIO,
460 TpuError::NotInitialized => Errno::ENODEV,
461 TpuError::Busy => Errno::EBUSY,
462 TpuError::Interrupted => Errno::EINTR,
463 }
464}
465
466fn dma_errno(operation: DmaOperation, source: &DmaError) -> Errno {
467 match operation {
468 DmaOperation::BufferAllocation => match source {
469 DmaError::LayoutError(_) => Errno::EINVAL,
470 _ => Errno::ENOMEM,
471 },
472 DmaOperation::DeviceIo => match source {
473 DmaError::NoMemory => Errno::ENOMEM,
474 DmaError::LayoutError(_) | DmaError::NullPointer | DmaError::ZeroSizedBuffer => {
475 Errno::EINVAL
476 }
477 _ => Errno::EIO,
478 },
479 }
480}
481
482fn io_errno(error: IoError) -> Errno {
483 match error {
484 IoError::AddrInUse => Errno::EADDRINUSE,
485 IoError::AlreadyConnected => Errno::EISCONN,
486 IoError::AddressFamilyUnsupported => Errno::EAFNOSUPPORT,
487 IoError::AlreadyExists => Errno::EEXIST,
488 IoError::ArgumentListTooLong => Errno::E2BIG,
489 IoError::BadAddress | IoError::BadState => Errno::EFAULT,
490 IoError::BadFileDescriptor => Errno::EBADF,
491 IoError::BrokenPipe => Errno::EPIPE,
492 IoError::ConnectionRefused => Errno::ECONNREFUSED,
493 IoError::ConnectionReset => Errno::ECONNRESET,
494 IoError::CrossesDevices => Errno::EXDEV,
495 IoError::DirectoryNotEmpty => Errno::ENOTEMPTY,
496 IoError::DestAddrRequired => Errno::EDESTADDRREQ,
497 IoError::FilesystemLoop => Errno::ELOOP,
498 IoError::FileTooLarge => Errno::EFBIG,
499 IoError::IllegalBytes => Errno::EILSEQ,
500 IoError::InProgress => Errno::EINPROGRESS,
501 IoError::Interrupted => Errno::EINTR,
502 IoError::InvalidData | IoError::InvalidInput => Errno::EINVAL,
503 IoError::InvalidExecutable => Errno::ENOEXEC,
504 IoError::Io | IoError::UnexpectedEof | IoError::WriteZero => Errno::EIO,
505 IoError::IsADirectory => Errno::EISDIR,
506 IoError::MessageTooLong => Errno::EMSGSIZE,
507 IoError::NameTooLong => Errno::ENAMETOOLONG,
508 IoError::NoMemory => Errno::ENOMEM,
509 IoError::NoSuchDevice => Errno::ENODEV,
510 IoError::NoSuchDeviceOrAddress => Errno::ENXIO,
511 IoError::NoSuchProcess => Errno::ESRCH,
512 IoError::NotADirectory => Errno::ENOTDIR,
513 IoError::NotASocket => Errno::ENOTSOCK,
514 IoError::NotATty => Errno::ENOTTY,
515 IoError::NotConnected => Errno::ENOTCONN,
516 IoError::NotFound => Errno::ENOENT,
517 IoError::OperationNotPermitted => Errno::EPERM,
518 IoError::OperationNotSupported => Errno::EOPNOTSUPP,
519 IoError::OutOfRange => Errno::ERANGE,
520 IoError::PermissionDenied => Errno::EACCES,
521 IoError::ProtocolOptionUnsupported => Errno::ENOPROTOOPT,
522 IoError::ReadOnlyFilesystem => Errno::EROFS,
523 IoError::ResourceBusy => Errno::EBUSY,
524 IoError::StorageFull => Errno::ENOSPC,
525 IoError::TimedOut => Errno::ETIMEDOUT,
526 IoError::TooManyOpenFiles => Errno::EMFILE,
527 IoError::Unsupported => Errno::ENOSYS,
528 IoError::WouldBlock => Errno::EAGAIN,
529 }
530}
531
532fn vfs_errno(error: VfsError) -> Errno {
533 match error {
534 VfsError::AlreadyExists => Errno::EEXIST,
535 VfsError::BadAddress | VfsError::BadState => Errno::EFAULT,
536 VfsError::BadFileDescriptor => Errno::EBADF,
537 VfsError::CrossesDevices => Errno::EXDEV,
538 VfsError::DataMissing => Errno::ENODATA,
539 VfsError::DirectoryNotEmpty => Errno::ENOTEMPTY,
540 VfsError::FilesystemCorrupted => Errno::EUCLEAN,
541 VfsError::FilesystemLoop => Errno::ELOOP,
542 VfsError::FileTooLarge => Errno::EFBIG,
543 VfsError::InvalidData | VfsError::InvalidInput => Errno::EINVAL,
544 VfsError::Interrupted => Errno::EINTR,
545 VfsError::Io => Errno::EIO,
546 VfsError::IsADirectory => Errno::EISDIR,
547 VfsError::NameTooLong => Errno::ENAMETOOLONG,
548 VfsError::NoMemory => Errno::ENOMEM,
549 VfsError::NoSuchDevice => Errno::ENODEV,
550 VfsError::NoSuchDeviceOrAddress => Errno::ENXIO,
551 VfsError::NotADirectory => Errno::ENOTDIR,
552 VfsError::NotATty => Errno::ENOTTY,
553 VfsError::NotFound => Errno::ENOENT,
554 VfsError::OperationNotPermitted => Errno::EPERM,
555 VfsError::OperationNotSupported => Errno::EOPNOTSUPP,
556 VfsError::PermissionDenied => Errno::EACCES,
557 VfsError::QuotaExceeded => Errno::EDQUOT,
558 VfsError::ReadOnlyFilesystem => Errno::EROFS,
559 VfsError::TextFileBusy => Errno::ETXTBSY,
560 VfsError::ResourceBusy => Errno::EBUSY,
561 VfsError::StorageFull => Errno::ENOSPC,
562 VfsError::TimedOut => Errno::ETIMEDOUT,
563 VfsError::TooManyLinks => Errno::EMLINK,
564 VfsError::Unsupported => Errno::ENOSYS,
565 VfsError::ValueOverflow => Errno::EOVERFLOW,
566 VfsError::WouldBlock => Errno::EAGAIN,
567 }
568}
569
570#[cfg(all(test, not(axtest)))]
571fn errno_cases_hold<const N: usize>(cases: [(StarryError, Errno); N]) -> bool {
572 cases
573 .into_iter()
574 .all(|(error, expected)| error.linux_errno() == expected)
575}
576
577#[cfg(all(test, not(axtest)))]
578fn memory_errno_mappings_hold() -> bool {
579 errno_cases_hold([
580 (VmError::BadAddress.into(), Errno::EFAULT),
581 (VmError::AccessDenied.into(), Errno::EFAULT),
582 (VmError::TooLong.into(), Errno::ENAMETOOLONG),
583 (
584 SignalError::UserMemory(VmError::BadAddress).into(),
585 Errno::EFAULT,
586 ),
587 (MmError::InvalidInput("test").into(), Errno::EINVAL),
588 (MmError::NoMemory.into(), Errno::ENOMEM),
589 (MmError::AlreadyExists.into(), Errno::EEXIST),
590 (MmError::BadAddress.into(), Errno::EFAULT),
591 (MmError::BadState("test").into(), Errno::EFAULT),
592 (MmError::Unsupported.into(), Errno::ENOSYS),
593 (
594 MmError::TlbShootdown(TlbShootdownError::Timeout).into(),
595 Errno::ETIMEDOUT,
596 ),
597 (MappingError::InvalidParam.into(), Errno::EINVAL),
598 (MappingError::AlreadyExists.into(), Errno::EEXIST),
599 (MappingError::BadState.into(), Errno::EFAULT),
600 (PagingError::NoMemory.into(), Errno::ENOMEM),
601 (PagingError::not_mapped().into(), Errno::EINVAL),
602 (TlbShootdownError::CpuOffline.into(), Errno::ENOSYS),
603 (TlbShootdownError::Timeout.into(), Errno::ETIMEDOUT),
604 (TlbShootdownError::Unsupported.into(), Errno::ENOSYS),
605 (TlbShootdownError::Platform.into(), Errno::EIO),
606 (
607 TlbShootdownError::GenerationExhausted.into(),
608 Errno::EOVERFLOW,
609 ),
610 (AllocError::InvalidParam.into(), Errno::EINVAL),
611 (AllocError::AlreadyInitialized.into(), Errno::EFAULT),
612 (AllocError::MemoryOverlap.into(), Errno::EEXIST),
613 (AllocError::NoMemory.into(), Errno::ENOMEM),
614 (AllocError::NotAllocated.into(), Errno::EINVAL),
615 (AllocError::NotInitialized.into(), Errno::EFAULT),
616 (AllocError::NotFound.into(), Errno::ENOENT),
617 (CgroupError::NotInitialized.into(), Errno::EINVAL),
618 (CgroupError::NotFound.into(), Errno::ENOENT),
619 (CgroupError::AlreadyExists.into(), Errno::EEXIST),
620 (CgroupError::ResourceBusy.into(), Errno::EBUSY),
621 (CgroupError::LimitExceeded.into(), Errno::EAGAIN),
622 (CgroupError::InvalidInput.into(), Errno::EINVAL),
623 (CgroupError::NoSuchProcess.into(), Errno::ESRCH),
624 (CgroupError::DirectoryNotEmpty.into(), Errno::ENOTEMPTY),
625 ])
626}
627
628#[cfg(all(test, not(axtest)))]
629fn vfs_errno_mappings_hold() -> bool {
630 errno_cases_hold([
631 (VfsError::AlreadyExists.into(), Errno::EEXIST),
632 (VfsError::BadAddress.into(), Errno::EFAULT),
633 (VfsError::BadFileDescriptor.into(), Errno::EBADF),
634 (VfsError::BadState.into(), Errno::EFAULT),
635 (VfsError::CrossesDevices.into(), Errno::EXDEV),
636 (VfsError::DataMissing.into(), Errno::ENODATA),
637 (VfsError::DirectoryNotEmpty.into(), Errno::ENOTEMPTY),
638 (VfsError::FilesystemCorrupted.into(), Errno::EUCLEAN),
639 (VfsError::FilesystemLoop.into(), Errno::ELOOP),
640 (VfsError::FileTooLarge.into(), Errno::EFBIG),
641 (VfsError::InvalidData.into(), Errno::EINVAL),
642 (VfsError::InvalidInput.into(), Errno::EINVAL),
643 (VfsError::Interrupted.into(), Errno::EINTR),
644 (VfsError::Io.into(), Errno::EIO),
645 (VfsError::IsADirectory.into(), Errno::EISDIR),
646 (VfsError::NameTooLong.into(), Errno::ENAMETOOLONG),
647 (VfsError::NoMemory.into(), Errno::ENOMEM),
648 (VfsError::NoSuchDevice.into(), Errno::ENODEV),
649 (VfsError::NoSuchDeviceOrAddress.into(), Errno::ENXIO),
650 (VfsError::NotADirectory.into(), Errno::ENOTDIR),
651 (VfsError::NotATty.into(), Errno::ENOTTY),
652 (VfsError::NotFound.into(), Errno::ENOENT),
653 (VfsError::OperationNotPermitted.into(), Errno::EPERM),
654 (VfsError::OperationNotSupported.into(), Errno::EOPNOTSUPP),
655 (VfsError::PermissionDenied.into(), Errno::EACCES),
656 (VfsError::QuotaExceeded.into(), Errno::EDQUOT),
657 (VfsError::ReadOnlyFilesystem.into(), Errno::EROFS),
658 (VfsError::ResourceBusy.into(), Errno::EBUSY),
659 (VfsError::StorageFull.into(), Errno::ENOSPC),
660 (VfsError::TimedOut.into(), Errno::ETIMEDOUT),
661 (VfsError::TooManyLinks.into(), Errno::EMLINK),
662 (VfsError::Unsupported.into(), Errno::ENOSYS),
663 (VfsError::ValueOverflow.into(), Errno::EOVERFLOW),
664 (VfsError::WouldBlock.into(), Errno::EAGAIN),
665 ])
666}
667
668#[cfg(all(test, not(axtest)))]
669fn io_errno_mappings_hold() -> bool {
670 errno_cases_hold([
671 (IoError::AddrInUse.into(), Errno::EADDRINUSE),
672 (IoError::AlreadyConnected.into(), Errno::EISCONN),
673 (
674 IoError::AddressFamilyUnsupported.into(),
675 Errno::EAFNOSUPPORT,
676 ),
677 (IoError::AlreadyExists.into(), Errno::EEXIST),
678 (IoError::ArgumentListTooLong.into(), Errno::E2BIG),
679 (IoError::BadAddress.into(), Errno::EFAULT),
680 (IoError::BadFileDescriptor.into(), Errno::EBADF),
681 (IoError::BadState.into(), Errno::EFAULT),
682 (IoError::BrokenPipe.into(), Errno::EPIPE),
683 (IoError::ConnectionRefused.into(), Errno::ECONNREFUSED),
684 (IoError::ConnectionReset.into(), Errno::ECONNRESET),
685 (IoError::CrossesDevices.into(), Errno::EXDEV),
686 (IoError::DirectoryNotEmpty.into(), Errno::ENOTEMPTY),
687 (IoError::DestAddrRequired.into(), Errno::EDESTADDRREQ),
688 (IoError::FilesystemLoop.into(), Errno::ELOOP),
689 (IoError::FileTooLarge.into(), Errno::EFBIG),
690 (IoError::IllegalBytes.into(), Errno::EILSEQ),
691 (IoError::InProgress.into(), Errno::EINPROGRESS),
692 (IoError::Interrupted.into(), Errno::EINTR),
693 (IoError::InvalidData.into(), Errno::EINVAL),
694 (IoError::InvalidExecutable.into(), Errno::ENOEXEC),
695 (IoError::InvalidInput.into(), Errno::EINVAL),
696 (IoError::Io.into(), Errno::EIO),
697 (IoError::IsADirectory.into(), Errno::EISDIR),
698 (IoError::NameTooLong.into(), Errno::ENAMETOOLONG),
699 (IoError::MessageTooLong.into(), Errno::EMSGSIZE),
700 (IoError::NoMemory.into(), Errno::ENOMEM),
701 (IoError::NoSuchDevice.into(), Errno::ENODEV),
702 (IoError::NoSuchDeviceOrAddress.into(), Errno::ENXIO),
703 (IoError::NoSuchProcess.into(), Errno::ESRCH),
704 (IoError::NotADirectory.into(), Errno::ENOTDIR),
705 (IoError::NotASocket.into(), Errno::ENOTSOCK),
706 (IoError::NotATty.into(), Errno::ENOTTY),
707 (IoError::NotConnected.into(), Errno::ENOTCONN),
708 (IoError::NotFound.into(), Errno::ENOENT),
709 (IoError::OperationNotPermitted.into(), Errno::EPERM),
710 (IoError::OperationNotSupported.into(), Errno::EOPNOTSUPP),
711 (IoError::OutOfRange.into(), Errno::ERANGE),
712 (IoError::PermissionDenied.into(), Errno::EACCES),
713 (
714 IoError::ProtocolOptionUnsupported.into(),
715 Errno::ENOPROTOOPT,
716 ),
717 (IoError::ReadOnlyFilesystem.into(), Errno::EROFS),
718 (IoError::ResourceBusy.into(), Errno::EBUSY),
719 (IoError::StorageFull.into(), Errno::ENOSPC),
720 (IoError::TimedOut.into(), Errno::ETIMEDOUT),
721 (IoError::TooManyOpenFiles.into(), Errno::EMFILE),
722 (IoError::UnexpectedEof.into(), Errno::EIO),
723 (IoError::Unsupported.into(), Errno::ENOSYS),
724 (IoError::WouldBlock.into(), Errno::EAGAIN),
725 (IoError::WriteZero.into(), Errno::EIO),
726 ])
727}
728
729#[cfg(all(test, not(axtest)))]
730fn block_errno_mappings_hold() -> bool {
731 let device_error = |source| {
732 StarryError::from(BlockError::Device {
733 stage: "submit",
734 operation: RequestOp::Read,
735 lba: 9,
736 source,
737 })
738 };
739
740 errno_cases_hold([
741 (BlockError::InvalidRequest.into(), Errno::EINVAL),
742 (BlockError::InvalidState.into(), Errno::EFAULT),
743 (BlockError::RuntimeUnavailable.into(), Errno::EFAULT),
744 (BlockError::WouldBlock.into(), Errno::EAGAIN),
745 (BlockError::NoMemory.into(), Errno::ENOMEM),
746 (BlockError::Unsupported.into(), Errno::ENOSYS),
747 (BlockError::TimedOut.into(), Errno::ETIMEDOUT),
748 (BlockError::Io.into(), Errno::EIO),
749 (BlockError::ResourceBusy.into(), Errno::EBUSY),
750 (BlockError::NotFound.into(), Errno::ENOENT),
751 (device_error(BlkError::NotSupported), Errno::ENOSYS),
752 (device_error(BlkError::Retry), Errno::EAGAIN),
753 (device_error(BlkError::NoMemory), Errno::ENOMEM),
754 (device_error(BlkError::InvalidBlockIndex(9)), Errno::EINVAL),
755 (device_error(BlkError::InvalidRequest), Errno::EINVAL),
756 (device_error(BlkError::TimedOut), Errno::ETIMEDOUT),
757 (device_error(BlkError::Io), Errno::EIO),
758 (device_error(BlkError::Other("device failure")), Errno::EIO),
759 ])
760}
761
762#[cfg(all(test, not(axtest)))]
763fn leaf_errno_mappings_hold() -> bool {
764 errno_cases_hold([
765 (StarryError::AlreadyExists, Errno::EEXIST),
766 (StarryError::ArgumentListTooLong, Errno::E2BIG),
767 (StarryError::BadAddress, Errno::EFAULT),
768 (StarryError::BadFileDescriptor, Errno::EBADF),
769 (StarryError::BadState, Errno::EFAULT),
770 (StarryError::BrokenPipe, Errno::EPIPE),
771 (StarryError::CrossesDevices, Errno::EXDEV),
772 (StarryError::FilesystemLoop, Errno::ELOOP),
773 (StarryError::IllegalBytes, Errno::EILSEQ),
774 (StarryError::InProgress, Errno::EINPROGRESS),
775 (StarryError::Interrupted, Errno::EINTR),
776 (StarryError::InterruptedNoRestart, Errno::EINTR),
777 (StarryError::InvalidData, Errno::EINVAL),
778 (StarryError::InvalidExecutable, Errno::ENOEXEC),
779 (StarryError::MalformedExecutable, Errno::ENOEXEC),
780 (StarryError::InvalidInput, Errno::EINVAL),
781 (StarryError::Io, Errno::EIO),
782 (StarryError::IsADirectory, Errno::EISDIR),
783 (StarryError::NameTooLong, Errno::ENAMETOOLONG),
784 (StarryError::NoMemory, Errno::ENOMEM),
785 (StarryError::NoSuchDevice, Errno::ENODEV),
786 (StarryError::NoSuchDeviceOrAddress, Errno::ENXIO),
787 (StarryError::NoSuchProcess, Errno::ESRCH),
788 (StarryError::NotADirectory, Errno::ENOTDIR),
789 (StarryError::NotASocket, Errno::ENOTSOCK),
790 (StarryError::NotATty, Errno::ENOTTY),
791 (StarryError::NotFound, Errno::ENOENT),
792 (StarryError::OperationNotPermitted, Errno::EPERM),
793 (StarryError::OperationNotSupported, Errno::EOPNOTSUPP),
794 (StarryError::OutOfRange, Errno::ERANGE),
795 (StarryError::PermissionDenied, Errno::EACCES),
796 (StarryError::ReadOnlyFilesystem, Errno::EROFS),
797 (StarryError::ResourceBusy, Errno::EBUSY),
798 (StarryError::StorageFull, Errno::ENOSPC),
799 (StarryError::TimedOut, Errno::ETIMEDOUT),
800 (StarryError::TooManyOpenFiles, Errno::EMFILE),
801 (StarryError::UnexpectedEof, Errno::EIO),
802 (StarryError::Unsupported, Errno::ENOSYS),
803 (StarryError::WouldBlock, Errno::EAGAIN),
804 (StarryError::WriteZero, Errno::EIO),
805 (StarryError::Format(core::fmt::Error), Errno::EINVAL),
806 (StarryError::Task(TaskError::TimerCapacity), Errno::ENOMEM),
807 (
808 StarryError::Runtime(RuntimeError::SerialNotStarted),
809 Errno::EFAULT,
810 ),
811 (
812 StarryError::Runtime(RuntimeError::SerialControlBusy),
813 Errno::EBUSY,
814 ),
815 (
816 StarryError::Runtime(RuntimeError::Task(TaskError::UnsafeContext)),
817 Errno::EPERM,
818 ),
819 (
820 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::InvalidBaudrate)),
821 Errno::EINVAL,
822 ),
823 (
824 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::UnsupportedDataBits)),
825 Errno::EINVAL,
826 ),
827 (
828 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::UnsupportedStopBits)),
829 Errno::EINVAL,
830 ),
831 (
832 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::UnsupportedParity)),
833 Errno::EINVAL,
834 ),
835 (
836 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::Timeout)),
837 Errno::ETIMEDOUT,
838 ),
839 (
840 StarryError::Runtime(RuntimeError::SerialConfig(ConfigError::RegisterError)),
841 Errno::EIO,
842 ),
843 (
844 StarryError::Runtime(RuntimeError::WouldBlock),
845 Errno::EAGAIN,
846 ),
847 (
848 StarryError::Runtime(RuntimeError::OperationNotSupported),
849 Errno::EOPNOTSUPP,
850 ),
851 (
852 StarryError::Runtime(RuntimeError::InvalidCpu { cpu: 99 }),
853 Errno::EINVAL,
854 ),
855 (
856 StarryError::Dma {
857 operation: DmaOperation::BufferAllocation,
858 source: DmaError::NoMemory,
859 },
860 Errno::ENOMEM,
861 ),
862 (
863 StarryError::Dma {
864 operation: DmaOperation::DeviceIo,
865 source: DmaError::NullPointer,
866 },
867 Errno::EINVAL,
868 ),
869 ])
870}
871
872#[cfg(all(test, not(axtest)))]
873fn domain_errno_mappings_hold() -> bool {
874 memory_errno_mappings_hold()
875 && vfs_errno_mappings_hold()
876 && io_errno_mappings_hold()
877 && block_errno_mappings_hold()
878 && leaf_errno_mappings_hold()
879 && StarryError::from(Errno::EOWNERDEAD).linux_errno() == Errno::EOWNERDEAD
880 && StarryError::from(Errno::new(4094)).linux_errno().into_raw() == 4094
881}
882
883pub type StarryResult<T = ()> = Result<T, StarryError>;
885
886#[cfg(all(test, not(axtest)))]
887mod tests {
888 use super::*;
889
890 #[test]
891 fn domain_errors_map_to_stable_linux_errno() {
892 assert!(domain_errno_mappings_hold());
893 }
894
895 #[test]
896 fn readiness_retry_recognizes_filesystem_would_block_without_flattening() {
897 assert!(StarryError::WouldBlock.is_would_block());
898 assert!(StarryError::from(VfsError::WouldBlock).is_would_block());
899 assert!(StarryError::from(IoError::WouldBlock).is_would_block());
900 assert!(!StarryError::from(VfsError::Io).is_would_block());
901 assert!(!StarryError::from(IoError::Io).is_would_block());
902 }
903
904 #[test]
905 fn native_linux_errno_is_not_canonicalized() {
906 let error = StarryError::from(Errno::EOWNERDEAD);
907 assert_eq!(error.linux_errno(), Errno::EOWNERDEAD);
908 }
909
910 #[test]
911 fn unknown_linux_errno_is_preserved() {
912 let error = StarryError::from(Errno::new(4094));
913 assert_eq!(error.linux_errno().into_raw(), 4094);
914 }
915
916 #[cfg(feature = "sg2002")]
917 #[test]
918 fn sg2002_tpu_errors_keep_their_linux_errno() {
919 let cases = [
920 (TpuError::Timeout, Errno::ETIMEDOUT),
921 (TpuError::InvalidDmabuf, Errno::EINVAL),
922 (TpuError::TdmaError(1), Errno::EIO),
923 (TpuError::TiuError(1), Errno::EIO),
924 (TpuError::NotInitialized, Errno::ENODEV),
925 (TpuError::Busy, Errno::EBUSY),
926 (TpuError::Interrupted, Errno::EINTR),
927 (TpuError::PmuBufferNotAligned, Errno::EINVAL),
928 (TpuError::DmabufNotAligned, Errno::EINVAL),
929 ];
930 for (error, expected) in cases {
931 assert_eq!(StarryError::from(error).linux_errno(), expected);
932 }
933 }
934}