diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index 9d61cc4e2d5f0..5b538691de183 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -232,16 +232,16 @@ You can also directly run Miri on a Rust source file:
 
 ## Advanced topic: Syncing with the rustc repo
 
-We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit
-changes between the rustc and Miri repositories. For now, the latest git version
-of josh needs to be built from source. This downloads and runs josh:
+We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit changes between the
+rustc and Miri repositories.
 
 ```sh
-git clone https://github.com/josh-project/josh
-cd josh
-cargo run --release -p josh-proxy -- --local=local --remote=https://github.com --no-background
+cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
+josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background
 ```
 
+This uses a directory `$HOME/.cache/josh` as a cache, to speed up repeated pulling/pushing.
+
 ### Importing changes from the rustc repo
 
 Josh needs to be running, as described above.
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 989a196b700c3..48581f6bbff1a 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -399,6 +399,8 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
   value from a load. This can help diagnose problems that disappear under
   `-Zmiri-disable-weak-memory-emulation`.
+* `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
+  `4` is default for most targets. This value should always be a power of 2 and nonzero.
 
 [function ABI]: https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier
 
@@ -574,6 +576,21 @@ extern "Rust" {
 
     /// Miri-provided extern function to deallocate memory.
     fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
+
+    /// Convert a path from the host Miri runs on to the target Miri interprets.
+    /// Performs conversion of path separators as needed.
+    ///
+    /// Usually Miri performs this kind of conversion automatically. However, manual conversion
+    /// might be necessary when reading an environment variable that was set on the host
+    /// (such as TMPDIR) and using it as a target path.
+    ///
+    /// Only works with isolation disabled.
+    ///
+    /// `in` must point to a null-terminated string, and will be read as the input host path.
+    /// `out` must point to at least `out_size` many bytes, and the result will be stored there
+    /// with a null terminator.
+    /// Returns 0 if the `out` buffer was large enough, and the required size otherwise.
+    fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
 }
 ```
 
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index a259576ed42a0..0c0bbbc70208e 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -243,7 +243,7 @@ if [ -z "$CARGO_PROFILE_DEV_OPT_LEVEL" ]; then
     export CARGO_PROFILE_DEV_OPT_LEVEL=2
 fi
 # Enable rustc-specific lints (ignored without `-Zunstable-options`).
-export RUSTFLAGS="-Zunstable-options -Wrustc::internal $RUSTFLAGS"
+export RUSTFLAGS="-Zunstable-options -Wrustc::internal -Wrust_2018_idioms -Wunused_lifetimes -Wsemicolon_in_expressions_from_macros $RUSTFLAGS"
 # We set the rpath so that Miri finds the private rustc libraries it needs.
 export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS"
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 8dd18ae98e6d6..ee75e7a29324b 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-203c8765ea33c65d888febe0e8219c4bb11b0d89
+4f4d0586ad20c66a16d547581ca379beafece93a
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index fce95b987f729..8c01748613cf8 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -512,6 +512,18 @@ fn main() {
             };
 
             miri_config.num_cpus = num_cpus;
+        } else if let Some(param) = arg.strip_prefix("-Zmiri-force-page-size=") {
+            let page_size = match param.parse::<u64>() {
+                Ok(i) =>
+                    if i.is_power_of_two() {
+                        i * 1024
+                    } else {
+                        show_error!("-Zmiri-force-page-size requires a power of 2: {}", i)
+                    },
+                Err(err) => show_error!("-Zmiri-force-page-size requires a `u64`: {}", err),
+            };
+
+            miri_config.page_size = Some(page_size);
         } else {
             // Forward to rustc.
             rustc_args.push(arg);
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index f896a337f42ca..9f6cbe7f3c72f 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -264,7 +264,11 @@ impl GlobalStateInner {
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+    fn retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
@@ -272,7 +276,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
-    fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn retag_place_contents(
+        &mut self,
+        kind: RetagKind,
+        place: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 24b3489e0d1d6..5f132bf11a92a 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -462,7 +462,9 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
                 let permission = permission
                     .expect("start_grant should set the current permission before popping a tag");
-                format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
+                format!(
+                    " due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})"
+                )
             }
         };
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index ffbc00864022f..bcdf2e751790e 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -14,6 +14,7 @@ use rustc_middle::mir::{Mutability, RetagKind};
 use rustc_middle::ty::{
     self,
     layout::{HasParamEnv, LayoutOf},
+    Ty,
 };
 use rustc_target::abi::{Abi, Size};
 
@@ -64,7 +65,7 @@ impl NewPermission {
     /// A key function: determine the permissions to grant at a retag for the given kind of
     /// reference/pointer.
     fn from_ref_ty<'tcx>(
-        ty: ty::Ty<'tcx>,
+        ty: Ty<'tcx>,
         kind: RetagKind,
         cx: &crate::MiriInterpCx<'_, 'tcx>,
     ) -> Self {
@@ -864,7 +865,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             RetagKind::FnEntry => unreachable!(),
             RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
         };
-        this.sb_retag_reference(&val, new_perm, retag_cause)
+        this.sb_retag_reference(val, new_perm, retag_cause)
     }
 
     fn sb_retag_place_contents(
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index bcbf45a3d2408..9646327966896 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -50,8 +50,10 @@ use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir;
+use rustc_span::Span;
 use rustc_target::abi::{Align, Size};
 
+use crate::diagnostics::RacingOp;
 use crate::*;
 
 use super::{
@@ -144,8 +146,8 @@ impl ThreadClockSet {
     /// Increment the happens-before clock at a
     /// known index.
     #[inline]
-    fn increment_clock(&mut self, index: VectorIdx) {
-        self.clock.increment_index(index);
+    fn increment_clock(&mut self, index: VectorIdx, current_span: Span) {
+        self.clock.increment_index(index, current_span);
     }
 
     /// Join the happens-before clock with that of
@@ -356,13 +358,9 @@ impl MemoryCellClocks {
         index: VectorIdx,
     ) -> Result<(), DataRace> {
         log::trace!("Atomic read with vectors: {:#?} :: {:#?}", self, clocks);
-        if self.write <= clocks.clock[self.write_index] {
-            let atomic = self.atomic_mut();
-            atomic.read_vector.set_at_index(&clocks.clock, index);
-            Ok(())
-        } else {
-            Err(DataRace)
-        }
+        let atomic = self.atomic_mut();
+        atomic.read_vector.set_at_index(&clocks.clock, index);
+        if self.write <= clocks.clock[self.write_index] { Ok(()) } else { Err(DataRace) }
     }
 
     /// Detect data-races with an atomic write, either with a non-atomic read or with
@@ -373,9 +371,9 @@ impl MemoryCellClocks {
         index: VectorIdx,
     ) -> Result<(), DataRace> {
         log::trace!("Atomic write with vectors: {:#?} :: {:#?}", self, clocks);
+        let atomic = self.atomic_mut();
+        atomic.write_vector.set_at_index(&clocks.clock, index);
         if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
-            let atomic = self.atomic_mut();
-            atomic.write_vector.set_at_index(&clocks.clock, index);
             Ok(())
         } else {
             Err(DataRace)
@@ -386,22 +384,22 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn read_race_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        clocks: &mut ThreadClockSet,
         index: VectorIdx,
+        current_span: Span,
     ) -> Result<(), DataRace> {
         log::trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, clocks);
+        if !current_span.is_dummy() {
+            clocks.clock[index].span = current_span;
+        }
         if self.write <= clocks.clock[self.write_index] {
             let race_free = if let Some(atomic) = self.atomic() {
                 atomic.write_vector <= clocks.clock
             } else {
                 true
             };
-            if race_free {
-                self.read.set_at_index(&clocks.clock, index);
-                Ok(())
-            } else {
-                Err(DataRace)
-            }
+            self.read.set_at_index(&clocks.clock, index);
+            if race_free { Ok(()) } else { Err(DataRace) }
         } else {
             Err(DataRace)
         }
@@ -411,21 +409,25 @@ impl MemoryCellClocks {
     /// returns true if a data-race is detected.
     fn write_race_detect(
         &mut self,
-        clocks: &ThreadClockSet,
+        clocks: &mut ThreadClockSet,
         index: VectorIdx,
         write_type: WriteType,
+        current_span: Span,
     ) -> Result<(), DataRace> {
         log::trace!("Unsynchronized write with vectors: {:#?} :: {:#?}", self, clocks);
+        if !current_span.is_dummy() {
+            clocks.clock[index].span = current_span;
+        }
         if self.write <= clocks.clock[self.write_index] && self.read <= clocks.clock {
             let race_free = if let Some(atomic) = self.atomic() {
                 atomic.write_vector <= clocks.clock && atomic.read_vector <= clocks.clock
             } else {
                 true
             };
+            self.write = clocks.clock[index];
+            self.write_index = index;
+            self.write_type = write_type;
             if race_free {
-                self.write = clocks.clock[index];
-                self.write_index = index;
-                self.write_type = write_type;
                 self.read.set_zero_vector();
                 Ok(())
             } else {
@@ -621,30 +623,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     /// Update the data-race detector for an atomic fence on the current thread.
     fn atomic_fence(&mut self, atomic: AtomicFenceOrd) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         if let Some(data_race) = &mut this.machine.data_race {
-            data_race.maybe_perform_sync_operation(&this.machine.threads, |index, mut clocks| {
-                log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
-
-                // Apply data-race detection for the current fences
-                // this treats AcqRel and SeqCst as the same as an acquire
-                // and release fence applied in the same timestamp.
-                if atomic != AtomicFenceOrd::Release {
-                    // Either Acquire | AcqRel | SeqCst
-                    clocks.apply_acquire_fence();
-                }
-                if atomic != AtomicFenceOrd::Acquire {
-                    // Either Release | AcqRel | SeqCst
-                    clocks.apply_release_fence();
-                }
-                if atomic == AtomicFenceOrd::SeqCst {
-                    data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index);
-                    clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow());
-                    clocks.write_seqcst.join(&data_race.last_sc_write.borrow());
-                }
+            data_race.maybe_perform_sync_operation(
+                &this.machine.threads,
+                current_span,
+                |index, mut clocks| {
+                    log::trace!("Atomic fence on {:?} with ordering {:?}", index, atomic);
+
+                    // Apply data-race detection for the current fences
+                    // this treats AcqRel and SeqCst as the same as an acquire
+                    // and release fence applied in the same timestamp.
+                    if atomic != AtomicFenceOrd::Release {
+                        // Either Acquire | AcqRel | SeqCst
+                        clocks.apply_acquire_fence();
+                    }
+                    if atomic != AtomicFenceOrd::Acquire {
+                        // Either Release | AcqRel | SeqCst
+                        clocks.apply_release_fence();
+                    }
+                    if atomic == AtomicFenceOrd::SeqCst {
+                        data_race.last_sc_fence.borrow_mut().set_at_index(&clocks.clock, index);
+                        clocks.fence_seqcst.join(&data_race.last_sc_fence.borrow());
+                        clocks.write_seqcst.join(&data_race.last_sc_write.borrow());
+                    }
 
-                // Increment timestamp in case of release semantics.
-                Ok(atomic != AtomicFenceOrd::Acquire)
-            })
+                    // Increment timestamp in case of release semantics.
+                    Ok(atomic != AtomicFenceOrd::Acquire)
+                },
+            )
         } else {
             Ok(())
         }
@@ -682,6 +689,7 @@ impl VClockAlloc {
         thread_mgr: &ThreadManager<'_, '_>,
         len: Size,
         kind: MemoryKind<MiriMemoryKind>,
+        current_span: Span,
     ) -> VClockAlloc {
         let (alloc_timestamp, alloc_index) = match kind {
             // User allocated and stack memory should track allocation.
@@ -693,7 +701,8 @@ impl VClockAlloc {
             )
             | MemoryKind::Stack => {
                 let (alloc_index, clocks) = global.current_thread_state(thread_mgr);
-                let alloc_timestamp = clocks.clock[alloc_index];
+                let mut alloc_timestamp = clocks.clock[alloc_index];
+                alloc_timestamp.span = current_span;
                 (alloc_timestamp, alloc_index)
             }
             // Other global memory should trace races but be allocated at the 0 timestamp.
@@ -704,7 +713,7 @@ impl VClockAlloc {
                 | MiriMemoryKind::ExternStatic
                 | MiriMemoryKind::Tls,
             )
-            | MemoryKind::CallerLocation => (0, VectorIdx::MAX_INDEX),
+            | MemoryKind::CallerLocation => (VTimestamp::ZERO, VectorIdx::MAX_INDEX),
         };
         VClockAlloc {
             alloc_ranges: RefCell::new(RangeMap::new(
@@ -735,7 +744,7 @@ impl VClockAlloc {
                     let idx = l_remainder_slice
                         .iter()
                         .enumerate()
-                        .find_map(|(idx, &r)| if r == 0 { None } else { Some(idx) })
+                        .find_map(|(idx, &r)| if r == VTimestamp::ZERO { None } else { Some(idx) })
                         .expect("Invalid VClock Invariant");
                     Some(idx + r_slice.len())
                 } else {
@@ -762,7 +771,7 @@ impl VClockAlloc {
     ) -> InterpResult<'tcx> {
         let (current_index, current_clocks) = global.current_thread_state(thread_mgr);
         let write_clock;
-        let (other_action, other_thread, _other_clock) = if range.write
+        let (other_action, other_thread, other_clock) = if range.write
             > current_clocks.clock[range.write_index]
         {
             // Convert the write action into the vector clock it
@@ -799,14 +808,19 @@ impl VClockAlloc {
         let other_thread_info = global.print_thread_metadata(thread_mgr, other_thread);
 
         // Throw the data-race detection.
-        throw_ub_format!(
-            "Data race detected between {} on {} and {} on {} at {:?}",
-            action,
-            current_thread_info,
-            other_action,
-            other_thread_info,
-            ptr_dbg,
-        )
+        Err(err_machine_stop!(TerminationInfo::DataRace {
+            ptr: ptr_dbg,
+            op1: RacingOp {
+                action: other_action.to_string(),
+                thread_info: other_thread_info,
+                span: other_clock.as_slice()[other_thread.index()].span_data(),
+            },
+            op2: RacingOp {
+                action: action.to_string(),
+                thread_info: current_thread_info,
+                span: current_clocks.clock.as_slice()[current_index.index()].span_data(),
+            },
+        }))?
     }
 
     /// Detect racing atomic read and writes (not data races)
@@ -840,12 +854,14 @@ impl VClockAlloc {
         range: AllocRange,
         machine: &MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
+        let current_span = machine.current_span();
         let global = machine.data_race.as_ref().unwrap();
         if global.race_detecting() {
-            let (index, clocks) = global.current_thread_state(&machine.threads);
+            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
             let mut alloc_ranges = self.alloc_ranges.borrow_mut();
             for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
-                if let Err(DataRace) = range.read_race_detect(&clocks, index) {
+                if let Err(DataRace) = range.read_race_detect(&mut clocks, index, current_span) {
+                    drop(clocks);
                     // Report data-race.
                     return Self::report_data_race(
                         global,
@@ -871,11 +887,15 @@ impl VClockAlloc {
         write_type: WriteType,
         machine: &mut MiriMachine<'_, '_>,
     ) -> InterpResult<'tcx> {
+        let current_span = machine.current_span();
         let global = machine.data_race.as_mut().unwrap();
         if global.race_detecting() {
-            let (index, clocks) = global.current_thread_state(&machine.threads);
+            let (index, mut clocks) = global.current_thread_state_mut(&machine.threads);
             for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
-                if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
+                if let Err(DataRace) =
+                    range.write_race_detect(&mut clocks, index, write_type, current_span)
+                {
+                    drop(clocks);
                     // Report data-race
                     return Self::report_data_race(
                         global,
@@ -1100,9 +1120,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
                     size.bytes()
                 );
 
+                let current_span = this.machine.current_span();
                 // Perform the atomic operation.
                 data_race.maybe_perform_sync_operation(
                     &this.machine.threads,
+                    current_span,
                     |index, mut clocks| {
                         for (offset, range) in
                             alloc_meta.alloc_ranges.borrow_mut().iter_mut(base_offset, size)
@@ -1303,7 +1325,12 @@ impl GlobalState {
     // Hook for thread creation, enabled multi-threaded execution and marks
     // the current thread timestamp as happening-before the current thread.
     #[inline]
-    pub fn thread_created(&mut self, thread_mgr: &ThreadManager<'_, '_>, thread: ThreadId) {
+    pub fn thread_created(
+        &mut self,
+        thread_mgr: &ThreadManager<'_, '_>,
+        thread: ThreadId,
+        current_span: Span,
+    ) {
         let current_index = self.current_index(thread_mgr);
 
         // Enable multi-threaded execution, there are now at least two threads
@@ -1320,7 +1347,7 @@ impl GlobalState {
             // Now re-configure the re-use candidate, increment the clock
             // for the new sync use of the vector.
             let vector_clocks = self.vector_clocks.get_mut();
-            vector_clocks[reuse_index].increment_clock(reuse_index);
+            vector_clocks[reuse_index].increment_clock(reuse_index, current_span);
 
             // Locate the old thread the vector was associated with and update
             // it to represent the new thread instead.
@@ -1360,8 +1387,8 @@ impl GlobalState {
 
         // Advance both threads after the synchronized operation.
         // Both operations are considered to have release semantics.
-        current.increment_clock(current_index);
-        created.increment_clock(created_index);
+        current.increment_clock(current_index, current_span);
+        created.increment_clock(created_index, current_span);
     }
 
     /// Hook on a thread join to update the implicit happens-before relation between the joined
@@ -1427,13 +1454,13 @@ impl GlobalState {
     /// This should be called strictly before any calls to
     /// `thread_joined`.
     #[inline]
-    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) {
+    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>, current_span: Span) {
         let current_index = self.current_index(thread_mgr);
 
         // Increment the clock to a unique termination timestamp.
         let vector_clocks = self.vector_clocks.get_mut();
         let current_clocks = &mut vector_clocks[current_index];
-        current_clocks.increment_clock(current_index);
+        current_clocks.increment_clock(current_index, current_span);
 
         // Load the current thread id for the executing vector.
         let vector_info = self.vector_info.get_mut();
@@ -1462,13 +1489,14 @@ impl GlobalState {
     fn maybe_perform_sync_operation<'tcx>(
         &self,
         thread_mgr: &ThreadManager<'_, '_>,
+        current_span: Span,
         op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
     ) -> InterpResult<'tcx> {
         if self.multi_threaded.get() {
             let (index, clocks) = self.current_thread_state_mut(thread_mgr);
             if op(index, clocks)? {
                 let (_, mut clocks) = self.current_thread_state_mut(thread_mgr);
-                clocks.increment_clock(index);
+                clocks.increment_clock(index, current_span);
             }
         }
         Ok(())
@@ -1501,10 +1529,10 @@ impl GlobalState {
     /// since an acquire operation should have occurred before, however
     /// for futex & condvar operations this is not the case and this
     /// operation must be used.
-    pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId) {
+    pub fn validate_lock_release(&self, lock: &mut VClock, thread: ThreadId, current_span: Span) {
         let (index, mut clocks) = self.load_thread_state_mut(thread);
         lock.clone_from(&clocks.clock);
-        clocks.increment_clock(index);
+        clocks.increment_clock(index, current_span);
     }
 
     /// Release a lock handle, express that this happens-before
@@ -1514,10 +1542,15 @@ impl GlobalState {
     /// For normal locks this should be equivalent to `validate_lock_release`.
     /// This function only exists for joining over the set of concurrent readers
     /// in a read-write lock and should not be used for anything else.
-    pub fn validate_lock_release_shared(&self, lock: &mut VClock, thread: ThreadId) {
+    pub fn validate_lock_release_shared(
+        &self,
+        lock: &mut VClock,
+        thread: ThreadId,
+        current_span: Span,
+    ) {
         let (index, mut clocks) = self.load_thread_state_mut(thread);
         lock.join(&clocks.clock);
-        clocks.increment_clock(index);
+        clocks.increment_clock(index, current_span);
     }
 
     /// Load the vector index used by the given thread as well as the set of vector clocks
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index 9c9d505297c2d..867683d355210 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -160,6 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn init_once_complete(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let init_once = &mut this.machine.threads.sync.init_onces[id];
 
         assert_eq!(
@@ -172,7 +173,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Each complete happens-before the end of the wait
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release(&mut init_once.data_race, current_thread);
+            data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
         }
 
         // Wake up everyone.
@@ -188,6 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn init_once_fail(&mut self, id: InitOnceId) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let init_once = &mut this.machine.threads.sync.init_onces[id];
         assert_eq!(
             init_once.status,
@@ -197,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Each complete happens-before the end of the wait
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release(&mut init_once.data_race, current_thread);
+            data_race.validate_lock_release(&mut init_once.data_race, current_thread, current_span);
         }
 
         // Wake up one waiting thread, so they can go ahead and try to init this.
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 402c9ce6fc9af..b962052397498 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -359,6 +359,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// return `None`.
     fn mutex_unlock(&mut self, id: MutexId, expected_owner: ThreadId) -> Option<usize> {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let mutex = &mut this.machine.threads.sync.mutexes[id];
         if let Some(current_owner) = mutex.owner {
             // Mutex is locked.
@@ -375,7 +376,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // The mutex is completely unlocked. Try transfering ownership
                 // to another thread.
                 if let Some(data_race) = &this.machine.data_race {
-                    data_race.validate_lock_release(&mut mutex.data_race, current_owner);
+                    data_race.validate_lock_release(
+                        &mut mutex.data_race,
+                        current_owner,
+                        current_span,
+                    );
                 }
                 this.mutex_dequeue_and_lock(id);
             }
@@ -454,6 +459,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Returns `true` if succeeded, `false` if this `reader` did not hold the lock.
     fn rwlock_reader_unlock(&mut self, id: RwLockId, reader: ThreadId) -> bool {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let rwlock = &mut this.machine.threads.sync.rwlocks[id];
         match rwlock.readers.entry(reader) {
             Entry::Occupied(mut entry) => {
@@ -470,7 +476,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Entry::Vacant(_) => return false, // we did not even own this lock
         }
         if let Some(data_race) = &this.machine.data_race {
-            data_race.validate_lock_release_shared(&mut rwlock.data_race_reader, reader);
+            data_race.validate_lock_release_shared(
+                &mut rwlock.data_race_reader,
+                reader,
+                current_span,
+            );
         }
 
         // The thread was a reader. If the lock is not held any more, give it to a writer.
@@ -511,6 +521,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     #[inline]
     fn rwlock_writer_unlock(&mut self, id: RwLockId, expected_writer: ThreadId) -> bool {
         let this = self.eval_context_mut();
+        let current_span = this.machine.current_span();
         let rwlock = &mut this.machine.threads.sync.rwlocks[id];
         if let Some(current_writer) = rwlock.writer {
             if current_writer != expected_writer {
@@ -523,8 +534,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             //  since this writer happens-before both the union of readers once they are finished
             //  and the next writer
             if let Some(data_race) = &this.machine.data_race {
-                data_race.validate_lock_release(&mut rwlock.data_race, current_writer);
-                data_race.validate_lock_release(&mut rwlock.data_race_reader, current_writer);
+                data_race.validate_lock_release(
+                    &mut rwlock.data_race,
+                    current_writer,
+                    current_span,
+                );
+                data_race.validate_lock_release(
+                    &mut rwlock.data_race_reader,
+                    current_writer,
+                    current_span,
+                );
             }
             // The thread was a writer.
             //
@@ -595,12 +614,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let condvar = &mut this.machine.threads.sync.condvars[id];
         let data_race = &this.machine.data_race;
 
         // Each condvar signal happens-before the end of the condvar wake
         if let Some(data_race) = data_race {
-            data_race.validate_lock_release(&mut condvar.data_race, current_thread);
+            data_race.validate_lock_release(&mut condvar.data_race, current_thread, current_span);
         }
         condvar.waiters.pop_front().map(|waiter| {
             if let Some(data_race) = data_race {
@@ -628,12 +648,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn futex_wake(&mut self, addr: u64, bitset: u32) -> Option<ThreadId> {
         let this = self.eval_context_mut();
         let current_thread = this.get_active_thread();
+        let current_span = this.machine.current_span();
         let futex = &mut this.machine.threads.sync.futexes.get_mut(&addr)?;
         let data_race = &this.machine.data_race;
 
         // Each futex-wake happens-before the end of the futex wait
         if let Some(data_race) = data_race {
-            data_race.validate_lock_release(&mut futex.data_race, current_thread);
+            data_race.validate_lock_release(&mut futex.data_race, current_thread, current_span);
         }
 
         // Wake up the first thread in the queue that matches any of the bits in the bitset.
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 03f9ed351fb69..9173eb3c4ee66 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -13,6 +13,7 @@ use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 use crate::concurrency::data_race;
@@ -617,6 +618,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     fn thread_terminated(
         &mut self,
         mut data_race: Option<&mut data_race::GlobalState>,
+        current_span: Span,
     ) -> Vec<Pointer<Provenance>> {
         let mut free_tls_statics = Vec::new();
         {
@@ -634,7 +636,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
         }
         // Set the thread into a terminated state in the data-race detector.
         if let Some(ref mut data_race) = data_race {
-            data_race.thread_terminated(self);
+            data_race.thread_terminated(self, current_span);
         }
         // Check if we need to unblock any threads.
         let mut joined_threads = vec![]; // store which threads joined, we'll need it
@@ -813,8 +815,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let mut state = tls::TlsDtorsState::default();
             Box::new(move |m| state.on_stack_empty(m))
         });
+        let current_span = this.machine.current_span();
         if let Some(data_race) = &mut this.machine.data_race {
-            data_race.thread_created(&this.machine.threads, new_thread_id);
+            data_race.thread_created(&this.machine.threads, new_thread_id, current_span);
         }
 
         // Write the current thread-id, switch to the next thread later
@@ -1041,7 +1044,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         assert!(thread.stack.is_empty(), "only threads with an empty stack can be terminated");
         thread.state = ThreadState::Terminated;
 
-        for ptr in this.machine.threads.thread_terminated(this.machine.data_race.as_mut()) {
+        let current_span = this.machine.current_span();
+        for ptr in
+            this.machine.threads.thread_terminated(this.machine.data_race.as_mut(), current_span)
+        {
             this.deallocate_ptr(ptr.into(), None, MiriMemoryKind::Tls.into())?;
         }
         Ok(())
diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs
index ba04991a5889d..ab4764dd1c87a 100644
--- a/src/tools/miri/src/concurrency/vector_clock.rs
+++ b/src/tools/miri/src/concurrency/vector_clock.rs
@@ -1,6 +1,11 @@
 use rustc_index::vec::Idx;
+use rustc_span::{Span, SpanData, DUMMY_SP};
 use smallvec::SmallVec;
-use std::{cmp::Ordering, fmt::Debug, ops::Index};
+use std::{
+    cmp::Ordering,
+    fmt::Debug,
+    ops::{Index, IndexMut},
+};
 
 /// A vector clock index, this is associated with a thread id
 /// but in some cases one vector index may be shared with
@@ -40,9 +45,42 @@ impl From<u32> for VectorIdx {
 /// clock vectors larger than this will be stored on the heap
 const SMALL_VECTOR: usize = 4;
 
-/// The type of the time-stamps recorded in the data-race detector
-/// set to a type of unsigned integer
-pub type VTimestamp = u32;
+/// The time-stamps recorded in the data-race detector consist of both
+/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
+/// so that diagnostics can report what code was responsible for an operation.
+#[derive(Clone, Copy, Debug)]
+pub struct VTimestamp {
+    time: u32,
+    pub span: Span,
+}
+
+impl VTimestamp {
+    pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP };
+
+    pub fn span_data(&self) -> SpanData {
+        self.span.data()
+    }
+}
+
+impl PartialEq for VTimestamp {
+    fn eq(&self, other: &Self) -> bool {
+        self.time == other.time
+    }
+}
+
+impl Eq for VTimestamp {}
+
+impl PartialOrd for VTimestamp {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for VTimestamp {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.time.cmp(&other.time)
+    }
+}
 
 /// A vector clock for detecting data-races, this is conceptually
 /// a map from a vector index (and thus a thread id) to a timestamp.
@@ -62,7 +100,7 @@ impl VClock {
     /// for a value at the given index
     pub fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock {
         let len = index.index() + 1;
-        let mut vec = smallvec::smallvec![0; len];
+        let mut vec = smallvec::smallvec![VTimestamp::ZERO; len];
         vec[index.index()] = timestamp;
         VClock(vec)
     }
@@ -79,7 +117,7 @@ impl VClock {
     #[inline]
     fn get_mut_with_min_len(&mut self, min_len: usize) -> &mut [VTimestamp] {
         if self.0.len() < min_len {
-            self.0.resize(min_len, 0);
+            self.0.resize(min_len, VTimestamp::ZERO);
         }
         assert!(self.0.len() >= min_len);
         self.0.as_mut_slice()
@@ -88,11 +126,14 @@ impl VClock {
     /// Increment the vector clock at a known index
     /// this will panic if the vector index overflows
     #[inline]
-    pub fn increment_index(&mut self, idx: VectorIdx) {
+    pub fn increment_index(&mut self, idx: VectorIdx, current_span: Span) {
         let idx = idx.index();
         let mut_slice = self.get_mut_with_min_len(idx + 1);
         let idx_ref = &mut mut_slice[idx];
-        *idx_ref = idx_ref.checked_add(1).expect("Vector clock overflow")
+        idx_ref.time = idx_ref.time.checked_add(1).expect("Vector clock overflow");
+        if !current_span.is_dummy() {
+            idx_ref.span = current_span;
+        }
     }
 
     // Join the two vector-clocks together, this
@@ -102,14 +143,23 @@ impl VClock {
         let rhs_slice = other.as_slice();
         let lhs_slice = self.get_mut_with_min_len(rhs_slice.len());
         for (l, &r) in lhs_slice.iter_mut().zip(rhs_slice.iter()) {
+            let l_span = l.span;
+            let r_span = r.span;
             *l = r.max(*l);
+            l.span = l.span.substitute_dummy(r_span).substitute_dummy(l_span);
         }
     }
 
     /// Set the element at the current index of the vector
     pub fn set_at_index(&mut self, other: &Self, idx: VectorIdx) {
         let mut_slice = self.get_mut_with_min_len(idx.index() + 1);
+
+        let prev_span = mut_slice[idx.index()].span;
+
         mut_slice[idx.index()] = other[idx];
+
+        let span = &mut mut_slice[idx.index()].span;
+        *span = span.substitute_dummy(prev_span);
     }
 
     /// Set the vector to the all-zero vector
@@ -313,7 +363,14 @@ impl Index<VectorIdx> for VClock {
 
     #[inline]
     fn index(&self, index: VectorIdx) -> &VTimestamp {
-        self.as_slice().get(index.to_u32() as usize).unwrap_or(&0)
+        self.as_slice().get(index.to_u32() as usize).unwrap_or(&VTimestamp::ZERO)
+    }
+}
+
+impl IndexMut<VectorIdx> for VClock {
+    #[inline]
+    fn index_mut(&mut self, index: VectorIdx) -> &mut VTimestamp {
+        self.0.as_mut_slice().get_mut(index.to_u32() as usize).unwrap()
     }
 }
 
@@ -324,6 +381,7 @@ impl Index<VectorIdx> for VClock {
 mod tests {
 
     use super::{VClock, VTimestamp, VectorIdx};
+    use rustc_span::DUMMY_SP;
     use std::cmp::Ordering;
 
     #[test]
@@ -331,13 +389,13 @@ mod tests {
         let mut c1 = VClock::default();
         let mut c2 = VClock::default();
         assert_eq!(c1, c2);
-        c1.increment_index(VectorIdx(5));
+        c1.increment_index(VectorIdx(5), DUMMY_SP);
         assert_ne!(c1, c2);
-        c2.increment_index(VectorIdx(53));
+        c2.increment_index(VectorIdx(53), DUMMY_SP);
         assert_ne!(c1, c2);
-        c1.increment_index(VectorIdx(53));
+        c1.increment_index(VectorIdx(53), DUMMY_SP);
         assert_ne!(c1, c2);
-        c2.increment_index(VectorIdx(5));
+        c2.increment_index(VectorIdx(5), DUMMY_SP);
         assert_eq!(c1, c2);
     }
 
@@ -386,14 +444,14 @@ mod tests {
         );
     }
 
-    fn from_slice(mut slice: &[VTimestamp]) -> VClock {
+    fn from_slice(mut slice: &[u32]) -> VClock {
         while let Some(0) = slice.last() {
             slice = &slice[..slice.len() - 1]
         }
-        VClock(smallvec::SmallVec::from_slice(slice))
+        VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect())
     }
 
-    fn assert_order(l: &[VTimestamp], r: &[VTimestamp], o: Option<Ordering>) {
+    fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
         let l = from_slice(l);
         let r = from_slice(r);
 
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index 391681444d9ba..2a48c9e6cd015 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -258,7 +258,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
             // The thread index and timestamp of the initialisation write
             // are never meaningfully used, so it's fine to leave them as 0
             store_index: VectorIdx::from(0),
-            timestamp: 0,
+            timestamp: VTimestamp::ZERO,
             val: init,
             is_seqcst: false,
             load_info: RefCell::new(LoadInfo::default()),
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index c22ac50e4557e..035c0e6423381 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -35,6 +35,17 @@ pub enum TerminationInfo {
         link_name: Symbol,
         span: SpanData,
     },
+    DataRace {
+        op1: RacingOp,
+        op2: RacingOp,
+        ptr: Pointer,
+    },
+}
+
+pub struct RacingOp {
+    pub action: String,
+    pub thread_info: String,
+    pub span: SpanData,
 }
 
 impl fmt::Display for TerminationInfo {
@@ -55,6 +66,12 @@ impl fmt::Display for TerminationInfo {
                 write!(f, "multiple definitions of symbol `{link_name}`"),
             SymbolShimClashing { link_name, .. } =>
                 write!(f, "found `{link_name}` symbol definition that clashes with a built-in shim",),
+            DataRace { ptr, op1, op2 } =>
+                write!(
+                    f,
+                    "Data race detected between (1) {} on {} and (2) {} on {} at {ptr:?}. (2) just happened here",
+                    op1.action, op1.thread_info, op2.action, op2.thread_info
+                ),
         }
     }
 }
@@ -167,7 +184,7 @@ pub fn report_error<'tcx, 'mir>(
             Abort(_) => Some("abnormal termination"),
             UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance =>
                 Some("unsupported operation"),
-            StackedBorrowsUb { .. } => Some("Undefined Behavior"),
+            StackedBorrowsUb { .. } | DataRace { .. } => Some("Undefined Behavior"),
             Deadlock => Some("deadlock"),
             MultipleSymbolDefinitions { .. } | SymbolShimClashing { .. } => None,
         };
@@ -205,6 +222,12 @@ pub fn report_error<'tcx, 'mir>(
                 vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
             Int2PtrWithStrictProvenance =>
                 vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
+            DataRace { op1, .. } =>
+                vec![
+                    (Some(op1.span), format!("and (1) occurred earlier here")),
+                    (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
+                    (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
+                ],
             _ => vec![],
         };
         (title, helps)
@@ -339,9 +362,11 @@ fn report_msg<'tcx>(
     }
 
     // Show note and help messages.
+    let mut extra_span = false;
     for (span_data, note) in &notes {
         if let Some(span_data) = span_data {
             err.span_note(span_data.span(), note);
+            extra_span = true;
         } else {
             err.note(note);
         }
@@ -349,13 +374,14 @@ fn report_msg<'tcx>(
     for (span_data, help) in &helps {
         if let Some(span_data) = span_data {
             err.span_help(span_data.span(), help);
+            extra_span = true;
         } else {
             err.help(help);
         }
     }
     if notes.len() + helps.len() > 0 {
         // Add visual separator before backtrace.
-        err.note("BACKTRACE:");
+        err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
     }
     // Add backtrace
     for (idx, frame_info) in stacktrace.iter().enumerate() {
@@ -395,7 +421,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
         let msg = match &e {
             CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
-            CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+            CreatedPointerTag(tag, Some(perm), None) =>
+                format!("created {tag:?} with {perm} derived from unknown tag"),
             CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
                 format!(
                     "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 30288e5a999bb..6c87dad1f1f4a 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -143,6 +143,8 @@ pub struct MiriConfig {
     pub gc_interval: u32,
     /// The number of CPUs to be reported by miri.
     pub num_cpus: u32,
+    /// Requires Miri to emulate pages of a certain size
+    pub page_size: Option<u64>,
 }
 
 impl Default for MiriConfig {
@@ -176,6 +178,7 @@ impl Default for MiriConfig {
             external_so_file: None,
             gc_interval: 10_000,
             num_cpus: 1,
+            page_size: None,
         }
     }
 }
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 7fb2539ca5a67..c11c6104c2843 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -138,55 +138,77 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .unwrap_or_else(|| panic!("failed to find required Rust item: {path:?}"))
     }
 
-    /// Evaluates the scalar at the specified path. Returns Some(val)
-    /// if the path could be resolved, and None otherwise
-    fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Provenance>> {
+    /// Evaluates the scalar at the specified path.
+    fn eval_path_scalar(&self, path: &[&str]) -> Scalar<Provenance> {
         let this = self.eval_context_ref();
         let instance = this.resolve_path(path, Namespace::ValueNS);
         let cid = GlobalId { instance, promoted: None };
         // We don't give a span -- this isn't actually used directly by the program anyway.
-        let const_val = this.eval_global(cid, None)?;
+        let const_val = this
+            .eval_global(cid, None)
+            .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}"));
         this.read_scalar(&const_val.into())
+            .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}"))
     }
 
     /// Helper function to get a `libc` constant as a `Scalar`.
-    fn eval_libc(&self, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn eval_libc(&self, name: &str) -> Scalar<Provenance> {
         self.eval_path_scalar(&["libc", name])
     }
 
     /// Helper function to get a `libc` constant as an `i32`.
-    fn eval_libc_i32(&self, name: &str) -> InterpResult<'tcx, i32> {
+    fn eval_libc_i32(&self, name: &str) -> i32 {
         // TODO: Cache the result.
-        self.eval_libc(name)?.to_i32()
+        self.eval_libc(name).to_i32().unwrap_or_else(|_err| {
+            panic!("required libc item has unexpected type (not `i32`): {name}")
+        })
+    }
+
+    /// Helper function to get a `libc` constant as an `u32`.
+    fn eval_libc_u32(&self, name: &str) -> u32 {
+        // TODO: Cache the result.
+        self.eval_libc(name).to_u32().unwrap_or_else(|_err| {
+            panic!("required libc item has unexpected type (not `u32`): {name}")
+        })
     }
 
     /// Helper function to get a `windows` constant as a `Scalar`.
-    fn eval_windows(&self, module: &str, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
+    fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
         self.eval_context_ref().eval_path_scalar(&["std", "sys", "windows", module, name])
     }
 
+    /// Helper function to get a `windows` constant as a `u32`.
+    fn eval_windows_u32(&self, module: &str, name: &str) -> u32 {
+        // TODO: Cache the result.
+        self.eval_windows(module, name).to_u32().unwrap_or_else(|_err| {
+            panic!("required Windows item has unexpected type (not `u32`): {module}::{name}")
+        })
+    }
+
     /// Helper function to get a `windows` constant as a `u64`.
-    fn eval_windows_u64(&self, module: &str, name: &str) -> InterpResult<'tcx, u64> {
+    fn eval_windows_u64(&self, module: &str, name: &str) -> u64 {
         // TODO: Cache the result.
-        self.eval_windows(module, name)?.to_u64()
+        self.eval_windows(module, name).to_u64().unwrap_or_else(|_err| {
+            panic!("required Windows item has unexpected type (not `u64`): {module}::{name}")
+        })
     }
 
     /// Helper function to get the `TyAndLayout` of a `libc` type
-    fn libc_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+    fn libc_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
         let this = self.eval_context_ref();
         let ty = this
             .resolve_path(&["libc", name], Namespace::TypeNS)
             .ty(*this.tcx, ty::ParamEnv::reveal_all());
-        this.layout_of(ty)
+        this.layout_of(ty).unwrap()
     }
 
     /// Helper function to get the `TyAndLayout` of a `windows` type
-    fn windows_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+    fn windows_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
         let this = self.eval_context_ref();
         let ty = this
             .resolve_path(&["std", "sys", "windows", "c", name], Namespace::TypeNS)
             .ty(*this.tcx, ty::ParamEnv::reveal_all());
-        this.layout_of(ty)
+        this.layout_of(ty).unwrap()
     }
 
     /// Project to the given *named* field of the mplace (which must be a struct or union type).
@@ -609,14 +631,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if target.families.iter().any(|f| f == "unix") {
             for &(name, kind) in UNIX_IO_ERROR_TABLE {
                 if err_kind == kind {
-                    return this.eval_libc(name);
+                    return Ok(this.eval_libc(name));
                 }
             }
             throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind)
         } else if target.families.iter().any(|f| f == "windows") {
             // FIXME: we have to finish implementing the Windows equivalent of this.
             use std::io::ErrorKind::*;
-            this.eval_windows(
+            Ok(this.eval_windows(
                 "c",
                 match err_kind {
                     NotFound => "ERROR_FILE_NOT_FOUND",
@@ -627,7 +649,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             err_kind
                         ),
                 },
-            )
+            ))
         } else {
             throw_unsup_format!(
                 "converting io::Error into errnum is unsupported for OS {}",
@@ -647,7 +669,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if target.families.iter().any(|f| f == "unix") {
             let errnum = errnum.to_i32()?;
             for &(name, kind) in UNIX_IO_ERROR_TABLE {
-                if errnum == this.eval_libc_i32(name)? {
+                if errnum == this.eval_libc_i32(name) {
                     return Ok(Some(kind));
                 }
             }
diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/intptrcast.rs
index c26828b11e0e1..618cf9df7f3f0 100644
--- a/src/tools/miri/src/intptrcast.rs
+++ b/src/tools/miri/src/intptrcast.rs
@@ -51,12 +51,12 @@ impl VisitTags for GlobalStateInner {
 }
 
 impl GlobalStateInner {
-    pub fn new(config: &MiriConfig) -> Self {
+    pub fn new(config: &MiriConfig, stack_addr: u64) -> Self {
         GlobalStateInner {
             int_to_ptr_map: Vec::default(),
             base_addr: FxHashMap::default(),
             exposed: FxHashSet::default(),
-            next_base_addr: STACK_ADDR,
+            next_base_addr: stack_addr,
             provenance_mode: config.provenance_mode,
         }
     }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 42519797976b7..97750cb78cdcb 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -27,6 +27,7 @@
     clippy::single_element_loop,
     clippy::needless_return,
     clippy::bool_to_int_with_if,
+    clippy::box_default,
     // We are not implementing queries here so it's fine
     rustc::potential_query_instability
 )]
@@ -107,7 +108,7 @@ pub use crate::helpers::EvalContextExt as _;
 pub use crate::intptrcast::ProvenanceMode;
 pub use crate::machine::{
     AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
-    PrimitiveLayouts, Provenance, ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
+    PrimitiveLayouts, Provenance, ProvenanceExtra,
 };
 pub use crate::mono_hash_map::MonoHashMap;
 pub use crate::operator::EvalContextExt as _;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ab629e4711b10..01a3d7550e2e0 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -9,6 +9,7 @@ use rand::rngs::StdRng;
 use rand::SeedableRng;
 
 use rustc_ast::ast::Mutability;
+use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[allow(unused)]
 use rustc_data_structures::static_assert_size;
@@ -22,9 +23,8 @@ use rustc_middle::{
 };
 use rustc_span::def_id::{CrateNum, DefId};
 use rustc_span::Symbol;
-use rustc_target::abi::{Size, Align};
+use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi;
-use rustc_const_eval::const_eval::CheckAlignment;
 
 use crate::{
     concurrency::{data_race, weak_memory},
@@ -32,10 +32,9 @@ use crate::{
     *,
 };
 
-// Some global facts about the emulated machine.
-pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
-pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
-pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
+/// The number of the available real-time signal with the lowest priority.
+/// Dummy constant related to epoll, must be between 32 and 64.
+pub const SIGRTMAX: i32 = 42;
 
 /// Extra data stored with each stack frame
 pub struct FrameExtra<'tcx> {
@@ -470,6 +469,10 @@ pub struct MiriMachine<'mir, 'tcx> {
     pub(crate) since_gc: u32,
     /// The number of CPUs to be reported by miri.
     pub(crate) num_cpus: u32,
+    /// Determines Miri's page size and associated values
+    pub(crate) page_size: u64,
+    pub(crate) stack_addr: u64,
+    pub(crate) stack_size: u64,
 }
 
 impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
@@ -483,11 +486,31 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
         let borrow_tracker = config.borrow_tracker.map(|bt| bt.instanciate_global_state(config));
         let data_race = config.data_race_detector.then(|| data_race::GlobalState::new(config));
+        let page_size = if let Some(page_size) = config.page_size {
+            page_size
+        } else {
+            let target = &layout_cx.tcx.sess.target;
+            match target.arch.as_ref() {
+                "wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
+                "aarch64" =>
+                    if target.options.vendor.as_ref() == "apple" {
+                        // No "definitive" source, but see:
+                        // https://www.wwdcnotes.com/notes/wwdc20/10214/
+                        // https://github.com/ziglang/zig/issues/11308 etc.
+                        16 * 1024
+                    } else {
+                        4 * 1024
+                    },
+                _ => 4 * 1024,
+            }
+        };
+        let stack_addr = page_size * 32;
+        let stack_size = page_size * 16;
         MiriMachine {
             tcx: layout_cx.tcx,
             borrow_tracker,
             data_race,
-            intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config)),
+            intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)),
             // `env_vars` depends on a full interpreter so we cannot properly initialize it yet.
             env_vars: EnvVars::default(),
             main_fn_ret_place: None,
@@ -549,6 +572,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             gc_interval: config.gc_interval,
             since_gc: 0,
             num_cpus: config.num_cpus,
+            page_size,
+            stack_addr,
+            stack_size,
         }
     }
 
@@ -693,6 +719,9 @@ impl VisitTags for MiriMachine<'_, '_> {
             gc_interval: _,
             since_gc: _,
             num_cpus: _,
+            page_size: _,
+            stack_addr: _,
+            stack_size: _,
         } = self;
 
         threads.visit_tags(visit);
@@ -927,6 +956,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
                 &ecx.machine.threads,
                 alloc.size(),
                 kind,
+                ecx.machine.current_span(),
             )
         });
         let buffer_alloc = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation);
@@ -981,9 +1011,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } => {
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
-            }
+            Provenance::Concrete { alloc_id, tag } =>
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 218aa89b3f9b0..e049eec57a384 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -170,7 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ))
             }
             None => {
-                let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND")?;
+                let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND");
                 this.set_last_error(envvar_not_found)?;
                 Scalar::from_u32(0) // return zero upon failure
             }
@@ -240,7 +240,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Ok(0) // return zero on success
         } else {
             // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             Ok(-1)
         }
@@ -274,7 +274,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
                 this.update_environ()?;
             }
-            Ok(this.eval_windows("c", "TRUE")?)
+            Ok(this.eval_windows("c", "TRUE"))
         } else {
             let value = this.read_os_str_from_wide_str(value_ptr)?;
             let var_ptr = alloc_env_var_as_wide_str(&name, &value, this)?;
@@ -282,7 +282,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
             }
             this.update_environ()?;
-            Ok(this.eval_windows("c", "TRUE")?)
+            Ok(this.eval_windows("c", "TRUE"))
         }
     }
 
@@ -306,7 +306,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             Ok(0)
         } else {
             // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             Ok(-1)
         }
@@ -335,7 +335,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 if this.write_path_to_c_str(&cwd, buf, size)?.0 {
                     return Ok(buf);
                 }
-                let erange = this.eval_libc("ERANGE")?;
+                let erange = this.eval_libc("ERANGE");
                 this.set_last_error(erange)?;
             }
             Err(e) => this.set_last_error_from_io_error(e.kind())?,
@@ -411,14 +411,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.reject_in_isolation("`SetCurrentDirectoryW`", reject_with)?;
             this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
 
-            return this.eval_windows("c", "FALSE");
+            return Ok(this.eval_windows("c", "FALSE"));
         }
 
         match env::set_current_dir(path) {
-            Ok(()) => this.eval_windows("c", "TRUE"),
+            Ok(()) => Ok(this.eval_windows("c", "TRUE")),
             Err(e) => {
                 this.set_last_error_from_io_error(e.kind())?;
-                this.eval_windows("c", "FALSE")
+                Ok(this.eval_windows("c", "FALSE"))
             }
         }
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index b7ed63e17c5b2..4321bdf9aae67 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -1,4 +1,4 @@
-use std::{collections::hash_map::Entry, io::Write, iter};
+use std::{collections::hash_map::Entry, io::Write, iter, path::Path};
 
 use log::trace;
 
@@ -442,6 +442,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
                 this.machine.static_roots.push(alloc_id);
             }
+            "miri_host_to_target_path" => {
+                let [ptr, out, out_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
+                let ptr = this.read_pointer(ptr)?;
+                let out = this.read_pointer(out)?;
+                let out_size = this.read_scalar(out_size)?.to_machine_usize(this)?;
+
+                // The host affects program behavior here, so this requires isolation to be disabled.
+                this.check_no_isolation("`miri_host_to_target_path`")?;
+
+                // We read this as a plain OsStr and write it as a path, which will convert it to the target.
+                let path = this.read_os_str_from_c_str(ptr)?.to_owned();
+                let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?;
+                // Return value: 0 on success, otherwise the size it would have needed.
+                this.write_int(if success { 0 } else { needed_size }, dest)?;
+            }
 
             // Obtains the size of a Miri backtrace. See the README for details.
             "miri_backtrace_size" => {
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index bc7ca82997bb8..0375a228a2148 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -174,7 +174,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_c_str(ptr)?;
 
-        Ok(match this.convert_path_separator(Cow::Borrowed(os_str), PathConversion::TargetToHost) {
+        Ok(match this.convert_path(Cow::Borrowed(os_str), PathConversion::TargetToHost) {
             Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
             Cow::Owned(y) => Cow::Owned(PathBuf::from(y)),
         })
@@ -188,10 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_wide_str(ptr)?;
 
-        Ok(this
-            .convert_path_separator(Cow::Owned(os_str), PathConversion::TargetToHost)
-            .into_owned()
-            .into())
+        Ok(this.convert_path(Cow::Owned(os_str), PathConversion::TargetToHost).into_owned().into())
     }
 
     /// Write a Path to the machine memory (as a null-terminated sequence of bytes),
@@ -203,8 +200,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.write_os_str_to_c_str(&os_str, ptr, size)
     }
 
@@ -217,8 +214,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         size: u64,
     ) -> InterpResult<'tcx, (bool, u64)> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.write_os_str_to_wide_str(&os_str, ptr, size)
     }
 
@@ -230,18 +227,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         memkind: MemoryKind<MiriMemoryKind>,
     ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
         let this = self.eval_context_mut();
-        let os_str = this
-            .convert_path_separator(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
+        let os_str =
+            this.convert_path(Cow::Borrowed(path.as_os_str()), PathConversion::HostToTarget);
         this.alloc_os_str_as_c_str(&os_str, memkind)
     }
 
-    fn convert_path_separator<'a>(
+    #[allow(clippy::get_first)]
+    fn convert_path<'a>(
         &self,
         os_str: Cow<'a, OsStr>,
         direction: PathConversion,
     ) -> Cow<'a, OsStr> {
         let this = self.eval_context_ref();
         let target_os = &this.tcx.sess.target.os;
+
         #[cfg(windows)]
         return if target_os == "windows" {
             // Windows-on-Windows, all fine.
@@ -252,24 +251,71 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 PathConversion::HostToTarget => ('\\', '/'),
                 PathConversion::TargetToHost => ('/', '\\'),
             };
-            let converted = os_str
+            let mut converted = os_str
                 .encode_wide()
                 .map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
                 .collect::<Vec<_>>();
+            // We also have to ensure that absolute paths remain absolute.
+            match direction {
+                PathConversion::HostToTarget => {
+                    // If this is an absolute Windows path that starts with a drive letter (`C:/...`
+                    // after separator conversion), it would not be considered absolute by Unix
+                    // target code.
+                    if converted.get(1).copied() == Some(b':' as u16)
+                        && converted.get(2).copied() == Some(b'/' as u16)
+                    {
+                        // We add a `/` at the beginning, to store the absolute Windows
+                        // path in something that looks like an absolute Unix path.
+                        converted.insert(0, b'/' as u16);
+                    }
+                }
+                PathConversion::TargetToHost => {
+                    // If the path is `\C:\`, the leading backslash was probably added by the above code
+                    // and we should get rid of it again.
+                    if converted.get(0).copied() == Some(b'\\' as u16)
+                        && converted.get(2).copied() == Some(b':' as u16)
+                        && converted.get(3).copied() == Some(b'\\' as u16)
+                    {
+                        converted.remove(0);
+                    }
+                }
+            }
             Cow::Owned(OsString::from_wide(&converted))
         };
         #[cfg(unix)]
         return if target_os == "windows" {
             // Windows target, Unix host.
             let (from, to) = match direction {
-                PathConversion::HostToTarget => ('/', '\\'),
-                PathConversion::TargetToHost => ('\\', '/'),
+                PathConversion::HostToTarget => (b'/', b'\\'),
+                PathConversion::TargetToHost => (b'\\', b'/'),
             };
-            let converted = os_str
+            let mut converted = os_str
                 .as_bytes()
                 .iter()
-                .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
+                .map(|&wchar| if wchar == from { to } else { wchar })
                 .collect::<Vec<_>>();
+            // We also have to ensure that absolute paths remain absolute.
+            match direction {
+                PathConversion::HostToTarget => {
+                    // If this start withs a `\`, we add `\\?` so it starts with `\\?\` which is
+                    // some magic path on Windos that *is* considered absolute.
+                    if converted.get(0).copied() == Some(b'\\') {
+                        converted.splice(0..0, b"\\\\?".iter().copied());
+                    }
+                }
+                PathConversion::TargetToHost => {
+                    // If this starts with `//?/`, it was probably produced by the above code and we
+                    // remove the `//?` that got added to get the Unix path back out.
+                    if converted.get(0).copied() == Some(b'/')
+                        && converted.get(1).copied() == Some(b'/')
+                        && converted.get(2).copied() == Some(b'?')
+                        && converted.get(3).copied() == Some(b'/')
+                    {
+                        // Remove first 3 characters
+                        converted.splice(0..3, std::iter::empty());
+                    }
+                }
+            }
             Cow::Owned(OsString::from_vec(converted))
         } else {
             // Unix-on-Unix, all is fine.
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index d263aab351b12..ef411eb8aa724 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -36,26 +36,26 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
                 // is just specified to be "faster and less precise", so we implement both the same way.
                 absolute_clocks = vec![
-                    this.eval_libc_i32("CLOCK_REALTIME")?,
-                    this.eval_libc_i32("CLOCK_REALTIME_COARSE")?,
+                    this.eval_libc_i32("CLOCK_REALTIME"),
+                    this.eval_libc_i32("CLOCK_REALTIME_COARSE"),
                 ];
                 // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
                 // never allowed to go backwards. We don't need to do any additonal monotonicity
                 // enforcement because std::time::Instant already guarantees that it is monotonic.
                 relative_clocks = vec![
-                    this.eval_libc_i32("CLOCK_MONOTONIC")?,
-                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
+                    this.eval_libc_i32("CLOCK_MONOTONIC"),
+                    this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"),
                 ];
             }
             "macos" => {
-                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
-                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
+                absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")];
+                relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")];
                 // Some clocks only seem to exist in the aarch64 version of the target.
                 if this.tcx.sess.target.arch == "aarch64" {
                     // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
                     // that's not really something a program running inside Miri can tell, anyway.
                     // We need to support it because std uses it.
-                    relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
+                    relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW"));
                 }
             }
             target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
@@ -68,7 +68,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.machine.clock.now().duration_since(this.machine.clock.anchor())
         } else {
             // Unsupported clock.
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         };
@@ -94,7 +94,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Using tz is obsolete and should always be null
         let tz = this.read_pointer(tz_op)?;
         if !this.ptr_is_null(tz)? {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(-1);
         }
@@ -118,9 +118,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         this.assert_target_os("windows", "GetSystemTimeAsFileTime");
         this.check_no_isolation("`GetSystemTimeAsFileTime`")?;
 
-        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?;
-        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?;
-        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?;
+        let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC");
+        let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC");
+        let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH");
         let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
         let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;
 
@@ -226,7 +226,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let duration = match this.read_timespec(&this.deref_operand(req_op)?)? {
             Some(duration) => duration,
             None => {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 return Ok(-1);
             }
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 54fdf2872ab4d..7768772338a77 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -303,12 +303,12 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(());
         }
         let thread_callback =
-            this.eval_windows("thread_local_key", "p_thread_callback")?.to_pointer(this)?;
+            this.eval_windows("thread_local_key", "p_thread_callback").to_pointer(this)?;
         let thread_callback = this.get_ptr_fn(thread_callback)?.as_instance()?;
 
         // FIXME: Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits
         // but std treats both the same.
-        let reason = this.eval_windows("c", "DLL_THREAD_DETACH")?;
+        let reason = this.eval_windows("c", "DLL_THREAD_DETACH");
 
         // The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`.
         // FIXME: `h` should be a handle to the current module and what `pv` should be is unknown
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 63cc132f3fc93..7f43afb7820b5 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -196,7 +196,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Align must be power of 2, and also at least ptr-sized (POSIX rules).
                 // But failure to adhere to this is not UB, it's an error condition.
                 if !align.is_power_of_two() || align < this.pointer_size().bytes() {
-                    let einval = this.eval_libc_i32("EINVAL")?;
+                    let einval = this.eval_libc_i32("EINVAL");
                     this.write_int(einval, dest)?;
                 } else {
                     if size == 0 {
@@ -234,7 +234,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // FIXME: Which of these are POSIX, and which are GNU/Linux?
                 // At least the names seem to all also exist on macOS.
                 let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar<Provenance>)] = &[
-                    ("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())),
+                    ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
                     ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     // 512 seems to be a reasonable default. The value is not critical, in
@@ -243,7 +243,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ];
                 let mut result = None;
                 for &(sysconf_name, value) in sysconfs {
-                    let sysconf_name = this.eval_libc_i32(sysconf_name)?;
+                    let sysconf_name = this.eval_libc_i32(sysconf_name);
                     if sysconf_name == name {
                         result = Some(value(this));
                         break;
@@ -480,7 +480,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None => format!("<unknown errnum in strerror_r: {errnum}>"),
                 };
                 let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
-                let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
+                let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE") };
                 this.write_int(ret, dest)?;
             }
             "getpid" => {
@@ -495,8 +495,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             if this.frame_in_std() => {
                 let [_attr, guard_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let guard_size = this.deref_operand(guard_size)?;
-                let guard_size_layout = this.libc_ty_layout("size_t")?;
-                this.write_scalar(Scalar::from_uint(crate::PAGE_SIZE, guard_size_layout.size), &guard_size.into())?;
+                let guard_size_layout = this.libc_ty_layout("size_t");
+                this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size.into())?;
 
                 // Return success (`0`).
                 this.write_null(dest)?;
@@ -525,11 +525,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let size_place = this.deref_operand(size_place)?;
 
                 this.write_scalar(
-                    Scalar::from_uint(STACK_ADDR, this.pointer_size()),
+                    Scalar::from_uint(this.machine.stack_addr, this.pointer_size()),
                     &addr_place.into(),
                 )?;
                 this.write_scalar(
-                    Scalar::from_uint(STACK_SIZE, this.pointer_size()),
+                    Scalar::from_uint(this.machine.stack_size, this.pointer_size()),
                     &size_place.into(),
                 )?;
 
@@ -589,7 +589,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.write_null(dest)?;
                 } else {
                     this.write_null(&result.into())?;
-                    this.write_scalar(this.eval_libc("ERANGE")?, dest)?;
+                    this.write_scalar(this.eval_libc("ERANGE"), dest)?;
                 }
             }
 
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 5af1b354e7bb1..1b8f52f36657d 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -17,20 +17,25 @@ use crate::shims::os_str::bytes_to_os_str;
 use crate::*;
 use shims::os_str::os_str_to_bytes;
 use shims::time::system_time_to_duration;
+use shims::unix::linux::fd::epoll::Epoll;
 
 #[derive(Debug)]
-struct FileHandle {
+pub struct FileHandle {
     file: File,
     writable: bool,
 }
 
-trait FileDescriptor: std::fmt::Debug {
+pub trait FileDescriptor: std::fmt::Debug {
     fn name(&self) -> &'static str;
 
     fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
         throw_unsup_format!("{} cannot be used as FileHandle", self.name());
     }
 
+    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
+        throw_unsup_format!("not an epoll file descriptor");
+    }
+
     fn read<'tcx>(
         &mut self,
         _communicate_allowed: bool,
@@ -274,7 +279,7 @@ impl FileDescriptor for NullOutput {
 
 #[derive(Debug)]
 pub struct FileHandler {
-    handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
+    pub handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
 }
 
 impl VisitTags for FileHandler {
@@ -297,7 +302,7 @@ impl FileHandler {
         FileHandler { handles }
     }
 
-    fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
+    pub fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
@@ -376,17 +381,6 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
         Ok(0)
     }
 
-    /// Function used when a handle is not found inside `FileHandler`. It returns `Ok(-1)`and sets
-    /// the last OS error to `libc::EBADF` (invalid file descriptor). This function uses
-    /// `T: From<i32>` instead of `i32` directly because some fs functions return different integer
-    /// types (like `read`, that returns an `i64`).
-    fn handle_not_found<T: From<i32>>(&mut self) -> InterpResult<'tcx, T> {
-        let this = self.eval_context_mut();
-        let ebadf = this.eval_libc("EBADF")?;
-        this.set_last_error(ebadf)?;
-        Ok((-1).into())
-    }
-
     fn file_type_to_d_type(
         &mut self,
         file_type: std::io::Result<FileType>,
@@ -395,11 +389,11 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
         match file_type {
             Ok(file_type) => {
                 if file_type.is_dir() {
-                    Ok(this.eval_libc("DT_DIR")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_DIR").to_u8()?.into())
                 } else if file_type.is_file() {
-                    Ok(this.eval_libc("DT_REG")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_REG").to_u8()?.into())
                 } else if file_type.is_symlink() {
-                    Ok(this.eval_libc("DT_LNK")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_LNK").to_u8()?.into())
                 } else {
                     // Certain file types are only supported when the host is a Unix system.
                     // (i.e. devices and sockets) If it is, check those cases, if not, fall back to
@@ -409,19 +403,19 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx
                     {
                         use std::os::unix::fs::FileTypeExt;
                         if file_type.is_block_device() {
-                            Ok(this.eval_libc("DT_BLK")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_BLK").to_u8()?.into())
                         } else if file_type.is_char_device() {
-                            Ok(this.eval_libc("DT_CHR")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_CHR").to_u8()?.into())
                         } else if file_type.is_fifo() {
-                            Ok(this.eval_libc("DT_FIFO")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_FIFO").to_u8()?.into())
                         } else if file_type.is_socket() {
-                            Ok(this.eval_libc("DT_SOCK")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_SOCK").to_u8()?.into())
                         } else {
-                            Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
+                            Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into())
                         }
                     }
                     #[cfg(not(unix))]
-                    Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
+                    Ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into())
                 }
             }
             Err(e) =>
@@ -532,9 +526,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let mut options = OpenOptions::new();
 
-        let o_rdonly = this.eval_libc_i32("O_RDONLY")?;
-        let o_wronly = this.eval_libc_i32("O_WRONLY")?;
-        let o_rdwr = this.eval_libc_i32("O_RDWR")?;
+        let o_rdonly = this.eval_libc_i32("O_RDONLY");
+        let o_wronly = this.eval_libc_i32("O_WRONLY");
+        let o_rdwr = this.eval_libc_i32("O_RDWR");
         // The first two bits of the flag correspond to the access mode in linux, macOS and
         // windows. We need to check that in fact the access mode flags for the current target
         // only use these two bits, otherwise we are in an unsupported target and should error.
@@ -561,18 +555,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // options.
         let mut mirror = access_mode;
 
-        let o_append = this.eval_libc_i32("O_APPEND")?;
-        if flag & o_append != 0 {
+        let o_append = this.eval_libc_i32("O_APPEND");
+        if flag & o_append == o_append {
             options.append(true);
             mirror |= o_append;
         }
-        let o_trunc = this.eval_libc_i32("O_TRUNC")?;
-        if flag & o_trunc != 0 {
+        let o_trunc = this.eval_libc_i32("O_TRUNC");
+        if flag & o_trunc == o_trunc {
             options.truncate(true);
             mirror |= o_trunc;
         }
-        let o_creat = this.eval_libc_i32("O_CREAT")?;
-        if flag & o_creat != 0 {
+        let o_creat = this.eval_libc_i32("O_CREAT");
+        if flag & o_creat == o_creat {
             // Get the mode.  On macOS, the argument type `mode_t` is actually `u16`, but
             // C integer promotion rules mean that on the ABI level, it gets passed as `u32`
             // (see https://github.com/rust-lang/rust/issues/71915).
@@ -591,20 +585,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             mirror |= o_creat;
 
-            let o_excl = this.eval_libc_i32("O_EXCL")?;
-            if flag & o_excl != 0 {
+            let o_excl = this.eval_libc_i32("O_EXCL");
+            if flag & o_excl == o_excl {
                 mirror |= o_excl;
                 options.create_new(true);
             } else {
                 options.create(true);
             }
         }
-        let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?;
-        if flag & o_cloexec != 0 {
+        let o_cloexec = this.eval_libc_i32("O_CLOEXEC");
+        if flag & o_cloexec == o_cloexec {
             // We do not need to do anything for this flag because `std` already sets it.
             // (Technically we do not support *not* setting this flag, but we ignore that.)
             mirror |= o_cloexec;
         }
+        if this.tcx.sess.target.os == "linux" {
+            let o_tmpfile = this.eval_libc_i32("O_TMPFILE");
+            if flag & o_tmpfile == o_tmpfile {
+                // if the flag contains `O_TMPFILE` then we return a graceful error
+                let eopnotsupp = this.eval_libc("EOPNOTSUPP");
+                this.set_last_error(eopnotsupp)?;
+                return Ok(-1);
+            }
+        }
         // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`,
         // then we throw an error.
         if flag != mirror {
@@ -648,18 +651,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         // We only support getting the flags for a descriptor.
-        if cmd == this.eval_libc_i32("F_GETFD")? {
+        if cmd == this.eval_libc_i32("F_GETFD") {
             // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
             // `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
             // always sets this flag when opening a file. However we still need to check that the
             // file itself is open.
             if this.machine.file_handler.handles.contains_key(&fd) {
-                Ok(this.eval_libc_i32("FD_CLOEXEC")?)
+                Ok(this.eval_libc_i32("FD_CLOEXEC"))
             } else {
                 this.handle_not_found()
             }
-        } else if cmd == this.eval_libc_i32("F_DUPFD")?
-            || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")?
+        } else if cmd == this.eval_libc_i32("F_DUPFD")
+            || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")
         {
             // Note that we always assume the FD_CLOEXEC flag is set for every open file, in part
             // because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
@@ -688,7 +691,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 }
                 None => this.handle_not_found(),
             }
-        } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC")? {
+        } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
             if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
                 // FIXME: Support fullfsync for all FDs
                 let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
@@ -717,6 +720,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         ))
     }
 
+    /// Function used when a handle is not found inside `FileHandler`. It returns `Ok(-1)`and sets
+    /// the last OS error to `libc::EBADF` (invalid file descriptor). This function uses
+    /// `T: From<i32>` instead of `i32` directly because some fs functions return different integer
+    /// types (like `read`, that returns an `i64`).
+    fn handle_not_found<T: From<i32>>(&mut self) -> InterpResult<'tcx, T> {
+        let this = self.eval_context_mut();
+        let ebadf = this.eval_libc("EBADF");
+        this.set_last_error(ebadf)?;
+        Ok((-1).into())
+    }
+
     fn read(
         &mut self,
         fd: i32,
@@ -821,14 +835,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let offset = this.read_scalar(offset_op)?.to_i64()?;
         let whence = this.read_scalar(whence_op)?.to_i32()?;
 
-        let seek_from = if whence == this.eval_libc_i32("SEEK_SET")? {
+        let seek_from = if whence == this.eval_libc_i32("SEEK_SET") {
             SeekFrom::Start(u64::try_from(offset).unwrap())
-        } else if whence == this.eval_libc_i32("SEEK_CUR")? {
+        } else if whence == this.eval_libc_i32("SEEK_CUR") {
             SeekFrom::Current(offset)
-        } else if whence == this.eval_libc_i32("SEEK_END")? {
+        } else if whence == this.eval_libc_i32("SEEK_END") {
             SeekFrom::End(offset)
         } else {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i64(-1));
         };
@@ -907,7 +921,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`stat`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -936,7 +950,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`lstat`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -994,7 +1008,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // If the statxbuf or pathname pointers are null, the function fails with `EFAULT`.
         if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? {
-            let efault = this.eval_libc("EFAULT")?;
+            let efault = this.eval_libc("EFAULT");
             this.set_last_error(efault)?;
             return Ok(-1);
         }
@@ -1005,13 +1019,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // as `isize`s instead of having the proper types. Thus, we have to recover the layout of
         // `statxbuf_op` by using the `libc::statx` struct type.
         let statxbuf = {
-            let statx_layout = this.libc_ty_layout("statx")?;
+            let statx_layout = this.libc_ty_layout("statx");
             MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout)
         };
 
         let path = this.read_path_from_c_str(pathname_ptr)?.into_owned();
         // See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
-        let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
+        let at_ampty_path = this.eval_libc_i32("AT_EMPTY_PATH");
+        let empty_path_flag = flags & at_ampty_path == at_ampty_path;
         // We only support:
         // * interpreting `path` as an absolute directory,
         // * interpreting `path` as a path relative to `dirfd` when the latter is `AT_FDCWD`, or
@@ -1020,7 +1035,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Other behaviors cannot be tested from `libstd` and thus are not implemented. If you
         // found this error, please open an issue reporting it.
         if !(path.is_absolute()
-            || dirfd == this.eval_libc_i32("AT_FDCWD")?
+            || dirfd == this.eval_libc_i32("AT_FDCWD")
             || (path.as_os_str().is_empty() && empty_path_flag))
         {
             throw_unsup_format!(
@@ -1033,16 +1048,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`statx`", reject_with)?;
-            let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD")? {
+            let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") {
                 // since `path` is provided, either absolute or
                 // relative to CWD, `EACCES` is the most relevant.
-                this.eval_libc("EACCES")?
+                this.eval_libc("EACCES")
             } else {
                 // `dirfd` is set to target file, and `path` is empty
                 // (or we would have hit the `throw_unsup_format`
                 // above). `EACCES` would violate the spec.
                 assert!(empty_path_flag);
-                this.eval_libc("EBADF")?
+                this.eval_libc("EBADF")
             };
             this.set_last_error(ecode)?;
             return Ok(-1);
@@ -1052,12 +1067,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // However `statx` is allowed to return information that was not requested or to not
         // return information that was requested. This `mask` represents the information we can
         // actually provide for any target.
-        let mut mask =
-            this.eval_libc("STATX_TYPE")?.to_u32()? | this.eval_libc("STATX_SIZE")?.to_u32()?;
+        let mut mask = this.eval_libc_u32("STATX_TYPE") | this.eval_libc_u32("STATX_SIZE");
 
         // If the `AT_SYMLINK_NOFOLLOW` flag is set, we query the file's metadata without following
         // symbolic links.
-        let follow_symlink = flags & this.eval_libc("AT_SYMLINK_NOFOLLOW")?.to_i32()? == 0;
+        let follow_symlink = flags & this.eval_libc_i32("AT_SYMLINK_NOFOLLOW") == 0;
 
         // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file
         // represented by dirfd, whether it's a directory or otherwise.
@@ -1086,7 +1100,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (access_sec, access_nsec) = metadata
             .accessed
             .map(|tup| {
-                mask |= this.eval_libc("STATX_ATIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_ATIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1094,7 +1108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (created_sec, created_nsec) = metadata
             .created
             .map(|tup| {
-                mask |= this.eval_libc("STATX_BTIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_BTIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1102,7 +1116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let (modified_sec, modified_nsec) = metadata
             .modified
             .map(|tup| {
-                mask |= this.eval_libc("STATX_MTIME")?.to_u32()?;
+                mask |= this.eval_libc_u32("STATX_MTIME");
                 InterpResult::Ok(tup)
             })
             .unwrap_or_else(|| Ok((0, 0)))?;
@@ -1175,7 +1189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let newpath_ptr = this.read_pointer(newpath_op)?;
 
         if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? {
-            let efault = this.eval_libc("EFAULT")?;
+            let efault = this.eval_libc("EFAULT");
             this.set_last_error(efault)?;
             return Ok(-1);
         }
@@ -1262,7 +1276,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`opendir`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::null_ptr(this));
         }
@@ -1298,7 +1312,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`readdir`", reject_with)?;
-            let eacc = this.eval_libc("EBADF")?;
+            let eacc = this.eval_libc("EBADF");
             this.set_last_error(eacc)?;
             return Ok(Scalar::null_ptr(this));
         }
@@ -1327,7 +1341,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let name_bytes = os_str_to_bytes(&name)?;
                 let name_len = u64::try_from(name_bytes.len()).unwrap();
 
-                let dirent64_layout = this.libc_ty_layout("dirent64")?;
+                let dirent64_layout = this.libc_ty_layout("dirent64");
                 let d_name_offset = dirent64_layout.fields.offset(4 /* d_name */).bytes();
                 let size = d_name_offset.checked_add(name_len).unwrap();
 
@@ -1522,13 +1536,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         let result = file.set_len(length);
                         this.try_unwrap_io_result(result.map(|_| 0i32))?
                     } else {
-                        let einval = this.eval_libc("EINVAL")?;
+                        let einval = this.eval_libc("EINVAL");
                         this.set_last_error(einval)?;
                         -1
                     }
                 } else {
                     // The file is not writable
-                    let einval = this.eval_libc("EINVAL")?;
+                    let einval = this.eval_libc("EINVAL");
                     this.set_last_error(einval)?;
                     -1
                 }
@@ -1602,15 +1616,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let flags = this.read_scalar(flags_op)?.to_i32()?;
 
         if offset < 0 || nbytes < 0 {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         }
-        let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")?
-            | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")?
-            | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER")?;
+        let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")
+            | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")
+            | this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_AFTER");
         if flags & allowed_flags != flags {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(Scalar::from_i32(-1));
         }
@@ -1647,7 +1661,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`readlink`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(-1);
         }
@@ -1658,7 +1672,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // 'readlink' truncates the resolved path if the provided buffer is not large
                 // enough, and does *not* add a null terminator. That means we cannot use the usual
                 // `write_path_to_c_str` and have to re-implement parts of it ourselves.
-                let resolved = this.convert_path_separator(
+                let resolved = this.convert_path(
                     Cow::Borrowed(resolved.as_ref()),
                     crate::shims::os_str::PathConversion::HostToTarget,
                 );
@@ -1692,7 +1706,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
         }
         // Fallback when the FD was not found or isolation is enabled.
-        let enotty = this.eval_libc("ENOTTY")?;
+        let enotty = this.eval_libc("ENOTTY");
         this.set_last_error(enotty)?;
         Ok(Scalar::from_i32(0))
     }
@@ -1711,7 +1725,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`realpath`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(Scalar::from_machine_usize(0, this));
         }
@@ -1720,7 +1734,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         match result {
             Ok(resolved) => {
                 let path_max = this
-                    .eval_libc_i32("PATH_MAX")?
+                    .eval_libc_i32("PATH_MAX")
                     .try_into()
                     .expect("PATH_MAX does not fit in u64");
                 let dest = if this.ptr_is_null(processed_ptr)? {
@@ -1742,7 +1756,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         // Note that we do not explicitly handle `FILENAME_MAX`
                         // (different from `PATH_MAX` above) as it is Linux-specific and
                         // seems like a bit of a mess anyway: <https://eklitzke.org/path-max-is-tricky>.
-                        let enametoolong = this.eval_libc("ENAMETOOLONG")?;
+                        let enametoolong = this.eval_libc("ENAMETOOLONG");
                         this.set_last_error(enametoolong)?;
                         return Ok(Scalar::from_machine_usize(0, this));
                     }
@@ -1775,7 +1789,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         //   * The value of `TMP_MAX` is at least 25.
         //   * On XSI-conformant systems, the value of `TMP_MAX` is at least 10000.
         // See <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html>.
-        let max_attempts = this.eval_libc("TMP_MAX")?.to_u32()?;
+        let max_attempts = this.eval_libc_u32("TMP_MAX");
 
         // Get the raw bytes from the template -- as a byte slice, this is a string in the target
         // (and the target is unix, so a byte slice is the right representation).
@@ -1786,7 +1800,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`mkstemp`", reject_with)?;
-            let eacc = this.eval_libc("EACCES")?;
+            let eacc = this.eval_libc("EACCES");
             this.set_last_error(eacc)?;
             return Ok(-1);
         }
@@ -1804,7 +1818,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // If we don't find the suffix, it is an error.
         if last_six_char_bytes != suffix_bytes {
-            let einval = this.eval_libc("EINVAL")?;
+            let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
             return Ok(-1);
         }
@@ -1880,7 +1894,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         // We ran out of attempts to create the file, return an error.
-        let eexist = this.eval_libc("EEXIST")?;
+        let eexist = this.eval_libc("EEXIST");
         this.set_last_error(eexist)?;
         Ok(-1)
     }
@@ -1958,7 +1972,7 @@ impl FileMetadata {
             "S_IFLNK"
         };
 
-        let mode = ecx.eval_libc(mode_name)?;
+        let mode = ecx.eval_libc(mode_name);
 
         let size = metadata.len();
 
diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs
new file mode 100644
index 0000000000000..212b7936341a7
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd.rs
@@ -0,0 +1,191 @@
+use rustc_middle::ty::ScalarInt;
+
+use crate::*;
+use epoll::{Epoll, EpollEvent};
+use event::Event;
+use socketpair::SocketPair;
+
+use shims::unix::fs::EvalContextExt as _;
+
+pub mod epoll;
+pub mod event;
+pub mod socketpair;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// This function returns a file descriptor referring to the new `Epoll` instance. This file
+    /// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument
+    /// is 0, then this function is the same as `epoll_create()`.
+    ///
+    /// <https://linux.die.net/man/2/epoll_create1>
+    fn epoll_create1(
+        &mut self,
+        flags: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let flags = this.read_scalar(flags)?.to_i32()?;
+
+        let epoll_cloexec = this.eval_libc_i32("EPOLL_CLOEXEC");
+        if flags == epoll_cloexec {
+            // Miri does not support exec, so this flag has no effect.
+        } else if flags != 0 {
+            throw_unsup_format!("epoll_create1 flags {flags} are not implemented");
+        }
+
+        let fd = this.machine.file_handler.insert_fd(Box::new(Epoll::default()));
+        Ok(Scalar::from_i32(fd))
+    }
+
+    /// This function performs control operations on the `Epoll` instance referred to by the file
+    /// descriptor `epfd`. It requests that the operation `op` be performed for the target file
+    /// descriptor, `fd`.
+    ///
+    /// Valid values for the op argument are:
+    /// `EPOLL_CTL_ADD` - Register the target file descriptor `fd` on the `Epoll` instance referred
+    /// to by the file descriptor `epfd` and associate the event `event` with the internal file
+    /// linked to `fd`.
+    /// `EPOLL_CTL_MOD` - Change the event `event` associated with the target file descriptor `fd`.
+    /// `EPOLL_CTL_DEL` - Deregister the target file descriptor `fd` from the `Epoll` instance
+    /// referred to by `epfd`. The `event` is ignored and can be null.
+    ///
+    /// <https://linux.die.net/man/2/epoll_ctl>
+    fn epoll_ctl(
+        &mut self,
+        epfd: &OpTy<'tcx, Provenance>,
+        op: &OpTy<'tcx, Provenance>,
+        fd: &OpTy<'tcx, Provenance>,
+        event: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let epfd = this.read_scalar(epfd)?.to_i32()?;
+        let op = this.read_scalar(op)?.to_i32()?;
+        let fd = this.read_scalar(fd)?.to_i32()?;
+        let _event = this.read_scalar(event)?.to_pointer(this)?;
+
+        let epoll_ctl_add = this.eval_libc_i32("EPOLL_CTL_ADD");
+        let epoll_ctl_mod = this.eval_libc_i32("EPOLL_CTL_MOD");
+        let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL");
+
+        if op == epoll_ctl_add || op == epoll_ctl_mod {
+            let event = this.deref_operand(event)?;
+
+            let events = this.mplace_field(&event, 0)?;
+            let events = this.read_scalar(&events.into())?.to_u32()?;
+            let data = this.mplace_field(&event, 1)?;
+            let data = this.read_scalar(&data.into())?;
+            let event = EpollEvent { events, data };
+
+            if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
+                let epfd = epfd.as_epoll_handle()?;
+
+                epfd.file_descriptors.insert(fd, event);
+                Ok(Scalar::from_i32(0))
+            } else {
+                Ok(Scalar::from_i32(this.handle_not_found()?))
+            }
+        } else if op == epoll_ctl_del {
+            if let Some(epfd) = this.machine.file_handler.handles.get_mut(&epfd) {
+                let epfd = epfd.as_epoll_handle()?;
+
+                epfd.file_descriptors.remove(&fd);
+                Ok(Scalar::from_i32(0))
+            } else {
+                Ok(Scalar::from_i32(this.handle_not_found()?))
+            }
+        } else {
+            let einval = this.eval_libc("EINVAL");
+            this.set_last_error(einval)?;
+            Ok(Scalar::from_i32(-1))
+        }
+    }
+
+    /// This function creates an `Event` that is used as an event wait/notify mechanism by
+    /// user-space applications, and by the kernel to notify user-space applications of events.
+    /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
+    /// with the value specified in the `initval` argument.
+    ///
+    /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`,
+    /// `select`, and `close` operations can be performed on the file descriptor. For more
+    /// information on these operations, see the man page linked below.
+    ///
+    /// The `flags` are not currently implemented for eventfd.
+    /// The `flags` may be bitwise ORed to change the behavior of `eventfd`:
+    /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
+    /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description.
+    /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics.
+    ///
+    /// <https://linux.die.net/man/2/eventfd>
+    fn eventfd(
+        &mut self,
+        val: &OpTy<'tcx, Provenance>,
+        flags: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let val = this.read_scalar(val)?.to_u32()?;
+        let flags = this.read_scalar(flags)?.to_i32()?;
+
+        let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC");
+        let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK");
+        let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE");
+
+        if flags & (efd_cloexec | efd_nonblock | efd_semaphore) == 0 {
+            throw_unsup_format!("{flags} is unsupported");
+        }
+        // FIXME handle the cloexec and nonblock flags
+        if flags & efd_cloexec == efd_cloexec {}
+        if flags & efd_nonblock == efd_nonblock {}
+        if flags & efd_semaphore == efd_semaphore {
+            throw_unsup_format!("EFD_SEMAPHORE is unsupported");
+        }
+
+        let fh = &mut this.machine.file_handler;
+        let fd = fh.insert_fd(Box::new(Event { val }));
+        Ok(Scalar::from_i32(fd))
+    }
+
+    /// Currently this function creates new `SocketPair`s without specifying the domain, type, or
+    /// protocol of the new socket and these are stored in the socket values `sv` argument.
+    ///
+    /// This function creates an unnamed pair of connected sockets in the specified domain, of the
+    /// specified type, and using the optionally specified protocol.
+    ///
+    /// The `domain` argument specified a communication domain; this selects the protocol family
+    /// used for communication. The socket `type` specifies the communication semantics.
+    /// The `protocol` specifies a particular protocol to use with the socket. Normally there's
+    /// only a single protocol supported for a particular socket type within a given protocol
+    /// family, in which case `protocol` can be specified as 0. It is possible that many protocols
+    /// exist and in that case, a particular protocol must be specified.
+    ///
+    /// For more information on the arguments see the socket manpage:
+    /// <https://linux.die.net/man/2/socket>
+    ///
+    /// <https://linux.die.net/man/2/socketpair>
+    fn socketpair(
+        &mut self,
+        domain: &OpTy<'tcx, Provenance>,
+        type_: &OpTy<'tcx, Provenance>,
+        protocol: &OpTy<'tcx, Provenance>,
+        sv: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_mut();
+
+        let _domain = this.read_scalar(domain)?.to_i32()?;
+        let _type_ = this.read_scalar(type_)?.to_i32()?;
+        let _protocol = this.read_scalar(protocol)?.to_i32()?;
+        let sv = this.deref_operand(sv)?;
+
+        let fh = &mut this.machine.file_handler;
+        let sv0 = fh.insert_fd(Box::new(SocketPair));
+        let sv0 = ScalarInt::try_from_int(sv0, sv.layout.size).unwrap();
+        let sv1 = fh.insert_fd(Box::new(SocketPair));
+        let sv1 = ScalarInt::try_from_int(sv1, sv.layout.size).unwrap();
+
+        this.write_scalar(sv0, &sv.into())?;
+        this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?.into())?;
+
+        Ok(Scalar::from_i32(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/epoll.rs b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
new file mode 100644
index 0000000000000..e33673fecf6f3
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/epoll.rs
@@ -0,0 +1,53 @@
+use crate::*;
+
+use crate::shims::unix::fs::FileDescriptor;
+
+use rustc_data_structures::fx::FxHashMap;
+use std::io;
+
+/// An `Epoll` file descriptor connects file handles and epoll events
+#[derive(Clone, Debug, Default)]
+pub struct Epoll {
+    /// The file descriptors we are watching, and what we are watching for.
+    pub file_descriptors: FxHashMap<i32, EpollEvent>,
+}
+
+/// Epoll Events associate events with data.
+/// These fields are currently unused by miri.
+/// This matches the `epoll_event` struct defined
+/// by the epoll_ctl man page. For more information
+/// see the man page:
+///
+/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
+#[derive(Clone, Debug)]
+pub struct EpollEvent {
+    pub events: u32,
+    /// `Scalar<Provenance>` is used to represent the
+    /// `epoll_data` type union.
+    pub data: Scalar<Provenance>,
+}
+
+impl FileDescriptor for Epoll {
+    fn name(&self) -> &'static str {
+        "epoll"
+    }
+
+    fn as_epoll_handle<'tcx>(&mut self) -> InterpResult<'tcx, &mut Epoll> {
+        Ok(self)
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(self.clone()))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/event.rs b/src/tools/miri/src/shims/unix/linux/fd/event.rs
new file mode 100644
index 0000000000000..239eb462a1d23
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/event.rs
@@ -0,0 +1,38 @@
+use crate::shims::unix::fs::FileDescriptor;
+
+use rustc_const_eval::interpret::InterpResult;
+
+use std::io;
+
+/// A kind of file descriptor created by `eventfd`.
+/// The `Event` type isn't currently written to by `eventfd`.
+/// The interface is meant to keep track of objects associated
+/// with a file descriptor. For more information see the man
+/// page below:
+///
+/// <https://man.netbsd.org/eventfd.2>
+#[derive(Debug)]
+pub struct Event {
+    pub val: u32,
+}
+
+impl FileDescriptor for Event {
+    fn name(&self) -> &'static str {
+        "event"
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(Event { val: self.val }))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
diff --git a/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
new file mode 100644
index 0000000000000..f9e56b4a2b40e
--- /dev/null
+++ b/src/tools/miri/src/shims/unix/linux/fd/socketpair.rs
@@ -0,0 +1,32 @@
+use crate::*;
+
+use crate::shims::unix::fs::FileDescriptor;
+
+use std::io;
+
+/// Pair of connected sockets.
+///
+/// We currently don't allow sending any data through this pair, so this can be just a dummy.
+#[derive(Debug)]
+pub struct SocketPair;
+
+impl FileDescriptor for SocketPair {
+    fn name(&self) -> &'static str {
+        "socketpair"
+    }
+
+    fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
+        Ok(Box::new(SocketPair))
+    }
+
+    fn is_tty(&self) -> bool {
+        false
+    }
+
+    fn close<'tcx>(
+        self: Box<Self>,
+        _communicate_allowed: bool,
+    ) -> InterpResult<'tcx, io::Result<i32>> {
+        Ok(Ok(0))
+    }
+}
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 acf47fe924803..82cb21c124a26 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -1,9 +1,11 @@
 use rustc_span::Symbol;
 use rustc_target::spec::abi::Abi;
 
+use crate::machine::SIGRTMAX;
 use crate::*;
 use shims::foreign_items::EmulateByNameResult;
 use shims::unix::fs::EvalContextExt as _;
+use shims::unix::linux::fd::EvalContextExt as _;
 use shims::unix::linux::sync::futex;
 use shims::unix::sync::EvalContextExt as _;
 use shims::unix::thread::EvalContextExt as _;
@@ -42,6 +44,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let result = this.sync_file_range(fd, offset, nbytes, flags)?;
                 this.write_scalar(result, dest)?;
             }
+            "epoll_create1" => {
+                let [flag] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_create1(flag)?;
+                this.write_scalar(result, dest)?;
+            }
+            "epoll_ctl" => {
+                let [epfd, op, fd, event] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.epoll_ctl(epfd, op, fd, event)?;
+                this.write_scalar(result, dest)?;
+            }
+            "eventfd" => {
+                let [val, flag] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.eventfd(val, flag)?;
+                this.write_scalar(result, dest)?;
+            }
+            "socketpair" => {
+                let [domain, type_, protocol, sv] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let result = this.socketpair(domain, type_, protocol, sv)?;
+                this.write_scalar(result, dest)?;
+            }
+            "__libc_current_sigrtmax" => {
+                let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?;
+            }
 
             // Threading
             "pthread_condattr_setclock" => {
@@ -88,11 +119,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // argument, we have to also check all arguments *before* it to ensure that they
                 // have the right type.
 
-                let sys_getrandom = this.eval_libc("SYS_getrandom")?.to_machine_usize(this)?;
+                let sys_getrandom = this.eval_libc("SYS_getrandom").to_machine_usize(this)?;
 
-                let sys_statx = this.eval_libc("SYS_statx")?.to_machine_usize(this)?;
+                let sys_statx = this.eval_libc("SYS_statx").to_machine_usize(this)?;
 
-                let sys_futex = this.eval_libc("SYS_futex")?.to_machine_usize(this)?;
+                let sys_futex = this.eval_libc("SYS_futex").to_machine_usize(this)?;
 
                 if args.is_empty() {
                     throw_ub_format!(
@@ -150,7 +181,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.read_machine_usize(cpusetsize)?;
                 this.deref_operand(mask)?;
                 // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`.
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_i32(-1), dest)?;
             }
diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs
index 498eb57c57fe0..437764c3824eb 100644
--- a/src/tools/miri/src/shims/unix/linux/mod.rs
+++ b/src/tools/miri/src/shims/unix/linux/mod.rs
@@ -1,3 +1,4 @@
 pub mod dlsym;
+pub mod fd;
 pub mod foreign_items;
 pub mod sync;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 343232c4bbb29..ef43c9b0ff438 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -37,12 +37,12 @@ pub fn futex<'tcx>(
     let addr = MPlaceTy::from_aligned_ptr(addr, this.machine.layouts.i32);
     let addr_usize = addr.ptr.addr().bytes();
 
-    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
-    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
-    let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET")?;
-    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;
-    let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET")?;
-    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME")?;
+    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG");
+    let futex_wait = this.eval_libc_i32("FUTEX_WAIT");
+    let futex_wait_bitset = this.eval_libc_i32("FUTEX_WAIT_BITSET");
+    let futex_wake = this.eval_libc_i32("FUTEX_WAKE");
+    let futex_wake_bitset = this.eval_libc_i32("FUTEX_WAKE_BITSET");
+    let futex_realtime = this.eval_libc_i32("FUTEX_CLOCK_REALTIME");
 
     // FUTEX_PRIVATE enables an optimization that stops it from working across processes.
     // Miri doesn't support that anyway, so we ignore that flag.
@@ -79,7 +79,7 @@ pub fn futex<'tcx>(
             };
 
             if bitset == 0 {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                 return Ok(());
@@ -90,7 +90,8 @@ pub fn futex<'tcx>(
             let timeout_time = if this.ptr_is_null(timeout.ptr)? {
                 None
             } else {
-                if op & futex_realtime != 0 {
+                let realtime = op & futex_realtime == futex_realtime;
+                if realtime {
                     this.check_no_isolation(
                         "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`",
                     )?;
@@ -98,7 +99,7 @@ pub fn futex<'tcx>(
                 let duration = match this.read_timespec(&timeout)? {
                     Some(duration) => duration,
                     None => {
-                        let einval = this.eval_libc("EINVAL")?;
+                        let einval = this.eval_libc("EINVAL");
                         this.set_last_error(einval)?;
                         this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                         return Ok(());
@@ -106,14 +107,14 @@ pub fn futex<'tcx>(
                 };
                 Some(if wait_bitset {
                     // FUTEX_WAIT_BITSET uses an absolute timestamp.
-                    if op & futex_realtime != 0 {
+                    if realtime {
                         Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
                     } else {
                         Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
                     }
                 } else {
                     // FUTEX_WAIT uses a relative timestamp.
-                    if op & futex_realtime != 0 {
+                    if realtime {
                         Time::RealTime(SystemTime::now().checked_add(duration).unwrap())
                     } else {
                         Time::Monotonic(this.machine.clock.now().checked_add(duration).unwrap())
@@ -193,7 +194,7 @@ pub fn futex<'tcx>(
                         fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
                             this.unblock_thread(self.thread);
                             this.futex_remove_waiter(self.addr_usize, self.thread);
-                            let etimedout = this.eval_libc("ETIMEDOUT")?;
+                            let etimedout = this.eval_libc("ETIMEDOUT");
                             this.set_last_error(etimedout)?;
                             this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?;
 
@@ -210,7 +211,7 @@ pub fn futex<'tcx>(
             } else {
                 // The futex value doesn't match the expected value, so we return failure
                 // right away without sleeping: -1 and errno set to EAGAIN.
-                let eagain = this.eval_libc("EAGAIN")?;
+                let eagain = this.eval_libc("EAGAIN");
                 this.set_last_error(eagain)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
             }
@@ -236,7 +237,7 @@ pub fn futex<'tcx>(
                 u32::MAX
             };
             if bitset == 0 {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?;
                 return Ok(());
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 2554fc7798454..a55b0ee523b08 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -162,13 +162,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "pthread_get_stackaddr_np" => {
                 let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.read_machine_usize(thread)?;
-                let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size());
+                let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size());
                 this.write_scalar(stack_addr, dest)?;
             }
             "pthread_get_stacksize_np" => {
                 let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 this.read_machine_usize(thread)?;
-                let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size());
+                let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size());
                 this.write_scalar(stack_size, dest)?;
             }
 
@@ -176,7 +176,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "pthread_setname_np" => {
                 let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let thread = this.pthread_self()?;
-                let max_len = this.eval_libc("MAXTHREADNAMESIZE")?.to_machine_usize(this)?;
+                let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_machine_usize(this)?;
                 let res = this.pthread_setname_np(
                     thread,
                     this.read_scalar(name)?,
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index f9b5774f0090e..b3c474dd3c9f1 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -21,14 +21,14 @@ fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
-    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?)
+    Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
 }
 
 fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
     ecx: &mut MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
-    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL")?;
+    let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
     Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
 }
 
@@ -217,7 +217,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
-        let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?;
+        let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT");
         mutexattr_set_kind(this, attr_op, default_kind)?;
 
         Ok(0)
@@ -231,7 +231,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         let kind = this.read_scalar(kind_op)?.to_i32()?;
-        if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL")? {
+        if kind == this.eval_libc_i32("PTHREAD_MUTEX_NORMAL") {
             // In `glibc` implementation, the numeric values of
             // `PTHREAD_MUTEX_NORMAL` and `PTHREAD_MUTEX_DEFAULT` are equal.
             // However, a mutex created by explicitly passing
@@ -247,17 +247,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             let normal_kind = kind | PTHREAD_MUTEX_NORMAL_FLAG;
             // Check that after setting the flag, the kind is distinguishable
             // from all other kinds.
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?);
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?);
-            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?);
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"));
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK"));
+            assert_ne!(normal_kind, this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE"));
             mutexattr_set_kind(this, attr_op, normal_kind)?;
-        } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
-            || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
-            || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
+        } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")
+            || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
+            || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
         {
             mutexattr_set_kind(this, attr_op, kind)?;
         } else {
-            let einval = this.eval_libc_i32("EINVAL")?;
+            let einval = this.eval_libc_i32("EINVAL");
             return Ok(einval);
         }
 
@@ -299,7 +299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let attr = this.read_pointer(attr_op)?;
         let kind = if this.ptr_is_null(attr)? {
-            this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")?
+            this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT")
         } else {
             mutexattr_get_kind(this, attr_op)?
         };
@@ -331,9 +331,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     throw_ub_format!("trying to acquire already locked default mutex");
                 } else if is_mutex_kind_normal(this, kind)? {
                     throw_machine_stop!(TerminationInfo::Deadlock);
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")? {
-                    this.eval_libc_i32("EDEADLK")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
+                    Ok(this.eval_libc_i32("EDEADLK"))
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
                     this.mutex_lock(id, active_thread);
                     Ok(0)
                 } else {
@@ -362,14 +362,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.mutex_is_locked(id) {
             let owner_thread = this.mutex_get_owner(id);
             if owner_thread != active_thread {
-                this.eval_libc_i32("EBUSY")
+                Ok(this.eval_libc_i32("EBUSY"))
             } else {
                 if is_mutex_kind_default(this, kind)?
                     || is_mutex_kind_normal(this, kind)?
-                    || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
+                    || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
                 {
-                    this.eval_libc_i32("EBUSY")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")? {
+                    Ok(this.eval_libc_i32("EBUSY"))
+                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
                     this.mutex_lock(id, active_thread);
                     Ok(0)
                 } else {
@@ -410,10 +410,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 throw_ub_format!(
                     "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
                 );
-            } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")?
-                || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")?
+            } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
+                || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
             {
-                this.eval_libc_i32("EPERM")
+                Ok(this.eval_libc_i32("EPERM"))
             } else {
                 throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
             }
@@ -471,7 +471,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let active_thread = this.get_active_thread();
 
         if this.rwlock_is_write_locked(id) {
-            this.eval_libc_i32("EBUSY")
+            Ok(this.eval_libc_i32("EBUSY"))
         } else {
             this.rwlock_reader_lock(id, active_thread);
             Ok(0)
@@ -518,7 +518,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let active_thread = this.get_active_thread();
 
         if this.rwlock_is_locked(id) {
-            this.eval_libc_i32("EBUSY")
+            Ok(this.eval_libc_i32("EBUSY"))
         } else {
             this.rwlock_writer_lock(id, active_thread);
             Ok(0)
@@ -575,7 +575,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // The default value of the clock attribute shall refer to the system
         // clock.
         // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
-        let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME")?;
+        let default_clock_id = this.eval_libc_i32("CLOCK_REALTIME");
         condattr_set_clock_id(this, attr_op, default_clock_id)?;
 
         Ok(0)
@@ -589,12 +589,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         let clock_id = this.read_scalar(clock_id_op)?.to_i32()?;
-        if clock_id == this.eval_libc_i32("CLOCK_REALTIME")?
-            || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")?
+        if clock_id == this.eval_libc_i32("CLOCK_REALTIME")
+            || clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")
         {
             condattr_set_clock_id(this, attr_op, clock_id)?;
         } else {
-            let einval = this.eval_libc_i32("EINVAL")?;
+            let einval = this.eval_libc_i32("EINVAL");
             return Ok(Scalar::from_i32(einval));
         }
 
@@ -638,7 +638,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let attr = this.read_pointer(attr_op)?;
         let clock_id = if this.ptr_is_null(attr)? {
-            this.eval_libc_i32("CLOCK_REALTIME")?
+            this.eval_libc_i32("CLOCK_REALTIME")
         } else {
             condattr_get_clock_id(this, attr_op)?
         };
@@ -718,16 +718,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? {
             Some(duration) => duration,
             None => {
-                let einval = this.eval_libc("EINVAL")?;
+                let einval = this.eval_libc("EINVAL");
                 this.write_scalar(einval, dest)?;
                 return Ok(());
             }
         };
 
-        let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME")? {
+        let timeout_time = if clock_id == this.eval_libc_i32("CLOCK_REALTIME") {
             this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
             Time::RealTime(SystemTime::UNIX_EPOCH.checked_add(duration).unwrap())
-        } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
+        } else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC") {
             Time::Monotonic(this.machine.clock.anchor().checked_add(duration).unwrap())
         } else {
             throw_unsup_format!("unsupported clock id: {}", clock_id);
@@ -763,7 +763,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 ecx.condvar_remove_waiter(self.id, self.active_thread);
 
                 // Set the return value: we timed out.
-                let etimedout = ecx.eval_libc("ETIMEDOUT")?;
+                let etimedout = ecx.eval_libc("ETIMEDOUT");
                 ecx.write_scalar(etimedout, &self.dest)?;
 
                 Ok(())
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index 2cb4858fdfdee..832628003d770 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -84,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // Comparing with `>=` to account for null terminator.
         if name.len() >= max_name_len {
-            return this.eval_libc("ERANGE");
+            return Ok(this.eval_libc("ERANGE"));
         }
 
         this.set_thread_name(thread, name);
@@ -107,7 +107,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let name = this.get_thread_name(thread).to_owned();
         let (success, _written) = this.write_c_str(&name, name_out, len)?;
 
-        if success { Ok(Scalar::from_u32(0)) } else { this.eval_libc("ERANGE") }
+        Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") })
     }
 
     fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 656f1a4ae7223..1da8f7c0e3e43 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -76,7 +76,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.read_machine_isize(handle)?;
                 let flags = this.read_scalar(flags)?.to_u32()?;
                 let size = this.read_machine_usize(size)?;
-                let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
+                let heap_zero_memory = 0x00000008; // HEAP_ZERO_MEMORY
+                let zero_init = (flags & heap_zero_memory) == heap_zero_memory;
                 let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?;
                 this.write_pointer(res, dest)?;
             }
@@ -158,7 +159,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Set page size.
                 let page_size = system_info.offset(field_offsets[2], dword_layout, &this.tcx)?;
                 this.write_scalar(
-                    Scalar::from_int(PAGE_SIZE, dword_layout.size),
+                    Scalar::from_int(this.machine.page_size, dword_layout.size),
                     &page_size.into(),
                 )?;
                 // Set number of processors.
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index 7892f35f7b05c..9177f1632f704 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -170,7 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         match this.init_once_status(id) {
             InitOnceStatus::Uninitialized => {
                 this.init_once_begin(id);
-                this.write_scalar(this.eval_windows("c", "TRUE")?, &pending_place)?;
+                this.write_scalar(this.eval_windows("c", "TRUE"), &pending_place)?;
             }
             InitOnceStatus::Begun => {
                 // Someone else is already on it.
@@ -195,8 +195,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                                 unreachable!(
                                     "status should have either been set to begun or complete"
                                 ),
-                            InitOnceStatus::Begun => this.eval_windows("c", "TRUE")?,
-                            InitOnceStatus::Complete => this.eval_windows("c", "FALSE")?,
+                            InitOnceStatus::Begun => this.eval_windows("c", "TRUE"),
+                            InitOnceStatus::Complete => this.eval_windows("c", "FALSE"),
                         };
 
                         this.write_scalar(pending, &self.pending_place)?;
@@ -213,12 +213,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             InitOnceStatus::Complete => {
                 this.init_once_observe_completed(id);
-                this.write_scalar(this.eval_windows("c", "FALSE")?, &pending_place)?;
+                this.write_scalar(this.eval_windows("c", "FALSE"), &pending_place)?;
             }
         }
 
         // This always succeeds (even if the thread is blocked, we will succeed if we ever unblock).
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn InitOnceComplete(
@@ -235,7 +235,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         let success = if flags == 0 {
             true
-        } else if flags == this.eval_windows("c", "INIT_ONCE_INIT_FAILED")?.to_u32()? {
+        } else if flags == this.eval_windows_u32("c", "INIT_ONCE_INIT_FAILED") {
             false
         } else {
             throw_unsup_format!("unsupported `dwFlags` {flags} in `InitOnceBeginInitialize`");
@@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             this.init_once_fail(id)?;
         }
 
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn WaitOnAddress(
@@ -280,14 +280,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let addr = ptr.addr().bytes();
 
         if size > 8 || !size.is_power_of_two() {
-            let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER")?;
+            let invalid_param = this.eval_windows("c", "ERROR_INVALID_PARAMETER");
             this.set_last_error(invalid_param)?;
             this.write_scalar(Scalar::from_i32(0), dest)?;
             return Ok(());
         };
         let size = Size::from_bytes(size);
 
-        let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? {
+        let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
             None
         } else {
             let duration = Duration::from_millis(timeout_ms.into());
@@ -325,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
                         this.unblock_thread(self.thread);
                         this.futex_remove_waiter(self.addr, self.thread);
-                        let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?;
+                        let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT");
                         this.set_last_error(error_timeout)?;
                         this.write_scalar(Scalar::from_i32(0), &self.dest)?;
 
@@ -377,7 +377,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?;
         let flags = this.read_scalar(flags_op)?.to_u32()?;
 
-        let timeout_time = if timeout_ms == this.eval_windows("c", "INFINITE")?.to_u32()? {
+        let timeout_time = if timeout_ms == this.eval_windows_u32("c", "INFINITE") {
             None
         } else {
             let duration = Duration::from_millis(timeout_ms.into());
@@ -431,9 +431,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                     this.condvar_remove_waiter(self.condvar_id, self.thread);
 
-                    let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT")?;
+                    let error_timeout = this.eval_windows("c", "ERROR_TIMEOUT");
                     this.set_last_error(error_timeout)?;
-                    this.write_scalar(this.eval_windows("c", "FALSE")?, &self.dest)?;
+                    this.write_scalar(this.eval_windows("c", "FALSE"), &self.dest)?;
                     Ok(())
                 }
             }
@@ -451,7 +451,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             );
         }
 
-        this.eval_windows("c", "TRUE")
+        Ok(this.eval_windows("c", "TRUE"))
     }
 
     fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs
index 1dbc848b03055..f5bf362ea1caf 100644
--- a/src/tools/miri/src/shims/windows/thread.rs
+++ b/src/tools/miri/src/shims/windows/thread.rs
@@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         };
 
         let stack_size_param_is_a_reservation =
-            this.eval_windows("c", "STACK_SIZE_PARAM_IS_A_RESERVATION")?.to_u32()?;
+            this.eval_windows_u32("c", "STACK_SIZE_PARAM_IS_A_RESERVATION");
 
         // We ignore the stack size, so we also ignore the
         // `STACK_SIZE_PARAM_IS_A_RESERVATION` flag.
@@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             _ => this.invalid_handle("WaitForSingleObject")?,
         };
 
-        if timeout != this.eval_windows("c", "INFINITE")?.to_u32()? {
+        if timeout != this.eval_windows_u32("c", "INFINITE") {
             throw_unsup_format!("`WaitForSingleObject` with non-infinite timeout");
         }
 
diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs
index 41c52b7017028..048dbbbaa0f06 100644
--- a/src/tools/miri/test-cargo-miri/src/main.rs
+++ b/src/tools/miri/test-cargo-miri/src/main.rs
@@ -2,6 +2,7 @@ use byteorder::{BigEndian, ByteOrder};
 use std::env;
 #[cfg(unix)]
 use std::io::{self, BufRead};
+use std::path::PathBuf;
 
 fn main() {
     // Check env var set by `build.rs`.
@@ -21,12 +22,30 @@ fn main() {
     // If there were no arguments, access stdin and test working dir.
     // (We rely on the test runner to always disable isolation when passing no arguments.)
     if std::env::args().len() <= 1 {
+        fn host_to_target_path(path: String) -> PathBuf {
+            use std::ffi::{CStr, CString};
+
+            let path = CString::new(path).unwrap();
+            let mut out = Vec::with_capacity(1024);
+
+            unsafe {
+                extern "Rust" {
+                    fn miri_host_to_target_path(
+                        path: *const i8,
+                        out: *mut i8,
+                        out_size: usize,
+                    ) -> usize;
+                }
+                let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+                assert_eq!(ret, 0);
+                let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+                PathBuf::from(out)
+            }
+        }
+
         // CWD should be crate root.
-        // We have to normalize slashes, as the env var might be set for a different target's conventions.
         let env_dir = env::current_dir().unwrap();
-        let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-        let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-        let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
+        let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
         assert_eq!(env_dir, crate_dir);
 
         #[cfg(unix)]
diff --git a/src/tools/miri/test-cargo-miri/subcrate/main.rs b/src/tools/miri/test-cargo-miri/subcrate/main.rs
index 4ce80b3707226..1cb8091f87750 100644
--- a/src/tools/miri/test-cargo-miri/subcrate/main.rs
+++ b/src/tools/miri/test-cargo-miri/subcrate/main.rs
@@ -4,13 +4,30 @@ use std::path::PathBuf;
 fn main() {
     println!("subcrate running");
 
+    fn host_to_target_path(path: String) -> PathBuf {
+        use std::ffi::{CStr, CString};
+
+        let path = CString::new(path).unwrap();
+        let mut out = Vec::with_capacity(1024);
+
+        unsafe {
+            extern "Rust" {
+                fn miri_host_to_target_path(
+                    path: *const i8,
+                    out: *mut i8,
+                    out_size: usize,
+                ) -> usize;
+            }
+            let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+            assert_eq!(ret, 0);
+            let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+            PathBuf::from(out)
+        }
+    }
+
     // CWD should be workspace root, i.e., one level up from crate root.
-    // We have to normalize slashes, as the env var might be set for a different target's conventions.
     let env_dir = env::current_dir().unwrap();
-    let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-    let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = PathBuf::from(crate_dir);
-    let crate_dir = crate_dir.parent().unwrap().to_string_lossy();
+    let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
+    let crate_dir = crate_dir.parent().unwrap();
     assert_eq!(env_dir, crate_dir);
 }
diff --git a/src/tools/miri/test-cargo-miri/subcrate/test.rs b/src/tools/miri/test-cargo-miri/subcrate/test.rs
index 77e3c2878ca0e..619d8c72fd0a7 100644
--- a/src/tools/miri/test-cargo-miri/subcrate/test.rs
+++ b/src/tools/miri/test-cargo-miri/subcrate/test.rs
@@ -1,16 +1,37 @@
 use std::env;
 
+use std::path::PathBuf;
+
 use byteorder::{ByteOrder, LittleEndian};
 
 fn main() {
     println!("subcrate testing");
 
+    fn host_to_target_path(path: String) -> PathBuf {
+        use std::ffi::{CStr, CString};
+
+        let path = CString::new(path).unwrap();
+        let mut out = Vec::with_capacity(1024);
+
+        unsafe {
+            extern "Rust" {
+                fn miri_host_to_target_path(
+                    path: *const i8,
+                    out: *mut i8,
+                    out_size: usize,
+                ) -> usize;
+            }
+            let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+            assert_eq!(ret, 0);
+            let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+            PathBuf::from(out)
+        }
+    }
+
     // CWD should be crate root.
     // We have to normalize slashes, as the env var might be set for a different target's conventions.
     let env_dir = env::current_dir().unwrap();
-    let env_dir = env_dir.to_string_lossy().replace("\\", "/");
-    let crate_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
-    let crate_dir = crate_dir.to_string_lossy().replace("\\", "/");
+    let crate_dir = host_to_target_path(env::var("CARGO_MANIFEST_DIR").unwrap());
     assert_eq!(env_dir, crate_dir);
 
     // Make sure we can call dev-dependencies.
diff --git a/src/tools/miri/tests/fail/box-cell-alias.stderr b/src/tools/miri/tests/fail/box-cell-alias.stderr
index f57b52c4bda7a..fc946d6d39b3e 100644
--- a/src/tools/miri/tests/fail/box-cell-alias.stderr
+++ b/src/tools/miri/tests/fail/box-cell-alias.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a Unique retag
    |
 LL |     let res = helper(val, ptr);
    |                      ^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
 note: inside `main`
   --> $DIR/box-cell-alias.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/crates/tokio_mvp.rs b/src/tools/miri/tests/fail/crates/tokio_mvp.rs
deleted file mode 100644
index 7cb42c09a9677..0000000000000
--- a/src/tools/miri/tests/fail/crates/tokio_mvp.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@compile-flags: -Zmiri-disable-isolation
-//@error-pattern: can't call foreign function: epoll_create1
-//@normalize-stderr-test: "   = note: inside .*\n" -> ""
-//@only-target-linux: the errors differ too much between platforms
-
-#[tokio::main]
-async fn main() {}
diff --git a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr b/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
deleted file mode 100644
index 1e7dfaa749904..0000000000000
--- a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: unsupported operation: can't call foreign function: epoll_create1
-  --> CARGO_REGISTRY/.../epoll.rs:LL:CC
-   |
-LL |         let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function: epoll_create1
-   |
-   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
-   = note: BACKTRACE:
-note: inside `main`
-  --> $DIR/tokio_mvp.rs:LL:CC
-   |
-LL | #[tokio::main]
-   | ^^^^^^^^^^^^^^
-   = note: this error originates in the macro `syscall` which comes from the expansion of the attribute macro `tokio::main` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to previous error
-
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
index 6040452a166cb..2698c63a44563 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.rs
@@ -37,7 +37,7 @@ pub fn main() {
             let pointer = &*ptr.0;
 
             // Note: could also error due to reading uninitialized memory, but the data-race detector triggers first.
-            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
index c6bfd12b24110..5b809722c7095 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_read_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_read_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/alloc_read_race.rs:LL:CC
+   |
+LL |             pointer.store(Box::into_raw(Box::new_uninit()), Ordering::Relaxed);
+   |                                         ^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/alloc_read_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
index 51d431b36f3a3..b78d5ef27d39f 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.rs
@@ -35,7 +35,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let pointer = &*ptr.0;
-            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>`
+            *pointer.load(Ordering::Relaxed) = 2; //~ ERROR: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
index c4efc175c2077..8520bcf4e4ee1 100644
--- a/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/alloc_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/alloc_write_race.rs:LL:CC
    |
 LL |             *pointer.load(Ordering::Relaxed) = 2;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Allocate on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Allocate on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/alloc_write_race.rs:LL:CC
+   |
+LL |                 .store(Box::into_raw(Box::<usize>::new_uninit()) as *mut usize, Ordering::Relaxed);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/alloc_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
index 79c6760b7c42a..3f811d0f64d04 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>`
+            (&*c.0).load(Ordering::SeqCst) //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
index 04adf0a98b6c5..e25629e14eada 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).load(Ordering::SeqCst)
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Load on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_read_na_write_race1.rs:LL:CC
+   |
+LL |             *(c.0 as *mut usize) = 32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_read_na_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
index e069ac4ad6a83..34fb3ac066f5f 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
index b48f927b8fcae..6953b1403b4b5 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_read_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Load on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_read_na_write_race2.rs:LL:CC
+   |
+LL |             atomic_ref.load(Ordering::SeqCst)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_read_na_write_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
index 9c025a0153d58..63b0806f3bb24 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() //~ ERROR: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
+            *atomic_ref.get_mut() //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
index fdb9b353a67bf..e52b8895a6af6 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race1.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut()
-   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_read_race1.rs:LL:CC
+   |
+LL |             atomic_ref.store(32, Ordering::SeqCst)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_read_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
index 30b3c4863740c..9092254be2164 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>`
+            (&*c.0).store(32, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
index ec581e322b7d1..513d13b0349a0 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_read_race2.rs:LL:CC
    |
 LL |             (&*c.0).store(32, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_read_race2.rs:LL:CC
+   |
+LL |             let _val = *(c.0 as *mut usize);
+   |                        ^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_read_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
index 02b17cc57b61a..5a713905f4edc 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.rs
@@ -20,7 +20,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>`
+            (&*c.0).store(64, Ordering::SeqCst); //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
index 4c75f94d71cf5..2ff70ef1f6d73 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race1.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race1.rs:LL:CC
    |
 LL |             (&*c.0).store(64, Ordering::SeqCst);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Atomic Store on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_write_race1.rs:LL:CC
+   |
+LL |             *(c.0 as *mut usize) = 32;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
index b5f4966d8842a..5848aa262b3eb 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs
@@ -23,7 +23,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             let atomic_ref = &mut *c.0;
-            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>`
+            *atomic_ref.get_mut() = 32; //~ ERROR: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
index 8c7f14081c87b..166b4d2269a88 100644
--- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/atomic_write_na_write_race2.rs:LL:CC
    |
 LL |             *atomic_ref.get_mut() = 32;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Atomic Store on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Atomic Store on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/atomic_write_na_write_race2.rs:LL:CC
+   |
+LL |             atomic_ref.store(64, Ordering::SeqCst);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/atomic_write_na_write_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
index 9922468e5f842..eecb980e90504 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.rs
@@ -34,7 +34,7 @@ fn main() {
 
     let join2 = unsafe {
         spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         })
     };
 
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
index 663bb8d4af512..a08b21ab0e4ab 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_async_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_async_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dangling_thread_async_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dangling_thread_async_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
index 8c8a6ac87f3ab..4c7fbdd7fe6e1 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.rs
@@ -33,6 +33,6 @@ fn main() {
     spawn(|| ()).join().unwrap();
 
     unsafe {
-        *c.0 = 64; //~ ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
+        *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
     }
 }
diff --git a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
index ad3e1735378f3..aa2e6a6f71265 100644
--- a/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/dangling_thread_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/dangling_thread_race.rs:LL:CC
    |
 LL |         *c.0 = 64;
-   |         ^^^^^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+   |         ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dangling_thread_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_thread_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
index 8e1216f5bf0a0..18593cf56ae56 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs
@@ -25,7 +25,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             __rust_dealloc(
-                //~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
index 194c2260baaab..5e546646479d2 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,11 +7,16 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   | |_____________^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_read_race1.rs:LL:CC
+   |
+LL |             let _val = *ptr.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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_read_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
index 38f76af9de137..a6f83d489e587 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs
@@ -28,7 +28,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            // Also an error of the form: Data race detected between Read on thread `<unnamed>` and Deallocate on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 //~ ERROR: dereferenced after this allocation got freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
index 665e5ce4a1706..c82bfed09ee51 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.rs
@@ -35,7 +35,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
index c986e912f03ba..beb70c5a7fa82 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_read_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between Deallocate on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_read_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_read_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
index b36c6b5ac0e45..1e93a6cb0940d 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs
@@ -24,7 +24,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             __rust_dealloc(
-                //~^ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
+                //~^ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
                 ptr.0 as *mut _,
                 std::mem::size_of::<usize>(),
                 std::mem::align_of::<usize>(),
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
index 56eb0b519c484..cc4c4524ba25d 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race1.rs:LL:CC
    |
 LL | /             __rust_dealloc(
@@ -7,11 +7,16 @@ LL | |                 ptr.0 as *mut _,
 LL | |                 std::mem::size_of::<usize>(),
 LL | |                 std::mem::align_of::<usize>(),
 LL | |             );
-   | |_____________^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   | |_____________^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_write_race1.rs:LL:CC
+   |
+LL |             *ptr.0 = 2;
+   |             ^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_write_race1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
index 4af8b904626d2..385584db27f92 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs
@@ -27,7 +27,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            // Also an error of the form: Data race detected between Write on thread `<unnamed>` and Deallocate on thread `<unnamed>`
+            // Also an error of the form: Data race detected between (1) Deallocate on thread `<unnamed>` and (2) Write on thread `<unnamed>`
             // but the invalid allocation is detected first.
             *ptr.0 = 2; //~ ERROR: dereferenced after this allocation got freed
         });
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
index f851ce95785f7..259fbdc497a2c 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.rs
@@ -35,7 +35,7 @@ pub fn main() {
                 sleep(Duration::from_millis(200));
 
                 // Now `stack_var` gets deallocated.
-            } //~ ERROR: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>`
+            } //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
index 7b77e2470a1ab..5f9f4f9bee423 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/dealloc_write_race_stack.rs:LL:CC
    |
 LL |             }
-   |             ^ Data race detected between Deallocate on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^ Data race detected between (1) Write on thread `<unnamed>` and (2) Deallocate on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/dealloc_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
index 27aa16a122f36..3d47b1accb31b 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.rs
@@ -30,7 +30,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
index 26c07ae6962b5..84d1c0bf7e666 100644
--- a/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
+++ b/src/tools/miri/tests/fail/data_race/enable_after_join_to_main.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/enable_after_join_to_main.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/enable_after_join_to_main.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/enable_after_join_to_main.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.rs b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
index 4d436d51f9895..0648aa55f4aa4 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.rs
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.rs
@@ -20,5 +20,5 @@ fn main() {
     // The fence is useless, since it did not happen-after the `store` in the other thread.
     // Hence this is a data race.
     // Also see https://github.com/rust-lang/miri/issues/2192.
-    unsafe { V = 2 } //~ERROR: Data race detected between Write on thread `main` and Write on thread `<unnamed>`
+    unsafe { V = 2 } //~ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main`
 }
diff --git a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
index 0abfe213db17d..c30d2354e768d 100644
--- a/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
+++ b/src/tools/miri/tests/fail/data_race/fence_after_load.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
   --> $DIR/fence_after_load.rs:LL:CC
    |
 LL |     unsafe { V = 2 }
-   |              ^^^^^ Data race detected between Write on thread `main` and Write on thread `<unnamed>` at ALLOC
+   |              ^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/fence_after_load.rs:LL:CC
+   |
+LL |         unsafe { V = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fence_after_load.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.rs b/src/tools/miri/tests/fail/data_race/read_write_race.rs
index b26ec6c41427a..d996141db3ef1 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.rs
@@ -19,7 +19,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race.stderr b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
index 08a19537312cf..13bc5c74ae333 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/read_write_race.rs:LL:CC
+   |
+LL |             let _val = *c.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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/read_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
index 2fbac173993e4..b4e371f430d2e 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.rs
@@ -42,7 +42,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+            stack_var //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
         });
 
         let j2 = spawn(move || {
diff --git a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
index 20f137afe7329..96fcb49482225 100644
--- a/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/read_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/read_write_race_stack.rs:LL:CC
    |
 LL |             stack_var
-   |             ^^^^^^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/read_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/read_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
index 24040a9496114..b7226fa626fbf 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.rs
@@ -37,7 +37,7 @@ pub fn main() {
 
         let j3 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
index 6121c25db22d7..92755f5551d97 100644
--- a/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/relax_acquire_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/relax_acquire_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/relax_acquire_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/relax_acquire_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.rs b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
index 2d7246858e108..dff33a42a1c2b 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.rs
@@ -41,7 +41,7 @@ pub fn main() {
         let j3 = spawn(move || {
             sleep(Duration::from_millis(500));
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
index 777bc4adadc6d..880268730db13 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/release_seq_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/release_seq_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
index 0f974e1c56d3f..f7a523841b812 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.rs
@@ -37,7 +37,7 @@ pub fn main() {
 
         let j2 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 2 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
index 0fcb192d920fd..386c012ba4e5e 100644
--- a/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
+++ b/src/tools/miri/tests/fail/data_race/release_seq_race_same_thread.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/release_seq_race_same_thread.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/release_seq_race_same_thread.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/release_seq_race_same_thread.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.rs b/src/tools/miri/tests/fail/data_race/rmw_race.rs
index 2d13da30b4639..2201362b167f7 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.rs
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.rs
@@ -38,7 +38,7 @@ pub fn main() {
 
         let j3 = spawn(move || {
             if SYNC.load(Ordering::Acquire) == 3 {
-                *c.0 //~ ERROR: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>`
+                *c.0 //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>`
             } else {
                 0
             }
diff --git a/src/tools/miri/tests/fail/data_race/rmw_race.stderr b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
index 3ae6f3b84fe12..82cb2c4ecbb47 100644
--- a/src/tools/miri/tests/fail/data_race/rmw_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/rmw_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/rmw_race.rs:LL:CC
    |
 LL |                 *c.0
-   |                 ^^^^ Data race detected between Read on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |                 ^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/rmw_race.rs:LL:CC
+   |
+LL |             *c.0 = 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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/rmw_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
index cf5c2ed81cb1d..dec5ff274ccf9 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.rs
@@ -21,4 +21,4 @@ fn race(local: i32) {
     // Deallocating the local (when `main` returns)
     // races with the read in the other thread.
     // Make sure the error points at this function's end, not just the call site.
-} //~ERROR: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>`
+} //~ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main`
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
index 0075f877b29dc..71e38c2727e1a 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
   --> $DIR/stack_pop_race.rs:LL:CC
    |
 LL | }
-   |  ^ Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
+   |  ^ Data race detected between (1) Read on thread `<unnamed>` and (2) Deallocate on thread `main` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/stack_pop_race.rs:LL:CC
+   |
+LL |         let _val = unsafe { *ptr.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
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
 note: inside `main`
   --> $DIR/stack_pop_race.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.rs b/src/tools/miri/tests/fail/data_race/write_write_race.rs
index 60e9ac2ac6c38..fe02d02f9dce6 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.rs
@@ -19,7 +19,7 @@ pub fn main() {
         });
 
         let j2 = spawn(move || {
-            *c.0 = 64; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            *c.0 = 64; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
         });
 
         j1.join().unwrap();
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race.stderr b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
index ee7072ccf5d17..3b7eb2b800017 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race.rs:LL:CC
    |
 LL |             *c.0 = 64;
-   |             ^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/write_write_race.rs:LL:CC
+   |
+LL |             *c.0 = 32;
+   |             ^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/write_write_race.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
index 0a29dc13cba17..c1c1b1fa6e38a 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.rs
@@ -39,7 +39,7 @@ pub fn main() {
 
             sleep(Duration::from_millis(200));
 
-            stack_var = 1usize; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+            stack_var = 1usize; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
 
             // read to silence errors
             stack_var
diff --git a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
index ceb473c2a4a41..c501ecd11a6d1 100644
--- a/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
+++ b/src/tools/miri/tests/fail/data_race/write_write_race_stack.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/write_write_race_stack.rs:LL:CC
    |
 LL |             stack_var = 1usize;
-   |             ^^^^^^^^^^^^^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |             ^^^^^^^^^^^^^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/write_write_race_stack.rs:LL:CC
+   |
+LL |             *pointer.load(Ordering::Acquire) = 3;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside closure at $DIR/write_write_race_stack.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
index 8eb9fa4ff5c27..09e4157b31f4f 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_clashing.stderr
@@ -14,7 +14,7 @@ help: then it's defined here again, in crate `exported_symbol_clashing`
    |
 LL | fn bar() {}
    | ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/exported_symbol_clashing.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
index 58a996e64530e..0d0055bb85c8c 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_shim_clashing.stderr
@@ -12,7 +12,7 @@ LL | |
 LL | |     unreachable!()
 LL | | }
    | |_^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/exported_symbol_shim_clashing.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr b/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
index 461275c3fa346..b22db3eb121ee 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/alias_through_mutation.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *target = 13;
    |     ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
index 4514abb4ab2e4..3ce39968cbb13 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
index 9ca9743cbd929..df4b6cf02561c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &i32, _y: &mut i32) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
index b504097a3c91f..55aaed62f4f5f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
    |
 LL |     safe_raw(xraw, xshr);
    |     ^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut3.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
index 6fe0d70902930..ddf197bc63955 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
    |             ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
 note: inside `main`
   --> $DIR/aliasing_mut4.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
index f114130f6fafd..76f4e81f71ba2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *our = 5;
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
 note: inside `demo_box_advanced_unique`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
index 139fcd0ca4583..59377aeb971a8 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
    |                ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
 note: inside `main`
   --> $DIR/box_noalias_violation.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
index 6aa14361287e3..fa3d7ca367625 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/buggy_as_mut_slice.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique retag
    |
 LL |         unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/buggy_as_mut_slice.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
index cdeccc0855a95..c75d8cab3fc85 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/buggy_split_at_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x10] by a Unique retag
    |
 LL |                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
index e05f44fac9d2f..bd79b401f667f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *base = 1;
    |         ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/disable_mut_does_not_merge_srw.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr
index bd51a6645a676..3d0cef241c3e6 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL |         core::ptr::drop_in_place(x);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `<HasDrop as std::ops::Drop>::drop` at $DIR/drop_in_place_protector.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<HasDrop> - shim(Some(HasDrop))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<(HasDrop, u8)> - shim(Some((HasDrop, u8)))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr
index 3f9e6708bdaad..7f2917e795053 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x1]
    |
 LL |         let x = core::ptr::addr_of!(x);
    |                 ^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::ptr::drop_in_place::<u8> - shim(None)` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
 note: inside `main`
   --> $DIR/drop_in_place_retag.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
index e81411bbdd86c..e3bffde1f0176 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique FnEntry reta
    |
 LL |     x.do_bad();
    |     ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fnentry_invalidation.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
index d6d0084fa2a77..b104de4b8d94d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0xc] by a Unique FnEntry reta
    |
 LL |     let _ = t.sli.as_mut_ptr();
    |             ^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
index f2f13d0d5594e..7fff60f25fbbe 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
@@ -16,7 +16,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
    |
 LL |         ptr1.write(0);
    |         ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
 note: inside `main`
   --> $DIR/illegal_deALLOC.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
index 95ff05d70c30e..7a159c9d3fefc 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw };
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
index 5cfdf77dee402..e3e79f6f0f05e 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a SharedReadOnly reta
    |
 LL |     let shr = unsafe { &*xraw };
    |                        ^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
index dacf71fa3ee39..3a8687ad9aa19 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read3.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xref1.r };
    |                         ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
index 5ce0cba617914..dcf37b2690154 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read4.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read4.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
index 63532f87944eb..1793798d15f6a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read5.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a read access
    |
 LL |     mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
    |                          ^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read5.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
index 93a96ab601ea3..17b28dee3c7ca 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         let x = &mut *x; // kill `raw`
    |                 ^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read6.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
index 2e8ac207beafb..b76446d60f6d2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read7.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |         let _val = ptr::read(raw);
    |                    ^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read7.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
index c34fa2d8955dd..b43079c3b7f3b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read8.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *y2 += 1;
    |         ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read8.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
index 43b4ec2ba652b..fbd5d8b956d97 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *exposed_ptr = 0;
    |         ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read_despite_exposed1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
index 832320fc202e1..19e4cbdb93855 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |         let _val = *exposed_ptr;
    |                    ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_read_despite_exposed2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
index 3bf27f4815e9a..c1e4918146587 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write1.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |         let x: *mut u32 = xref as *const _ as *mut _;
    |                           ^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
index a9fe8cb6ccc02..3e11e86eb81b3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     drop(&mut *target); // reborrow
    |          ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
index d64f2ddd87670..4053325821e75 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |     let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
    |               ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
index e3b8621eb74f2..fceda8db4cef5 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write4.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     let _mut_ref: &mut i32 = unsafe { mem::transmute(raw) }; // &mut, with raw tag
    |                                       ^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write4.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
index bbeb81258bde6..c71780b7e03e0 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write5.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 15 };
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write5.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
index 49d9050f30947..3d3d2a24c2852 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
    |        ^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
 note: inside `main`
   --> $DIR/illegal_write6.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
index 87ddf61d7586c..1bb3afe483eba 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *exposed_ptr = 0;
    |         ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/illegal_write_despite_exposed1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
index 1d68727c82af4..da55e724fd81e 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *c.get() = UnsafeCell::new(1); // invalidates inner_shr
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/interior_mut1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
index 8a3357142261b..8c8a96cbbbd63 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/interior_mut2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |         *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/interior_mut2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
index a53c633c38130..95fa4c51d12fd 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &mut i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
index 6ee78d1aac682..8f677bd547ce3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector2.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
index 2b38dea9dbb71..1648ca9e58bb1 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
 note: inside `main`
   --> $DIR/invalidate_against_protector3.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
index 08dc171c9eef0..7aca065ca0d70 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/load_invalid_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
index 50bbed2b295c9..7eb973ae7f2af 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 42 }; // unfreeze
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/load_invalid_shr.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
index 2f3900c40d726..3e7fe11b5202a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     *our = 5;
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code_2` at $DIR/mut_exclusive_violation1.rs:LL:CC
 note: inside `demo_mut_advanced_unique`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
index 43b5325fc541a..30ce698761f3d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         let _raw2 = ptr2.as_mut();
    |                     ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/mut_exclusive_violation2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
index 90677dfaf555e..0cba380ea1a30 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    |                          ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside closure
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
index f189d0483d12d..f76b6a57eaca0 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
@@ -16,7 +16,7 @@ help: <TAG> is this argument
    |
 LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    |                          ^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside closure
diff --git a/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr b/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
index 8c2bba5391888..ad366bdabcee6 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/outdated_local.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     x = 1; // this invalidates y by reactivating the lowermost uniq borrow for this local
    |     ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/outdated_local.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
index d7ab930aa3785..96cec327b9df5 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/pass_invalid_mut.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
index c14b35c75c83d..5243858a91a7d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pass_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a write access
    |
 LL |     unsafe { *xraw = 42 }; // unfreeze
    |              ^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/pass_invalid_shr.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
index 7d58d1aebbecd..e20b5b89a2fca 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x1] by a write access
    |
 LL |     *val = 2; // this invalidates any raw ptrs `fun1` might have created.
    |     ^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `fun2` at $DIR/pointer_smuggling.rs:LL:CC
 note: inside `main`
   --> $DIR/pointer_smuggling.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
index d75934445e6d2..9f7e7a058dfcf 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |     let raw2 = &mut l as *mut _; // invalidates raw1
    |                ^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/raw_tracking.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
index 309d7a22be64f..a63cd03366f68 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.rs
@@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>`
+        *p = 5; //~ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>`
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
index 5dc936f070744..c53a495b5e18b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_read.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between Write on thread `<unnamed>` and Read on thread `<unnamed>` at ALLOC
+   |         ^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/retag_data_race_read.rs:LL:CC
+   |
+LL |         let _r = &*p;
+   |                  ^^^
    = 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: BACKTRACE (of the first span):
    = note: inside `thread_2` at $DIR/retag_data_race_read.rs:LL:CC
 note: inside closure
   --> $DIR/retag_data_race_read.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
index 9368a0a919eb3..c1dded40d3c35 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.rs
@@ -15,7 +15,7 @@ fn thread_1(p: SendPtr) {
 fn thread_2(p: SendPtr) {
     let p = p.0;
     unsafe {
-        *p = 5; //~ ERROR: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>`
+        *p = 5; //~ ERROR: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>`
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
index 03c2450356416..da5af60067565 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+error: Undefined Behavior: Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |         *p = 5;
-   |         ^^^^^^ Data race detected between Write on thread `<unnamed>` and Write on thread `<unnamed>` at ALLOC
+   |         ^^^^^^ Data race detected between (1) Write on thread `<unnamed>` and (2) Write on thread `<unnamed>` at ALLOC. (2) just happened here
    |
+help: and (1) occurred earlier here
+  --> $DIR/retag_data_race_write.rs:LL:CC
+   |
+LL |         let _r = &mut *p;
+   |                  ^^^^^^^
    = 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: BACKTRACE (of the first span):
    = note: inside `thread_2` at $DIR/retag_data_race_write.rs:LL:CC
 note: inside closure
   --> $DIR/retag_data_race_write.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
index 1b28f780c1c54..2bf91b676c4c0 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
index db14dcafa0084..ff00c54570cd3 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut_option.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
index 81ed4218aade7..61d041a8816d2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a read access
    |
 LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_mut_tuple.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
index 9c8cc50b2d7ac..d3a73a00fa605 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
index 00ce6f6cd5fe1..f14e8b8532f55 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr_option.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
index bbd17b1284c5e..9ddaad4d1be30 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x8] by a write access
    |
 LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC
 note: inside `main`
   --> $DIR/return_invalid_shr_tuple.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
index 3a139c3ab2120..589e1291ba731 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak1.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique retag
    |
 LL |         shr_rw.set(1);
    |         ^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/shared_rw_borrows_are_weak1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
index 0609a73e79315..0e37c4ffb394c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shared_rw_borrows_are_weak2.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [$HEX..$HEX] by a Unique retag
    |
 LL |         shr_rw.replace(1);
    |         ^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/shared_rw_borrows_are_weak2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
index fe0ac211318aa..a69116f2afae7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
    |
 LL |         *(x as *const i32 as *mut i32) = 7;
    |           ^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
 note: inside `foo`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
index 6f1d0ccd348ec..05be0d3f1e98a 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/track_caller.stderr
@@ -19,7 +19,7 @@ help: <TAG> was later invalidated at offsets [0x0..0x4] by a read access
    |
 LL |     callee(xraw);
    |     ^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/track_caller.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
index a2ecb07fd3117..ac962311d4260 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x4..0x8]
    |
 LL |     let raw = (&mut x[1] as *mut i32).wrapping_offset(-1);
    |                ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/transmute-is-no-escape.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
index 01a4bf4340c78..7a40d1078b3b7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/unescaped_static.stderr
@@ -14,7 +14,7 @@ help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x1]
    |
 LL |     let ptr_to_first = &ARRAY[0] as *const u8;
    |                        ^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/unescaped_static.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
index e134ee2845d05..950abc4cbcf92 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
@@ -14,7 +14,7 @@ help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0
    |
 LL |         assert_eq!(*s.get_unchecked(1), 2);
    |                     ^^^^^^^^^^^^^^^^^^
-   = note: BACKTRACE:
+   = note: BACKTRACE (of the first span):
    = note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
 note: inside `main`
   --> $DIR/zst_slice.rs:LL:CC
diff --git a/src/tools/miri/tests/pass-dep/page_size.rs b/src/tools/miri/tests/pass-dep/page_size.rs
index cdcabf3333814..fb060317538d3 100644
--- a/src/tools/miri/tests/pass-dep/page_size.rs
+++ b/src/tools/miri/tests/pass-dep/page_size.rs
@@ -3,4 +3,17 @@ fn main() {
 
     // In particular, this checks that it is not 0.
     assert!(page_size.is_power_of_two(), "page size not a power of two: {}", page_size);
+    // Most architectures have 4k pages by default
+    #[cfg(not(any(
+        target_arch = "wasm32",
+        target_arch = "wasm64",
+        all(target_arch = "aarch64", target_vendor = "apple")
+    )))]
+    assert!(page_size == 4 * 1024, "non-4k default page size: {}", page_size);
+    // ... except aarch64-apple with 16k
+    #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
+    assert!(page_size == 16 * 1024, "aarch64 apple reports non-16k page size: {}", page_size);
+    // ... and wasm with 64k
+    #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
+    assert!(page_size == 64 * 1024, "wasm reports non-64k page size: {}", page_size);
 }
diff --git a/src/tools/miri/tests/pass-dep/page_size_override.rs b/src/tools/miri/tests/pass-dep/page_size_override.rs
new file mode 100644
index 0000000000000..68858f38759a6
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/page_size_override.rs
@@ -0,0 +1,7 @@
+//@compile-flags: -Zmiri-force-page-size=8
+
+fn main() {
+    let page_size = page_size::get();
+
+    assert!(page_size == 8 * 1024, "8k page size override not respected: {}", page_size);
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
index acf16ecb7e06d..ba5b269f65242 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
@@ -5,8 +5,8 @@
 #![feature(io_error_uncategorized)]
 
 use std::convert::TryInto;
-use std::ffi::CString;
-use std::fs::{canonicalize, remove_file, File};
+use std::ffi::{CStr, CString};
+use std::fs::{canonicalize, remove_dir_all, remove_file, File};
 use std::io::{Error, ErrorKind, Write};
 use std::os::unix::ffi::OsStrExt;
 use std::path::PathBuf;
@@ -18,23 +18,26 @@ fn main() {
     test_file_open_unix_allow_two_args();
     test_file_open_unix_needs_three_args();
     test_file_open_unix_extra_third_arg();
+    #[cfg(target_os = "linux")]
+    test_o_tmpfile_flag();
 }
 
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-
-            #[cfg(windows)]
-            return PathBuf::from(tmp.replace("/", "\\"));
-
-            #[cfg(not(windows))]
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
 }
 
 /// Prepare: compute filename and make sure the file does not exist.
@@ -45,6 +48,15 @@ fn prepare(filename: &str) -> PathBuf {
     path
 }
 
+/// Prepare directory: compute directory name and make sure it does not exist.
+#[allow(unused)]
+fn prepare_dir(dirname: &str) -> PathBuf {
+    let path = tmp().join(&dirname);
+    // Clean the directory for robustness.
+    remove_dir_all(&path).ok();
+    path
+}
+
 /// Prepare like above, and also write some initial content to the file.
 fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
     let path = prepare(filename);
@@ -135,3 +147,22 @@ fn test_readlink() {
     assert_eq!(res, -1);
     assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
 }
+
+#[cfg(target_os = "linux")]
+fn test_o_tmpfile_flag() {
+    use std::fs::{create_dir, OpenOptions};
+    use std::os::unix::fs::OpenOptionsExt;
+    let dir_path = prepare_dir("miri_test_fs_dir");
+    create_dir(&dir_path).unwrap();
+    // test that the `O_TMPFILE` custom flag gracefully errors instead of stopping execution
+    assert_eq!(
+        Some(libc::EOPNOTSUPP),
+        OpenOptions::new()
+            .read(true)
+            .write(true)
+            .custom_flags(libc::O_TMPFILE)
+            .open(dir_path)
+            .unwrap_err()
+            .raw_os_error(),
+    );
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
index 2a4300fcd049e..20e96a92c7c5f 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs
@@ -7,15 +7,23 @@ use std::os::unix::io::AsRawFd;
 use std::path::PathBuf;
 
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    use std::ffi::{CStr, CString};
+
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
 }
 
 /// Test allocating variant of `realpath`.
diff --git a/src/tools/miri/tests/pass-dep/tokio_mvp.rs b/src/tools/miri/tests/pass-dep/tokio_mvp.rs
new file mode 100644
index 0000000000000..642168253c2fa
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/tokio_mvp.rs
@@ -0,0 +1,6 @@
+// Need to disable preemption to stay on the supported MVP codepath in mio.
+//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-preemption-rate=0
+//@only-target-x86_64-unknown-linux: support for tokio exists only on linux and x86
+
+#[tokio::main]
+async fn main() {}
diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs
index b18d903e36ceb..c411f748a0602 100644
--- a/src/tools/miri/tests/pass/provenance.rs
+++ b/src/tools/miri/tests/pass/provenance.rs
@@ -10,6 +10,7 @@ fn main() {
     bytewise_ptr_methods();
     bytewise_custom_memcpy();
     bytewise_custom_memcpy_chunked();
+    int_load_strip_provenance();
 }
 
 /// Some basic smoke tests for provenance.
@@ -137,3 +138,9 @@ fn bytewise_custom_memcpy_chunked() {
         assert_eq!(*ptr, 42);
     }
 }
+
+fn int_load_strip_provenance() {
+    let ptrs = [&42];
+    let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
+    assert_eq!(ptrs[0] as *const _ as usize, ints[0]);
+}
diff --git a/src/tools/miri/tests/pass/shims/env/current_dir.rs b/src/tools/miri/tests/pass/shims/env/current_dir.rs
index 069b462ab371a..ca90912eabc54 100644
--- a/src/tools/miri/tests/pass/shims/env/current_dir.rs
+++ b/src/tools/miri/tests/pass/shims/env/current_dir.rs
@@ -3,8 +3,9 @@ use std::env;
 use std::io::ErrorKind;
 
 fn main() {
-    // Test that `getcwd` is available
+    // Test that `getcwd` is available and an absolute path
     let cwd = env::current_dir().unwrap();
+    assert!(cwd.is_absolute(), "cwd {:?} is not absolute", cwd);
     // Test that changing dir to `..` actually sets the current directory to the parent of `cwd`.
     // The only exception here is if `cwd` is the root directory, then changing directory must
     // keep the current directory equal to `cwd`.
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 65cf6fe66ba5e..a7d4800faecc4 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -15,6 +15,7 @@ use std::io::{Error, ErrorKind, IsTerminal, Read, Result, Seek, SeekFrom, Write}
 use std::path::{Path, PathBuf};
 
 fn main() {
+    test_path_conversion();
     test_file();
     test_file_clone();
     test_file_create_new();
@@ -30,21 +31,28 @@ fn main() {
     test_from_raw_os_error();
 }
 
+fn host_to_target_path(path: String) -> PathBuf {
+    use std::ffi::{CStr, CString};
+
+    let path = CString::new(path).unwrap();
+    let mut out = Vec::with_capacity(1024);
+
+    unsafe {
+        extern "Rust" {
+            fn miri_host_to_target_path(path: *const i8, out: *mut i8, out_size: usize) -> usize;
+        }
+        let ret = miri_host_to_target_path(path.as_ptr(), out.as_mut_ptr(), out.capacity());
+        assert_eq!(ret, 0);
+        let out = CStr::from_ptr(out.as_ptr()).to_str().unwrap();
+        PathBuf::from(out)
+    }
+}
+
 fn tmp() -> PathBuf {
-    std::env::var("MIRI_TEMP")
-        .map(|tmp| {
-            // MIRI_TEMP is set outside of our emulated
-            // program, so it may have path separators that don't
-            // correspond to our target platform. We normalize them here
-            // before constructing a `PathBuf`
-
-            #[cfg(windows)]
-            return PathBuf::from(tmp.replace("/", "\\"));
-
-            #[cfg(not(windows))]
-            return PathBuf::from(tmp.replace("\\", "/"));
-        })
-        .unwrap_or_else(|_| std::env::temp_dir())
+    let path = std::env::var("MIRI_TEMP")
+        .unwrap_or_else(|_| std::env::temp_dir().into_os_string().into_string().unwrap());
+    // These are host paths. We need to convert them to the target.
+    host_to_target_path(path)
 }
 
 /// Prepare: compute filename and make sure the file does not exist.
@@ -71,6 +79,12 @@ fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf {
     path
 }
 
+fn test_path_conversion() {
+    let tmp = tmp();
+    assert!(tmp.is_absolute(), "{:?} is not absolute", tmp);
+    assert!(tmp.is_dir(), "{:?} is not a directory", tmp);
+}
+
 fn test_file() {
     let bytes = b"Hello, World!\n";
     let path = prepare("miri_test_fs_file.txt");
diff --git a/src/tools/miri/tests/pass/vec.rs b/src/tools/miri/tests/pass/vec.rs
index fb1d8e306f293..3a6655e2ba69f 100644
--- a/src/tools/miri/tests/pass/vec.rs
+++ b/src/tools/miri/tests/pass/vec.rs
@@ -48,7 +48,7 @@ fn vec_into_iter_zst() {
     assert_eq!(v, 0);
 
     let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
-    it.advance_by(1);
+    it.advance_by(1).unwrap();
     drop(it);
 
     let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();