Set the vm phys_bits through the phys and hostphysbits in XML
<phys bits='43' /> corresponds to "-cpu-phys-bits=42"
<hostphysbits /> corresponds to "host-phys-bits=on"

<cpu mode='host-passthrough' check='none'>
    <phys bits='43' />
    <hostphysbits />
</cpu>

---
 src/conf/cpu_conf.c     | 34 ++++++++++++++++++++++++++++++++++
 src/conf/cpu_conf.h     |  2 ++
 src/qemu/qemu_command.c |  6 ++++++
 3 files changed, 42 insertions(+)

diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
index 380a74691d..41f7c26f63 100644
--- a/src/conf/cpu_conf.c
+++ b/src/conf/cpu_conf.c
@@ -158,6 +158,8 @@ virCPUDefCopyModelFilter(virCPUDefPtr dst,
     dst->model = g_strdup(src->model);
     dst->vendor = g_strdup(src->vendor);
     dst->vendor_id = g_strdup(src->vendor_id);
+    dst->phys_bits = src->phys_bits;
+    dst->host_phys_bits = src->host_phys_bits;
     dst->microcodeVersion = src->microcodeVersion;
     dst->nfeatures_max = src->nfeatures;
     dst->nfeatures = 0;
@@ -540,6 +542,18 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
         return -1;
     }

+    if (virXPathNode("./phys[1]", ctxt)) {
+        unsigned long phys_bits;
+        if (virXPathULong("string(./phys[1]/@bits)",
+                ctxt, &phys_bits) >=0 ) {
+            def->phys_bits = (unsigned int) phys_bits;
+        }
+    }
+
+    if (virXPathNode("./hostphysbits[1]", ctxt)) {
+        def->host_phys_bits = true;
+    }
+
     if (virXPathNode("./topology[1]", ctxt)) {
         unsigned long ul;

@@ -811,6 +825,12 @@ virCPUDefFormatBuf(virBufferPtr buf,
         virBufferAddLit(buf, "/>\n");
     }

+    if (def->phys_bits > 0)
+        virBufferAsprintf(buf, "<phys bits='%u' />\n", def->phys_bits);
+
+    if (def->host_phys_bits)
+        virBufferAddLit(buf, "<hostphysbits />\n");
+
     if (def->sockets && def->dies && def->cores && def->threads) {
         virBufferAddLit(buf, "<topology");
         virBufferAsprintf(buf, " sockets='%u'", def->sockets);
@@ -1067,6 +1087,20 @@ virCPUDefIsEqual(virCPUDefPtr src,
         return false;
     }

+    if (src->phys_bits != dst->phys_bits) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target CPU phys_bits %d does not match source %d"),
+                       dst->phys_bits, src->phys_bits);
+        goto cleanup;
+    }
+
+    if (src->host_phys_bits != dst->host_phys_bits) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target CPU host_phys_bits %d does not match source %d"),
+                       dst->host_phys_bits, src->host_phys_bits);
+        goto cleanup;
+    }
+
     if (src->sockets != dst->sockets) {
         MISMATCH(_("Target CPU sockets %d does not match source %d"),
                  dst->sockets, src->sockets);
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
index 7ab198d370..f2a23ad41e 100644
--- a/src/conf/cpu_conf.h
+++ b/src/conf/cpu_conf.h
@@ -132,6 +132,8 @@ struct _virCPUDef {
     char *vendor_id;    /* vendor id returned by CPUID in the guest */
     int fallback;       /* enum virCPUFallback */
     char *vendor;
+    unsigned int phys_bits;
+    bool host_phys_bits;
     unsigned int microcodeVersion;
     unsigned int sockets;
     unsigned int dies;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1b4fa77867..d9bf3d5ce8 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6729,6 +6729,12 @@ qemuBuildCpuCommandLine(virCommandPtr cmd,
             virBufferAddLit(&buf, ",l3-cache=off");
     }

+    if (def->cpu && def->cpu->phys_bits > 0)
+        virBufferAsprintf(&buf, ",phys-bits=%u", def->cpu->phys_bits);
+
+    if (def->cpu && def->cpu->host_phys_bits)
+        virBufferAddLit(&buf, ",host-phys-bits=on");
+
     cpu = virBufferContentAndReset(&cpu_buf);
     cpu_flags = virBufferContentAndReset(&buf);

--
2.24.3