diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs
index ff64d2aa82515..550a4b1b94b93 100644
--- a/library/std/src/sys/common/mod.rs
+++ b/library/std/src/sys/common/mod.rs
@@ -11,3 +11,4 @@
 #![allow(dead_code)]
 
 pub mod alloc;
+pub mod time;
diff --git a/library/std/src/sys/common/time.rs b/library/std/src/sys/common/time.rs
new file mode 100644
index 0000000000000..0c22478a25e65
--- /dev/null
+++ b/library/std/src/sys/common/time.rs
@@ -0,0 +1,35 @@
+use crate::env;
+use crate::sync::atomic::{AtomicU8, Ordering};
+
+#[repr(u8)]
+#[derive(Copy, Clone)]
+pub enum InstantReliability {
+    // 0 is the placeholder for initialization pending
+    Default = 1,
+    AssumeMonotonic = 2,
+    AssumeBroken = 3,
+}
+
+static INSTANT_RELIABILITY: AtomicU8 = AtomicU8::new(0);
+
+pub fn instant_reliability_override() -> InstantReliability {
+    let current = INSTANT_RELIABILITY.load(Ordering::Relaxed);
+
+    if current == 0 {
+        let new = match env::var("RUST_CLOCK_ASSUME_MONOTONIC").as_deref() {
+            Ok("1") => InstantReliability::AssumeMonotonic,
+            Ok("0") => InstantReliability::AssumeBroken,
+            Ok(_) => {
+                eprintln!("unsupported value in RUST_CLOCK_ASSUME_MONOTONIC; using default");
+                InstantReliability::Default
+            }
+            _ => InstantReliability::Default,
+        };
+        INSTANT_RELIABILITY.store(new as u8, Ordering::Relaxed);
+        new
+    } else {
+        // SAFETY: The enum has a compatible layout and after initialization only values
+        // cast from enum variants are stored in the atomic static.
+        unsafe { crate::mem::transmute(current) }
+    }
+}
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 23a5c81c0053b..25c4f88828eac 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -273,12 +273,12 @@ mod inner {
 
 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
 mod inner {
+    use super::Timespec;
     use crate::fmt;
+    use crate::sys::common::time::{instant_reliability_override, InstantReliability};
     use crate::sys::cvt;
     use crate::time::Duration;
 
-    use super::Timespec;
-
     #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
     pub struct Instant {
         t: Timespec,
@@ -301,9 +301,15 @@ mod inner {
         }
 
         pub fn actually_monotonic() -> bool {
-            (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
-                || (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
-                || cfg!(target_os = "fuchsia")
+            match instant_reliability_override() {
+                InstantReliability::Default => {
+                    (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64"))
+                        || (cfg!(target_os = "linux") && cfg!(target_arch = "x86"))
+                        || cfg!(target_os = "fuchsia")
+                }
+                InstantReliability::AssumeMonotonic => true,
+                InstantReliability::AssumeBroken => false,
+            }
         }
 
         pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs
index 91e4f7654840d..1778203fe5335 100644
--- a/library/std/src/sys/windows/time.rs
+++ b/library/std/src/sys/windows/time.rs
@@ -3,6 +3,7 @@ use crate::convert::TryInto;
 use crate::fmt;
 use crate::mem;
 use crate::sys::c;
+use crate::sys::common::time::{instant_reliability_override, InstantReliability};
 use crate::time::Duration;
 
 use core::hash::{Hash, Hasher};
@@ -42,7 +43,11 @@ impl Instant {
     }
 
     pub fn actually_monotonic() -> bool {
-        false
+        match instant_reliability_override() {
+            InstantReliability::Default => false,
+            InstantReliability::AssumeMonotonic => true,
+            InstantReliability::AssumeBroken => false,
+        }
     }
 
     pub const fn zero() -> Instant {
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 89addae078948..eea51e043d961 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -103,6 +103,28 @@ pub use core::time::Duration;
 /// > structure cannot represent the new point in time.
 ///
 /// [`add`]: Instant::add
+///
+/// ## Reliability
+///
+/// On platforms where the underlying system call's API contract guarantees monotonicity
+/// Instant may rely on that property. Otherwise it will add its own synchronization
+/// to ensure monotonicity. Sometimes operating system guarantees are broken by hardware
+/// or virtualization bugs. This can manifest in Duration between an older and newer Instant
+/// appearing to be negative which results in a panic.
+///
+/// On windows and some unix systems you can override rust's choice to add
+/// its own synchronization or rely on the operating system by setting the environment variable
+/// `RUST_CLOCK_ASSUME_MONOTONIC` to `1` (trust the system-provided time) or `0`
+/// (apply additional synchronization). The value of the variable is only read
+/// the first time an Instant is created. Altering it later will have no effect.
+///
+/// > Note: The environment variable is experimental and meant to diagnose bugs.
+/// > It is not part of the normal Rust stability guarantees.
+///
+/// If you encounter a case where additional synchronization is necessary please
+/// [file an issue]
+///
+/// [file an issue]: https://github.com/rust-lang/rust/issues
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[stable(feature = "time2", since = "1.8.0")]
 pub struct Instant(time::Instant);
@@ -327,7 +349,9 @@ impl Instant {
     ///
     /// This function may panic if the current time is earlier than this
     /// instant, which is something that can happen if an `Instant` is
-    /// produced synthetically.
+    /// produced synthetically or due to [hardware bugs]
+    ///
+    /// [hardware bugs]: Instant#reliability
     ///
     /// # Examples
     ///