---
 include/libvirt/virterror.h          |   2 +-
 libvirt.spec.in                      |   7 +
 m4/virt-driver-jailhouse.m4          |  42 +++++
 meson.build                          |   4 +
 meson_options.txt                    |   1 +
 src/conf/domain_conf.c               |   1 +
 src/conf/domain_conf.h               |   1 +
 src/jailhouse/Makefile.inc.am        |  21 +++
 src/jailhouse/jailhouse_driver.c     | 219 +++++++++++++++++++++++++++
 src/jailhouse/jailhouse_driver.h     |  23 +++
 src/jailhouse/libvirtd_jailhouse.aug |  43 ++++++
 src/jailhouse/meson.build            |  48 ++++++
 src/libvirt.c                        |  10 ++
 src/meson.build                      |   1 +
 src/qemu/qemu_command.c              |   1 +
 src/util/virerror.c                  |   1 +
 16 files changed, 424 insertions(+), 1 deletion(-)
 create mode 100644 m4/virt-driver-jailhouse.m4
 create mode 100644 src/jailhouse/Makefile.inc.am
 create mode 100644 src/jailhouse/jailhouse_driver.c
 create mode 100644 src/jailhouse/jailhouse_driver.h
 create mode 100644 src/jailhouse/libvirtd_jailhouse.aug
 create mode 100644 src/jailhouse/meson.build

diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 0f1c32283d..97f2ac16d8 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -136,7 +136,7 @@ typedef enum {

     VIR_FROM_TPM = 70,          /* Error from TPM */
     VIR_FROM_BPF = 71,          /* Error from BPF code */
-
+    VIR_FROM_JAILHOUSE = 72,    /* Error from Jailhouse driver */
 # ifdef VIR_ENUM_SENTINELS
     VIR_ERR_DOMAIN_LAST
 # endif
diff --git a/libvirt.spec.in b/libvirt.spec.in
index bb74443484..074410eaa1 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -17,6 +17,7 @@
 %define with_lxc           0%{!?_without_lxc:1}
 %define with_libxl         0%{!?_without_libxl:1}
 %define with_vbox          0%{!?_without_vbox:1}
+%define with_jailhouse     0%{!?_without_jailhouse:1}

 %define with_qemu_tcg      %{with_qemu}

@@ -1045,6 +1046,12 @@ exit 1
     %define arg_vmware -Ddriver_vmware=disabled
 %endif

+%if %{with_jailhouse}
+    %define arg_jailhouse --with-jailhouse
+%else
+    %define arg_jailhouse --without-jailhouse
+%endif
+
 %if %{with_storage_rbd}
     %define arg_storage_rbd -Dstorage_rbd=enabled
 %else
diff --git a/m4/virt-driver-jailhouse.m4 b/m4/virt-driver-jailhouse.m4
new file mode 100644
index 0000000000..9008c6ce30
--- /dev/null
+++ b/m4/virt-driver-jailhouse.m4
@@ -0,0 +1,42 @@
+dnl The Jailhouse driver
+dnl
+dnl Copyright (C) 2016 Red Hat, Inc.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library.  If not, see
+dnl <http://www.gnu.org/licenses/>.
+dnl
+
+AC_DEFUN([LIBVIRT_DRIVER_ARG_JAILHOUSE], [
+  LIBVIRT_ARG_WITH_FEATURE([JAILHOUSE], [Jailhouse], [check])
+])
+
+AC_DEFUN([LIBVIRT_DRIVER_CHECK_JAILHOUSE], [
+  if test "$with_jailhouse" = "check"; then
+    with_jailhouse=$with_linux
+  fi
+
+  if test "$with_jailhouse" = "yes" && test "$with_linux" = "no"; then
+    AC_MSG_ERROR([The Jailhouse driver can be enabled on Linux only.])
+  fi
+
+  if test "$with_jailhouse" = "yes"; then
+    AC_DEFINE_UNQUOTED([WITH_JAILHOUSE], 1, [whether Jailhouse driver is enabled])
+  fi
+
+  AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"])
+])
+
+AC_DEFUN([LIBVIRT_DRIVER_RESULT_JAILHOUSE], [
+  LIBVIRT_RESULT([Jailhouse], [$with_jailhouse])
+])
diff --git a/meson.build b/meson.build
index dabd4196e6..d0f31f916b 100644
--- a/meson.build
+++ b/meson.build
@@ -1889,6 +1889,10 @@ elif get_option('secdriver_selinux').enabled()
   error('You must install the libselinux development package in order to compile libvirt.')
 endif

+if get_option('driver_jailhouse').enabled()
+  conf.set('WITH_JAILHOUSE', 1)
+endif
+
 if conf.has('WITH_QEMU') or conf.has('WITH_LXC') or conf.has('WITH_NETWORK')
   conf.set('WITH_BRIDGE', 1)
 endif
diff --git a/meson_options.txt b/meson_options.txt
index 79554c3186..c1f2b51427 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -68,6 +68,7 @@ option('driver_vbox', type: 'feature', value: 'enabled', description: 'VirtualBo
 option('vbox_xpcomc_dir', type: 'string', value: '', description: 'Location of directory containing VirtualBox XPCOMC library')
 option('driver_vmware', type: 'feature', value: 'enabled', description: 'VMware driver')
 option('driver_vz', type: 'feature', value: 'auto', description: 'Virtuozzo driver')
+option('driver_jailhouse', type: 'feature', value: 'auto', description: 'Jailhouse driver')

 option('secdriver_apparmor', type: 'feature', value: 'auto', description: 'use AppArmor security driver')
 option('apparmor_profiles', type: 'boolean', value: false, description: 'install apparmor profiles')
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5d3ae8bb28..cb946d5e87 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -130,6 +130,7 @@ VIR_ENUM_IMPL(virDomainVirt,
               "parallels",
               "bhyve",
               "vz",
+              "jailhouse",
 );

 VIR_ENUM_IMPL(virDomainOS,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8a0f26f5c0..cc51547bc2 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -139,6 +139,7 @@ typedef enum {
     VIR_DOMAIN_VIRT_PARALLELS,
     VIR_DOMAIN_VIRT_BHYVE,
     VIR_DOMAIN_VIRT_VZ,
+    VIR_DOMAIN_VIRT_JAILHOUSE,

     VIR_DOMAIN_VIRT_LAST
 } virDomainVirtType;
diff --git a/src/jailhouse/Makefile.inc.am b/src/jailhouse/Makefile.inc.am
new file mode 100644
index 0000000000..02822b2ea1
--- /dev/null
+++ b/src/jailhouse/Makefile.inc.am
@@ -0,0 +1,21 @@
+# vim: filetype=automake
+
+JAILHOUSE_DRIVER_SOURCES = \
+       jailhouse/jailhouse_driver.c \
+       jailhouse/jailhouse_driver.h \
+       $(NULL)
+
+
+DRIVER_SOURCE_FILES += $(addprefix $(srcdir)/,$(JAILHOUSE_DRIVER_SOURCES))
+
+EXTRA_DIST += $(JAILHOUSE_DRIVER_SOURCES)
+
+if WITH_JAILHOUSE
+noinst_LTLIBRARIES += libvirt_driver_jailhouse.la
+libvirt_la_BUILT_LIBADD += libvirt_driver_jailhouse.la
+libvirt_driver_jailhouse_la_CFLAGS = \
+       -I$(srcdir)/conf \
+       $(AM_CFLAGS) \
+       $(NULL)
+libvirt_driver_jailhouse_la_SOURCES = $(JAILHOUSE_DRIVER_SOURCES)
+endif WITH_JAILHOUSE
diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c
new file mode 100644
index 0000000000..0175ba771b
--- /dev/null
+++ b/src/jailhouse/jailhouse_driver.c
@@ -0,0 +1,219 @@
+/*
+ * jailhouse_driver.c: Implementation of driver for Jailhouse hypervisor
+ *
+ * Copyright (C) 2020 Prakhar Bansal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "jailhouse_driver.h"
+#include "virtypedparam.h"
+#include "virerror.h"
+#include "virstring.h"
+#include "viralloc.h"
+#include "domain_conf.h"
+#include "virfile.h"
+#include "datatypes.h"
+#include "vircommand.h"
+#include <string.h>
+
+#define UNUSED(x) (void)(x)
+
+static virDrvOpenStatus
+jailhouseConnectOpen(virConnectPtr conn,
+                     virConnectAuthPtr auth,
+                     virConfPtr conf,
+                     unsigned int flags)
+{
+    UNUSED(conn);
+    UNUSED(auth);
+    UNUSED(conf);
+    UNUSED(flags);
+    return 0;
+}
+
+static int
+jailhouseConnectClose(virConnectPtr conn)
+{
+    UNUSED(conn);
+    return 0;
+}
+
+static const char *
+jailhouseConnectGetType(virConnectPtr conn)
+{
+    UNUSED(conn);
+    return NULL;
+
+}
+
+static char *
+jailhouseConnectGetHostname(virConnectPtr conn)
+{
+    UNUSED(conn);
+    return NULL;
+}
+
+static int
+jailhouseNodeGetInfo(virConnectPtr conn,
+                     virNodeInfoPtr info)
+{
+    UNUSED(conn);
+    UNUSED(info);
+    return -1;
+}
+
+static int
+jailhouseConnectListDomains(virConnectPtr conn,
+                            int *ids,
+                            int maxids)
+{
+    UNUSED(conn);
+    UNUSED(ids);
+    UNUSED(maxids);
+    return -1;
+}
+
+static int
+jailhouseConnectNumOfDomains(virConnectPtr conn)
+{
+    UNUSED(conn);
+    return -1;
+}
+
+static int
+jailhouseConnectListAllDomains(virConnectPtr conn,
+                               virDomainPtr **domain,
+                               unsigned int flags)
+{
+    UNUSED(conn);
+    UNUSED(domain);
+    UNUSED(flags);
+    return -1;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByID(virConnectPtr conn,
+                          int id)
+{
+    UNUSED(conn);
+    UNUSED(id);
+    return NULL;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByName(virConnectPtr conn,
+                            const char *name)
+{
+    UNUSED(conn);
+    UNUSED(name);
+    return NULL;
+}
+
+static virDomainPtr
+jailhouseDomainLookupByUUID(virConnectPtr conn,
+                            const unsigned char *uuid)
+{
+    UNUSED(conn);
+    UNUSED(uuid);
+    return NULL;
+}
+
+static int
+jailhouseDomainCreate(virDomainPtr domain)
+{
+    UNUSED(domain);
+    return -1;
+
+}
+
+static int
+jailhouseDomainShutdown(virDomainPtr domain)
+{
+    UNUSED(domain);
+    return -1;
+}
+
+
+static int
+jailhouseDomainDestroy(virDomainPtr domain)
+{
+    UNUSED(domain);
+    return -1;
+}
+
+static int
+jailhouseDomainGetInfo(virDomainPtr domain,
+                       virDomainInfoPtr info)
+{
+    UNUSED(domain);
+    UNUSED(info);
+    return -1;
+}
+
+static int
+jailhouseDomainGetState(virDomainPtr domain,
+                        int *state,
+                        int *reason,
+                        unsigned int flags)
+{
+    UNUSED(domain);
+    UNUSED(state);
+    UNUSED(reason);
+    UNUSED(flags);
+    return -1;
+}
+
+static char *
+jailhouseDomainGetXMLDesc(virDomainPtr domain,
+                          unsigned int flags)
+{
+    UNUSED(domain);
+    UNUSED(flags);
+    return NULL;
+}
+
+static virHypervisorDriver jailhouseHypervisorDriver = {
+    .name = "JAILHOUSE",
+    .connectOpen = jailhouseConnectOpen, /* 6.3.0 */
+    .connectClose = jailhouseConnectClose, /* 6.3.0 */
+    .connectListDomains = jailhouseConnectListDomains, /* 6.3.0 */
+    .connectNumOfDomains = jailhouseConnectNumOfDomains, /* 6.3.0 */
+    .connectListAllDomains = jailhouseConnectListAllDomains, /* 6.3.0 */
+    .domainLookupByID = jailhouseDomainLookupByID, /* 6.3.0 */
+    .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 6.3.0 */
+    .domainLookupByName = jailhouseDomainLookupByName, /* 6.3.0 */
+    .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 6.3.0 */
+    .domainCreate = jailhouseDomainCreate, /* 6.3.0 */
+    .connectGetType = jailhouseConnectGetType, /* 6.3.0 */
+    .connectGetHostname = jailhouseConnectGetHostname, /* 6.3.0 */
+    .nodeGetInfo = jailhouseNodeGetInfo, /* 6.3.0 */
+    .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */
+    .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */
+    .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */
+    .domainGetState = jailhouseDomainGetState, /* 6.3.0 */
+};
+
+static virConnectDriver jailhouseConnectDriver = {
+    .hypervisorDriver = &jailhouseHypervisorDriver,
+};
+
+int
+jailhouseRegister(void)
+{
+    return virRegisterConnectDriver(&jailhouseConnectDriver, false);
+}
diff --git a/src/jailhouse/jailhouse_driver.h b/src/jailhouse/jailhouse_driver.h
new file mode 100644
index 0000000000..b0dbc8d033
--- /dev/null
+++ b/src/jailhouse/jailhouse_driver.h
@@ -0,0 +1,23 @@
+/*
+ * jailhouse_driver.h: Libvirt driver for Jailhouse hypervisor
+ *
+ * Copyright (C) 2020 Prakhar Bansal
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+int jailhouseRegister(void);
diff --git a/src/jailhouse/libvirtd_jailhouse.aug b/src/jailhouse/libvirtd_jailhouse.aug
new file mode 100644
index 0000000000..96a186eae2
--- /dev/null
+++ b/src/jailhouse/libvirtd_jailhouse.aug
@@ -0,0 +1,43 @@
+(* /etc/libvirt/jailhouse.conf *)
+
+module Libvirtd_jailhouse =
+   autoload xfm
+
+   let eol   = del /[ \t]*\n/ "\n"
+   let value_sep   = del /[ \t]*=[ \t]*/  " = "
+   let indent = del /[ \t]*/ ""
+
+   let array_sep  = del /,[ \t\n]*/ ", "
+   let array_start = del /\[[ \t\n]*/ "[ "
+   let array_end = del /\]/ "]"
+
+   let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
+   let bool_val = store /0|1/
+   let int_val = store /[0-9]+/
+   let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
+   let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
+
+   let str_entry       (kw:string) = [ key kw . value_sep . str_val ]
+   let bool_entry      (kw:string) = [ key kw . value_sep . bool_val ]
+   let int_entry       (kw:string) = [ key kw . value_sep . int_val ]
+   let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
+
+   (* Config entry grouped by function - same order as example config *)
+   let log_entry = bool_entry "log_with_libvirtd"
+                 | str_entry "security_driver"
+                 | bool_entry "security_default_confined"
+                 | bool_entry "security_require_confined"
+
+   (* Each entry in the config is one of the following three ... *)
+   let entry = log_entry
+   let comment = [ label "#comment" . del /#[ \t]*/ "# " .  store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
+   let empty = [ label "#empty" . eol ]
+
+   let record = indent . entry . eol
+
+   let lns = ( record | comment | empty ) *
+
+   let filter = incl "/etc/libvirt/jailhouse.conf"
+              . Util.stdexcl
+
+   let xfm = transform lns filter
diff --git a/src/jailhouse/meson.build b/src/jailhouse/meson.build
new file mode 100644
index 0000000000..45ceeecca3
--- /dev/null
+++ b/src/jailhouse/meson.build
@@ -0,0 +1,48 @@
+jailhouse_sources = files(
+  'jailhouse_driver.c',
+)
+
+driver_source_files += jailhouse_sources
+stateful_driver_source_files += jailhouse_sources
+
+if conf.has('WITH_JAILHOUSE')
+  jailhouse_driver_impl = static_library(
+    'virt_driver_jailhouse_impl',
+    [
+      jailhouse_sources,
+    ],
+    dependencies: [
+      access_dep,
+      src_dep,
+    ],
+    include_directories: [
+      conf_inc_dir,
+      hypervisor_inc_dir,
+    ],
+  )
+
+  virt_modules += {
+    'name': 'virt_driver_jailhouse',
+    'link_whole': [
+      jailhouse_driver_impl,
+    ],
+    'link_args': [
+      libvirt_no_undefined,
+    ],
+  }
+
+  virt_daemons += {
+    'name': 'virtjailhoused',
+    'c_args': [
+      '-DDAEMON_NAME="virtjailhoused"',
+      '-DMODULE_NAME="jailhouse"'
+    ],
+  }
+
+  virt_conf_files += files('jailhouse.conf')
+  virt_aug_files += files('libvirtd_jailhouse.aug')
+
+  virt_daemon_confs += {
+    'name': 'virtjailhoused',
+  }
+endif
diff --git a/src/libvirt.c b/src/libvirt.c
index b2d0ba3d23..59b75c6f7b 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -75,6 +75,9 @@
 #ifdef WITH_BHYVE
 # include "bhyve/bhyve_driver.h"
 #endif
+#ifdef WITH_JAILHOUSE
+# include "jailhouse/jailhouse_driver.h"
+#endif
 #include "access/viraccessmanager.h"

 #define VIR_FROM_THIS VIR_FROM_NONE
@@ -271,6 +274,10 @@ virGlobalInit(void)
     if (hypervRegister() == -1)
         goto error;
 #endif
+#ifdef WITH_JAILHOUSE
+    if (jailhouseRegister() == -1)
+        goto error;
+#endif
 #ifdef WITH_REMOTE
     if (remoteRegister() == -1)
         goto error;
@@ -1003,6 +1010,9 @@ virConnectOpenInternal(const char *name,
 #endif
 #ifndef WITH_VZ
              STRCASEEQ(ret->uri->scheme, "parallels") ||
+#endif
+#ifndef WITH_JAILHOUSE
+             STRCASEEQ(ret->uri->scheme, "jailhouse") ||
 #endif
              false)) {
             virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_CONFIG_UNSUPPORTED,
diff --git a/src/meson.build b/src/meson.build
index 5d8deaf548..7188dc623e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -268,6 +268,7 @@ subdir('security')
 subdir('storage')

 subdir('bhyve')
+subdir('jailhouse')
 subdir('esx')
 subdir('hyperv')
 subdir('libxl')
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6798febf8d..f750270230 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6819,6 +6819,7 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
     case VIR_DOMAIN_VIRT_PHYP:
     case VIR_DOMAIN_VIRT_PARALLELS:
     case VIR_DOMAIN_VIRT_BHYVE:
+    case VIR_DOMAIN_VIRT_JAILHOUSE:
     case VIR_DOMAIN_VIRT_VZ:
     case VIR_DOMAIN_VIRT_NONE:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
diff --git a/src/util/virerror.c b/src/util/virerror.c
index 507a29f50f..8caf24a5f2 100644
--- a/src/util/virerror.c
+++ b/src/util/virerror.c
@@ -134,6 +134,7 @@ VIR_ENUM_IMPL(virErrorDomain,
               "Thread jobs",
               "Admin Interface",
               "Log Manager",
+              "Jailhouse Driver",
               "Xen XL Config",

               "Perf", /* 65 */
--
2.17.1