about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
Diffstat (limited to 'library/std')
-rw-r--r--library/std/Cargo.toml12
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/lib.rs5
-rw-r--r--library/std/src/net/socket_addr.rs43
-rw-r--r--library/std/src/num/f128.rs16
-rw-r--r--library/std/src/num/f16.rs16
-rw-r--r--library/std/src/num/f32.rs19
-rw-r--r--library/std/src/num/f64.rs19
-rw-r--r--library/std/src/os/darwin/mod.rs2
-rw-r--r--library/std/src/os/darwin/objc.rs13
-rw-r--r--library/std/src/os/unix/process.rs2
-rw-r--r--library/std/src/os/windows/ffi.rs2
-rw-r--r--library/std/src/panic.rs2
-rw-r--r--library/std/src/panicking.rs26
-rw-r--r--library/std/src/path.rs36
-rw-r--r--library/std/src/process.rs29
-rw-r--r--library/std/src/process/tests.rs102
-rw-r--r--library/std/src/rt.rs6
-rw-r--r--library/std/src/sync/nonpoison/mutex.rs2
-rw-r--r--library/std/src/sync/nonpoison/rwlock.rs2
-rw-r--r--library/std/src/sync/poison/mutex.rs2
-rw-r--r--library/std/src/sync/poison/rwlock.rs2
-rw-r--r--library/std/src/sync/reentrant_lock.rs2
-rw-r--r--library/std/src/sys/alloc/mod.rs3
-rw-r--r--library/std/src/sys/alloc/vexos.rs96
-rw-r--r--library/std/src/sys/args/zkvm.rs103
-rw-r--r--library/std/src/sys/env_consts.rs13
-rw-r--r--library/std/src/sys/fs/mod.rs4
-rw-r--r--library/std/src/sys/fs/unix.rs120
-rw-r--r--library/std/src/sys/fs/vexos.rs615
-rw-r--r--library/std/src/sys/fs/wasi.rs9
-rw-r--r--library/std/src/sys/net/connection/sgx.rs29
-rw-r--r--library/std/src/sys/net/connection/socket/mod.rs58
-rw-r--r--library/std/src/sys/net/connection/socket/tests.rs2
-rw-r--r--library/std/src/sys/net/connection/uefi/mod.rs22
-rw-r--r--library/std/src/sys/net/connection/unsupported.rs22
-rw-r--r--library/std/src/sys/net/connection/wasip1.rs22
-rw-r--r--library/std/src/sys/net/connection/xous/dns.rs45
-rw-r--r--library/std/src/sys/net/connection/xous/mod.rs2
-rw-r--r--library/std/src/sys/pal/hermit/time.rs11
-rw-r--r--library/std/src/sys/pal/mod.rs4
-rw-r--r--library/std/src/sys/pal/trusty/mod.rs2
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs4
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs2
-rw-r--r--library/std/src/sys/pal/unix/time.rs27
-rw-r--r--library/std/src/sys/pal/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/pal/vexos/mod.rs80
-rw-r--r--library/std/src/sys/pal/vexos/time.rs28
-rw-r--r--library/std/src/sys/pal/zkvm/mod.rs2
-rw-r--r--library/std/src/sys/process/mod.rs2
-rw-r--r--library/std/src/sys/process/uefi.rs9
-rw-r--r--library/std/src/sys/process/unix/common.rs9
-rw-r--r--library/std/src/sys/process/unix/fuchsia.rs1
-rw-r--r--library/std/src/sys/process/unix/mod.rs2
-rw-r--r--library/std/src/sys/process/unix/unix.rs1
-rw-r--r--library/std/src/sys/process/unix/unix/tests.rs1
-rw-r--r--library/std/src/sys/process/unix/unsupported.rs1
-rw-r--r--library/std/src/sys/process/unix/vxworks.rs4
-rw-r--r--library/std/src/sys/process/unsupported.rs9
-rw-r--r--library/std/src/sys/process/windows.rs7
-rw-r--r--library/std/src/sys/random/mod.rs2
-rw-r--r--library/std/src/sys/stdio/mod.rs4
-rw-r--r--library/std/src/sys/stdio/vexos.rs100
-rw-r--r--library/std/src/sys/thread/mod.rs7
-rw-r--r--library/std/src/sys/thread/vexos.rs17
-rw-r--r--library/std/src/sys/thread_local/mod.rs2
-rw-r--r--library/std/src/thread/local.rs2
-rw-r--r--library/std/tests/path.rs16
-rw-r--r--library/std/tests/process_spawning.rs1
-rw-r--r--library/std/tests/time.rs16
73 files changed, 1433 insertions, 473 deletions
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index d28a7f0b460..888914a2f77 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -62,7 +62,7 @@ path = "../windows_targets"
 rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
 rand_xorshift = "0.4.0"
 
-[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
+[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
@@ -89,6 +89,11 @@ wasip2 = { version = '0.14.4', features = [
 r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] }
 r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] }
 
+[target.'cfg(target_os = "vexos")'.dependencies]
+vex-sdk = { version = "0.27.0", features = [
+    'rustc-dep-of-std',
+], default-features = false }
+
 [features]
 backtrace = [
     'addr2line/rustc-dep-of-std',
@@ -106,11 +111,6 @@ compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
 
-# Make panics and failed asserts immediately abort without formatting any message
-panic_immediate_abort = [
-    "core/panic_immediate_abort",
-    "alloc/panic_immediate_abort",
-]
 # Choose algorithms that are optimized for binary size instead of runtime performance
 optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
 
diff --git a/library/std/build.rs b/library/std/build.rs
index ef695601a44..8a5a785060c 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -52,6 +52,7 @@ fn main() {
         || target_os == "rtems"
         || target_os == "nuttx"
         || target_os == "cygwin"
+        || target_os == "vexos"
 
         // See src/bootstrap/src/core/build_steps/synthetic_targets.rs
         || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index e457cd61c75..6d716bd8544 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -1098,6 +1098,7 @@ pub mod consts {
     /// * `"redox"`
     /// * `"solaris"`
     /// * `"solid_asp3`
+    /// * `"vexos"`
     /// * `"vita"`
     /// * `"vxworks"`
     /// * `"xous"`
@@ -1148,6 +1149,7 @@ pub mod consts {
     ///
     /// <details><summary>Full list of possible values</summary>
     ///
+    /// * `"bin"`
     /// * `"exe"`
     /// * `"efi"`
     /// * `"js"`
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index a39565d2159..6c098034eea 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -137,7 +137,7 @@ impl OsString {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
-    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]
     pub const fn new() -> OsString {
         OsString { inner: Buf::from_string(String::new()) }
     }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index ff0e29e04c2..a45edd08e8c 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1081,7 +1081,7 @@ pub trait Read {
         default_read_buf_exact(self, cursor)
     }
 
-    /// Creates a "by reference" adaptor for this instance of `Read`.
+    /// Creates a "by reference" adapter for this instance of `Read`.
     ///
     /// The returned adapter also implements `Read` and will simply borrow this
     /// current reader.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 33e3bf0c085..61b7d170b8b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -235,7 +235,7 @@
     test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
 )]
 #![doc(rust_logo)]
-#![doc(cfg_hide(not(test), no_global_oom_handling, not(no_global_oom_handling)))]
+#![doc(auto_cfg(hide(no_global_oom_handling)))]
 // Don't link to std. We are std.
 #![no_std]
 // Tell the compiler to link to either panic_abort or panic_unwind
@@ -285,7 +285,6 @@
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
 #![feature(doc_cfg)]
-#![feature(doc_cfg_hide)]
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
 #![feature(dropck_eyepatch)]
@@ -332,6 +331,7 @@
 #![feature(char_internals)]
 #![feature(clone_to_uninit)]
 #![feature(const_convert)]
+#![feature(const_mul_add)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
 #![feature(drop_guard)]
@@ -381,7 +381,6 @@
 #![feature(allocator_api)]
 #![feature(get_mut_unchecked)]
 #![feature(map_try_insert)]
-#![feature(new_zeroed_alloc)]
 #![feature(slice_concat_trait)]
 #![feature(thin_box)]
 #![feature(try_reserve_kind)]
diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs
index 41e623e79ce..8214ad381f1 100644
--- a/library/std/src/net/socket_addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -6,7 +6,6 @@ mod tests;
 pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
 
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-use crate::sys::net::LookupHost;
 use crate::{io, iter, option, slice, vec};
 
 /// A trait for objects which can be converted or resolved to one or more
@@ -29,6 +28,8 @@ use crate::{io, iter, option, slice, vec};
 ///    [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
 ///    `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
 ///
+///  * <code>&[[SocketAddr]]</code>: all [`SocketAddr`] values in the slice will be used.
+///
 /// This trait allows constructing network objects like [`TcpStream`] or
 /// [`UdpSocket`] easily with values of various types for the bind/connection
 /// address. It is needed because sometimes one type is more appropriate than
@@ -188,15 +189,9 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
     }
 }
 
-fn resolve_socket_addr(lh: LookupHost) -> io::Result<vec::IntoIter<SocketAddr>> {
-    let p = lh.port();
-    let v: Vec<_> = lh
-        .map(|mut a| {
-            a.set_port(p);
-            a
-        })
-        .collect();
-    Ok(v.into_iter())
+fn lookup_host(host: &str, port: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
+    let addrs = crate::sys::net::lookup_host(host, port)?;
+    Ok(Vec::from_iter(addrs).into_iter())
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -205,17 +200,14 @@ impl ToSocketAddrs for (&str, u16) {
     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
         let (host, port) = *self;
 
-        // try to parse the host as a regular IP address first
-        if let Ok(addr) = host.parse::<Ipv4Addr>() {
-            let addr = SocketAddrV4::new(addr, port);
-            return Ok(vec![SocketAddr::V4(addr)].into_iter());
-        }
-        if let Ok(addr) = host.parse::<Ipv6Addr>() {
-            let addr = SocketAddrV6::new(addr, port, 0, 0);
-            return Ok(vec![SocketAddr::V6(addr)].into_iter());
+        // Try to parse the host as a regular IP address first
+        if let Ok(addr) = host.parse::<IpAddr>() {
+            let addr = SocketAddr::new(addr, port);
+            return Ok(vec![addr].into_iter());
         }
 
-        resolve_socket_addr((host, port).try_into()?)
+        // Otherwise, make the system look it up.
+        lookup_host(host, port)
     }
 }
 
@@ -232,12 +224,21 @@ impl ToSocketAddrs for (String, u16) {
 impl ToSocketAddrs for str {
     type Iter = vec::IntoIter<SocketAddr>;
     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
-        // try to parse as a regular SocketAddr first
+        // Try to parse as a regular SocketAddr first
         if let Ok(addr) = self.parse() {
             return Ok(vec![addr].into_iter());
         }
 
-        resolve_socket_addr(self.try_into()?)
+        // Otherwise, split the string by ':' and convert the second part to u16...
+        let Some((host, port_str)) = self.rsplit_once(':') else {
+            return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid socket address"));
+        };
+        let Ok(port) = port_str.parse::<u16>() else {
+            return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid port value"));
+        };
+
+        // ... and make the system look up the host.
+        lookup_host(host, port)
     }
 }
 
diff --git a/library/std/src/num/f128.rs b/library/std/src/num/f128.rs
index b83692390b6..5d206c4b7da 100644
--- a/library/std/src/num/f128.rs
+++ b/library/std/src/num/f128.rs
@@ -44,7 +44,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn powf(self, n: f128) -> f128 {
-        unsafe { intrinsics::powf128(self, n) }
+        intrinsics::powf128(self, n)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -76,7 +76,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn exp(self) -> f128 {
-        unsafe { intrinsics::expf128(self) }
+        intrinsics::expf128(self)
     }
 
     /// Returns `2^(self)`.
@@ -106,7 +106,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn exp2(self) -> f128 {
-        unsafe { intrinsics::exp2f128(self) }
+        intrinsics::exp2f128(self)
     }
 
     /// Returns the natural logarithm of the number.
@@ -151,7 +151,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn ln(self) -> f128 {
-        unsafe { intrinsics::logf128(self) }
+        intrinsics::logf128(self)
     }
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
@@ -241,7 +241,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn log2(self) -> f128 {
-        unsafe { intrinsics::log2f128(self) }
+        intrinsics::log2f128(self)
     }
 
     /// Returns the base 10 logarithm of the number.
@@ -284,7 +284,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn log10(self) -> f128 {
-        unsafe { intrinsics::log10f128(self) }
+        intrinsics::log10f128(self)
     }
 
     /// Returns the cube root of a number.
@@ -385,7 +385,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn sin(self) -> f128 {
-        unsafe { intrinsics::sinf128(self) }
+        intrinsics::sinf128(self)
     }
 
     /// Computes the cosine of a number (in radians).
@@ -414,7 +414,7 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn cos(self) -> f128 {
-        unsafe { intrinsics::cosf128(self) }
+        intrinsics::cosf128(self)
     }
 
     /// Computes the tangent of a number (in radians).
diff --git a/library/std/src/num/f16.rs b/library/std/src/num/f16.rs
index 5599528717c..2565ef0f9f2 100644
--- a/library/std/src/num/f16.rs
+++ b/library/std/src/num/f16.rs
@@ -44,7 +44,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn powf(self, n: f16) -> f16 {
-        unsafe { intrinsics::powf16(self, n) }
+        intrinsics::powf16(self, n)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -76,7 +76,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn exp(self) -> f16 {
-        unsafe { intrinsics::expf16(self) }
+        intrinsics::expf16(self)
     }
 
     /// Returns `2^(self)`.
@@ -106,7 +106,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn exp2(self) -> f16 {
-        unsafe { intrinsics::exp2f16(self) }
+        intrinsics::exp2f16(self)
     }
 
     /// Returns the natural logarithm of the number.
@@ -151,7 +151,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn ln(self) -> f16 {
-        unsafe { intrinsics::logf16(self) }
+        intrinsics::logf16(self)
     }
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
@@ -241,7 +241,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn log2(self) -> f16 {
-        unsafe { intrinsics::log2f16(self) }
+        intrinsics::log2f16(self)
     }
 
     /// Returns the base 10 logarithm of the number.
@@ -284,7 +284,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn log10(self) -> f16 {
-        unsafe { intrinsics::log10f16(self) }
+        intrinsics::log10f16(self)
     }
 
     /// Compute the distance between the origin and a point (`x`, `y`) on the
@@ -350,7 +350,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn sin(self) -> f16 {
-        unsafe { intrinsics::sinf16(self) }
+        intrinsics::sinf16(self)
     }
 
     /// Computes the cosine of a number (in radians).
@@ -379,7 +379,7 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn cos(self) -> f16 {
-        unsafe { intrinsics::cosf16(self) }
+        intrinsics::cosf16(self)
     }
 
     /// Computes the tangent of a number (in radians).
diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs
index 0247080a8d6..e7810e77e76 100644
--- a/library/std/src/num/f32.rs
+++ b/library/std/src/num/f32.rs
@@ -217,7 +217,8 @@ impl f32 {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn mul_add(self, a: f32, b: f32) -> f32 {
+    #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")]
+    pub const fn mul_add(self, a: f32, b: f32) -> f32 {
         core::f32::math::mul_add(self, a, b)
     }
 
@@ -338,7 +339,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powf(self, n: f32) -> f32 {
-        unsafe { intrinsics::powf32(self, n) }
+        intrinsics::powf32(self, n)
     }
 
     /// Returns the square root of a number.
@@ -395,7 +396,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn exp(self) -> f32 {
-        unsafe { intrinsics::expf32(self) }
+        intrinsics::expf32(self)
     }
 
     /// Returns `2^(self)`.
@@ -420,7 +421,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn exp2(self) -> f32 {
-        unsafe { intrinsics::exp2f32(self) }
+        intrinsics::exp2f32(self)
     }
 
     /// Returns the natural logarithm of the number.
@@ -455,7 +456,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ln(self) -> f32 {
-        unsafe { intrinsics::logf32(self) }
+        intrinsics::logf32(self)
     }
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
@@ -525,7 +526,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn log2(self) -> f32 {
-        unsafe { intrinsics::log2f32(self) }
+        intrinsics::log2f32(self)
     }
 
     /// Returns the base 10 logarithm of the number.
@@ -558,7 +559,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn log10(self) -> f32 {
-        unsafe { intrinsics::log10f32(self) }
+        intrinsics::log10f32(self)
     }
 
     /// The positive difference of two numbers.
@@ -683,7 +684,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sin(self) -> f32 {
-        unsafe { intrinsics::sinf32(self) }
+        intrinsics::sinf32(self)
     }
 
     /// Computes the cosine of a number (in radians).
@@ -707,7 +708,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cos(self) -> f32 {
-        unsafe { intrinsics::cosf32(self) }
+        intrinsics::cosf32(self)
     }
 
     /// Computes the tangent of a number (in radians).
diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs
index 1cfd3909d96..cbebbfb1be1 100644
--- a/library/std/src/num/f64.rs
+++ b/library/std/src/num/f64.rs
@@ -217,7 +217,8 @@ impl f64 {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn mul_add(self, a: f64, b: f64) -> f64 {
+    #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")]
+    pub const fn mul_add(self, a: f64, b: f64) -> f64 {
         core::f64::math::mul_add(self, a, b)
     }
 
@@ -338,7 +339,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powf(self, n: f64) -> f64 {
-        unsafe { intrinsics::powf64(self, n) }
+        intrinsics::powf64(self, n)
     }
 
     /// Returns the square root of a number.
@@ -395,7 +396,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn exp(self) -> f64 {
-        unsafe { intrinsics::expf64(self) }
+        intrinsics::expf64(self)
     }
 
     /// Returns `2^(self)`.
@@ -420,7 +421,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn exp2(self) -> f64 {
-        unsafe { intrinsics::exp2f64(self) }
+        intrinsics::exp2f64(self)
     }
 
     /// Returns the natural logarithm of the number.
@@ -455,7 +456,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ln(self) -> f64 {
-        unsafe { intrinsics::logf64(self) }
+        intrinsics::logf64(self)
     }
 
     /// Returns the logarithm of the number with respect to an arbitrary base.
@@ -525,7 +526,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn log2(self) -> f64 {
-        unsafe { intrinsics::log2f64(self) }
+        intrinsics::log2f64(self)
     }
 
     /// Returns the base 10 logarithm of the number.
@@ -558,7 +559,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn log10(self) -> f64 {
-        unsafe { intrinsics::log10f64(self) }
+        intrinsics::log10f64(self)
     }
 
     /// The positive difference of two numbers.
@@ -683,7 +684,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sin(self) -> f64 {
-        unsafe { intrinsics::sinf64(self) }
+        intrinsics::sinf64(self)
     }
 
     /// Computes the cosine of a number (in radians).
@@ -707,7 +708,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cos(self) -> f64 {
-        unsafe { intrinsics::cosf64(self) }
+        intrinsics::cosf64(self)
     }
 
     /// Computes the tangent of a number (in radians).
diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs
index 3b1bd974fa3..ff184f477fb 100644
--- a/library/std/src/os/darwin/mod.rs
+++ b/library/std/src/os/darwin/mod.rs
@@ -17,6 +17,8 @@
 #![doc(cfg(target_vendor = "apple"))]
 
 pub mod fs;
+pub mod objc;
+
 // deprecated, but used for public reexport under `std::os::unix::raw`, as
 // well as `std::os::macos`/`std::os::ios`, because those modules precede the
 // decision to remove these.
diff --git a/library/std/src/os/darwin/objc.rs b/library/std/src/os/darwin/objc.rs
new file mode 100644
index 00000000000..a4b31fee7c5
--- /dev/null
+++ b/library/std/src/os/darwin/objc.rs
@@ -0,0 +1,13 @@
+//! Defines types and macros for Objective-C interoperability.
+//!
+//! This module re-exports all the items in [`core::os::darwin::objc`].
+//!
+//! [`core::os::darwin::objc`]: ../../../../core/os/darwin/objc/index.html "mod core::os::darwin::objc"
+
+#![unstable(feature = "darwin_objc", issue = "145496")]
+
+// We can't generate an intra-doc link for this automatically since `core::os::darwin` isn't
+// compiled into `core` on every platform even though it's documented on every platform.
+// We just link to it directly in the module documentation above instead.
+#[cfg(not(doc))]
+pub use core::os::darwin::objc::*;
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 09429af06e3..5b7b5a8ea80 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -406,8 +406,10 @@ pub trait ChildExt: Sealed {
     /// use libc::SIGTERM;
     ///
     /// fn main() -> io::Result<()> {
+    ///     # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
     ///     let child = Command::new("cat").stdin(Stdio::piped()).spawn()?;
     ///     child.send_signal(SIGTERM)?;
+    ///     # }
     ///     Ok(())
     /// }
     /// ```
diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs
index 345d5b74285..20e5383dc09 100644
--- a/library/std/src/os/windows/ffi.rs
+++ b/library/std/src/os/windows/ffi.rs
@@ -141,7 +141,7 @@ impl OsStrExt for OsStr {
 pub struct EncodeWide<'a> {
     inner: alloc::wtf8::EncodeWide<'a>,
 }
-#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "encode_wide_debug", since = "1.91.0")]
 impl fmt::Debug for EncodeWide<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner, f)
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 5e8d2f8e78e..1997785885d 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -122,7 +122,7 @@ impl<'a> PanicHookInfo<'a> {
     /// ```
     #[must_use]
     #[inline]
-    #[stable(feature = "panic_payload_as_str", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "panic_payload_as_str", since = "1.91.0")]
     pub fn payload_as_str(&self) -> Option<&str> {
         if let Some(s) = self.payload.downcast_ref::<&str>() {
             Some(s)
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 8b7282c51d1..b7be869c4eb 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -331,7 +331,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 #[unstable(feature = "update_panic_count", issue = "none")]
 pub mod panic_count {
     /// A reason for forcing an immediate abort on panic.
@@ -371,7 +371,7 @@ pub mod panic_count {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 #[unstable(feature = "update_panic_count", issue = "none")]
 pub mod panic_count {
     use crate::cell::Cell;
@@ -499,13 +499,13 @@ pub mod panic_count {
 pub use realstd::rt::panic_count;
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     Ok(f())
 }
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     union Data<F, R> {
         f: ManuallyDrop<F>,
@@ -720,14 +720,14 @@ pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
 #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
 #[cfg_attr(not(any(test, doctest)), lang = "begin_panic")]
 // lang item for CTFE panic support
-// never inline unless panic_immediate_abort to avoid code
+// never inline unless panic=immediate-abort to avoid code
 // bloat at the call sites as much as possible
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[rustc_do_not_const_check] // hooked by const-eval
 pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         intrinsics::abort()
     }
 
@@ -861,7 +861,7 @@ fn panic_with_hook(
 
 /// This is the entry point for `resume_unwind`.
 /// It just forwards the payload to the panic runtime.
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
     panic_count::increase(false);
 
@@ -890,16 +890,14 @@ pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
 /// on which to slap yer breakpoints.
 #[inline(never)]
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
     let code = unsafe { __rust_start_panic(msg) };
     rtabort!("failed to initiate panic, error {code}")
 }
 
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 fn rust_panic(_: &mut dyn PanicPayload) -> ! {
-    unsafe {
-        crate::intrinsics::abort();
-    }
+    crate::intrinsics::abort();
 }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 70ba502d684..718c7c2e3b1 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1191,7 +1191,7 @@ impl PathBuf {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
-    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]
     pub const fn new() -> PathBuf {
         PathBuf { inner: OsString::new() }
     }
@@ -1594,7 +1594,7 @@ impl PathBuf {
     /// p.add_extension("");
     /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());
     /// ```
-    #[stable(feature = "path_add_extension", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "path_add_extension", since = "1.91.0")]
     pub fn add_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
         self._add_extension(extension.as_ref())
     }
@@ -2103,35 +2103,35 @@ impl PartialEq for PathBuf {
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<str> for PathBuf {
     #[inline]
     fn eq(&self, other: &str) -> bool {
-        Path::eq(self, other)
+        self.as_path() == other
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<PathBuf> for str {
     #[inline]
     fn eq(&self, other: &PathBuf) -> bool {
-        other == self
+        self == other.as_path()
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<String> for PathBuf {
     #[inline]
     fn eq(&self, other: &String) -> bool {
-        **self == **other
+        self.as_path() == other.as_str()
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<PathBuf> for String {
     #[inline]
     fn eq(&self, other: &PathBuf) -> bool {
-        other == self
+        self.as_str() == other.as_path()
     }
 }
 
@@ -2724,7 +2724,7 @@ impl Path {
     ///
     /// [`Path::file_stem`]: Path::file_stem
     ///
-    #[stable(feature = "path_file_prefix", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "path_file_prefix", since = "1.91.0")]
     #[must_use]
     pub fn file_prefix(&self) -> Option<&OsStr> {
         self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before))
@@ -2888,7 +2888,7 @@ impl Path {
     /// assert_eq!(path.with_added_extension("xz"), PathBuf::from("foo.tar.gz.xz"));
     /// assert_eq!(path.with_added_extension("").with_added_extension("txt"), PathBuf::from("foo.tar.gz.txt"));
     /// ```
-    #[stable(feature = "path_add_extension", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "path_add_extension", since = "1.91.0")]
     pub fn with_added_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
         let mut new_path = self.to_path_buf();
         new_path.add_extension(extension);
@@ -3405,7 +3405,7 @@ impl PartialEq for Path {
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<str> for Path {
     #[inline]
     fn eq(&self, other: &str) -> bool {
@@ -3414,7 +3414,7 @@ impl cmp::PartialEq<str> for Path {
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<Path> for str {
     #[inline]
     fn eq(&self, other: &Path) -> bool {
@@ -3422,19 +3422,19 @@ impl cmp::PartialEq<Path> for str {
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<String> for Path {
     #[inline]
     fn eq(&self, other: &String) -> bool {
-        self == &*other
+        self == other.as_str()
     }
 }
 
-#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "eq_str_for_path", since = "1.91.0")]
 impl cmp::PartialEq<Path> for String {
     #[inline]
     fn eq(&self, other: &Path) -> bool {
-        other == self
+        self.as_str() == other
     }
 }
 
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 48265de90c4..5c0ac526a36 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -268,8 +268,8 @@ impl AsInner<imp::Process> for Child {
     }
 }
 
-impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
-    fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
+impl FromInner<(imp::Process, StdioPipes)> for Child {
+    fn from_inner((handle, io): (imp::Process, StdioPipes)) -> Child {
         Child {
             handle,
             stdin: io.stdin.map(ChildStdin::from_inner),
@@ -296,6 +296,15 @@ impl fmt::Debug for Child {
     }
 }
 
+/// The pipes connected to a spawned process.
+///
+/// Used to pass pipe handles between this module and [`imp`].
+pub(crate) struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
 /// A handle to a child process's standard input (stdin).
 ///
 /// This struct is used in the [`stdin`] field on [`Child`].
@@ -532,6 +541,7 @@ impl fmt::Debug for ChildStderr {
 /// to be changed (for example, by adding arguments) prior to spawning:
 ///
 /// ```
+/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
 /// use std::process::Command;
 ///
 /// let output = if cfg!(target_os = "windows") {
@@ -548,6 +558,7 @@ impl fmt::Debug for ChildStderr {
 /// };
 ///
 /// let hello = output.stdout;
+/// # }
 /// ```
 ///
 /// `Command` can be reused to spawn multiple processes. The builder methods
@@ -1348,7 +1359,7 @@ impl Output {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     /// assert!(Command::new("false").output().unwrap().exit_ok().is_err());
     /// # }
@@ -1695,7 +1706,7 @@ impl From<io::Stdout> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1724,7 +1735,7 @@ impl From<io::Stderr> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1800,7 +1811,7 @@ impl ExitStatus {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # if cfg!(unix) {
+    /// # if cfg!(all(unix, not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::process::Command;
     ///
     /// let status = Command::new("ls")
@@ -1907,7 +1918,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
 ///
 /// ```
 /// #![feature(exit_status_error)]
-/// # if cfg!(all(unix, not(target_os = "android"))) {
+/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
 /// use std::process::{Command, ExitStatusError};
 ///
 /// fn run(cmd: &str) -> Result<(), ExitStatusError> {
@@ -1950,7 +1961,7 @@ impl ExitStatusError {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     ///
     /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
@@ -1975,7 +1986,7 @@ impl ExitStatusError {
     /// ```
     /// #![feature(exit_status_error)]
     ///
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::num::NonZero;
     /// use std::process::Command;
     ///
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 5879914ca20..12c5130defe 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -5,7 +5,15 @@ use crate::mem::MaybeUninit;
 use crate::str;
 
 fn known_command() -> Command {
-    if cfg!(windows) { Command::new("help") } else { Command::new("echo") }
+    if cfg!(windows) {
+        Command::new("help")
+    } else if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
+        // iOS/tvOS/watchOS/visionOS have a very limited set of commandline
+        // binaries available.
+        Command::new("log")
+    } else {
+        Command::new("echo")
+    }
 }
 
 #[cfg(target_os = "android")]
@@ -19,7 +27,10 @@ fn shell_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn smoke() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 0"]).spawn()
@@ -41,7 +52,10 @@ fn smoke_failure() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn exit_reported_right() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn()
@@ -56,7 +70,10 @@ fn exit_reported_right() {
 
 #[test]
 #[cfg(unix)]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn signal_reported_right() {
     use crate::os::unix::process::ExitStatusExt;
 
@@ -80,7 +97,10 @@ pub fn run_output(mut cmd: Command) -> String {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdout_works() {
     if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -94,7 +114,11 @@ fn stdout_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn set_current_dir_works() {
     // On many Unix platforms this will use the posix_spawn path.
     let mut cmd = shell_cmd();
@@ -116,7 +140,11 @@ fn set_current_dir_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdin_works() {
     let mut p = shell_cmd()
         .arg("-c")
@@ -134,7 +162,10 @@ fn stdin_works() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn child_stdout_read_buf() {
     let mut cmd = if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -165,7 +196,10 @@ fn child_stdout_read_buf() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_status() {
     let mut status = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
@@ -191,7 +225,10 @@ fn test_process_output_fail_to_start() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_output() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
@@ -206,7 +243,10 @@ fn test_process_output_output() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_error() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
@@ -221,7 +261,10 @@ fn test_process_output_error() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_once() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -232,7 +275,10 @@ fn test_finish_once() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_twice() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -244,7 +290,10 @@ fn test_finish_twice() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_wait_with_output_once() {
     let prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
@@ -279,7 +328,10 @@ pub fn env_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_override_env() {
     use crate::env;
 
@@ -302,7 +354,10 @@ fn test_override_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_add_to_env() {
     let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
     let output = String::from_utf8_lossy(&result.stdout).to_string();
@@ -314,7 +369,10 @@ fn test_add_to_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_capture_env_at_spawn() {
     use crate::env;
 
@@ -378,7 +436,10 @@ fn test_interior_nul_in_current_dir_is_error() {
 
 // Regression tests for #30862.
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_key_is_error() {
     match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
@@ -387,7 +448,10 @@ fn test_interior_nul_in_env_key_is_error() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_value_is_error() {
     match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index b3f3b301e3d..2717b7b469c 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -39,11 +39,11 @@ fn __rust_abort() {
 // - nothing (so this macro is a no-op)
 macro_rules! rtprintpanic {
     ($($t:tt)*) => {
-        #[cfg(not(feature = "panic_immediate_abort"))]
+        #[cfg(not(panic = "immediate-abort"))]
         if let Some(mut out) = crate::sys::stdio::panic_output() {
             let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
         }
-        #[cfg(feature = "panic_immediate_abort")]
+        #[cfg(panic = "immediate-abort")]
         {
             let _ = format_args!($($t)*);
         }
@@ -161,7 +161,7 @@ fn lang_start_internal(
     // mechanism itself.
     //
     // There are a couple of instances where unwinding can begin. First is inside of the
-    // `rt::init`, `rt::cleanup` and similar functions controlled by bstd. In those instances a
+    // `rt::init`, `rt::cleanup` and similar functions controlled by std. In those instances a
     // panic is a std implementation bug. A quite likely one too, as there isn't any way to
     // prevent std from accidentally introducing a panic to these functions. Another is from
     // user code from `main` or, more nefariously, as described in e.g. issue #86030.
diff --git a/library/std/src/sync/nonpoison/mutex.rs b/library/std/src/sync/nonpoison/mutex.rs
index 07430ce3a13..eeecf5d7107 100644
--- a/library/std/src/sync/nonpoison/mutex.rs
+++ b/library/std/src/sync/nonpoison/mutex.rs
@@ -373,7 +373,7 @@ impl<T: ?Sized> Mutex<T> {
     /// or written through after the mutex is dropped.
     #[unstable(feature = "mutex_data_ptr", issue = "140368")]
     // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
-    pub fn data_ptr(&self) -> *mut T {
+    pub const fn data_ptr(&self) -> *mut T {
         self.data.get()
     }
 }
diff --git a/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs
index eb0aef99cc1..b2f26edc083 100644
--- a/library/std/src/sync/nonpoison/rwlock.rs
+++ b/library/std/src/sync/nonpoison/rwlock.rs
@@ -495,7 +495,7 @@ impl<T: ?Sized> RwLock<T> {
     /// or written through after the lock is dropped.
     #[unstable(feature = "rwlock_data_ptr", issue = "140368")]
     // #[unstable(feature = "nonpoison_rwlock", issue = "134645")]
-    pub fn data_ptr(&self) -> *mut T {
+    pub const fn data_ptr(&self) -> *mut T {
         self.data.get()
     }
 }
diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs
index 7e9d920d92f..6fdb4f6799e 100644
--- a/library/std/src/sync/poison/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
@@ -668,7 +668,7 @@ impl<T: ?Sized> Mutex<T> {
     /// are properly synchronized to avoid data races, and that it is not read
     /// or written through after the mutex is dropped.
     #[unstable(feature = "mutex_data_ptr", issue = "140368")]
-    pub fn data_ptr(&self) -> *mut T {
+    pub const fn data_ptr(&self) -> *mut T {
         self.data.get()
     }
 }
diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 0a463f3f9c7..e3a72c73bf4 100644
--- a/library/std/src/sync/poison/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
@@ -667,7 +667,7 @@ impl<T: ?Sized> RwLock<T> {
     /// are properly synchronized to avoid data races, and that it is not read
     /// or written through after the lock is dropped.
     #[unstable(feature = "rwlock_data_ptr", issue = "140368")]
-    pub fn data_ptr(&self) -> *mut T {
+    pub const fn data_ptr(&self) -> *mut T {
         self.data.get()
     }
 }
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 4140718560c..f560b616dd9 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -355,7 +355,7 @@ impl<T: ?Sized> ReentrantLock<T> {
     /// properly synchronized to avoid data races, and that it is not read
     /// through after the lock is dropped.
     #[unstable(feature = "reentrant_lock_data_ptr", issue = "140368")]
-    pub fn data_ptr(&self) -> *const T {
+    pub const fn data_ptr(&self) -> *const T {
         &raw const self.data
     }
 
diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs
index 6d4b09494a3..2045b2fecc6 100644
--- a/library/std/src/sys/alloc/mod.rs
+++ b/library/std/src/sys/alloc/mod.rs
@@ -92,6 +92,9 @@ cfg_select! {
     target_os = "uefi" => {
         mod uefi;
     }
+    target_os = "vexos" => {
+        mod vexos;
+    }
     target_family = "wasm" => {
         mod wasm;
     }
diff --git a/library/std/src/sys/alloc/vexos.rs b/library/std/src/sys/alloc/vexos.rs
new file mode 100644
index 00000000000..c1fb6896a89
--- /dev/null
+++ b/library/std/src/sys/alloc/vexos.rs
@@ -0,0 +1,96 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::ptr;
+use crate::sync::atomic::{AtomicBool, Ordering};
+
+// Symbols for heap section boundaries defined in the target's linkerscript
+unsafe extern "C" {
+    static mut __heap_start: u8;
+    static mut __heap_end: u8;
+}
+
+static mut DLMALLOC: dlmalloc::Dlmalloc<Vexos> = dlmalloc::Dlmalloc::new_with_allocator(Vexos);
+
+struct Vexos;
+
+unsafe impl dlmalloc::Allocator for Vexos {
+    /// Allocs system resources
+    fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) {
+        static INIT: AtomicBool = AtomicBool::new(false);
+
+        if !INIT.swap(true, Ordering::Relaxed) {
+            // This target has no growable heap, as user memory has a fixed
+            // size/location and VEXos does not manage allocation for us.
+            unsafe {
+                (
+                    (&raw mut __heap_start).cast::<u8>(),
+                    (&raw const __heap_end).offset_from_unsigned(&raw const __heap_start),
+                    0,
+                )
+            }
+        } else {
+            (ptr::null_mut(), 0, 0)
+        }
+    }
+
+    fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
+        ptr::null_mut()
+    }
+
+    fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool {
+        false
+    }
+
+    fn free(&self, _ptr: *mut u8, _size: usize) -> bool {
+        return false;
+    }
+
+    fn can_release_part(&self, _flags: u32) -> bool {
+        false
+    }
+
+    fn allocates_zeros(&self) -> bool {
+        false
+    }
+
+    fn page_size(&self) -> usize {
+        0x1000
+    }
+}
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+        // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+        // Calling malloc() is safe because preconditions on this function match the trait method preconditions.
+        unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+        // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+        // Calling calloc() is safe because preconditions on this function match the trait method preconditions.
+        unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+        // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+        // Calling free() is safe because preconditions on this function match the trait method preconditions.
+        unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
+        // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
+        // Calling realloc() is safe because preconditions on this function match the trait method preconditions.
+        unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
+    }
+}
diff --git a/library/std/src/sys/args/zkvm.rs b/library/std/src/sys/args/zkvm.rs
index 194ba7159d4..d26bf1eaff9 100644
--- a/library/std/src/sys/args/zkvm.rs
+++ b/library/std/src/sys/args/zkvm.rs
@@ -1,25 +1,20 @@
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::sys::os_str;
+use crate::ffi::{OsStr, OsString};
+use crate::num::NonZero;
+use crate::sync::OnceLock;
 use crate::sys::pal::{WORD_SIZE, abi};
-use crate::sys_common::FromInner;
-
-pub struct Args {
-    i_forward: usize,
-    i_back: usize,
-    count: usize,
-}
+use crate::{fmt, ptr, slice};
 
 pub fn args() -> Args {
-    let count = unsafe { abi::sys_argc() };
-    Args { i_forward: 0, i_back: 0, count }
+    Args { iter: ARGS.get_or_init(|| get_args()).iter() }
 }
 
-impl Args {
-    /// Use sys_argv to get the arg at the requested index. Does not check that i is less than argc
-    /// and will not return if the index is out of bounds.
-    fn argv(i: usize) -> OsString {
-        let arg_len = unsafe { abi::sys_argv(crate::ptr::null_mut(), 0, i) };
+fn get_args() -> Vec<&'static OsStr> {
+    let argc = unsafe { abi::sys_argc() };
+    let mut args = Vec::with_capacity(argc);
+
+    for i in 0..argc {
+        // Get the size of the argument then the data.
+        let arg_len = unsafe { abi::sys_argv(ptr::null_mut(), 0, i) };
 
         let arg_len_words = (arg_len + WORD_SIZE - 1) / WORD_SIZE;
         let words = unsafe { abi::sys_alloc_words(arg_len_words) };
@@ -27,20 +22,24 @@ impl Args {
         let arg_len2 = unsafe { abi::sys_argv(words, arg_len_words, i) };
         debug_assert_eq!(arg_len, arg_len2);
 
-        // Convert to OsString.
-        //
-        // FIXME: We can probably get rid of the extra copy here if we
-        // reimplement "os_str" instead of just using the generic unix
-        // "os_str".
-        let arg_bytes: &[u8] =
-            unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, arg_len) };
-        OsString::from_inner(os_str::Buf { inner: arg_bytes.to_vec() })
+        let arg_bytes = unsafe { slice::from_raw_parts(words.cast(), arg_len) };
+        args.push(unsafe { OsStr::from_encoded_bytes_unchecked(arg_bytes) });
     }
+    args
 }
 
+static ARGS: OnceLock<Vec<&'static OsStr>> = OnceLock::new();
+
+pub struct Args {
+    iter: slice::Iter<'static, &'static OsStr>,
+}
+
+impl !Send for Args {}
+impl !Sync for Args {}
+
 impl fmt::Debug for Args {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().finish()
+        self.iter.as_slice().fmt(f)
     }
 }
 
@@ -48,34 +47,48 @@ impl Iterator for Args {
     type Item = OsString;
 
     fn next(&mut self) -> Option<OsString> {
-        if self.i_forward >= self.count - self.i_back {
-            None
-        } else {
-            let arg = Self::argv(self.i_forward);
-            self.i_forward += 1;
-            Some(arg)
-        }
+        self.iter.next().map(|arg| arg.to_os_string())
     }
 
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.count, Some(self.count))
+        self.iter.size_hint()
     }
-}
 
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize {
-        self.count
+    #[inline]
+    fn count(self) -> usize {
+        self.iter.len()
+    }
+
+    fn last(self) -> Option<OsString> {
+        self.iter.last().map(|arg| arg.to_os_string())
+    }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        self.iter.advance_by(n)
     }
 }
 
 impl DoubleEndedIterator for Args {
     fn next_back(&mut self) -> Option<OsString> {
-        if self.i_back >= self.count - self.i_forward {
-            None
-        } else {
-            let arg = Self::argv(self.count - 1 - self.i_back);
-            self.i_back += 1;
-            Some(arg)
-        }
+        self.iter.next_back().map(|arg| arg.to_os_string())
+    }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        self.iter.advance_back_by(n)
+    }
+}
+
+impl ExactSizeIterator for Args {
+    #[inline]
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+
+    #[inline]
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
     }
 }
diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs
index 9683fd47cf9..573f540483b 100644
--- a/library/std/src/sys/env_consts.rs
+++ b/library/std/src/sys/env_consts.rs
@@ -2,7 +2,7 @@
 
 // Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates.
 // This ensures that they must be mutually exclusive and do not have precedence
-// like cfg_if!.
+// like cfg_select!.
 macro cfg_unordered(
     $(#[cfg($cfg:meta)] $os:item)*
     #[else] $fallback:item
@@ -323,6 +323,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "efi";
 }
 
+#[cfg(target_os = "vexos")]
+pub mod os {
+    pub const FAMILY: &str = "";
+    pub const OS: &str = "vexos";
+    pub const DLL_PREFIX: &str = "";
+    pub const DLL_SUFFIX: &str = "";
+    pub const DLL_EXTENSION: &str = "";
+    pub const EXE_SUFFIX: &str = ".bin";
+    pub const EXE_EXTENSION: &str = "bin";
+}
+
 #[cfg(target_os = "visionos")]
 pub mod os {
     pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index 0276bf6e64c..64f5a6b36d3 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -35,6 +35,10 @@ cfg_select! {
         mod uefi;
         use uefi as imp;
     }
+    target_os = "vexos" => {
+        mod vexos;
+        use vexos as imp;
+    }
     target_os = "wasi" => {
         mod wasi;
         use wasi as imp;
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index dfd6ce56a76..33a1e7ff5e4 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -21,29 +21,31 @@ use libc::fstatat as fstatat64;
 #[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))]
 use libc::fstatat64;
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "solaris",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
     target_os = "illumos",
-    target_os = "aix",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
     all(target_os = "linux", target_env = "musl"),
 ))]
 use libc::readdir as readdir64;
 #[cfg(not(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
+    target_os = "freebsd",
+    target_os = "fuchsia",
+    target_os = "hurd",
     target_os = "illumos",
     target_os = "l4re",
-    target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 )))]
 use libc::readdir_r as readdir64_r;
 #[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))]
@@ -271,16 +273,17 @@ unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 ))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -295,16 +298,17 @@ pub struct DirEntry {
 // we're not using the immediate `d_name` on these targets. Keeping this as an
 // `entry` field in `DirEntry` helps reduce the `cfg` boilerplate elsewhere.
 #[cfg(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 ))]
 struct dirent64_min {
     d_ino: u64,
@@ -319,16 +323,17 @@ struct dirent64_min {
 }
 
 #[cfg(not(any(
+    target_os = "aix",
     target_os = "android",
-    target_os = "linux",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "freebsd",
     target_os = "fuchsia",
-    target_os = "redox",
-    target_os = "aix",
+    target_os = "hurd",
+    target_os = "illumos",
+    target_os = "linux",
     target_os = "nto",
+    target_os = "redox",
+    target_os = "solaris",
     target_os = "vita",
-    target_os = "hurd",
 )))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -698,16 +703,17 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     #[cfg(any(
+        target_os = "aix",
         target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
+        target_os = "freebsd",
         target_os = "fuchsia",
-        target_os = "redox",
+        target_os = "hurd",
         target_os = "illumos",
-        target_os = "aix",
+        target_os = "linux",
         target_os = "nto",
+        target_os = "redox",
+        target_os = "solaris",
         target_os = "vita",
-        target_os = "hurd",
     ))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         use crate::sys::os::{errno, set_errno};
@@ -768,6 +774,9 @@ impl Iterator for ReadDir {
                 // only access those bytes.
                 #[cfg(not(target_os = "vita"))]
                 let entry = dirent64_min {
+                    #[cfg(target_os = "freebsd")]
+                    d_ino: (*entry_ptr).d_fileno,
+                    #[cfg(not(target_os = "freebsd"))]
                     d_ino: (*entry_ptr).d_ino as u64,
                     #[cfg(not(any(
                         target_os = "solaris",
@@ -791,16 +800,17 @@ impl Iterator for ReadDir {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
-        target_os = "linux",
-        target_os = "solaris",
+        target_os = "freebsd",
         target_os = "fuchsia",
-        target_os = "redox",
+        target_os = "hurd",
         target_os = "illumos",
-        target_os = "aix",
+        target_os = "linux",
         target_os = "nto",
+        target_os = "redox",
+        target_os = "solaris",
         target_os = "vita",
-        target_os = "hurd",
     )))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         if self.end_of_stream {
@@ -970,36 +980,32 @@ impl DirEntry {
     }
 
     #[cfg(any(
-        target_os = "linux",
+        target_os = "aix",
+        target_os = "android",
         target_os = "cygwin",
         target_os = "emscripten",
-        target_os = "android",
-        target_os = "solaris",
-        target_os = "illumos",
-        target_os = "haiku",
-        target_os = "l4re",
-        target_os = "fuchsia",
-        target_os = "redox",
-        target_os = "vxworks",
         target_os = "espidf",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "haiku",
         target_os = "horizon",
-        target_os = "vita",
-        target_os = "aix",
-        target_os = "nto",
         target_os = "hurd",
+        target_os = "illumos",
+        target_os = "l4re",
+        target_os = "linux",
+        target_os = "nto",
+        target_os = "redox",
         target_os = "rtems",
+        target_os = "solaris",
+        target_os = "vita",
+        target_os = "vxworks",
         target_vendor = "apple",
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
     }
 
-    #[cfg(any(
-        target_os = "freebsd",
-        target_os = "openbsd",
-        target_os = "netbsd",
-        target_os = "dragonfly"
-    ))]
+    #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly"))]
     pub fn ino(&self) -> u64 {
         self.entry.d_fileno as u64
     }
@@ -1014,7 +1020,6 @@ impl DirEntry {
     #[cfg(any(
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "freebsd",
         target_os = "dragonfly",
         target_vendor = "apple",
     ))]
@@ -1030,7 +1035,6 @@ impl DirEntry {
     #[cfg(not(any(
         target_os = "netbsd",
         target_os = "openbsd",
-        target_os = "freebsd",
         target_os = "dragonfly",
         target_vendor = "apple",
     )))]
@@ -1040,6 +1044,7 @@ impl DirEntry {
 
     #[cfg(not(any(
         target_os = "android",
+        target_os = "freebsd",
         target_os = "linux",
         target_os = "solaris",
         target_os = "illumos",
@@ -1055,6 +1060,7 @@ impl DirEntry {
     }
     #[cfg(any(
         target_os = "android",
+        target_os = "freebsd",
         target_os = "linux",
         target_os = "solaris",
         target_os = "illumos",
diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs
new file mode 100644
index 00000000000..f642e7cb074
--- /dev/null
+++ b/library/std/src/sys/fs/vexos.rs
@@ -0,0 +1,615 @@
+use crate::ffi::{OsString, c_char};
+use crate::fmt;
+use crate::fs::TryLockError;
+use crate::hash::Hash;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
+use crate::path::{Path, PathBuf};
+use crate::sys::common::small_c_string::run_path_with_cstr;
+use crate::sys::time::SystemTime;
+use crate::sys::{unsupported, unsupported_err};
+
+#[expect(dead_code)]
+#[path = "unsupported.rs"]
+mod unsupported_fs;
+pub use unsupported_fs::{
+    DirBuilder, FileTimes, canonicalize, link, readlink, remove_dir_all, rename, rmdir, symlink,
+    unlink,
+};
+
+/// VEXos file descriptor.
+///
+/// This stores an opaque pointer to a [FatFs file object structure] managed by VEXos
+/// representing an open file on disk.
+///
+/// [FatFs file object structure]: https://github.com/Xilinx/embeddedsw/blob/master/lib/sw_services/xilffs/src/include/ff.h?rgh-link-date=2025-09-23T20%3A03%3A43Z#L215
+///
+/// # Safety
+///
+/// Since this platform uses a pointer to to an internal filesystem structure with a lifetime
+/// associated with it (rather than a UNIX-style file descriptor table), care must be taken to
+/// ensure that the pointer held by `FileDesc` is valid for as long as it exists.
+#[derive(Debug)]
+struct FileDesc(*mut vex_sdk::FIL);
+
+// SAFETY: VEXos's FDs can be used on a thread other than the one they were created on.
+unsafe impl Send for FileDesc {}
+// SAFETY: We assume an environment without threads (i.e. no RTOS).
+// (If there were threads, it is possible that a mutex would be required.)
+unsafe impl Sync for FileDesc {}
+
+pub struct File {
+    fd: FileDesc,
+}
+
+#[derive(Clone)]
+pub enum FileAttr {
+    Dir,
+    File { size: u64 },
+}
+
+pub struct ReadDir(!);
+
+pub struct DirEntry {
+    path: PathBuf,
+}
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {
+    read: bool,
+    write: bool,
+    append: bool,
+    truncate: bool,
+    create: bool,
+    create_new: bool,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions {}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub struct FileType {
+    is_dir: bool,
+}
+
+impl FileAttr {
+    pub fn size(&self) -> u64 {
+        match self {
+            Self::File { size } => *size,
+            Self::Dir => 0,
+        }
+    }
+
+    pub fn perm(&self) -> FilePermissions {
+        FilePermissions {}
+    }
+
+    pub fn file_type(&self) -> FileType {
+        FileType { is_dir: matches!(self, FileAttr::Dir) }
+    }
+
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        unsupported()
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        unsupported()
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        unsupported()
+    }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        false
+    }
+
+    pub fn set_readonly(&mut self, _readonly: bool) {
+        panic!("Perimissions do not exist")
+    }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool {
+        self.is_dir
+    }
+
+    pub fn is_file(&self) -> bool {
+        !self.is_dir
+    }
+
+    pub fn is_symlink(&self) -> bool {
+        // No symlinks in VEXos - entries are either files or directories.
+        false
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        self.0
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        self.path.clone()
+    }
+
+    pub fn file_name(&self) -> OsString {
+        self.path.file_name().unwrap_or_default().into()
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        stat(&self.path)
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        Ok(self.metadata()?.file_type())
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions {
+            read: false,
+            write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+        }
+    }
+
+    pub fn read(&mut self, read: bool) {
+        self.read = read;
+    }
+    pub fn write(&mut self, write: bool) {
+        self.write = write;
+    }
+    pub fn append(&mut self, append: bool) {
+        self.append = append;
+    }
+    pub fn truncate(&mut self, truncate: bool) {
+        self.truncate = truncate;
+    }
+    pub fn create(&mut self, create: bool) {
+        self.create = create;
+    }
+    pub fn create_new(&mut self, create_new: bool) {
+        self.create_new = create_new;
+    }
+}
+
+impl File {
+    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        run_path_with_cstr(path, &|path| {
+            // Enforce the invariants of `create_new`/`create`.
+            //
+            // Since VEXos doesn't have anything akin to POSIX's `oflags`, we need to enforce
+            // the requirements that `create_new` can't have an existing file and `!create`
+            // doesn't create a file ourselves.
+            if !opts.read && (opts.write || opts.append) && (opts.create_new || !opts.create) {
+                let status = unsafe { vex_sdk::vexFileStatus(path.as_ptr()) };
+
+                if opts.create_new && status != 0 {
+                    return Err(io::const_error!(io::ErrorKind::AlreadyExists, "file exists",));
+                } else if !opts.create && status == 0 {
+                    return Err(io::const_error!(
+                        io::ErrorKind::NotFound,
+                        "no such file or directory",
+                    ));
+                }
+            }
+
+            let file = match opts {
+                // read + write - unsupported
+                OpenOptions { read: true, write: true, .. } => {
+                    return Err(io::const_error!(
+                        io::ErrorKind::InvalidInput,
+                        "opening files with read and write access is unsupported on this target",
+                    ));
+                }
+
+                // read
+                OpenOptions {
+                    read: true,
+                    write: false,
+                    append: _,
+                    truncate: false,
+                    create: false,
+                    create_new: false,
+                } => unsafe { vex_sdk::vexFileOpen(path.as_ptr(), c"".as_ptr()) },
+
+                // append
+                OpenOptions {
+                    read: false,
+                    write: _,
+                    append: true,
+                    truncate: false,
+                    create: _,
+                    create_new: _,
+                } => unsafe { vex_sdk::vexFileOpenWrite(path.as_ptr()) },
+
+                // write
+                OpenOptions {
+                    read: false,
+                    write: true,
+                    append: false,
+                    truncate,
+                    create: _,
+                    create_new: _,
+                } => unsafe {
+                    if *truncate {
+                        vex_sdk::vexFileOpenCreate(path.as_ptr())
+                    } else {
+                        // Open in append, but jump to the start of the file.
+                        let fd = vex_sdk::vexFileOpenWrite(path.as_ptr());
+                        vex_sdk::vexFileSeek(fd, 0, 0);
+                        fd
+                    }
+                },
+
+                _ => {
+                    return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid argument"));
+                }
+            };
+
+            if file.is_null() {
+                Err(io::const_error!(io::ErrorKind::NotFound, "could not open file"))
+            } else {
+                Ok(Self { fd: FileDesc(file) })
+            }
+        })
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        // `vexFileSize` returns -1 upon error, so u64::try_from will fail on error.
+        if let Ok(size) = u64::try_from(unsafe {
+            // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+            vex_sdk::vexFileSize(self.fd.0)
+        }) {
+            Ok(FileAttr::File { size })
+        } else {
+            Err(io::const_error!(io::ErrorKind::InvalidData, "failed to get file size"))
+        }
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        self.flush()
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        self.flush()
+    }
+
+    pub fn lock(&self) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn lock_shared(&self) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn try_lock(&self) -> Result<(), TryLockError> {
+        Err(TryLockError::Error(unsupported_err()))
+    }
+
+    pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
+        Err(TryLockError::Error(unsupported_err()))
+    }
+
+    pub fn unlock(&self) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn truncate(&self, _size: u64) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        let len = buf.len() as u32;
+        let buf_ptr = buf.as_mut_ptr();
+        let read = unsafe {
+            // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+            vex_sdk::vexFileRead(buf_ptr.cast::<c_char>(), 1, len, self.fd.0)
+        };
+
+        if read < 0 {
+            Err(io::const_error!(io::ErrorKind::Other, "could not read from file"))
+        } else {
+            Ok(read as usize)
+        }
+    }
+
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        crate::io::default_read_vectored(|b| self.read(b), bufs)
+    }
+
+    #[inline]
+    pub fn is_read_vectored(&self) -> bool {
+        false
+    }
+
+    pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        crate::io::default_read_buf(|b| self.read(b), cursor)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        let len = buf.len() as u32;
+        let buf_ptr = buf.as_ptr();
+        let written = unsafe {
+            // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+            vex_sdk::vexFileWrite(buf_ptr.cast_mut().cast::<c_char>(), 1, len, self.fd.0)
+        };
+
+        if written < 0 {
+            Err(io::const_error!(io::ErrorKind::Other, "could not write to file"))
+        } else {
+            Ok(written as usize)
+        }
+    }
+
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        crate::io::default_write_vectored(|b| self.write(b), bufs)
+    }
+
+    #[inline]
+    pub fn is_write_vectored(&self) -> bool {
+        false
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        unsafe {
+            // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+            vex_sdk::vexFileSync(self.fd.0);
+        }
+        Ok(())
+    }
+
+    pub fn tell(&self) -> io::Result<u64> {
+        // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+        let position = unsafe { vex_sdk::vexFileTell(self.fd.0) };
+
+        position.try_into().map_err(|_| {
+            io::const_error!(io::ErrorKind::InvalidData, "failed to get current location in file")
+        })
+    }
+
+    pub fn size(&self) -> Option<io::Result<u64>> {
+        None
+    }
+
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        const SEEK_SET: i32 = 0;
+        const SEEK_CUR: i32 = 1;
+        const SEEK_END: i32 = 2;
+
+        fn try_convert_offset<T: TryInto<u32>>(offset: T) -> io::Result<u32> {
+            offset.try_into().map_err(|_| {
+                io::const_error!(
+                    io::ErrorKind::InvalidInput,
+                    "cannot seek to an offset too large to fit in a 32 bit integer",
+                )
+            })
+        }
+
+        // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime.
+        match pos {
+            SeekFrom::Start(offset) => unsafe {
+                map_fresult(vex_sdk::vexFileSeek(self.fd.0, try_convert_offset(offset)?, SEEK_SET))?
+            },
+            SeekFrom::End(offset) => unsafe {
+                if offset >= 0 {
+                    map_fresult(vex_sdk::vexFileSeek(
+                        self.fd.0,
+                        try_convert_offset(offset)?,
+                        SEEK_END,
+                    ))?
+                } else {
+                    // `vexFileSeek` does not support seeking with negative offset, meaning
+                    // we have to calculate the offset from the end of the file ourselves.
+
+                    // Seek to the end of the file to get the end position in the open buffer.
+                    map_fresult(vex_sdk::vexFileSeek(self.fd.0, 0, SEEK_END))?;
+                    let end_position = self.tell()?;
+
+                    map_fresult(vex_sdk::vexFileSeek(
+                        self.fd.0,
+                        // NOTE: Files internally use a 32-bit representation for stream
+                        // position, so `end_position as i64` should never overflow.
+                        try_convert_offset(end_position as i64 + offset)?,
+                        SEEK_SET,
+                    ))?
+                }
+            },
+            SeekFrom::Current(offset) => unsafe {
+                if offset >= 0 {
+                    map_fresult(vex_sdk::vexFileSeek(
+                        self.fd.0,
+                        try_convert_offset(offset)?,
+                        SEEK_CUR,
+                    ))?
+                } else {
+                    // `vexFileSeek` does not support seeking with negative offset, meaning
+                    // we have to calculate the offset from the stream position ourselves.
+                    map_fresult(vex_sdk::vexFileSeek(
+                        self.fd.0,
+                        try_convert_offset((self.tell()? as i64) + offset)?,
+                        SEEK_SET,
+                    ))?
+                }
+            },
+        }
+
+        Ok(self.tell()?)
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        unsupported()
+    }
+
+    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
+        unsupported()
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("File").field("fd", &self.fd.0).finish()
+    }
+}
+impl Drop for File {
+    fn drop(&mut self) {
+        unsafe { vex_sdk::vexFileClose(self.fd.0) };
+    }
+}
+
+pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
+    // While there *is* a userspace function for reading file directories,
+    // the necessary implementation cannot currently be done cleanly, as
+    // VEXos does not expose directory length to user programs.
+    //
+    // This means that we would need to create a large fixed-length buffer
+    // and hope that the folder's contents didn't exceed that buffer's length,
+    // which obviously isn't behavior we want to rely on in the standard library.
+    unsupported()
+}
+
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    unsupported()
+}
+
+pub fn exists(path: &Path) -> io::Result<bool> {
+    run_path_with_cstr(path, &|path| Ok(unsafe { vex_sdk::vexFileStatus(path.as_ptr()) } != 0))
+}
+
+pub fn stat(p: &Path) -> io::Result<FileAttr> {
+    // `vexFileStatus` returns 3 if the given path is a directory, 1 if the path is a
+    // file, or 0 if no such path exists.
+    const FILE_STATUS_DIR: u32 = 3;
+
+    run_path_with_cstr(p, &|c_path| {
+        let file_type = unsafe { vex_sdk::vexFileStatus(c_path.as_ptr()) };
+
+        // We can't get the size if its a directory because we cant open it as a file
+        if file_type == FILE_STATUS_DIR {
+            Ok(FileAttr::Dir)
+        } else {
+            let mut opts = OpenOptions::new();
+            opts.read(true);
+            let file = File::open(p, &opts)?;
+            file.file_attr()
+        }
+    })
+}
+
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    // Symlinks aren't supported in this filesystem
+    stat(p)
+}
+
+// Cannot use `copy` from `common` here, since `File::set_permissions` is unsupported on this target.
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    use crate::fs::File;
+
+    // NOTE: If `from` is a directory, this call should fail due to vexFileOpen* returning null.
+    let mut reader = File::open(from)?;
+    let mut writer = File::create(to)?;
+
+    io::copy(&mut reader, &mut writer)
+}
+
+fn map_fresult(fresult: vex_sdk::FRESULT) -> io::Result<()> {
+    // VEX uses a derivative of FatFs (Xilinx's xilffs library) for filesystem operations.
+    match fresult {
+        vex_sdk::FRESULT::FR_OK => Ok(()),
+        vex_sdk::FRESULT::FR_DISK_ERR => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "internal function reported an unrecoverable hard error",
+        )),
+        vex_sdk::FRESULT::FR_INT_ERR => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "internal error in filesystem runtime",
+        )),
+        vex_sdk::FRESULT::FR_NOT_READY => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "the storage device could not be prepared to work",
+        )),
+        vex_sdk::FRESULT::FR_NO_FILE => Err(io::const_error!(
+            io::ErrorKind::NotFound,
+            "could not find the file in the directory"
+        )),
+        vex_sdk::FRESULT::FR_NO_PATH => Err(io::const_error!(
+            io::ErrorKind::NotFound,
+            "a directory in the path name could not be found",
+        )),
+        vex_sdk::FRESULT::FR_INVALID_NAME => Err(io::const_error!(
+            io::ErrorKind::InvalidInput,
+            "the given string is invalid as a path name",
+        )),
+        vex_sdk::FRESULT::FR_DENIED => Err(io::const_error!(
+            io::ErrorKind::PermissionDenied,
+            "the required access for this operation was denied",
+        )),
+        vex_sdk::FRESULT::FR_EXIST => Err(io::const_error!(
+            io::ErrorKind::AlreadyExists,
+            "an object with the same name already exists in the directory",
+        )),
+        vex_sdk::FRESULT::FR_INVALID_OBJECT => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "invalid or null file/directory object",
+        )),
+        vex_sdk::FRESULT::FR_WRITE_PROTECTED => Err(io::const_error!(
+            io::ErrorKind::PermissionDenied,
+            "a write operation was performed on write-protected media",
+        )),
+        vex_sdk::FRESULT::FR_INVALID_DRIVE => Err(io::const_error!(
+            io::ErrorKind::InvalidInput,
+            "an invalid drive number was specified in the path name",
+        )),
+        vex_sdk::FRESULT::FR_NOT_ENABLED => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "work area for the logical drive has not been registered",
+        )),
+        vex_sdk::FRESULT::FR_NO_FILESYSTEM => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "valid FAT volume could not be found on the drive",
+        )),
+        vex_sdk::FRESULT::FR_MKFS_ABORTED => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "failed to create filesystem volume"
+        )),
+        vex_sdk::FRESULT::FR_TIMEOUT => Err(io::const_error!(
+            io::ErrorKind::TimedOut,
+            "the function was canceled due to a timeout of thread-safe control",
+        )),
+        vex_sdk::FRESULT::FR_LOCKED => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "the operation to the object was rejected by file sharing control",
+        )),
+        vex_sdk::FRESULT::FR_NOT_ENOUGH_CORE => {
+            Err(io::const_error!(io::ErrorKind::OutOfMemory, "not enough memory for the operation"))
+        }
+        vex_sdk::FRESULT::FR_TOO_MANY_OPEN_FILES => Err(io::const_error!(
+            io::ErrorKind::Uncategorized,
+            "maximum number of open files has been reached",
+        )),
+        vex_sdk::FRESULT::FR_INVALID_PARAMETER => {
+            Err(io::const_error!(io::ErrorKind::InvalidInput, "a given parameter was invalid"))
+        }
+        _ => unreachable!(), // C-style enum
+    }
+}
diff --git a/library/std/src/sys/fs/wasi.rs b/library/std/src/sys/fs/wasi.rs
index b65d86de12a..0b65b9cb389 100644
--- a/library/std/src/sys/fs/wasi.rs
+++ b/library/std/src/sys/fs/wasi.rs
@@ -848,7 +848,14 @@ fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> {
 
     // Iterate over all the entries in this directory, and travel recursively if
     // necessary
-    for entry in ReadDir::new(fd, dummy_root) {
+    //
+    // Note that all directory entries for this directory are read first before
+    // any removal is done. This works around the fact that the WASIp1 API for
+    // reading directories is not well-designed for handling mutations between
+    // invocations of reading a directory. By reading all the entries at once
+    // this ensures that, at least without concurrent modifications, it should
+    // be possible to delete everything.
+    for entry in ReadDir::new(fd, dummy_root).collect::<Vec<_>>() {
         let entry = entry?;
         let path = crate::str::from_utf8(&entry.name).map_err(|_| {
             io::const_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found")
diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs
index 9b54571997d..8c9c17d3f17 100644
--- a/library/std/src/sys/net/connection/sgx.rs
+++ b/library/std/src/sys/net/connection/sgx.rs
@@ -499,16 +499,6 @@ impl fmt::Display for NonIpSockAddr {
 
 pub struct LookupHost(!);
 
-impl LookupHost {
-    fn new(host: String) -> io::Result<LookupHost> {
-        Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host }))
-    }
-
-    pub fn port(&self) -> u16 {
-        self.0
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -516,18 +506,9 @@ impl Iterator for LookupHost {
     }
 }
 
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(v: &str) -> io::Result<LookupHost> {
-        LookupHost::new(v.to_owned())
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
-        LookupHost::new(format!("{host}:{port}"))
-    }
+pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
+    Err(io::Error::new(
+        io::ErrorKind::Uncategorized,
+        NonIpSockAddr { host: format!("{host}:{port}") },
+    ))
 }
diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs
index 564f2e3a01f..1dd06e97bba 100644
--- a/library/std/src/sys/net/connection/socket/mod.rs
+++ b/library/std/src/sys/net/connection/socket/mod.rs
@@ -258,7 +258,7 @@ fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// get_host_addresses
+// lookup_host
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct LookupHost {
@@ -267,12 +267,6 @@ pub struct LookupHost {
     port: u16,
 }
 
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.port
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -281,7 +275,10 @@ impl Iterator for LookupHost {
                 let cur = self.cur.as_ref()?;
                 self.cur = cur.ai_next;
                 match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
-                    Ok(addr) => return Some(addr),
+                    Ok(mut addr) => {
+                        addr.set_port(self.port);
+                        return Some(addr);
+                    }
                     Err(_) => continue,
                 }
             }
@@ -298,42 +295,17 @@ impl Drop for LookupHost {
     }
 }
 
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(s: &str) -> io::Result<LookupHost> {
-        macro_rules! try_opt {
-            ($e:expr, $msg:expr) => {
-                match $e {
-                    Some(r) => r,
-                    None => return Err(io::const_error!(io::ErrorKind::InvalidInput, $msg)),
-                }
-            };
+pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
+    init();
+    run_with_cstr(host.as_bytes(), &|c_host| {
+        let mut hints: c::addrinfo = unsafe { mem::zeroed() };
+        hints.ai_socktype = c::SOCK_STREAM;
+        let mut res = ptr::null_mut();
+        unsafe {
+            cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
+                .map(|_| LookupHost { original: res, cur: res, port })
         }
-
-        // split the string by ':' and convert the second part to u16
-        let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
-        let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
-        (host, port).try_into()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
-        init();
-
-        run_with_cstr(host.as_bytes(), &|c_host| {
-            let mut hints: c::addrinfo = unsafe { mem::zeroed() };
-            hints.ai_socktype = c::SOCK_STREAM;
-            let mut res = ptr::null_mut();
-            unsafe {
-                cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
-                    .map(|_| LookupHost { original: res, cur: res, port })
-            }
-        })
-    }
+    })
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sys/net/connection/socket/tests.rs b/library/std/src/sys/net/connection/socket/tests.rs
index fc236b8027b..049355afca7 100644
--- a/library/std/src/sys/net/connection/socket/tests.rs
+++ b/library/std/src/sys/net/connection/socket/tests.rs
@@ -4,7 +4,7 @@ use crate::collections::HashMap;
 #[test]
 fn no_lookup_host_duplicates() {
     let mut addrs = HashMap::new();
-    let lh = match LookupHost::try_from(("localhost", 0)) {
+    let lh = match lookup_host("localhost", 0) {
         Ok(lh) => lh,
         Err(e) => panic!("couldn't resolve `localhost`: {e}"),
     };
diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs
index 00368042873..004f6d413a1 100644
--- a/library/std/src/sys/net/connection/uefi/mod.rs
+++ b/library/std/src/sys/net/connection/uefi/mod.rs
@@ -333,12 +333,6 @@ impl fmt::Debug for UdpSocket {
 
 pub struct LookupHost(!);
 
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.0
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -346,18 +340,6 @@ impl Iterator for LookupHost {
     }
 }
 
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: &str) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
-        unsupported()
-    }
+pub fn lookup_host(_host: &str, _port: u16) -> io::Result<LookupHost> {
+    unsupported()
 }
diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs
index fbc86343272..fb18e8dec55 100644
--- a/library/std/src/sys/net/connection/unsupported.rs
+++ b/library/std/src/sys/net/connection/unsupported.rs
@@ -304,12 +304,6 @@ impl fmt::Debug for UdpSocket {
 
 pub struct LookupHost(!);
 
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.0
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -317,18 +311,6 @@ impl Iterator for LookupHost {
     }
 }
 
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: &str) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
-        unsupported()
-    }
+pub fn lookup_host(_host: &str, _port: u16) -> io::Result<LookupHost> {
+    unsupported()
 }
diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs
index cdfa25c8a44..048dafdcd7f 100644
--- a/library/std/src/sys/net/connection/wasip1.rs
+++ b/library/std/src/sys/net/connection/wasip1.rs
@@ -477,12 +477,6 @@ impl fmt::Debug for UdpSocket {
 
 pub struct LookupHost(!);
 
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.0
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -490,18 +484,6 @@ impl Iterator for LookupHost {
     }
 }
 
-impl<'a> TryFrom<&'a str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: &'a str) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
-        unsupported()
-    }
+pub fn lookup_host(_host: &str, _port: u16) -> io::Result<LookupHost> {
+    unsupported()
 }
diff --git a/library/std/src/sys/net/connection/xous/dns.rs b/library/std/src/sys/net/connection/xous/dns.rs
index bb29d211fad..b139376f597 100644
--- a/library/std/src/sys/net/connection/xous/dns.rs
+++ b/library/std/src/sys/net/connection/xous/dns.rs
@@ -1,15 +1,8 @@
-use core::convert::{TryFrom, TryInto};
-
 use crate::io;
 use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
 use crate::os::xous::ffi::lend_mut;
 use crate::os::xous::services::{DnsLendMut, dns_server};
 
-pub struct DnsError {
-    #[allow(dead_code)]
-    pub code: u8,
-}
-
 #[repr(C, align(4096))]
 struct LookupHostQuery([u8; 4096]);
 
@@ -20,12 +13,6 @@ pub struct LookupHost {
     count: usize,
 }
 
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        self.port
-    }
-}
-
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> {
@@ -72,7 +59,7 @@ impl Iterator for LookupHost {
     }
 }
 
-pub fn lookup(query: &str, port: u16) -> Result<LookupHost, DnsError> {
+pub fn lookup_host(query: &str, port: u16) -> io::Result<LookupHost> {
     let mut result = LookupHost { data: LookupHostQuery([0u8; 4096]), offset: 0, count: 0, port };
 
     // Copy the query into the message that gets sent to the DNS server
@@ -89,7 +76,7 @@ pub fn lookup(query: &str, port: u16) -> Result<LookupHost, DnsError> {
     )
     .unwrap();
     if result.data.0[0] != 0 {
-        return Err(DnsError { code: result.data.0[1] });
+        return Err(io::const_error!(io::ErrorKind::InvalidInput, "DNS failure"));
     }
     assert_eq!(result.offset, 0);
     result.count = result.data.0[1] as usize;
@@ -98,31 +85,3 @@ pub fn lookup(query: &str, port: u16) -> Result<LookupHost, DnsError> {
     result.offset = 2;
     Ok(result)
 }
-
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(s: &str) -> io::Result<LookupHost> {
-        macro_rules! try_opt {
-            ($e:expr, $msg:expr) => {
-                match $e {
-                    Some(r) => r,
-                    None => return Err(io::const_error!(io::ErrorKind::InvalidInput, &$msg)),
-                }
-            };
-        }
-
-        // split the string by ':' and convert the second part to u16
-        let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
-        let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
-        (host, port).try_into()
-    }
-}
-
-impl TryFrom<(&str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(v: (&str, u16)) -> io::Result<LookupHost> {
-        lookup(v.0, v.1).map_err(|_e| io::const_error!(io::ErrorKind::InvalidInput, "DNS failure"))
-    }
-}
diff --git a/library/std/src/sys/net/connection/xous/mod.rs b/library/std/src/sys/net/connection/xous/mod.rs
index e44a375b9e3..0f77be5c3fa 100644
--- a/library/std/src/sys/net/connection/xous/mod.rs
+++ b/library/std/src/sys/net/connection/xous/mod.rs
@@ -45,4 +45,4 @@ pub struct GetAddress {
     raw: [u8; 4096],
 }
 
-pub use dns::LookupHost;
+pub use dns::lookup_host;
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index f76a5f96c87..bd6fd5a3de4 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -26,15 +26,22 @@ impl Timespec {
     }
 
     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
+            debug_assert!(a >= b);
+            a.wrapping_sub(b).cast_unsigned()
+        }
+
         if self >= other {
+            // Logic here is identical to Unix version of `Timestamp::sub_timespec`,
+            // check comments there why operations do not overflow.
             Ok(if self.t.tv_nsec >= other.t.tv_nsec {
                 Duration::new(
-                    (self.t.tv_sec - other.t.tv_sec) as u64,
+                    sub_ge_to_unsigned(self.t.tv_sec, other.t.tv_sec),
                     (self.t.tv_nsec - other.t.tv_nsec) as u32,
                 )
             } else {
                 Duration::new(
-                    (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+                    sub_ge_to_unsigned(self.t.tv_sec - 1, other.t.tv_sec),
                     (self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32,
                 )
             })
diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs
index 513121c6d30..dd5e83ee570 100644
--- a/library/std/src/sys/pal/mod.rs
+++ b/library/std/src/sys/pal/mod.rs
@@ -45,6 +45,10 @@ cfg_select! {
         mod trusty;
         pub use self::trusty::*;
     }
+    target_os = "vexos" => {
+        mod vexos;
+        pub use self::vexos::*;
+    }
     all(target_os = "wasi", target_env = "p2") => {
         mod wasip2;
         pub use self::wasip2::*;
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
index 275f6062463..cf0c098f8a2 100644
--- a/library/std/src/sys/pal/trusty/mod.rs
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -7,8 +7,6 @@ mod common;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/thread.rs"]
-pub mod thread;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index b50574de937..c0d69c3e002 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -92,6 +92,9 @@ pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ff
 ///
 /// Queries a handle to determine if it supports a specified protocol. If the protocol is
 /// supported by the handle, it opens the protocol on behalf of the calling agent.
+///
+/// The protocol is opened with the attribute GET_PROTOCOL, which means the caller is not required
+/// to close the protocol interface with `EFI_BOOT_SERVICES.CloseProtocol()`
 pub(crate) fn open_protocol<T>(
     handle: NonNull<crate::ffi::c_void>,
     mut protocol_guid: Guid,
@@ -473,6 +476,7 @@ impl<'a> crate::fmt::Debug for DevicePathNode<'a> {
     }
 }
 
+/// Protocols installed by Rust side on a handle.
 pub(crate) struct OwnedProtocol<T> {
     guid: r_efi::efi::Guid,
     handle: NonNull<crate::ffi::c_void>,
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 0d2100d66bc..51463eef5b7 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -72,7 +72,7 @@ mod imp {
     use crate::sync::OnceLock;
     use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
     use crate::sys::pal::unix::os;
-    use crate::{io, mem, panic, ptr};
+    use crate::{io, mem, ptr};
 
     // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
     // (unmapped pages) at the end of every thread's stack, so if a thread ends
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index bd7f74fea6a..c207f41cad4 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -134,28 +134,25 @@ impl Timespec {
     }
 
     pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        // When a >= b, the difference fits in u64.
+        fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
+            debug_assert!(a >= b);
+            a.wrapping_sub(b).cast_unsigned()
+        }
+
         if self >= other {
-            // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
-            // to optimize it into a branchless form (see also #75545):
-            //
-            // 1. `self.tv_sec - other.tv_sec` shows up as a common expression
-            //    in both branches, i.e. the `else` must have its `- 1`
-            //    subtraction after the common one, not interleaved with it
-            //    (it used to be `self.tv_sec - 1 - other.tv_sec`)
-            //
-            // 2. the `Duration::new` call (or any other additional complexity)
-            //    is outside of the `if`-`else`, not duplicated in both branches
-            //
-            // Ideally this code could be rearranged such that it more
-            // directly expresses the lower-cost behavior we want from it.
             let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() {
                 (
-                    (self.tv_sec - other.tv_sec) as u64,
+                    sub_ge_to_unsigned(self.tv_sec, other.tv_sec),
                     self.tv_nsec.as_inner() - other.tv_nsec.as_inner(),
                 )
             } else {
+                // Following sequence of assertions explain why `self.tv_sec - 1` does not underflow.
+                debug_assert!(self.tv_nsec < other.tv_nsec);
+                debug_assert!(self.tv_sec > other.tv_sec);
+                debug_assert!(self.tv_sec > i64::MIN);
                 (
-                    (self.tv_sec - other.tv_sec - 1) as u64,
+                    sub_ge_to_unsigned(self.tv_sec - 1, other.tv_sec),
                     self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(),
                 )
             };
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 5e3295b1331..e64bbc7c616 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -2,7 +2,6 @@
 
 pub mod os;
 pub mod pipe;
-pub mod thread;
 pub mod time;
 
 mod common;
diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs
new file mode 100644
index 00000000000..61a34b0f68a
--- /dev/null
+++ b/library/std/src/sys/pal/vexos/mod.rs
@@ -0,0 +1,80 @@
+#[path = "../unsupported/os.rs"]
+pub mod os;
+#[path = "../unsupported/pipe.rs"]
+pub mod pipe;
+pub mod time;
+
+#[expect(dead_code)]
+#[path = "../unsupported/common.rs"]
+mod unsupported_common;
+
+pub use unsupported_common::{
+    decode_error_kind, init, is_interrupted, unsupported, unsupported_err,
+};
+
+use crate::arch::global_asm;
+use crate::ptr;
+use crate::sys::stdio;
+use crate::time::{Duration, Instant};
+
+global_asm!(
+    r#"
+    .section .boot, "ax"
+    .global _boot
+
+    _boot:
+        ldr sp, =__stack_top @ Set up the user stack.
+        b _start             @ Jump to the Rust entrypoint.
+    "#
+);
+
+#[cfg(not(test))]
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn _start() -> ! {
+    unsafe extern "C" {
+        static mut __bss_start: u8;
+        static mut __bss_end: u8;
+
+        fn main() -> i32;
+    }
+
+    // Clear the .bss (uninitialized statics) section by filling it with zeroes.
+    // This is required, since the compiler assumes it will be zeroed on first access.
+    ptr::write_bytes(
+        &raw mut __bss_start,
+        0,
+        (&raw mut __bss_end).offset_from_unsigned(&raw mut __bss_start),
+    );
+
+    main();
+
+    cleanup();
+    abort_internal()
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {
+    let exit_time = Instant::now();
+    const FLUSH_TIMEOUT: Duration = Duration::from_millis(15);
+
+    // Force the serial buffer to flush
+    while exit_time.elapsed() < FLUSH_TIMEOUT {
+        vex_sdk::vexTasksRun();
+
+        // If the buffer has been fully flushed, exit the loop
+        if vex_sdk::vexSerialWriteFree(stdio::STDIO_CHANNEL) == (stdio::STDOUT_BUF_SIZE as i32) {
+            break;
+        }
+    }
+}
+
+pub fn abort_internal() -> ! {
+    unsafe {
+        vex_sdk::vexSystemExitRequest();
+
+        loop {
+            vex_sdk::vexTasksRun();
+        }
+    }
+}
diff --git a/library/std/src/sys/pal/vexos/time.rs b/library/std/src/sys/pal/vexos/time.rs
new file mode 100644
index 00000000000..f95d96cd27a
--- /dev/null
+++ b/library/std/src/sys/pal/vexos/time.rs
@@ -0,0 +1,28 @@
+use crate::time::Duration;
+
+#[expect(dead_code)]
+#[path = "../unsupported/time.rs"]
+mod unsupported_time;
+pub use unsupported_time::{SystemTime, UNIX_EPOCH};
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct Instant(Duration);
+
+impl Instant {
+    pub fn now() -> Instant {
+        let micros = unsafe { vex_sdk::vexSystemHighResTimeGet() };
+        Self(Duration::from_micros(micros))
+    }
+
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
+    }
+
+    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
+        Some(Instant(self.0.checked_add(*other)?))
+    }
+
+    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
+        Some(Instant(self.0.checked_sub(*other)?))
+    }
+}
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index e1efa240685..9069c8d12fa 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -14,8 +14,6 @@ pub mod abi;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
-#[path = "../unsupported/thread.rs"]
-pub mod thread;
 #[path = "../unsupported/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/process/mod.rs b/library/std/src/sys/process/mod.rs
index 9ef5496e57a..a1ed0cd2cdd 100644
--- a/library/std/src/sys/process/mod.rs
+++ b/library/std/src/sys/process/mod.rs
@@ -24,7 +24,7 @@ mod env;
 
 pub use env::CommandEnvs;
 pub use imp::{
-    Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes,
+    Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
 };
 
 #[cfg(any(
diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs
index 4864c586988..11c8b682bb9 100644
--- a/library/std/src/sys/process/uefi.rs
+++ b/library/std/src/sys/process/uefi.rs
@@ -6,6 +6,7 @@ pub use crate::ffi::OsString as EnvKey;
 use crate::ffi::{OsStr, OsString};
 use crate::num::{NonZero, NonZeroI32};
 use crate::path::Path;
+use crate::process::StdioPipes;
 use crate::sys::fs::File;
 use crate::sys::pal::helpers;
 use crate::sys::pal::os::error_string;
@@ -27,14 +28,6 @@ pub struct Command {
     env: CommandEnv,
 }
 
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum Stdio {
     Inherit,
diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs
index ea45b08e90a..1d5909e99ba 100644
--- a/library/std/src/sys/process/unix/common.rs
+++ b/library/std/src/sys/process/unix/common.rs
@@ -9,6 +9,7 @@ use crate::collections::BTreeMap;
 use crate::ffi::{CStr, CString, OsStr, OsString};
 use crate::os::unix::prelude::*;
 use crate::path::Path;
+use crate::process::StdioPipes;
 use crate::sys::fd::FileDesc;
 use crate::sys::fs::File;
 #[cfg(not(target_os = "fuchsia"))]
@@ -104,14 +105,6 @@ pub struct Command {
     setsid: bool,
 }
 
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
 // passed to do_exec() with configuration of what the child stdio should look
 // like
 #[cfg_attr(target_os = "vita", allow(dead_code))]
diff --git a/library/std/src/sys/process/unix/fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs
index d71be510b6a..3fae5ec1468 100644
--- a/library/std/src/sys/process/unix/fuchsia.rs
+++ b/library/std/src/sys/process/unix/fuchsia.rs
@@ -2,6 +2,7 @@ use libc::{c_int, size_t};
 
 use super::common::*;
 use crate::num::NonZero;
+use crate::process::StdioPipes;
 use crate::sys::pal::fuchsia::*;
 use crate::{fmt, io, mem, ptr};
 
diff --git a/library/std/src/sys/process/unix/mod.rs b/library/std/src/sys/process/unix/mod.rs
index b4cf060fba9..cda1bf74f1c 100644
--- a/library/std/src/sys/process/unix/mod.rs
+++ b/library/std/src/sys/process/unix/mod.rs
@@ -23,5 +23,5 @@ cfg_select! {
 
 pub use imp::{ExitStatus, ExitStatusError, Process};
 
-pub use self::common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes};
+pub use self::common::{Command, CommandArgs, ExitCode, Stdio};
 pub use crate::ffi::OsString as EnvKey;
diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs
index 11d48878727..7d944f2f7ee 100644
--- a/library/std/src/sys/process/unix/unix.rs
+++ b/library/std/src/sys/process/unix/unix.rs
@@ -13,6 +13,7 @@ use libc::{gid_t, uid_t};
 use super::common::*;
 use crate::io::{self, Error, ErrorKind};
 use crate::num::NonZero;
+use crate::process::StdioPipes;
 use crate::sys::cvt;
 #[cfg(target_os = "linux")]
 use crate::sys::pal::linux::pidfd::PidFd;
diff --git a/library/std/src/sys/process/unix/unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs
index f4d6ac6b4e3..663ba61f966 100644
--- a/library/std/src/sys/process/unix/unix/tests.rs
+++ b/library/std/src/sys/process/unix/unix/tests.rs
@@ -51,6 +51,7 @@ fn exitstatus_display_tests() {
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn test_command_fork_no_unwind() {
     let got = catch_unwind(|| {
         let mut c = Command::new("echo");
diff --git a/library/std/src/sys/process/unix/unsupported.rs b/library/std/src/sys/process/unix/unsupported.rs
index 87403cd50f8..9bda394f246 100644
--- a/library/std/src/sys/process/unix/unsupported.rs
+++ b/library/std/src/sys/process/unix/unsupported.rs
@@ -3,6 +3,7 @@ use libc::{c_int, pid_t};
 use super::common::*;
 use crate::io;
 use crate::num::NonZero;
+use crate::process::StdioPipes;
 use crate::sys::pal::unsupported::*;
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs
index 2275cbb946a..346ca6d74c9 100644
--- a/library/std/src/sys/process/unix/vxworks.rs
+++ b/library/std/src/sys/process/unix/vxworks.rs
@@ -4,8 +4,8 @@ use libc::{self, RTP_ID, c_char, c_int};
 use super::common::*;
 use crate::io::{self, ErrorKind};
 use crate::num::NonZero;
-use crate::sys::cvt;
-use crate::sys::pal::thread;
+use crate::process::StdioPipes;
+use crate::sys::{cvt, thread};
 use crate::{fmt, sys};
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sys/process/unsupported.rs b/library/std/src/sys/process/unsupported.rs
index 469922c78ac..636465b68e5 100644
--- a/library/std/src/sys/process/unsupported.rs
+++ b/library/std/src/sys/process/unsupported.rs
@@ -3,6 +3,7 @@ pub use crate::ffi::OsString as EnvKey;
 use crate::ffi::{OsStr, OsString};
 use crate::num::NonZero;
 use crate::path::Path;
+use crate::process::StdioPipes;
 use crate::sys::fs::File;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::unsupported;
@@ -23,14 +24,6 @@ pub struct Command {
     stderr: Option<Stdio>,
 }
 
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
 #[derive(Debug)]
 pub enum Stdio {
     Inherit,
diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs
index f9e15b82475..1f2001bdc20 100644
--- a/library/std/src/sys/process/windows.rs
+++ b/library/std/src/sys/process/windows.rs
@@ -15,6 +15,7 @@ use crate::os::windows::ffi::{OsStrExt, OsStringExt};
 use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle};
 use crate::os::windows::process::ProcThreadAttributeList;
 use crate::path::{Path, PathBuf};
+use crate::process::StdioPipes;
 use crate::sync::Mutex;
 use crate::sys::args::{self, Arg};
 use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS};
@@ -169,12 +170,6 @@ pub enum Stdio {
     Handle(Handle),
 }
 
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
 impl Command {
     pub fn new(program: &OsStr) -> Command {
         Command {
diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs
index 1e0eec07b50..3c5a4c82a9f 100644
--- a/library/std/src/sys/random/mod.rs
+++ b/library/std/src/sys/random/mod.rs
@@ -101,6 +101,7 @@ cfg_select! {
     any(
         all(target_family = "wasm", target_os = "unknown"),
         target_os = "xous",
+        target_os = "vexos",
     ) => {
         // FIXME: finally remove std support for wasm32-unknown-unknown
         // FIXME: add random data generation to xous
@@ -116,6 +117,7 @@ cfg_select! {
     all(target_family = "wasm", target_os = "unknown"),
     all(target_os = "wasi", target_env = "p2"),
     target_os = "xous",
+    target_os = "vexos",
 )))]
 pub fn hashmap_random_keys() -> (u64, u64) {
     let mut buf = [0; 16];
diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs
index 7436e4d9de4..404ac877926 100644
--- a/library/std/src/sys/stdio/mod.rs
+++ b/library/std/src/sys/stdio/mod.rs
@@ -29,6 +29,10 @@ cfg_select! {
         mod uefi;
         pub use uefi::*;
     }
+    target_os = "vexos" => {
+        mod vexos;
+        pub use vexos::*;
+    }
     all(target_os = "wasi", target_env = "p1") => {
         mod wasip1;
         pub use wasip1::*;
diff --git a/library/std/src/sys/stdio/vexos.rs b/library/std/src/sys/stdio/vexos.rs
new file mode 100644
index 00000000000..9a391feb7a8
--- /dev/null
+++ b/library/std/src/sys/stdio/vexos.rs
@@ -0,0 +1,100 @@
+use crate::io;
+
+pub struct Stdin;
+pub struct Stdout;
+pub type Stderr = Stdout;
+
+pub const STDIO_CHANNEL: u32 = 1;
+
+impl Stdin {
+    pub const fn new() -> Stdin {
+        Stdin
+    }
+}
+
+impl io::Read for Stdin {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let mut count = 0;
+
+        for out_byte in buf.iter_mut() {
+            let byte = unsafe { vex_sdk::vexSerialReadChar(STDIO_CHANNEL) };
+            if byte < 0 {
+                break;
+            }
+
+            *out_byte = byte as u8;
+            count += 1;
+        }
+
+        Ok(count)
+    }
+}
+
+impl Stdout {
+    pub const fn new() -> Stdout {
+        Stdout
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let mut written = 0;
+
+        // HACK: VEXos holds an internal ringbuffer for serial writes that is flushed to USB1
+        // roughly every millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we
+        // must block until that buffer is flushed to USB1 before writing the rest of `buf`.
+        //
+        // This is fairly nonstandard for a `write` implementation, but it avoids a guaranteed
+        // recursive panic when using macros such as `print!` to write large amounts of data
+        // (buf.len() > 2048) to stdout at once.
+        for chunk in buf.chunks(STDOUT_BUF_SIZE) {
+            if unsafe { vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize } < chunk.len() {
+                self.flush().unwrap();
+            }
+
+            let count: usize = unsafe {
+                vex_sdk::vexSerialWriteBuffer(STDIO_CHANNEL, chunk.as_ptr(), chunk.len() as u32)
+            }
+            .try_into()
+            .map_err(|_| {
+                io::const_error!(io::ErrorKind::Uncategorized, "internal write error occurred")
+            })?;
+
+            written += count;
+
+            // This is a sanity check to ensure that we don't end up with non-contiguous
+            // buffer writes. e.g. a chunk gets only partially written, but we continue
+            // attempting to write the remaining chunks.
+            //
+            // In practice, this should never really occur since the previous flush ensures
+            // enough space in FIFO to write the entire chunk to vexSerialWriteBuffer.
+            if count != chunk.len() {
+                break;
+            }
+        }
+
+        Ok(written)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        // This may block for up to a millisecond.
+        unsafe {
+            while (vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize) != STDOUT_BUF_SIZE {
+                vex_sdk::vexTasksRun();
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub const STDIN_BUF_SIZE: usize = 4096;
+pub const STDOUT_BUF_SIZE: usize = 2048;
+
+pub fn is_ebadf(_err: &io::Error) -> bool {
+    false
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Some(Stdout::new())
+}
diff --git a/library/std/src/sys/thread/mod.rs b/library/std/src/sys/thread/mod.rs
index 6bb7fc1a20e..3bd83dd760a 100644
--- a/library/std/src/sys/thread/mod.rs
+++ b/library/std/src/sys/thread/mod.rs
@@ -81,6 +81,13 @@ cfg_select! {
         ))]
         pub use unsupported::set_name;
     }
+    target_os = "vexos" => {
+        mod vexos;
+        pub use vexos::{sleep, yield_now};
+        #[expect(dead_code)]
+        mod unsupported;
+        pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE};
+    }
     all(target_os = "wasi", target_env = "p1") => {
         mod wasip1;
         pub use wasip1::{DEFAULT_MIN_STACK_SIZE, sleep, yield_now};
diff --git a/library/std/src/sys/thread/vexos.rs b/library/std/src/sys/thread/vexos.rs
new file mode 100644
index 00000000000..d917dde4d0b
--- /dev/null
+++ b/library/std/src/sys/thread/vexos.rs
@@ -0,0 +1,17 @@
+use crate::time::{Duration, Instant};
+
+pub fn yield_now() {
+    unsafe {
+        vex_sdk::vexTasksRun();
+    }
+}
+
+pub fn sleep(dur: Duration) {
+    let start = Instant::now();
+
+    while start.elapsed() < dur {
+        unsafe {
+            vex_sdk::vexTasksRun();
+        }
+    }
+}
diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs
index cff74857c47..d5c795093cf 100644
--- a/library/std/src/sys/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
@@ -29,6 +29,7 @@ cfg_select! {
         target_os = "uefi",
         target_os = "zkvm",
         target_os = "trusty",
+        target_os = "vexos",
     ) => {
         mod no_threads;
         pub use no_threads::{EagerStorage, LazyStorage, thread_local_inner};
@@ -98,6 +99,7 @@ pub(crate) mod guard {
             target_os = "uefi",
             target_os = "zkvm",
             target_os = "trusty",
+            target_os = "vexos",
         ) => {
             pub(crate) fn enable() {
                 // FIXME: Right now there is no concept of "thread exit" on
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 797feeb2bbb..0a6f2e5d508 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -230,7 +230,7 @@ impl fmt::Display for AccessError {
 impl Error for AccessError {}
 
 // This ensures the panicking code is outlined from `with` for `LocalKey`.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
 #[track_caller]
 #[cold]
 fn panic_access_error(err: AccessError) -> ! {
diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs
index fa76c50597b..837a14b808f 100644
--- a/library/std/tests/path.rs
+++ b/library/std/tests/path.rs
@@ -2528,7 +2528,17 @@ fn normalize_lexically() {
 }
 
 #[test]
-/// See issue#146183
-fn compare_path_to_str() {
-    assert!(&PathBuf::from("x") == "x");
+/// See issue#146183 and issue#146940
+fn compare_path_like_to_str_like() {
+    let path_buf = PathBuf::from("x");
+    let path = Path::new("x");
+    let s = String::from("x");
+    assert!(path == "x");
+    assert!("x" == path);
+    assert!(path == &s);
+    assert!(&s == path);
+    assert!(&path_buf == "x");
+    assert!("x" == &path_buf);
+    assert!(path_buf == s);
+    assert!(s == path_buf);
 }
diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs
index 43b45cb2d2b..93f73ccad3e 100644
--- a/library/std/tests/process_spawning.rs
+++ b/library/std/tests/process_spawning.rs
@@ -7,6 +7,7 @@ mod common;
 #[test]
 // Process spawning not supported by Miri, Emscripten and wasi
 #[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn issue_15149() {
     // If we're the parent, copy our own binary to a new directory.
     let my_path = env::current_exe().unwrap();
diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs
index 40709eae37c..be1948af915 100644
--- a/library/std/tests/time.rs
+++ b/library/std/tests/time.rs
@@ -227,3 +227,19 @@ fn big_math() {
     check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub);
     check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub);
 }
+
+#[test]
+#[cfg(unix)]
+fn system_time_duration_since_max_range_on_unix() {
+    // Repro regression https://github.com/rust-lang/rust/issues/146228
+
+    // Min and max values of `SystemTime` on Unix.
+    let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0));
+    let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999));
+
+    let delta_a = max.duration_since(min).expect("duration_since overflow");
+    let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration();
+
+    assert_eq!(Duration::MAX, delta_a);
+    assert_eq!(Duration::MAX, delta_b);
+}