+static uint64_t
+virtual_timeout_inflate64(unsigned int vti, uint64_t timeout, uint64_t max_timeout)
+{
+ if (vti >= 64) {
+ return max_timeout;
+ }
+
+ if ((timeout << vti) >> vti != timeout) {
+ return max_timeout;
+ }
+
+ if ((timeout << vti) > max_timeout) {
+ return max_timeout;
+ }
+
+ return timeout << vti;
+}
+
+static uint32_t
+virtual_timeout_inflate32(unsigned int vti, uint32_t timeout, uint32_t max_timeout)
+{
+ if (vti >= 32) {
+ return max_timeout;
+ }
+
+ if ((timeout << vti) >> vti != timeout) {
+ return max_timeout;
+ }
+
+ return timeout << vti;
+}
+
+/*
+ * Some timeouts are later adjusted or used in calculations setting
+ * other values. In order to avoid overflow, cap the max timeout as
+ * 2^47ns (~39 hours).
+ */
+static const uint64_t max_timeout_ns = 1ULL << 47;
+
+/*
+ * Inflate a timeout in absolutetime.
+ */
+static uint64_t
+virtual_timeout_inflate_abs(unsigned int vti, uint64_t timeout)
+{
+ uint64_t max_timeout;
+ nanoseconds_to_absolutetime(max_timeout_ns, &max_timeout);
+ return virtual_timeout_inflate64(vti, timeout, max_timeout);
+}
+
+/*
+ * Inflate a value in TSC ticks.
+ */
+static uint64_t
+virtual_timeout_inflate_tsc(unsigned int vti, uint64_t timeout)
+{
+ const uint64_t max_timeout = tmrCvt(max_timeout_ns, tscFCvtn2t);
+ return virtual_timeout_inflate64(vti, timeout, max_timeout);
+}
+
+/*
+ * Inflate a timeout in microseconds.
+ */
+static uint32_t
+virtual_timeout_inflate_us(unsigned int vti, uint64_t timeout)
+{
+ const uint32_t max_timeout = ~0;
+ return virtual_timeout_inflate32(vti, timeout, max_timeout);
+}
+