diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index 8899f75..a10d28e 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -962,6 +962,25 @@ FIFO-based event channel ABI support up to 131,071 event channels.
 Other guests are limited to 4095 (64-bit x86 and ARM) or 1023 (32-bit
 x86).
 
+=item B<nvdimm=[ "NVDIMM_SPEC_STRING", "NVDIMM_SPEC_STRING", ... ]>
+
+Specifies the NVDIMM devices which are provided to the guest.
+
+Each B<NVDIMM_SPEC_STRING> is a comma-separated list of C<KEY=VALUE>
+settings, from the following list:
+
+=over 4
+
+=item C<file=PATH_TO_NVDIMM_DEVICE_FILE>
+
+Specifies the path to the file of the NVDIMM device, e.g. file=/dev/pmem0.
+
+=item C<size=MBYTES>
+
+Specifies the size in Mbytes of the NVDIMM device.
+
+=back
+
 =back
 
 =head2 Paravirtualised (PV) Guest Specific Options
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 0aaefd9..6fb4bbb 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -763,6 +763,7 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
     const libxl_device_nic *nics = guest_config->nics;
     const int num_disks = guest_config->num_disks;
     const int num_nics = guest_config->num_nics;
+    const int num_nvdimms = guest_config->num_nvdimms;
     const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
     const libxl_sdl_info *sdl = dm_sdl(guest_config);
     const char *keymap = dm_keymap(guest_config);
@@ -1124,7 +1125,6 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
                                             machinearg, max_ram_below_4g);
             }
         }
-
         if (libxl_defbool_val(b_info->u.hvm.gfx_passthru)) {
             enum libxl_gfx_passthru_kind gfx_passthru_kind =
                             libxl__detect_gfx_passthru_kind(gc, guest_config);
@@ -1140,7 +1140,8 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
                 return ERROR_INVAL;
             }
         }
-
+        if (num_nvdimms)
+            machinearg = libxl__sprintf(gc, "%s,nvdimm", machinearg);
         flexarray_append(dm_args, machinearg);
         for (i = 0; b_info->extra_hvm && b_info->extra_hvm[i] != NULL; i++)
             flexarray_append(dm_args, b_info->extra_hvm[i]);
@@ -1154,6 +1155,16 @@ static int libxl__build_device_model_args_new(libxl__gc *gc,
     flexarray_append(dm_args, GCSPRINTF("%"PRId64, ram_size));
 
     if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
+        for (i = 0; i < num_nvdimms; i++) {
+            flexarray_append(dm_args, "-device");
+            flexarray_append(dm_args,
+                             libxl__sprintf(gc, "pc-nvdimm,file=%s,size=%"PRIu64,
+                                            guest_config->nvdimms[i].file,
+                                            guest_config->nvdimms[i].size_mb));
+        }
+    }
+
+    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
         if (b_info->u.hvm.hdtype == LIBXL_HDTYPE_AHCI)
             flexarray_append_pair(dm_args, "-device", "ahci,id=ahci0");
         for (i = 0; i < num_disks; i++) {
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 9658356..0a955a1 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -617,6 +617,14 @@ libxl_device_vtpm = Struct("device_vtpm", [
     ("uuid",             libxl_uuid),
 ])
 
+libxl_device_nvdimm = Struct("device_nvdimm", [
+    ("backend_domid",    libxl_domid),
+    ("backend_domname",  string),
+    ("devid",            libxl_devid),
+    ("file",             string),
+    ("size_mb",          uint64),
+])
+
 libxl_device_channel = Struct("device_channel", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -641,6 +649,7 @@ libxl_domain_config = Struct("domain_config", [
     ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
+    ("nvdimms", Array(libxl_device_nvdimm, "num_nvdimms")),
     # a channel manifests as a console with a name,
     # see docs/misc/channels.txt
     ("channels", Array(libxl_device_channel, "num_channels")),
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index f9933cb..2db7d45 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1255,6 +1255,49 @@ static void parse_vnuma_config(const XLU_Config *config,
     free(vcpu_parsed);
 }
 
+/*
+ * NVDIMM config is in the format:
+ *   nvdimm = [ 'file=path-to-pmem-dev,size=size-of-file-in-MByte',
+ *              'file=path-to-pmem-dev,size=size-of-file-in-MByte',
+ *              ... ]
+ */
+static void parse_nvdimm_config(XLU_Config *config,
+                                libxl_domain_config *d_config)
+{
+    XLU_ConfigList *nvdimms;
+    const char *buf;
+
+    if (!xlu_cfg_get_list (config, "nvdimm", &nvdimms, 0, 0)) {
+        while ((buf = xlu_cfg_get_listitem(nvdimms,
+                                           d_config->num_nvdimms)) != NULL) {
+            libxl_device_nvdimm *nvdimm =
+                ARRAY_EXTEND_INIT(d_config->nvdimms, d_config->num_nvdimms,
+                                  libxl_device_nvdimm_init);
+            char *nvdimm_cfg_str = strdup(buf);
+            char *p, *p2;
+
+            p = strtok(nvdimm_cfg_str, ",");
+            if (!p)
+                goto next_nvdimm;
+            do {
+                while (*p == ' ')
+                    p++;
+                if ((p2 = strchr(p, '=')) == NULL)
+                    break;
+                *p2 = '\0';
+                if (!strcmp(p, "file")) {
+                    nvdimm->file = strdup(p2 + 1);
+                } else if (!strcmp(p, "size")) {
+                    nvdimm->size_mb = parse_ulong(p2 + 1);
+                }
+            } while ((p = strtok(NULL, ",")) != NULL);
+
+        next_nvdimm:
+            free(nvdimm_cfg_str);
+        }
+    }
+}
+
 static void parse_config_data(const char *config_source,
                               const char *config_data,
                               int config_len,
@@ -2392,6 +2435,8 @@ skip_vfb:
         }
      }
 
+    parse_nvdimm_config(config, d_config);
+
     xlu_cfg_destroy(config);
 }
 
