about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-25 22:59:40 +0000
committerbors <bors@rust-lang.org>2025-02-25 22:59:40 +0000
commitcb06d12710575a0d7ff71d6fe108f3bcff4f9195 (patch)
tree1d2263c41f45a887f2a6829bc177e5cd45a0c893
parent85abb276361c424d64743c0965242dd0e7b866d1 (diff)
parent716dd22c04e936853b9bc963da616e1b28525e6b (diff)
downloadrust-cb06d12710575a0d7ff71d6fe108f3bcff4f9195.tar.gz
rust-cb06d12710575a0d7ff71d6fe108f3bcff4f9195.zip
Auto merge of #137594 - RalfJung:miri-sync, r=RalfJung
Miri subtree update

r? `@ghost`

try-job: x86_64-gnu-aux
-rw-r--r--library/coretests/tests/num/int_log.rs1
-rw-r--r--src/build_helper/src/git.rs1
-rw-r--r--src/tools/miri/.github/workflows/ci.yml2
-rw-r--r--src/tools/miri/.github/workflows/setup/action.yml6
-rw-r--r--src/tools/miri/Cargo.toml4
-rw-r--r--src/tools/miri/build.rs10
-rwxr-xr-xsrc/tools/miri/ci/ci.sh13
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs6
-rw-r--r--src/tools/miri/src/helpers.rs69
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs16
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs163
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs34
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs5
-rw-r--r--src/tools/miri/src/math.rs16
-rw-r--r--src/tools/miri/src/shims/aarch64.rs78
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs64
-rw-r--r--src/tools/miri/src/shims/mod.rs1
-rw-r--r--src/tools/miri/src/shims/panic.rs4
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs153
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux_like/sync.rs8
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_abort.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr4
-rw-r--r--src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs14
-rw-r--r--src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr15
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-misc.rs5
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs8
-rw-r--r--src/tools/miri/tests/pass/float.rs235
-rw-r--r--src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs40
-rw-r--r--src/tools/miri/tests/ui.rs14
-rw-r--r--src/tools/miri/tests/x86_64-unknown-kernel.json1
38 files changed, 715 insertions, 298 deletions
diff --git a/library/coretests/tests/num/int_log.rs b/library/coretests/tests/num/int_log.rs
index 60902752dab..9c630a61dd5 100644
--- a/library/coretests/tests/num/int_log.rs
+++ b/library/coretests/tests/num/int_log.rs
@@ -34,6 +34,7 @@ fn checked_ilog() {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // FIXME test is broken on Miri: https://github.com/rust-lang/rust/issues/137591
 fn checked_ilog2() {
     assert_eq!(5u32.checked_ilog2(), Some(2));
     assert_eq!(0u64.checked_ilog2(), None);
diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs
index 3ef9c7ac35e..8f0b67ddbd3 100644
--- a/src/build_helper/src/git.rs
+++ b/src/build_helper/src/git.rs
@@ -154,7 +154,6 @@ pub fn get_closest_merge_commit(
         "rev-list",
         &format!("--author={}", config.git_merge_commit_email),
         "-n1",
-        "--first-parent",
         &merge_base,
     ]);
 
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 81df0964d59..59bae513a58 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -30,6 +30,8 @@ jobs:
     steps:
       - uses: actions/checkout@v4
       - uses: ./.github/workflows/setup
+        with:
+          toolchain_flags: "--host ${{ matrix.host_target }}"
 
       # The `style` job only runs on Linux; this makes sure the Windows-host-specific
       # code is also covered by clippy.
diff --git a/src/tools/miri/.github/workflows/setup/action.yml b/src/tools/miri/.github/workflows/setup/action.yml
index bf5749a7b17..146b432171e 100644
--- a/src/tools/miri/.github/workflows/setup/action.yml
+++ b/src/tools/miri/.github/workflows/setup/action.yml
@@ -1,5 +1,9 @@
 name: "Miri CI setup"
 description: "Sets up Miri CI"
+inputs:
+  toolchain_flags:
+    required: false
+    default: ''
 runs:
   using: "composite"
   steps:
@@ -45,7 +49,7 @@ runs:
             echo "Building against latest rustc git version"
             git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
           fi
-          ./miri toolchain
+          ./miri toolchain ${{ inputs.toolchain_flags }}
         shell: bash
 
       - name: Show Rust version (miri toolchain)
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index de80722fc3d..728a7552fd8 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -67,6 +67,10 @@ default = ["stack-cache"]
 stack-cache = []
 stack-cache-consistency-check = ["stack-cache"]
 
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = ['cfg(bootstrap)']
+
 # Be aware that this file is inside a workspace when used via the
 # submodule in the rustc repo. That means there are many cargo features
 # we cannot use, such as profiles.
diff --git a/src/tools/miri/build.rs b/src/tools/miri/build.rs
deleted file mode 100644
index 0918c9b1321..00000000000
--- a/src/tools/miri/build.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    // Don't rebuild miri when nothing changed.
-    println!("cargo:rerun-if-changed=build.rs");
-    // Re-export the TARGET environment variable so it can be accessed by miri. Needed to know the
-    // "host" triple inside Miri.
-    let target = std::env::var("TARGET").unwrap();
-    println!("cargo:rustc-env=TARGET={target}");
-    // Allow some cfgs.
-    println!("cargo::rustc-check-cfg=cfg(bootstrap)");
-}
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 5583030b490..3327ad17c44 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-set -euo pipefail
+set -eu
 
 function begingroup {
   echo "::group::$@"
@@ -11,6 +11,17 @@ function endgroup {
   echo "::endgroup"
 }
 
+begingroup "Sanity-check environment"
+
+# Ensure the HOST_TARGET is what it should be.
+if ! rustc -vV | grep -q "^host: $HOST_TARGET\$"; then
+  echo "This runner should be using host target $HOST_TARGET but rustc disagrees:"
+  rustc -vV
+  exit 1
+fi
+
+endgroup
+
 begingroup "Building Miri"
 
 # Global configuration
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 6e84524c8aa..b3e207f53b8 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-6dd75f0d6802f56564f5f9c947a85ded286d3986
+f5729cfed3c45e061e8a443677fc1d5ef9277df7
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 6b051da1b5a..56ee96502b3 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -29,8 +29,8 @@ use std::num::NonZero;
 use std::ops::Range;
 use std::path::PathBuf;
 use std::str::FromStr;
-use std::sync::{Arc, Once};
 use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
+use std::sync::{Arc, Once};
 
 use miri::{
     BacktraceStyle, BorrowTrackerMethod, MiriConfig, MiriEntryFnType, ProvenanceMode, RetagFields,
@@ -720,8 +720,8 @@ fn main() {
 
     // Ensure we have parallelism for many-seeds mode.
     if many_seeds.is_some() && !rustc_args.iter().any(|arg| arg.starts_with("-Zthreads=")) {
-        // Clamp to 10 threads; things get a lot less efficient beyond that due to lock contention.
-        let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(10);
+        // Clamp to 20 threads; things get a less efficient beyond that due to lock contention.
+        let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(20);
         rustc_args.push(format!("-Zthreads={threads}"));
     }
     let many_seeds =
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a26f12cdfb1..12e7d0f1a62 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -999,7 +999,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
     {
         self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
-        check_arg_count(args)
+
+        if abi.c_variadic {
+            throw_ub_format!(
+                "calling a non-variadic function with a variadic caller-side signature"
+            );
+        }
+        if let Ok(ops) = args.try_into() {
+            return interp_ok(ops);
+        }
+        throw_ub_format!(
+            "incorrect number of arguments for `{link_name}`: got {}, expected {}",
+            args.len(),
+            N
+        )
     }
 
     /// Check shim for variadic function.
@@ -1015,7 +1028,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>,
     {
         self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
-        check_vargarg_fixed_arg_count(link_name, abi, args)
+
+        if !abi.c_variadic {
+            throw_ub_format!(
+                "calling a variadic function with a non-variadic caller-side signature"
+            );
+        }
+        if abi.fixed_count != u32::try_from(N).unwrap() {
+            throw_ub_format!(
+                "incorrect number of fixed arguments for variadic function `{}`: got {}, expected {N}",
+                link_name.as_str(),
+                abi.fixed_count
+            )
+        }
+        if let Some(args) = args.split_first_chunk() {
+            return interp_ok(args);
+        }
+        panic!("mismatch between signature and `args` slice");
     }
 
     /// Mark a machine allocation that was just created as immutable.
@@ -1199,7 +1228,7 @@ impl<'tcx> MiriMachine<'tcx> {
 }
 
 /// Check that the number of args is what we expect.
-pub fn check_arg_count<'a, 'tcx, const N: usize>(
+pub fn check_intrinsic_arg_count<'a, 'tcx, const N: usize>(
     args: &'a [OpTy<'tcx>],
 ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>
 where
@@ -1208,7 +1237,11 @@ where
     if let Ok(ops) = args.try_into() {
         return interp_ok(ops);
     }
-    throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N)
+    throw_ub_format!(
+        "incorrect number of arguments for intrinsic: got {}, expected {}",
+        args.len(),
+        N
+    )
 }
 
 /// Check that the number of varargs is at least the minimum what we expect.
@@ -1228,34 +1261,6 @@ pub fn check_min_vararg_count<'a, 'tcx, const N: usize>(
     )
 }
 
-/// Check the number of fixed args of a vararg function.
-/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
-fn check_vargarg_fixed_arg_count<'a, 'tcx, const N: usize>(
-    link_name: Symbol,
-    abi: &FnAbi<'tcx, Ty<'tcx>>,
-    args: &'a [OpTy<'tcx>],
-) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> {
-    if !abi.c_variadic {
-        throw_ub_format!("calling a variadic function with a non-variadic caller-side signature");
-    }
-    if abi.fixed_count != u32::try_from(N).unwrap() {
-        throw_ub_format!(
-            "incorrect number of fixed arguments for variadic function `{}`: got {}, expected {N}",
-            link_name.as_str(),
-            abi.fixed_count
-        )
-    }
-    if let Some(args) = args.split_first_chunk() {
-        return interp_ok(args);
-    }
-    throw_ub_format!(
-        "incorrect number of arguments for `{}`: got {}, expected at least {}",
-        link_name.as_str(),
-        args.len(),
-        N
-    )
-}
-
 pub fn isolation_abort_error<'tcx>(name: &str) -> InterpResult<'tcx> {
     throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!(
         "{name} not available when isolation is enabled",
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 6d2a575ed76..dcafa7b6cab 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -1,7 +1,7 @@
 use rustc_middle::mir::BinOp;
 use rustc_middle::{mir, ty};
 
-use self::helpers::check_arg_count;
+use self::helpers::check_intrinsic_arg_count;
 use crate::*;
 
 pub enum AtomicOp {
@@ -131,7 +131,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let [place] = check_arg_count(args)?;
+        let [place] = check_intrinsic_arg_count(args)?;
         let place = this.deref_pointer(place)?;
 
         // Perform atomic load.
@@ -144,7 +144,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     fn atomic_store(&mut self, args: &[OpTy<'tcx>], atomic: AtomicWriteOrd) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let [place, val] = check_arg_count(args)?;
+        let [place, val] = check_intrinsic_arg_count(args)?;
         let place = this.deref_pointer(place)?;
 
         // Perform regular load.
@@ -159,7 +159,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         args: &[OpTy<'tcx>],
         atomic: AtomicFenceOrd,
     ) -> InterpResult<'tcx> {
-        let [] = check_arg_count(args)?;
+        let [] = check_intrinsic_arg_count(args)?;
         let _ = atomic;
         //FIXME: compiler fences are currently ignored
         interp_ok(())
@@ -171,7 +171,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         atomic: AtomicFenceOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let [] = check_arg_count(args)?;
+        let [] = check_intrinsic_arg_count(args)?;
         this.atomic_fence(atomic)?;
         interp_ok(())
     }
@@ -185,7 +185,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let [place, rhs] = check_arg_count(args)?;
+        let [place, rhs] = check_intrinsic_arg_count(args)?;
         let place = this.deref_pointer(place)?;
         let rhs = this.read_immediate(rhs)?;
 
@@ -226,7 +226,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let [place, new] = check_arg_count(args)?;
+        let [place, new] = check_intrinsic_arg_count(args)?;
         let place = this.deref_pointer(place)?;
         let new = this.read_scalar(new)?;
 
@@ -245,7 +245,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let [place, expect_old, new] = check_arg_count(args)?;
+        let [place, expect_old, new] = check_intrinsic_arg_count(args)?;
         let place = this.deref_pointer(place)?;
         let expect_old = this.read_immediate(expect_old)?; // read as immediate for the sake of `binary_op()`
         let new = this.read_scalar(new)?;
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 0faad0f7621..85fb280a9a9 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -7,12 +7,13 @@ use rand::Rng;
 use rustc_abi::Size;
 use rustc_apfloat::{Float, Round};
 use rustc_middle::mir;
-use rustc_middle::ty::{self, FloatTy};
+use rustc_middle::ty::{self, FloatTy, ScalarInt};
 use rustc_span::{Symbol, sym};
 
 use self::atomic::EvalContextExt as _;
-use self::helpers::{ToHost, ToSoft, check_arg_count};
+use self::helpers::{ToHost, ToSoft, check_intrinsic_arg_count};
 use self::simd::EvalContextExt as _;
+use crate::math::apply_random_float_error_ulp;
 use crate::*;
 
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -104,24 +105,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
             // Raw memory accesses
             "volatile_load" => {
-                let [place] = check_arg_count(args)?;
+                let [place] = check_intrinsic_arg_count(args)?;
                 let place = this.deref_pointer(place)?;
                 this.copy_op(&place, dest)?;
             }
             "volatile_store" => {
-                let [place, dest] = check_arg_count(args)?;
+                let [place, dest] = check_intrinsic_arg_count(args)?;
                 let place = this.deref_pointer(place)?;
                 this.copy_op(dest, &place)?;
             }
 
             "volatile_set_memory" => {
-                let [ptr, val_byte, count] = check_arg_count(args)?;
+                let [ptr, val_byte, count] = check_intrinsic_arg_count(args)?;
                 this.write_bytes_intrinsic(ptr, val_byte, count, "volatile_set_memory")?;
             }
 
             // Memory model / provenance manipulation
             "ptr_mask" => {
-                let [ptr, mask] = check_arg_count(args)?;
+                let [ptr, mask] = check_intrinsic_arg_count(args)?;
 
                 let ptr = this.read_pointer(ptr)?;
                 let mask = this.read_target_usize(mask)?;
@@ -137,7 +138,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             // ```
             // Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
             "is_val_statically_known" => {
-                let [_arg] = check_arg_count(args)?;
+                let [_arg] = check_intrinsic_arg_count(args)?;
                 // FIXME: should we check for validity here? It's tricky because we do not have a
                 // place. Codegen does not seem to set any attributes like `noundef` for intrinsic
                 // calls, so we don't *have* to do anything.
@@ -146,7 +147,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "floorf16" | "ceilf16" | "truncf16" | "roundf16" | "round_ties_even_f16" => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f16()?;
                 let mode = match intrinsic_name {
                     "floorf16" => Round::TowardNegative,
@@ -161,7 +162,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "round_ties_even_f32" => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
                 let mode = match intrinsic_name {
                     "floorf32" => Round::TowardNegative,
@@ -176,7 +177,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "round_ties_even_f64" => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
                 let mode = match intrinsic_name {
                     "floorf64" => Round::TowardNegative,
@@ -191,7 +192,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "floorf128" | "ceilf128" | "truncf128" | "roundf128" | "round_ties_even_f128" => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f128()?;
                 let mode = match intrinsic_name {
                     "floorf128" => Round::TowardNegative,
@@ -206,65 +207,98 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
 
+            "sqrtf32" => {
+                let [f] = check_intrinsic_arg_count(args)?;
+                let f = this.read_scalar(f)?.to_f32()?;
+                // Sqrt is specified to be fully precise.
+                let res = math::sqrt(f);
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
+            }
+            "sqrtf64" => {
+                let [f] = check_intrinsic_arg_count(args)?;
+                let f = this.read_scalar(f)?.to_f64()?;
+                // Sqrt is specified to be fully precise.
+                let res = math::sqrt(f);
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
+            }
+
             #[rustfmt::skip]
             | "sinf32"
             | "cosf32"
-            | "sqrtf32"
             | "expf32"
             | "exp2f32"
             | "logf32"
             | "log10f32"
             | "log2f32"
             => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
-                // Using host floats except for sqrt (but it's fine, these operations do not have
+                // Using host floats (but it's fine, these operations do not have
                 // guaranteed precision).
+                let host = f.to_host();
                 let res = match intrinsic_name {
-                    "sinf32" => f.to_host().sin().to_soft(),
-                    "cosf32" => f.to_host().cos().to_soft(),
-                    "sqrtf32" => math::sqrt(f),
-                    "expf32" => f.to_host().exp().to_soft(),
-                    "exp2f32" => f.to_host().exp2().to_soft(),
-                    "logf32" => f.to_host().ln().to_soft(),
-                    "log10f32" => f.to_host().log10().to_soft(),
-                    "log2f32" => f.to_host().log2().to_soft(),
+                    "sinf32" => host.sin(),
+                    "cosf32" => host.cos(),
+                    "expf32" => host.exp(),
+                    "exp2f32" => host.exp2(),
+                    "logf32" => host.ln(),
+                    "log10f32" => host.log10(),
+                    "log2f32" => host.log2(),
                     _ => bug!(),
                 };
+                let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = apply_random_float_error_ulp(
+                //     this,
+                //     res,
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
             #[rustfmt::skip]
             | "sinf64"
             | "cosf64"
-            | "sqrtf64"
             | "expf64"
             | "exp2f64"
             | "logf64"
             | "log10f64"
             | "log2f64"
             => {
-                let [f] = check_arg_count(args)?;
+                let [f] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
-                // Using host floats except for sqrt (but it's fine, these operations do not have
+                // Using host floats (but it's fine, these operations do not have
                 // guaranteed precision).
+                let host = f.to_host();
                 let res = match intrinsic_name {
-                    "sinf64" => f.to_host().sin().to_soft(),
-                    "cosf64" => f.to_host().cos().to_soft(),
-                    "sqrtf64" => math::sqrt(f),
-                    "expf64" => f.to_host().exp().to_soft(),
-                    "exp2f64" => f.to_host().exp2().to_soft(),
-                    "logf64" => f.to_host().ln().to_soft(),
-                    "log10f64" => f.to_host().log10().to_soft(),
-                    "log2f64" => f.to_host().log2().to_soft(),
+                    "sinf64" => host.sin(),
+                    "cosf64" => host.cos(),
+                    "expf64" => host.exp(),
+                    "exp2f64" => host.exp2(),
+                    "logf64" => host.ln(),
+                    "log10f64" => host.log10(),
+                    "log2f64" => host.log2(),
                     _ => bug!(),
                 };
+                let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = apply_random_float_error_ulp(
+                //     this,
+                //     res,
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
 
             "fmaf32" => {
-                let [a, b, c] = check_arg_count(args)?;
+                let [a, b, c] = check_intrinsic_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f32()?;
                 let b = this.read_scalar(b)?.to_f32()?;
                 let c = this.read_scalar(c)?.to_f32()?;
@@ -274,7 +308,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "fmaf64" => {
-                let [a, b, c] = check_arg_count(args)?;
+                let [a, b, c] = check_intrinsic_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f64()?;
                 let b = this.read_scalar(b)?.to_f64()?;
                 let c = this.read_scalar(c)?.to_f64()?;
@@ -285,7 +319,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "fmuladdf32" => {
-                let [a, b, c] = check_arg_count(args)?;
+                let [a, b, c] = check_intrinsic_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f32()?;
                 let b = this.read_scalar(b)?.to_f32()?;
                 let c = this.read_scalar(c)?.to_f32()?;
@@ -300,7 +334,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "fmuladdf64" => {
-                let [a, b, c] = check_arg_count(args)?;
+                let [a, b, c] = check_intrinsic_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f64()?;
                 let b = this.read_scalar(b)?.to_f64()?;
                 let c = this.read_scalar(c)?.to_f64()?;
@@ -316,7 +350,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "powf32" => {
-                let [f1, f2] = check_arg_count(args)?;
+                // FIXME: apply random relative error but without altering behaviour of powf
+                let [f1, f2] = check_intrinsic_arg_count(args)?;
                 let f1 = this.read_scalar(f1)?.to_f32()?;
                 let f2 = this.read_scalar(f2)?.to_f32()?;
                 // Using host floats (but it's fine, this operation does not have guaranteed precision).
@@ -325,7 +360,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "powf64" => {
-                let [f1, f2] = check_arg_count(args)?;
+                // FIXME: apply random relative error but without altering behaviour of powf
+                let [f1, f2] = check_intrinsic_arg_count(args)?;
                 let f1 = this.read_scalar(f1)?.to_f64()?;
                 let f2 = this.read_scalar(f2)?.to_f64()?;
                 // Using host floats (but it's fine, this operation does not have guaranteed precision).
@@ -335,7 +371,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "powif32" => {
-                let [f, i] = check_arg_count(args)?;
+                // FIXME: apply random relative error but without altering behaviour of powi
+                let [f, i] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
                 let i = this.read_scalar(i)?.to_i32()?;
                 // Using host floats (but it's fine, this operation does not have guaranteed precision).
@@ -344,7 +381,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(res, dest)?;
             }
             "powif64" => {
-                let [f, i] = check_arg_count(args)?;
+                // FIXME: apply random relative error but without altering behaviour of powi
+                let [f, i] = check_intrinsic_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
                 let i = this.read_scalar(i)?.to_i32()?;
                 // Using host floats (but it's fine, this operation does not have guaranteed precision).
@@ -360,7 +398,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             | "fdiv_algebraic"
             | "frem_algebraic"
             => {
-                let [a, b] = check_arg_count(args)?;
+                let [a, b] = check_intrinsic_arg_count(args)?;
                 let a = this.read_immediate(a)?;
                 let b = this.read_immediate(b)?;
                 let op = match intrinsic_name {
@@ -372,7 +410,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     _ => bug!(),
                 };
                 let res = this.binary_op(op, &a, &b)?;
-                // `binary_op` already called `generate_nan` if necessary.
+                // `binary_op` already called `generate_nan` if needed.
+                // Apply a relative error of 16ULP to simulate non-deterministic precision loss
+                // due to optimizations.
+                let res = apply_random_float_error_to_imm(this, res, 4 /* log2(16) */)?;
                 this.write_immediate(*res, dest)?;
             }
 
@@ -383,7 +424,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             | "fdiv_fast"
             | "frem_fast"
             => {
-                let [a, b] = check_arg_count(args)?;
+                let [a, b] = check_intrinsic_arg_count(args)?;
                 let a = this.read_immediate(a)?;
                 let b = this.read_immediate(b)?;
                 let op = match intrinsic_name {
@@ -418,16 +459,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     _ => {}
                 }
                 let res = this.binary_op(op, &a, &b)?;
+                // This cannot be a NaN so we also don't have to apply any non-determinism.
+                // (Also, `binary_op` already called `generate_nan` if needed.)
                 if !float_finite(&res)? {
                     throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
                 }
-                // This cannot be a NaN so we also don't have to apply any non-determinism.
-                // (Also, `binary_op` already called `generate_nan` if needed.)
+                // Apply a relative error of 16ULP to simulate non-deterministic precision loss
+                // due to optimizations.
+                let res = apply_random_float_error_to_imm(this, res, 4 /* log2(16) */)?;
                 this.write_immediate(*res, dest)?;
             }
 
             "float_to_int_unchecked" => {
-                let [val] = check_arg_count(args)?;
+                let [val] = check_intrinsic_arg_count(args)?;
                 let val = this.read_immediate(val)?;
 
                 let res = this
@@ -444,7 +488,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
             // Other
             "breakpoint" => {
-                let [] = check_arg_count(args)?;
+                let [] = check_intrinsic_arg_count(args)?;
                 // normally this would raise a SIGTRAP, which aborts if no debugger is connected
                 throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
             }
@@ -455,3 +499,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         interp_ok(EmulateItemResult::NeedsReturn)
     }
 }
+
+/// Applies a random 16ULP floating point error to `val` and returns the new value.
+/// Will fail if `val` is not a floating point number.
+fn apply_random_float_error_to_imm<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
+    val: ImmTy<'tcx>,
+    ulp_exponent: u32,
+) -> InterpResult<'tcx, ImmTy<'tcx>> {
+    let scalar = val.to_scalar_int()?;
+    let res: ScalarInt = match val.layout.ty.kind() {
+        ty::Float(FloatTy::F16) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f16(), ulp_exponent).into(),
+        ty::Float(FloatTy::F32) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f32(), ulp_exponent).into(),
+        ty::Float(FloatTy::F64) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f64(), ulp_exponent).into(),
+        ty::Float(FloatTy::F128) =>
+            apply_random_float_error_ulp(ecx, scalar.to_f128(), ulp_exponent).into(),
+        _ => bug!("intrinsic called with non-float input type"),
+    };
+
+    interp_ok(ImmTy::from_scalar_int(res, val.layout))
+}
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index 3e8b3ef46e4..de5da6ec898 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -7,7 +7,9 @@ use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::{mir, ty};
 use rustc_span::{Symbol, sym};
 
-use crate::helpers::{ToHost, ToSoft, bool_to_simd_element, check_arg_count, simd_element_to_bool};
+use crate::helpers::{
+    ToHost, ToSoft, bool_to_simd_element, check_intrinsic_arg_count, simd_element_to_bool,
+};
 use crate::*;
 
 #[derive(Copy, Clone)]
@@ -50,7 +52,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             | "bswap"
             | "bitreverse"
             => {
-                let [op] = check_arg_count(args)?;
+                let [op] = check_intrinsic_arg_count(args)?;
                 let (op, op_len) = this.project_to_simd(op)?;
                 let (dest, dest_len) = this.project_to_simd(dest)?;
 
@@ -197,7 +199,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             => {
                 use mir::BinOp;
 
-                let [left, right] = check_arg_count(args)?;
+                let [left, right] = check_intrinsic_arg_count(args)?;
                 let (left, left_len) = this.project_to_simd(left)?;
                 let (right, right_len) = this.project_to_simd(right)?;
                 let (dest, dest_len) = this.project_to_simd(dest)?;
@@ -288,7 +290,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "fma" | "relaxed_fma" => {
-                let [a, b, c] = check_arg_count(args)?;
+                let [a, b, c] = check_intrinsic_arg_count(args)?;
                 let (a, a_len) = this.project_to_simd(a)?;
                 let (b, b_len) = this.project_to_simd(b)?;
                 let (c, c_len) = this.project_to_simd(c)?;
@@ -352,7 +354,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             | "reduce_min" => {
                 use mir::BinOp;
 
-                let [op] = check_arg_count(args)?;
+                let [op] = check_intrinsic_arg_count(args)?;
                 let (op, op_len) = this.project_to_simd(op)?;
 
                 let imm_from_bool =
@@ -415,7 +417,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             | "reduce_mul_ordered" => {
                 use mir::BinOp;
 
-                let [op, init] = check_arg_count(args)?;
+                let [op, init] = check_intrinsic_arg_count(args)?;
                 let (op, op_len) = this.project_to_simd(op)?;
                 let init = this.read_immediate(init)?;
 
@@ -433,7 +435,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_immediate(*res, dest)?;
             }
             "select" => {
-                let [mask, yes, no] = check_arg_count(args)?;
+                let [mask, yes, no] = check_intrinsic_arg_count(args)?;
                 let (mask, mask_len) = this.project_to_simd(mask)?;
                 let (yes, yes_len) = this.project_to_simd(yes)?;
                 let (no, no_len) = this.project_to_simd(no)?;
@@ -455,7 +457,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
             // Variant of `select` that takes a bitmask rather than a "vector of bool".
             "select_bitmask" => {
-                let [mask, yes, no] = check_arg_count(args)?;
+                let [mask, yes, no] = check_intrinsic_arg_count(args)?;
                 let (yes, yes_len) = this.project_to_simd(yes)?;
                 let (no, no_len) = this.project_to_simd(no)?;
                 let (dest, dest_len) = this.project_to_simd(dest)?;
@@ -529,7 +531,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
             // Converts a "vector of bool" into a bitmask.
             "bitmask" => {
-                let [op] = check_arg_count(args)?;
+                let [op] = check_intrinsic_arg_count(args)?;
                 let (op, op_len) = this.project_to_simd(op)?;
                 let bitmask_len = op_len.next_multiple_of(8);
                 if bitmask_len > 64 {
@@ -577,7 +579,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "cast" | "as" | "cast_ptr" | "expose_provenance" | "with_exposed_provenance" => {
-                let [op] = check_arg_count(args)?;
+                let [op] = check_intrinsic_arg_count(args)?;
                 let (op, op_len) = this.project_to_simd(op)?;
                 let (dest, dest_len) = this.project_to_simd(dest)?;
 
@@ -634,7 +636,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "shuffle_const_generic" => {
-                let [left, right] = check_arg_count(args)?;
+                let [left, right] = check_intrinsic_arg_count(args)?;
                 let (left, left_len) = this.project_to_simd(left)?;
                 let (right, right_len) = this.project_to_simd(right)?;
                 let (dest, dest_len) = this.project_to_simd(dest)?;
@@ -664,7 +666,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "shuffle" => {
-                let [left, right, index] = check_arg_count(args)?;
+                let [left, right, index] = check_intrinsic_arg_count(args)?;
                 let (left, left_len) = this.project_to_simd(left)?;
                 let (right, right_len) = this.project_to_simd(right)?;
                 let (index, index_len) = this.project_to_simd(index)?;
@@ -695,7 +697,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "gather" => {
-                let [passthru, ptrs, mask] = check_arg_count(args)?;
+                let [passthru, ptrs, mask] = check_intrinsic_arg_count(args)?;
                 let (passthru, passthru_len) = this.project_to_simd(passthru)?;
                 let (ptrs, ptrs_len) = this.project_to_simd(ptrs)?;
                 let (mask, mask_len) = this.project_to_simd(mask)?;
@@ -721,7 +723,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "scatter" => {
-                let [value, ptrs, mask] = check_arg_count(args)?;
+                let [value, ptrs, mask] = check_intrinsic_arg_count(args)?;
                 let (value, value_len) = this.project_to_simd(value)?;
                 let (ptrs, ptrs_len) = this.project_to_simd(ptrs)?;
                 let (mask, mask_len) = this.project_to_simd(mask)?;
@@ -741,7 +743,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "masked_load" => {
-                let [mask, ptr, default] = check_arg_count(args)?;
+                let [mask, ptr, default] = check_intrinsic_arg_count(args)?;
                 let (mask, mask_len) = this.project_to_simd(mask)?;
                 let ptr = this.read_pointer(ptr)?;
                 let (default, default_len) = this.project_to_simd(default)?;
@@ -767,7 +769,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
             }
             "masked_store" => {
-                let [mask, ptr, vals] = check_arg_count(args)?;
+                let [mask, ptr, vals] = check_intrinsic_arg_count(args)?;
                 let (mask, mask_len) = this.project_to_simd(mask)?;
                 let ptr = this.read_pointer(ptr)?;
                 let (vals, vals_len) = this.project_to_simd(vals)?;
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 9ac19a2a5f2..0bf5ae87f38 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -1,4 +1,5 @@
 #![feature(rustc_private)]
+#![feature(cfg_match)]
 #![feature(cell_update)]
 #![feature(float_gamma)]
 #![feature(float_erf)]
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 6bd1076a8a8..4ece8f7895d 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -713,12 +713,13 @@ impl<'tcx> MiriMachine<'tcx> {
             clock: Clock::new(config.isolated_op == IsolatedOp::Allow),
             #[cfg(unix)]
             native_lib: config.native_lib.as_ref().map(|lib_file_path| {
+                let host_triple = rustc_session::config::host_tuple();
                 let target_triple = tcx.sess.opts.target_triple.tuple();
                 // Check if host target == the session target.
-                if env!("TARGET") != target_triple {
+                if host_triple != target_triple {
                     panic!(
                         "calling external C functions in linked .so file requires host and target to be the same: host={}, target={}",
-                        env!("TARGET"),
+                        host_triple,
                         target_triple,
                     );
                 }
diff --git a/src/tools/miri/src/math.rs b/src/tools/miri/src/math.rs
index 7117f722fee..fdd021f8539 100644
--- a/src/tools/miri/src/math.rs
+++ b/src/tools/miri/src/math.rs
@@ -27,6 +27,22 @@ pub(crate) fn apply_random_float_error<F: rustc_apfloat::Float>(
     (val * (F::from_u128(1).value + err).value).value
 }
 
+/// [`apply_random_float_error`] gives instructions to apply a 2^N ULP error.
+/// This function implements these instructions such that applying a 2^N ULP error is less error prone.
+/// So for a 2^N ULP error, you would pass N as the `ulp_exponent` argument.
+pub(crate) fn apply_random_float_error_ulp<F: rustc_apfloat::Float>(
+    ecx: &mut crate::MiriInterpCx<'_>,
+    val: F,
+    ulp_exponent: u32,
+) -> F {
+    let n = i32::try_from(ulp_exponent)
+        .expect("`err_scale_for_ulp`: exponent is too large to create an error scale");
+    // we know this fits
+    let prec = i32::try_from(F::PRECISION).unwrap();
+    let err_scale = -(prec - n - 1);
+    apply_random_float_error(ecx, val, err_scale)
+}
+
 pub(crate) fn sqrt<S: rustc_apfloat::ieee::Semantics>(x: IeeeFloat<S>) -> IeeeFloat<S> {
     match x.category() {
         // preserve zero sign
diff --git a/src/tools/miri/src/shims/aarch64.rs b/src/tools/miri/src/shims/aarch64.rs
new file mode 100644
index 00000000000..7cccc9e51d8
--- /dev/null
+++ b/src/tools/miri/src/shims/aarch64.rs
@@ -0,0 +1,78 @@
+use rustc_middle::mir::BinOp;
+use rustc_middle::ty::Ty;
+use rustc_span::Symbol;
+use rustc_target::callconv::{Conv, FnAbi};
+
+use crate::*;
+
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    fn emulate_aarch64_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: &FnAbi<'tcx, Ty<'tcx>>,
+        args: &[OpTy<'tcx>],
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx, EmulateItemResult> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.aarch64.").unwrap();
+        match unprefixed_name {
+            "isb" => {
+                let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
+                let arg = this.read_scalar(arg)?.to_i32()?;
+                match arg {
+                    // SY ("full system scope")
+                    15 => {
+                        this.yield_active_thread();
+                    }
+                    _ => {
+                        throw_unsup_format!("unsupported llvm.aarch64.isb argument {}", arg);
+                    }
+                }
+            }
+
+            // Used to implement the vpmaxq_u8 function.
+            // Computes the maximum of adjacent pairs; the first half of the output is produced from the
+            // `left` input, the second half of the output from the `right` input.
+            // https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxq_u8
+            "neon.umaxp.v16i8" => {
+                let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
+
+                let (left, left_len) = this.project_to_simd(left)?;
+                let (right, right_len) = this.project_to_simd(right)?;
+                let (dest, lane_count) = this.project_to_simd(dest)?;
+                assert_eq!(left_len, right_len);
+                assert_eq!(lane_count, left_len);
+
+                for lane_idx in 0..lane_count {
+                    let src = if lane_idx < (lane_count / 2) { &left } else { &right };
+                    let src_idx = lane_idx.strict_rem(lane_count / 2);
+
+                    let lhs_lane =
+                        this.read_immediate(&this.project_index(src, src_idx.strict_mul(2))?)?;
+                    let rhs_lane = this.read_immediate(
+                        &this.project_index(src, src_idx.strict_mul(2).strict_add(1))?,
+                    )?;
+
+                    // Compute `if lhs > rhs { lhs } else { rhs }`, i.e., `max`.
+                    let res_lane = if this
+                        .binary_op(BinOp::Gt, &lhs_lane, &rhs_lane)?
+                        .to_scalar()
+                        .to_bool()?
+                    {
+                        lhs_lane
+                    } else {
+                        rhs_lane
+                    };
+
+                    let dest = this.project_index(&dest, lane_idx)?;
+                    this.write_immediate(*res_lane, &dest)?;
+                }
+            }
+
+            _ => return interp_ok(EmulateItemResult::NotSupported),
+        }
+        interp_ok(EmulateItemResult::NeedsReturn)
+    }
+}
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index bedc1ebdc95..505c079143a 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -766,6 +766,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     _ => bug!(),
                 };
                 let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(
+                //     this,
+                //     res,
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
@@ -788,6 +796,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     "fdimf" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
                     _ => bug!(),
                 };
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(
+                //     this,
+                //     res,
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f1, f2]);
                 this.write_scalar(res, dest)?;
             }
@@ -827,6 +843,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     _ => bug!(),
                 };
                 let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(
+                //     this,
+                //     res.to_soft(),
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
@@ -849,6 +873,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     "fdim" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
                     _ => bug!(),
                 };
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(
+                //     this,
+                //     res,
+                //     4, // log2(16)
+                // );
                 let res = this.adjust_nan(res, &[f1, f2]);
                 this.write_scalar(res, dest)?;
             }
@@ -874,7 +906,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
-                let res = this.adjust_nan(res.to_soft(), &[x]);
+                let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(this, res, 4 /* log2(16) */);
+                let res = this.adjust_nan(res, &[x]);
                 this.write_scalar(res, dest)?;
             }
             "lgamma_r" => {
@@ -885,7 +922,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Using host floats (but it's fine, these operations do not have guaranteed precision).
                 let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
-                let res = this.adjust_nan(res.to_soft(), &[x]);
+                let res = res.to_soft();
+                // Apply a relative error of 16ULP to introduce some non-determinism
+                // simulating imprecise implementations and optimizations.
+                // FIXME: temporarily disabled as it breaks std tests.
+                // let res = math::apply_random_float_error_ulp(this, res, 4 /* log2(16) */);
+                let res = this.adjust_nan(res, &[x]);
                 this.write_scalar(res, dest)?;
             }
 
@@ -947,20 +989,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                     this, link_name, abi, args, dest,
                 );
             }
-            // FIXME: Move these to an `arm` submodule.
-            "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
-                let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
-                let arg = this.read_scalar(arg)?.to_i32()?;
-                match arg {
-                    // SY ("full system scope")
-                    15 => {
-                        this.yield_active_thread();
-                    }
-                    _ => {
-                        throw_unsup_format!("unsupported llvm.aarch64.isb argument {}", arg);
-                    }
-                }
+            name if name.starts_with("llvm.aarch64.") && this.tcx.sess.target.arch == "aarch64" => {
+                return shims::aarch64::EvalContextExt::emulate_aarch64_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
             }
+            // FIXME: Move this to an `arm` submodule.
             "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
                 let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
                 let arg = this.read_scalar(arg)?.to_i32()?;
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 61681edcf76..b498551ace3 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -1,5 +1,6 @@
 #![warn(clippy::arithmetic_side_effects)]
 
+mod aarch64;
 mod alloc;
 mod backtrace;
 mod files;
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 83f331bb173..fc58d88591f 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -15,7 +15,7 @@ use rustc_abi::ExternAbi;
 use rustc_middle::{mir, ty};
 use rustc_target::spec::PanicStrategy;
 
-use self::helpers::check_arg_count;
+use self::helpers::check_intrinsic_arg_count;
 use crate::*;
 
 /// Holds all of the relevant data for when unwinding hits a `try` frame.
@@ -77,7 +77,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // a pointer to `Box<dyn Any + Send + 'static>`.
 
         // Get all the arguments.
-        let [try_fn, data, catch_fn] = check_arg_count(args)?;
+        let [try_fn, data, catch_fn] = check_intrinsic_arg_count(args)?;
         let try_fn = this.read_pointer(try_fn)?;
         let data = this.read_immediate(data)?;
         let catch_fn = this.read_pointer(catch_fn)?;
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index d459ec7cb77..09757071075 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -815,7 +815,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.handle_miri_start_unwind(payload)?;
                 return interp_ok(EmulateItemResult::NeedsUnwind);
             }
-            "getuid" => {
+            "getuid" | "geteuid" => {
                 let [] = this.check_shim(abi, Conv::C, link_name, args)?;
                 // For now, just pretend we always have this fixed UID.
                 this.write_int(UID, dest)?;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index c7399b00d3f..f8e0c638c90 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -178,92 +178,91 @@ impl UnixFileDescription for FileHandle {
         op: FlockOp,
     ) -> InterpResult<'tcx, io::Result<()>> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
-        #[cfg(target_family = "unix")]
-        {
-            use std::os::fd::AsRawFd;
-
-            use FlockOp::*;
-            // We always use non-blocking call to prevent interpreter from being blocked
-            let (host_op, lock_nb) = match op {
-                SharedLock { nonblocking } => (libc::LOCK_SH | libc::LOCK_NB, nonblocking),
-                ExclusiveLock { nonblocking } => (libc::LOCK_EX | libc::LOCK_NB, nonblocking),
-                Unlock => (libc::LOCK_UN, false),
-            };
+        cfg_match! {
+            all(target_family = "unix", not(target_os = "solaris")) => {
+                use std::os::fd::AsRawFd;
+
+                use FlockOp::*;
+                // We always use non-blocking call to prevent interpreter from being blocked
+                let (host_op, lock_nb) = match op {
+                    SharedLock { nonblocking } => (libc::LOCK_SH | libc::LOCK_NB, nonblocking),
+                    ExclusiveLock { nonblocking } => (libc::LOCK_EX | libc::LOCK_NB, nonblocking),
+                    Unlock => (libc::LOCK_UN, false),
+                };
 
-            let fd = self.file.as_raw_fd();
-            let ret = unsafe { libc::flock(fd, host_op) };
-            let res = match ret {
-                0 => Ok(()),
-                -1 => {
-                    let err = io::Error::last_os_error();
-                    if !lock_nb && err.kind() == io::ErrorKind::WouldBlock {
-                        throw_unsup_format!("blocking `flock` is not currently supported");
+                let fd = self.file.as_raw_fd();
+                let ret = unsafe { libc::flock(fd, host_op) };
+                let res = match ret {
+                    0 => Ok(()),
+                    -1 => {
+                        let err = io::Error::last_os_error();
+                        if !lock_nb && err.kind() == io::ErrorKind::WouldBlock {
+                            throw_unsup_format!("blocking `flock` is not currently supported");
+                        }
+                        Err(err)
                     }
-                    Err(err)
-                }
-                ret => panic!("Unexpected return value from flock: {ret}"),
-            };
-            interp_ok(res)
-        }
-
-        #[cfg(target_family = "windows")]
-        {
-            use std::os::windows::io::AsRawHandle;
+                    ret => panic!("Unexpected return value from flock: {ret}"),
+                };
+                interp_ok(res)
+            }
+            target_family = "windows" => {
+                use std::os::windows::io::AsRawHandle;
 
-            use windows_sys::Win32::Foundation::{
-                ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE,
-            };
-            use windows_sys::Win32::Storage::FileSystem::{
-                LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, LockFileEx, UnlockFile,
-            };
+                use windows_sys::Win32::Foundation::{
+                    ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE,
+                };
+                use windows_sys::Win32::Storage::FileSystem::{
+                    LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, LockFileEx, UnlockFile,
+                };
 
-            let fh = self.file.as_raw_handle() as HANDLE;
+                let fh = self.file.as_raw_handle() as HANDLE;
 
-            use FlockOp::*;
-            let (ret, lock_nb) = match op {
-                SharedLock { nonblocking } | ExclusiveLock { nonblocking } => {
-                    // We always use non-blocking call to prevent interpreter from being blocked
-                    let mut flags = LOCKFILE_FAIL_IMMEDIATELY;
-                    if matches!(op, ExclusiveLock { .. }) {
-                        flags |= LOCKFILE_EXCLUSIVE_LOCK;
+                use FlockOp::*;
+                let (ret, lock_nb) = match op {
+                    SharedLock { nonblocking } | ExclusiveLock { nonblocking } => {
+                        // We always use non-blocking call to prevent interpreter from being blocked
+                        let mut flags = LOCKFILE_FAIL_IMMEDIATELY;
+                        if matches!(op, ExclusiveLock { .. }) {
+                            flags |= LOCKFILE_EXCLUSIVE_LOCK;
+                        }
+                        let ret = unsafe { LockFileEx(fh, flags, 0, !0, !0, &mut std::mem::zeroed()) };
+                        (ret, nonblocking)
                     }
-                    let ret = unsafe { LockFileEx(fh, flags, 0, !0, !0, &mut std::mem::zeroed()) };
-                    (ret, nonblocking)
-                }
-                Unlock => {
-                    let ret = unsafe { UnlockFile(fh, 0, 0, !0, !0) };
-                    (ret, false)
-                }
-            };
+                    Unlock => {
+                        let ret = unsafe { UnlockFile(fh, 0, 0, !0, !0) };
+                        (ret, false)
+                    }
+                };
 
-            let res = match ret {
-                TRUE => Ok(()),
-                FALSE => {
-                    let mut err = io::Error::last_os_error();
-                    // This only runs on Windows hosts so we can use `raw_os_error`.
-                    // We have to be careful not to forward that error code to target code.
-                    let code: u32 = err.raw_os_error().unwrap().try_into().unwrap();
-                    if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) {
-                        if lock_nb {
-                            // The io error mapping does not know about these error codes,
-                            // so we translate it to `WouldBlock` manually.
-                            let desc = format!("LockFileEx wouldblock error: {err}");
-                            err = io::Error::new(io::ErrorKind::WouldBlock, desc);
-                        } else {
-                            throw_unsup_format!("blocking `flock` is not currently supported");
+                let res = match ret {
+                    TRUE => Ok(()),
+                    FALSE => {
+                        let mut err = io::Error::last_os_error();
+                        // This only runs on Windows hosts so we can use `raw_os_error`.
+                        // We have to be careful not to forward that error code to target code.
+                        let code: u32 = err.raw_os_error().unwrap().try_into().unwrap();
+                        if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) {
+                            if lock_nb {
+                                // The io error mapping does not know about these error codes,
+                                // so we translate it to `WouldBlock` manually.
+                                let desc = format!("LockFileEx wouldblock error: {err}");
+                                err = io::Error::new(io::ErrorKind::WouldBlock, desc);
+                            } else {
+                                throw_unsup_format!("blocking `flock` is not currently supported");
+                            }
                         }
+                        Err(err)
                     }
-                    Err(err)
-                }
-                _ => panic!("Unexpected return value: {ret}"),
-            };
-            interp_ok(res)
-        }
-
-        #[cfg(not(any(target_family = "unix", target_family = "windows")))]
-        {
-            let _ = op;
-            compile_error!("flock is supported only on UNIX and Windows hosts");
+                    _ => panic!("Unexpected return value: {ret}"),
+                };
+                interp_ok(res)
+            }
+            _ => {
+                let _ = op;
+                throw_unsup_format!(
+                    "flock is supported only on UNIX (except Solaris) and Windows hosts"
+                );
+            }
         }
     }
 }
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 10af245dcc0..f5da7b0170b 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -133,8 +133,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 this.write_scalar(ptr, dest)?;
             }
             "mremap" => {
-                let [old_address, old_size, new_size, flags] =
-                    this.check_shim(abi, Conv::C, link_name, args)?;
+                let ([old_address, old_size, new_size, flags], _) =
+                    this.check_shim_variadic(abi, Conv::C, link_name, args)?;
                 let ptr = this.mremap(old_address, old_size, new_size, flags)?;
                 this.write_scalar(ptr, dest)?;
             }
diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs
index 280bee4800f..86e8b57824c 100644
--- a/src/tools/miri/src/shims/unix/linux_like/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs
@@ -13,14 +13,6 @@ pub fn futex<'tcx>(
     varargs: &[OpTy<'tcx>],
     dest: &MPlaceTy<'tcx>,
 ) -> InterpResult<'tcx> {
-    // The amount of arguments used depends on the type of futex operation.
-    // The full futex syscall takes six arguments (excluding the syscall
-    // number), which is also the maximum amount of arguments a linux syscall
-    // can take on most architectures.
-    // However, not all futex operations use all six arguments. The unused ones
-    // may or may not be left out from the `syscall()` call.
-    // Therefore we don't use `check_arg_count` here, but only check for the
-    // number of arguments to fall within a range.
     let [addr, op, val] = check_min_vararg_count("`syscall(SYS_futex, ...)`", varargs)?;
 
     // The first three arguments (after the syscall number itself) are the same to all futex operations:
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.rs b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.rs
index 967a78bf831..db7bd223bd4 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.rs
@@ -5,6 +5,6 @@ fn main() {
 
     unsafe {
         abort(1);
-        //~^ ERROR: Undefined Behavior: incorrect number of arguments: got 1, expected 0
+        //~^ ERROR: Undefined Behavior: incorrect number of arguments for `abort`: got 1, expected 0
     }
 }
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr
index 687d0538b3c..3c81ba4e141 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_abort.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: incorrect number of arguments: got 1, expected 0
+error: Undefined Behavior: incorrect number of arguments for `abort`: got 1, expected 0
   --> tests/fail/function_calls/check_arg_count_abort.rs:LL:CC
    |
 LL |         abort(1);
-   |         ^^^^^^^^ incorrect number of arguments: got 1, expected 0
+   |         ^^^^^^^^ incorrect number of arguments for `abort`: got 1, expected 0
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs
index 223c95ffca4..41aebea2d8a 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.rs
@@ -4,6 +4,6 @@ fn main() {
     }
 
     unsafe {
-        let _ = malloc(); //~ ERROR: Undefined Behavior: incorrect number of arguments: got 0, expected 1
+        let _ = malloc(); //~ ERROR: Undefined Behavior: incorrect number of arguments for `malloc`: got 0, expected 1
     };
 }
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr
index d778eae64fa..eacd4045ae0 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_few_args.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: incorrect number of arguments: got 0, expected 1
+error: Undefined Behavior: incorrect number of arguments for `malloc`: got 0, expected 1
   --> tests/fail/function_calls/check_arg_count_too_few_args.rs:LL:CC
    |
 LL |         let _ = malloc();
-   |                 ^^^^^^^^ incorrect number of arguments: got 0, expected 1
+   |                 ^^^^^^^^ incorrect number of arguments for `malloc`: got 0, expected 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs
index 7ee9c40bf7a..1f5c509c666 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.rs
@@ -4,6 +4,6 @@ fn main() {
     }
 
     unsafe {
-        let _ = malloc(1, 2); //~ ERROR: Undefined Behavior: incorrect number of arguments: got 2, expected 1
+        let _ = malloc(1, 2); //~ ERROR: Undefined Behavior: incorrect number of arguments for `malloc`: got 2, expected 1
     };
 }
diff --git a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr
index dfec2a86287..42d5e98c01a 100644
--- a/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_arg_count_too_many_args.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: incorrect number of arguments: got 2, expected 1
+error: Undefined Behavior: incorrect number of arguments for `malloc`: got 2, expected 1
   --> tests/fail/function_calls/check_arg_count_too_many_args.rs:LL:CC
    |
 LL |         let _ = malloc(1, 2);
-   |                 ^^^^^^^^^^^^ incorrect number of arguments: got 2, expected 1
+   |                 ^^^^^^^^^^^^ incorrect number of arguments for `malloc`: got 2, expected 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs
new file mode 100644
index 00000000000..515e467fb54
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs
@@ -0,0 +1,14 @@
+//@ignore-target: windows # No libc pipe on Windows
+
+// Declare a non-variadic function as variadic.
+extern "C" {
+    fn pipe(fds: *mut std::ffi::c_int, ...) -> std::ffi::c_int;
+}
+
+// Test the error caused by invoking non-vararg shim with a vararg import.
+fn main() {
+    let mut fds = [-1, -1];
+    let res = unsafe { pipe(fds.as_mut_ptr()) };
+    //~^ ERROR: calling a non-variadic function with a variadic caller-side signature
+    assert_eq!(res, 0);
+}
diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr
new file mode 100644
index 00000000000..2782f3b3269
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: calling a non-variadic function with a variadic caller-side signature
+  --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC
+   |
+LL |     let res = unsafe { pipe(fds.as_mut_ptr()) };
+   |                        ^^^^^^^^^^^^^^^^^^^^^^ calling a non-variadic function with a variadic caller-side signature
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs
index f07007fa705..d1c0085b024 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-misc.rs
@@ -78,11 +78,16 @@ fn test_getuid() {
     let _val = unsafe { libc::getuid() };
 }
 
+fn test_geteuid() {
+    let _val = unsafe { libc::geteuid() };
+}
+
 fn main() {
     test_thread_local_errno();
     test_environ();
     test_dlsym();
     test_getuid();
+    test_geteuid();
 
     #[cfg(target_os = "linux")]
     test_sigrt();
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
index bbf0e215953..9163fd3d06f 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
@@ -88,8 +88,7 @@ fn test_socketpair_threaded() {
         assert_eq!(res, 5);
         assert_eq!(buf, "abcde".as_bytes());
     });
-    // FIXME: we should yield here once blocking is implemented.
-    //thread::yield_now();
+    thread::yield_now();
     let data = "abcde".as_bytes().as_ptr();
     let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
@@ -97,14 +96,11 @@ fn test_socketpair_threaded() {
 
     // Read and write from different direction
     let thread2 = thread::spawn(move || {
-        // FIXME: we should yield here once blocking is implemented.
-        //thread::yield_now();
+        thread::yield_now();
         let data = "12345".as_bytes().as_ptr();
         let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
         assert_eq!(res, 5);
     });
-    // FIXME: we should not yield here once blocking is implemented.
-    thread::yield_now();
     let mut buf: [u8; 5] = [0; 5];
     let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
     assert_eq!(res, 5);
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index 51cafbb3f43..b3b6fe1a5d7 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -13,11 +13,34 @@ use std::fmt::{Debug, Display, LowerHex};
 use std::hint::black_box;
 use std::{f32, f64};
 
+/// Compare the two floats, allowing for $ulp many ULPs of error.
+///
+/// ULP means "Units in the Last Place" or "Units of Least Precision".
+/// The ULP of a float `a`` is the smallest possible change at `a`, so the ULP difference represents how
+/// many discrete floating-point steps are needed to reach the actual value from the expected value.
+///
+/// Essentially ULP can be seen as a distance metric of floating-point numbers, but with
+/// the same amount of "spacing" between all consecutive representable values. So even though 2 very large floating point numbers
+/// have a large value difference, their ULP can still be 1, so they are still "approximatly equal",
+/// but the EPSILON check would have failed.
 macro_rules! assert_approx_eq {
-    ($a:expr, $b:expr) => {{
-        let (a, b) = (&$a, &$b);
-        assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
+    ($a:expr, $b:expr, $ulp:expr) => {{
+        let (actual, expected) = ($a, $b);
+        let allowed_ulp_diff = $ulp;
+        let _force_same_type = actual == expected;
+        // Approximate the ULP by taking half the distance between the number one place "up"
+        // and the number one place "down".
+        let ulp = (expected.next_up() - expected.next_down()) / 2.0;
+        let ulp_diff = ((actual - expected) / ulp).abs().round() as i32;
+        if ulp_diff > allowed_ulp_diff {
+            panic!("{actual:?} is not approximately equal to {expected:?}\ndifference in ULP: {ulp_diff} > {allowed_ulp_diff}");
+        };
     }};
+
+    ($a:expr, $b: expr) => {
+        // accept up to 64ULP (16ULP for host floats and 16ULP for miri artificial error and 32 for any rounding errors)
+        assert_approx_eq!($a, $b, 64);
+    };
 }
 
 fn main() {
@@ -33,6 +56,7 @@ fn main() {
     test_algebraic();
     test_fmuladd();
     test_min_max_nondet();
+    test_non_determinism();
 }
 
 trait Float: Copy + PartialEq + Debug {
@@ -1029,7 +1053,7 @@ pub fn libm() {
     assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4);
 
     assert_approx_eq!(1.0f32.sinh(), 1.1752012f32);
-    assert_approx_eq!(1.0f64.sinh(), 1.1752012f64);
+    assert_approx_eq!(1.0f64.sinh(), 1.1752011936438014f64);
     assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
     assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
 
@@ -1041,12 +1065,12 @@ pub fn libm() {
     assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4);
 
     assert_approx_eq!(1.0f32.cosh(), 1.54308f32);
-    assert_approx_eq!(1.0f64.cosh(), 1.54308f64);
+    assert_approx_eq!(1.0f64.cosh(), 1.5430806348152437f64);
     assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32);
     assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64);
 
     assert_approx_eq!(1.0f32.tan(), 1.557408f32);
-    assert_approx_eq!(1.0f64.tan(), 1.557408f64);
+    assert_approx_eq!(1.0f64.tan(), 1.5574077246549023f64);
     assert_approx_eq!(1.0_f32, 1.0_f32.tan().atan());
     assert_approx_eq!(1.0_f64, 1.0_f64.tan().atan());
     assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32);
@@ -1091,11 +1115,11 @@ fn test_fast() {
     pub fn test_operations_f16(a: f16, b: f16) {
         // make sure they all map to the correct operation
         unsafe {
-            assert_eq!(fadd_fast(a, b), a + b);
-            assert_eq!(fsub_fast(a, b), a - b);
-            assert_eq!(fmul_fast(a, b), a * b);
-            assert_eq!(fdiv_fast(a, b), a / b);
-            assert_eq!(frem_fast(a, b), a % b);
+            assert_approx_eq!(fadd_fast(a, b), a + b);
+            assert_approx_eq!(fsub_fast(a, b), a - b);
+            assert_approx_eq!(fmul_fast(a, b), a * b);
+            assert_approx_eq!(fdiv_fast(a, b), a / b);
+            assert_approx_eq!(frem_fast(a, b), a % b);
         }
     }
 
@@ -1103,11 +1127,11 @@ fn test_fast() {
     pub fn test_operations_f32(a: f32, b: f32) {
         // make sure they all map to the correct operation
         unsafe {
-            assert_eq!(fadd_fast(a, b), a + b);
-            assert_eq!(fsub_fast(a, b), a - b);
-            assert_eq!(fmul_fast(a, b), a * b);
-            assert_eq!(fdiv_fast(a, b), a / b);
-            assert_eq!(frem_fast(a, b), a % b);
+            assert_approx_eq!(fadd_fast(a, b), a + b);
+            assert_approx_eq!(fsub_fast(a, b), a - b);
+            assert_approx_eq!(fmul_fast(a, b), a * b);
+            assert_approx_eq!(fdiv_fast(a, b), a / b);
+            assert_approx_eq!(frem_fast(a, b), a % b);
         }
     }
 
@@ -1115,11 +1139,11 @@ fn test_fast() {
     pub fn test_operations_f64(a: f64, b: f64) {
         // make sure they all map to the correct operation
         unsafe {
-            assert_eq!(fadd_fast(a, b), a + b);
-            assert_eq!(fsub_fast(a, b), a - b);
-            assert_eq!(fmul_fast(a, b), a * b);
-            assert_eq!(fdiv_fast(a, b), a / b);
-            assert_eq!(frem_fast(a, b), a % b);
+            assert_approx_eq!(fadd_fast(a, b), a + b);
+            assert_approx_eq!(fsub_fast(a, b), a - b);
+            assert_approx_eq!(fmul_fast(a, b), a * b);
+            assert_approx_eq!(fdiv_fast(a, b), a / b);
+            assert_approx_eq!(frem_fast(a, b), a % b);
         }
     }
 
@@ -1127,11 +1151,11 @@ fn test_fast() {
     pub fn test_operations_f128(a: f128, b: f128) {
         // make sure they all map to the correct operation
         unsafe {
-            assert_eq!(fadd_fast(a, b), a + b);
-            assert_eq!(fsub_fast(a, b), a - b);
-            assert_eq!(fmul_fast(a, b), a * b);
-            assert_eq!(fdiv_fast(a, b), a / b);
-            assert_eq!(frem_fast(a, b), a % b);
+            assert_approx_eq!(fadd_fast(a, b), a + b);
+            assert_approx_eq!(fsub_fast(a, b), a - b);
+            assert_approx_eq!(fmul_fast(a, b), a * b);
+            assert_approx_eq!(fdiv_fast(a, b), a / b);
+            assert_approx_eq!(frem_fast(a, b), a % b);
         }
     }
 
@@ -1153,41 +1177,41 @@ fn test_algebraic() {
     #[inline(never)]
     pub fn test_operations_f16(a: f16, b: f16) {
         // make sure they all map to the correct operation
-        assert_eq!(fadd_algebraic(a, b), a + b);
-        assert_eq!(fsub_algebraic(a, b), a - b);
-        assert_eq!(fmul_algebraic(a, b), a * b);
-        assert_eq!(fdiv_algebraic(a, b), a / b);
-        assert_eq!(frem_algebraic(a, b), a % b);
+        assert_approx_eq!(fadd_algebraic(a, b), a + b);
+        assert_approx_eq!(fsub_algebraic(a, b), a - b);
+        assert_approx_eq!(fmul_algebraic(a, b), a * b);
+        assert_approx_eq!(fdiv_algebraic(a, b), a / b);
+        assert_approx_eq!(frem_algebraic(a, b), a % b);
     }
 
     #[inline(never)]
     pub fn test_operations_f32(a: f32, b: f32) {
         // make sure they all map to the correct operation
-        assert_eq!(fadd_algebraic(a, b), a + b);
-        assert_eq!(fsub_algebraic(a, b), a - b);
-        assert_eq!(fmul_algebraic(a, b), a * b);
-        assert_eq!(fdiv_algebraic(a, b), a / b);
-        assert_eq!(frem_algebraic(a, b), a % b);
+        assert_approx_eq!(fadd_algebraic(a, b), a + b);
+        assert_approx_eq!(fsub_algebraic(a, b), a - b);
+        assert_approx_eq!(fmul_algebraic(a, b), a * b);
+        assert_approx_eq!(fdiv_algebraic(a, b), a / b);
+        assert_approx_eq!(frem_algebraic(a, b), a % b);
     }
 
     #[inline(never)]
     pub fn test_operations_f64(a: f64, b: f64) {
         // make sure they all map to the correct operation
-        assert_eq!(fadd_algebraic(a, b), a + b);
-        assert_eq!(fsub_algebraic(a, b), a - b);
-        assert_eq!(fmul_algebraic(a, b), a * b);
-        assert_eq!(fdiv_algebraic(a, b), a / b);
-        assert_eq!(frem_algebraic(a, b), a % b);
+        assert_approx_eq!(fadd_algebraic(a, b), a + b);
+        assert_approx_eq!(fsub_algebraic(a, b), a - b);
+        assert_approx_eq!(fmul_algebraic(a, b), a * b);
+        assert_approx_eq!(fdiv_algebraic(a, b), a / b);
+        assert_approx_eq!(frem_algebraic(a, b), a % b);
     }
 
     #[inline(never)]
     pub fn test_operations_f128(a: f128, b: f128) {
         // make sure they all map to the correct operation
-        assert_eq!(fadd_algebraic(a, b), a + b);
-        assert_eq!(fsub_algebraic(a, b), a - b);
-        assert_eq!(fmul_algebraic(a, b), a * b);
-        assert_eq!(fdiv_algebraic(a, b), a / b);
-        assert_eq!(frem_algebraic(a, b), a % b);
+        assert_approx_eq!(fadd_algebraic(a, b), a + b);
+        assert_approx_eq!(fsub_algebraic(a, b), a - b);
+        assert_approx_eq!(fmul_algebraic(a, b), a * b);
+        assert_approx_eq!(fdiv_algebraic(a, b), a / b);
+        assert_approx_eq!(frem_algebraic(a, b), a % b);
     }
 
     test_operations_f16(11., 2.);
@@ -1245,3 +1269,122 @@ fn test_min_max_nondet() {
     ensure_both(|| f128::min(0.0, -0.0).is_sign_positive());
     ensure_both(|| f128::max(0.0, -0.0).is_sign_positive());
 }
+
+fn test_non_determinism() {
+    use std::intrinsics::{
+        fadd_algebraic, fadd_fast, fdiv_algebraic, fdiv_fast, fmul_algebraic, fmul_fast,
+        frem_algebraic, frem_fast, fsub_algebraic, fsub_fast,
+    };
+    use std::{f32, f64};
+    // TODO: Also test powi and powf when the non-determinism is implemented for them
+
+    /// Ensure that the operation is non-deterministic
+    #[track_caller]
+    fn ensure_nondet<T: PartialEq + std::fmt::Debug>(f: impl Fn() -> T) {
+
+        let rounds = 16;
+        let first = f();
+        for _ in 1..rounds {
+            if f() != first {
+                // We saw two different values!
+                return;
+            }
+        }
+        // We saw the same thing N times.
+        // FIXME: temporarily disabled as it breaks std tests.
+        //panic!("expected non-determinism, got {rounds} times the same result: {first:?}");
+    }
+
+    macro_rules! test_operations_f {
+        ($a:expr, $b:expr) => {
+            ensure_nondet(|| fadd_algebraic($a, $b));
+            ensure_nondet(|| fsub_algebraic($a, $b));
+            ensure_nondet(|| fmul_algebraic($a, $b));
+            ensure_nondet(|| fdiv_algebraic($a, $b));
+            ensure_nondet(|| frem_algebraic($a, $b));
+
+            unsafe {
+                ensure_nondet(|| fadd_fast($a, $b));
+                ensure_nondet(|| fsub_fast($a, $b));
+                ensure_nondet(|| fmul_fast($a, $b));
+                ensure_nondet(|| fdiv_fast($a, $b));
+                ensure_nondet(|| frem_fast($a, $b));
+            }
+        };
+    }
+
+    pub fn test_operations_f16(a: f16, b: f16) {
+        test_operations_f!(a, b);
+    }
+    pub fn test_operations_f32(a: f32, b: f32) {
+        test_operations_f!(a, b);
+        ensure_nondet(|| a.log(b));
+        ensure_nondet(|| a.exp());
+        ensure_nondet(|| 10f32.exp2());
+        ensure_nondet(|| f32::consts::E.ln());
+        ensure_nondet(|| 1f32.ln_1p());
+        ensure_nondet(|| 10f32.log10());
+        ensure_nondet(|| 8f32.log2());
+        ensure_nondet(|| 27.0f32.cbrt());
+        ensure_nondet(|| 3.0f32.hypot(4.0f32));
+        ensure_nondet(|| 1f32.sin());
+        ensure_nondet(|| 0f32.cos());
+        // On i686-pc-windows-msvc , these functions are implemented by calling the `f64` version,
+        // which means the little rounding errors Miri introduces are discard by the cast down to `f32`.
+        // Just skip the test for them.
+        if !cfg!(all(target_os = "windows", target_env = "msvc", target_arch = "x86")) {
+            ensure_nondet(|| 1.0f32.tan());
+            ensure_nondet(|| 1.0f32.asin());
+            ensure_nondet(|| 5.0f32.acos());
+            ensure_nondet(|| 1.0f32.atan());
+            ensure_nondet(|| 1.0f32.atan2(2.0f32));
+            ensure_nondet(|| 1.0f32.sinh());
+            ensure_nondet(|| 1.0f32.cosh());
+            ensure_nondet(|| 1.0f32.tanh());
+        }
+        ensure_nondet(|| 1.0f32.asinh());
+        ensure_nondet(|| 2.0f32.acosh());
+        ensure_nondet(|| 0.5f32.atanh());
+        ensure_nondet(|| 5.0f32.gamma());
+        ensure_nondet(|| 5.0f32.ln_gamma());
+        ensure_nondet(|| 5.0f32.erf());
+        ensure_nondet(|| 5.0f32.erfc());
+    }
+    pub fn test_operations_f64(a: f64, b: f64) {
+        test_operations_f!(a, b);
+        ensure_nondet(|| a.log(b));
+        ensure_nondet(|| a.exp());
+        ensure_nondet(|| 50f64.exp2());
+        ensure_nondet(|| 3f64.ln());
+        ensure_nondet(|| 1f64.ln_1p());
+        ensure_nondet(|| f64::consts::E.log10());
+        ensure_nondet(|| f64::consts::E.log2());
+        ensure_nondet(|| 27.0f64.cbrt());
+        ensure_nondet(|| 3.0f64.hypot(4.0f64));
+        ensure_nondet(|| 1f64.sin());
+        ensure_nondet(|| 0f64.cos());
+        ensure_nondet(|| 1.0f64.tan());
+        ensure_nondet(|| 1.0f64.asin());
+        ensure_nondet(|| 5.0f64.acos());
+        ensure_nondet(|| 1.0f64.atan());
+        ensure_nondet(|| 1.0f64.atan2(2.0f64));
+        ensure_nondet(|| 1.0f64.sinh());
+        ensure_nondet(|| 1.0f64.cosh());
+        ensure_nondet(|| 1.0f64.tanh());
+        ensure_nondet(|| 1.0f64.asinh());
+        ensure_nondet(|| 3.0f64.acosh());
+        ensure_nondet(|| 0.5f64.atanh());
+        ensure_nondet(|| 5.0f64.gamma());
+        ensure_nondet(|| 5.0f64.ln_gamma());
+        ensure_nondet(|| 5.0f64.erf());
+        ensure_nondet(|| 5.0f64.erfc());
+    }
+    pub fn test_operations_f128(a: f128, b: f128) {
+        test_operations_f!(a, b);
+    }
+
+    test_operations_f16(5., 7.);
+    test_operations_f32(12., 5.);
+    test_operations_f64(19., 11.);
+    test_operations_f128(25., 18.);
+}
diff --git a/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs
new file mode 100644
index 00000000000..84485dbad8c
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/aarch64/intrinsics-aarch64-neon.rs
@@ -0,0 +1,40 @@
+// We're testing aarch64 target specific features
+//@only-target: aarch64
+//@compile-flags: -C target-feature=+neon
+
+use std::arch::aarch64::*;
+use std::arch::is_aarch64_feature_detected;
+
+fn main() {
+    assert!(is_aarch64_feature_detected!("neon"));
+
+    unsafe {
+        test_neon();
+    }
+}
+
+#[target_feature(enable = "neon")]
+unsafe fn test_neon() {
+    // Adapted from library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs
+    unsafe fn test_vpmaxq_u8() {
+        let a = vld1q_u8([1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8].as_ptr());
+        let b = vld1q_u8([0, 3, 2, 5, 4, 7, 6, 9, 0, 3, 2, 5, 4, 7, 6, 9].as_ptr());
+        let e = [2, 4, 6, 8, 2, 4, 6, 8, 3, 5, 7, 9, 3, 5, 7, 9];
+        let mut r = [0; 16];
+        vst1q_u8(r.as_mut_ptr(), vpmaxq_u8(a, b));
+        assert_eq!(r, e);
+    }
+    test_vpmaxq_u8();
+
+    unsafe fn test_vpmaxq_u8_is_unsigned() {
+        let a = vld1q_u8(
+            [255, 0, 253, 252, 251, 250, 249, 248, 255, 254, 253, 252, 251, 250, 249, 248].as_ptr(),
+        );
+        let b = vld1q_u8([254, 3, 2, 5, 4, 7, 6, 9, 0, 3, 2, 5, 4, 7, 6, 9].as_ptr());
+        let e = [255, 253, 251, 249, 255, 253, 251, 249, 254, 5, 7, 9, 3, 5, 7, 9];
+        let mut r = [0; 16];
+        vst1q_u8(r.as_mut_ptr(), vpmaxq_u8(a, b));
+        assert_eq!(r, e);
+    }
+    test_vpmaxq_u8_is_unsigned();
+}
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 3bc953c3a5f..85ce38f57d6 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -217,15 +217,11 @@ fn run_tests(
         ui_test::default_file_filter,
         // This could be used to overwrite the `Config` on a per-test basis.
         |_, _| {},
-        (
-            match args.format {
-                Format::Terse => status_emitter::Text::quiet(),
-                Format::Pretty => status_emitter::Text::verbose(),
-            },
-            status_emitter::Gha::</* GHA Actions groups*/ false> {
-                name: format!("{mode:?} {path} ({target})"),
-            },
-        ),
+        // No GHA output as that would also show in the main rustc repo.
+        match args.format {
+            Format::Terse => status_emitter::Text::quiet(),
+            Format::Pretty => status_emitter::Text::verbose(),
+        },
     )
 }
 
diff --git a/src/tools/miri/tests/x86_64-unknown-kernel.json b/src/tools/miri/tests/x86_64-unknown-kernel.json
index 8135b618d0d..8da67d3a1c6 100644
--- a/src/tools/miri/tests/x86_64-unknown-kernel.json
+++ b/src/tools/miri/tests/x86_64-unknown-kernel.json
@@ -10,6 +10,7 @@
   "vendor": "unknown",
   "linker": "rust-lld",
   "linker-flavor": "gnu-lld",
+  "rustc-abi": "x86-softfloat",
   "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float",
   "dynamic-linking": false,
   "executables": true,