--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -84,12 +84,24 @@ static bool is_intel(xc_interface *xch)
 	return r;
 }
 
+static const char path_debug[] = "/etc/xen/xc_domain_restore.debug";
+static int do_debug;
+static void set_debug(xc_interface *xch, const char *fn)
+{
+    do_debug = access(path_debug, F_OK) == 0;
+    IPRINTF("%s: debug %s because '%s' does%s exist,",
+            fn, do_debug ? "ENABLED" : "DISABLED",
+            path_debug,
+            do_debug ? "" : " not");
+}
+
 #ifndef __MINIOS__
 static ssize_t rdexact(xc_interface *xch, struct restore_ctx *ctx,
+                       unsigned ln,
                        int fd, void* buf, size_t size)
 {
     size_t offset = 0;
-    int ret;
+    int ret, rc = 0;
     ssize_t len;
     struct timeval tv;
     fd_set rfds;
@@ -111,7 +123,8 @@ static ssize_t rdexact(xc_interface *xch
             if ( !FD_ISSET(fd, &rfds) ) {
                 PERROR("%s failed (select returned %d), domid %u", __func__, ret, ctx->dom);
                 errno = ETIMEDOUT;
-                return -1;
+                rc = -1;
+                goto out;
             }
         }
 
@@ -125,7 +138,8 @@ static ssize_t rdexact(xc_interface *xch
             if (zero_shown > 123) {
                 PERROR("0-length read after %ld iterations, domid %u", (long)zero_shown, ctx->dom);
                 errno = ETIMEDOUT;
-                return -1;
+                rc = -1;
+                goto out;
             }
             errno = 0;
             if (nanosleep(&t, NULL))
@@ -133,17 +147,25 @@ static ssize_t rdexact(xc_interface *xch
         }
         else if ( len < 0 ) {
             PERROR("%s failed, domid %u offset %ld size %ld", __func__, ctx->dom, (long)offset, (long)size);
-            return -1;
+            rc = -1;
+            goto out;
         }
         offset += len;
         if ( len )
             zero_shown = 0;
     }
 
-    return 0;
+out:
+    if (do_debug) {
+        if (size && (size & ~XC_PAGE_MASK) == 0)
+            DPRINTF("r %u p%zu", ln, size >> XC_PAGE_SHIFT);
+        else
+            DPRINTF("r %u b%zu", ln, size);
+    }
+    return rc;
 }
 
-#define RDEXACT(fd,buf,size) rdexact(xch, ctx, fd, buf, size)
+#define RDEXACT(fd,buf,size) rdexact(xch, ctx, __LINE__, fd, buf, size)
 #else
 #define RDEXACT read_exact
 #endif
@@ -819,7 +841,12 @@ static int pagebuf_get_one(xc_interface
         return -1;
     }
 
-    // DPRINTF("reading batch of %d pages\n", count);
+    if (do_debug) {
+        if (count < 0)
+            DPRINTF("reading XC_SAVE_ID_* %d", count);
+        else
+            DPRINTF("reading batch of %d pages", count);
+    }
 
     switch ( count )
     {
@@ -1518,9 +1545,17 @@ int xc_domain_restore(xc_interface *xch,
     struct restore_ctx _ctx;
     struct restore_ctx *ctx = &_ctx;
     struct domain_info_context *dinfo = &ctx->dinfo;
+    struct stat statbuf = {};
+    int is_file = 0;
+    rc = fstat(io_fd, &statbuf);
+    if (rc == 0)
+        is_file = (statbuf.st_mode & S_IFMT) == S_IFREG;
+    rc = 1;
 
     DPRINTF("%s: starting restore of new domid %u", __func__, dom);
 
+    set_debug(xch, __func__);
+
     pagebuf_init(&pagebuf);
     memset(&tailbuf, 0, sizeof(tailbuf));
     tailbuf.ishvm = hvm;
@@ -1574,6 +1609,7 @@ int xc_domain_restore(xc_interface *xch,
             io_fd, &pae_extended_cr3, &ext_vcpucontext,
             &vcpuextstate, &vcpuextstate_size);
 
+        DPRINTF("load_p2m_frame_list done");
         if ( !p2m_frame_list )
             goto out;
 
@@ -1649,6 +1685,7 @@ int xc_domain_restore(xc_interface *xch,
 
     n = m = 0;
  loadpages:
+    DPRINTF("loadpages");
     for ( ; ; )
     {
         int j, curbatch;
@@ -1752,6 +1789,7 @@ int xc_domain_restore(xc_interface *xch,
          * Discard cache for portion of file read so far up to last
          *  page boundary every 16MB or so.
          */
+        if (is_file)
         m += j;
         if ( m > MAX_PAGECACHE_USAGE )
         {
@@ -2414,6 +2452,7 @@ int xc_domain_restore(xc_interface *xch,
     tailbuf_free(&tailbuf);
 
     /* discard cache for save file  */
+    if (is_file)
     discard_file_cache(xch, io_fd, 1 /*flush*/);
 
     fcntl(io_fd, F_SETFL, orig_io_fd_flags);
