diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9d4e163931..737cd31dea 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1025,6 +1025,7 @@ virStrToLong_ul;
 virStrToLong_ull;
 virStrcpy;
 virStrncpy;
+virTimeMs;
 virTimestamp;
 virVasprintf;
 
diff --git a/src/util/util.c b/src/util/util.c
index 457becf834..d00f065b56 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -2471,6 +2471,30 @@ virTimestamp(void)
     return timestamp;
 }
 
+#define timeval_to_ms(tv)   (((tv).tv_sec * 1000ull) + ((tv).tv_usec / 1000))
+
+/**
+ * virTimeMs:
+ *
+ * Get current time in milliseconds.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+virTimeMs(unsigned long long *ms)
+{
+    struct timeval now;
+
+    if (gettimeofday(&now, NULL) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("cannot get time of day"));
+        return -1;
+    }
+
+    *ms = timeval_to_ms(now);
+    return 0;
+}
+
 #if HAVE_LIBDEVMAPPER_H
 bool
 virIsDevMapperDevice(const char *devname)
diff --git a/src/util/util.h b/src/util/util.h
index 68a8431683..0c43f7a77f 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -254,6 +254,8 @@ int virBuildPathInternal(char **path, ...) ATTRIBUTE_SENTINEL;
 
 char *virTimestamp(void);
 
+int virTimeMs(unsigned long long *ms) ATTRIBUTE_NONNULL(1);
+
 bool virIsDevMapperDevice(const char *devname) ATTRIBUTE_NONNULL(1);
 
 int virEmitXMLWarning(int fd,