[libvirt PATCH 0/9] [GSoC]: Libvirt driver for Jailhouse

I'm sending this series on behalf of Prakhar Bansal who has been unable to sucessfully send the whole series. GMail is blocking sending of certain patches for unknown reasons. https://www.redhat.com/archives/libvir-list/2020-September/msg00309.html It is also available at https://github.com/pbansal2/libvirt/tree/jailhouse_driver Prakhar Bansal (9): Jailhouse driver: first commit with skeleton code Jailhouse driver: Implementation of ConnectOpen Jailhouse driver: Implementation of ConnectGetType Jailhouse driver: Implementation of DomainCreate* callbacks Jailhouse driver: Implementation of DomainInfo/State/List Jailhouse driver: Implementation of DomainLookup* callbacks Jailhouse driver: Implementation of DomainShutdown/Destroy callbacks Jailhouse driver: Fixes for creation of cells, fetching cell info, disabling jailhouse hypervisor Jailhouse driver: Add events to events queue in DomainCreate/Shutdown/Destroy include/libvirt/virterror.h | 1 + libvirt.spec.in | 7 + m4/virt-driver-jailhouse.m4 | 42 ++ meson.build | 4 + meson_options.txt | 1 + po/POTFILES.in | 2 + src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/jailhouse/Makefile.inc.am | 47 ++ src/jailhouse/jailhouse.conf | 10 + src/jailhouse/jailhouse_api.c | 458 +++++++++++++++ src/jailhouse/jailhouse_api.h | 103 ++++ src/jailhouse/jailhouse_driver.c | 837 +++++++++++++++++++++++++++ src/jailhouse/jailhouse_driver.h | 82 +++ src/jailhouse/libvirtd_jailhouse.aug | 43 ++ src/jailhouse/meson.build | 49 ++ src/meson.build | 1 + src/qemu/qemu_command.c | 1 + src/remote/remote_daemon.c | 4 + src/remote/remote_daemon_dispatch.c | 3 +- src/util/virerror.c | 1 + 21 files changed, 1697 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.conf create mode 100644 src/jailhouse/jailhouse_api.c create mode 100644 src/jailhouse/jailhouse_api.h 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 -- 2.26.2

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- 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 62b401bd08..ca65063e79 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} @@ -1043,6 +1044,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 195d7cd784..f4f9ca4119 100644 --- a/meson.build +++ b/meson.build @@ -1895,6 +1895,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 7838630c1e..4f237be5dc 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -69,6 +69,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 4d296f7bcb..b764a5962d 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 cf76f340ee..46a8a1708c 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 0748eb2352..8a78cbcf3a 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; @@ -1045,6 +1052,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 897b5ecbca..9e2b97900e 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 0ba348e911..78976c2153 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6843,6 +6843,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 80a7cfe0ed..560e0a1f0f 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.26.2

On Thu, Sep 17, 2020 at 04:23:51PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
--- 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 62b401bd08..ca65063e79 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}
The RPM spec targets Fedora and RHEL distros and AFAIK, neither of these ship jailhouse. So we should fix it to have jailhouse disabled in the RPM builds. ie just set -Ddriver_jailhouse=disabled in %meson
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)
G_GNUC_UNUSED is the way we mark parameters as unused, but....
+ +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; +}
Just remove all of these stubs except for Open/Close. The upper level driver entry points report errors correctly when a callback is simply not registered.
+ +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/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
This should be added in the patch that adds the corresponding config file
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')
The jailhouse.conf file doesn't exist in this patch, so this should be added later in the series. Essentially each patch is expected to successfully build and install, so you can't add build rules until the file is added.
+ virt_aug_files += files('libvirtd_jailhouse.aug')
This should be moved too.
+ + virt_daemon_confs += { + 'name': 'virtjailhoused', + } +endif
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Tue, Sep 22, 2020 at 07:08:00PM +0100, Daniel P. Berrangé wrote:
On Thu, Sep 17, 2020 at 04:23:51PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
--- 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
In addition all of the autotools related files should be removed as well because we use only meson: m4/virt-driver-jailhouse.m4 src/jailhouse/Makefile.inc.am Pavel

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- include/libvirt/virterror.h | 1 + po/POTFILES.in | 2 + src/jailhouse/Makefile.inc.am | 34 ++- src/jailhouse/jailhouse.conf | 10 + src/jailhouse/jailhouse_api.c | 372 ++++++++++++++++++++++++++++ src/jailhouse/jailhouse_api.h | 74 ++++++ src/jailhouse/jailhouse_driver.c | 302 +++++++++++++++++----- src/jailhouse/jailhouse_driver.h | 51 ++++ src/jailhouse/meson.build | 1 + src/libvirt.c | 10 - src/remote/remote_daemon.c | 4 + src/remote/remote_daemon_dispatch.c | 3 +- 12 files changed, 783 insertions(+), 81 deletions(-) create mode 100644 src/jailhouse/jailhouse.conf create mode 100644 src/jailhouse/jailhouse_api.c create mode 100644 src/jailhouse/jailhouse_api.h diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 97f2ac16d8..9f1bca2684 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -137,6 +137,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/po/POTFILES.in b/po/POTFILES.in index 471af30b89..317db58a21 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -85,6 +85,8 @@ @SRCDIR@src/interface/interface_backend_netcf.c @SRCDIR@src/interface/interface_backend_udev.c @SRCDIR@src/internal.h +@SRCDIR@src/jailhouse/jailhouse_api.c +@SRCDIR@src/jailhouse/jailhouse_driver.c @SRCDIR@src/libvirt-domain-checkpoint.c @SRCDIR@src/libvirt-domain-snapshot.c @SRCDIR@src/libvirt-domain.c diff --git a/src/jailhouse/Makefile.inc.am b/src/jailhouse/Makefile.inc.am index 02822b2ea1..324c3b1b16 100644 --- a/src/jailhouse/Makefile.inc.am +++ b/src/jailhouse/Makefile.inc.am @@ -1,8 +1,11 @@ # vim: filetype=automake + JAILHOUSE_DRIVER_SOURCES = \ jailhouse/jailhouse_driver.c \ jailhouse/jailhouse_driver.h \ + jailhouse/jailhouse_api.c \ + jailhouse/jailhouse_api.h \ $(NULL) @@ -11,11 +14,34 @@ 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 = \ + +noinst_LTLIBRARIES += libvirt_driver_jailhouse_impl.la +libvirt_driver_jailhouse_la_SOURCES = +libvirt_driver_jailhouse_la_LIBADD = \ + libvirt_driver_jailhouse_impl.la \ + libvirt.la \ + $(GLIB_LIBS) \ + $(NULL) +mod_LTLIBRARIES += libvirt_driver_jailhouse.la +libvirt_driver_jailhouse_la_LDFLAGS = $(AM_LDFLAGS_MOD_NOUNDEF) + +libvirt_driver_jailhouse_impl_la_CFLAGS = \ -I$(srcdir)/conf \ $(AM_CFLAGS) \ $(NULL) -libvirt_driver_jailhouse_la_SOURCES = $(JAILHOUSE_DRIVER_SOURCES) +libvirt_driver_jailhouse_impl_la_SOURCES = \ + $(JAILHOUSE_DRIVER_SOURCES) + +sbin_PROGRAMS += virtjailhoused + +virtjailhoused_SOURCES = $(REMOTE_DAEMON_SOURCES) +nodist_virtjailhoused_SOURCES = $(REMOTE_DAEMON_GENERATED) +virtjailhoused_CFLAGS = \ + $(REMOTE_DAEMON_CFLAGS) \ + -DDAEMON_NAME="\"virtjailhoused\"" \ + -DMODULE_NAME="\"jailhouse\"" \ + $(NULL) +virtjailhoused_LDFLAGS = $(REMOTE_DAEMON_LD_FLAGS) +virtjailhoused_LDADD = $(REMOTE_DAEMON_LD_ADD) + endif WITH_JAILHOUSE diff --git a/src/jailhouse/jailhouse.conf b/src/jailhouse/jailhouse.conf new file mode 100644 index 0000000000..587068b9d0 --- /dev/null +++ b/src/jailhouse/jailhouse.conf @@ -0,0 +1,10 @@ +# Configuration for the Jailhouse driver. + +# Jailhouse system configuration file to enable the Jailhouse hypervisor on the +# system. This is a required configuration parameter for the driver. +#system_config = "/etc/libvirt/jailhouse/qemu-x86.cell" + +# Specify a directory which contains all the non-root cell configurations which +# should be created by the driver at the startup. This is optional. Default +# value of "/etc/libvirt/jailhouse/cells/" will be used if left empty. +#non_root_cells_dir = "/etc/libvirt/jailhouse/cells/" diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c new file mode 100644 index 0000000000..cda00b50e7 --- /dev/null +++ b/src/jailhouse/jailhouse_api.c @@ -0,0 +1,372 @@ +/* + * jailhouse_api.c: Jailhouse API + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <linux/types.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" +#include "virstring.h" +#include "jailhouse_api.h" + +#define JAILHOUSE_DEVICE "/dev/jailhouse" +#define JAILHOUSE_CELLS "/sys/devices/jailhouse/cells" +#define MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE 1024*1024 +#define MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE 1024 + + +#define JAILHOUSE_ENABLE _IOW(0, 0, void *) +#define JAILHOUSE_DISABLE _IO(0, 1) +#define JAILHOUSE_CELL_CREATE _IOW(0, 2, virJailhouseCellCreate) +#define JAILHOUSE_CELL_DESTROY _IOW(0, 5, virJailhouseCellId) + +#define VIR_FROM_THIS VIR_FROM_JAILHOUSE + +VIR_LOG_INIT("jailhouse.jailhouse_api"); + +#define JAILHOUSE_CELL_FILE_EXTENSION ".cell" + +/* Forward declarations */ + +/* Open the Jailhouse device for ioctl APIs */ +int openDev(void); + +/* Reads cell's property given by 'entry' using sysfs API */ +char *readSysfsCellString(const unsigned int id, const char *entry); + +int cell_match(const struct dirent *dirent); + +int createCell(const char *conf_file); + +int destroyCell(virJailhouseCellId cell_id); + +int getCellInfo(const unsigned int id, + virJailhouseCellInfoPtr * cell_info); + +int +jailhouseEnable(const char *sys_conf_file_path) +{ + int err = -1, len; + g_autofree char *buffer = NULL; + VIR_AUTOCLOSE fd = -1; + + if (!virFileExists(sys_conf_file_path)) + return 0; + + len = virFileReadAll(sys_conf_file_path, MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE, &buffer); + if (len < 0 || !buffer) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Failed to read the system configuration file")); + return -1; + } + + fd = openDev(); + + err = ioctl(fd, JAILHOUSE_ENABLE, buffer); + if (err) { + virReportSystemError(errno, "%s", _("Failed to enable jailhouse")); + return err; + } + + VIR_DEBUG("Jailhouse hypervisor is enabled"); + + return 1; +} + +int +jailhouseDisable(void) +{ + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev(); + + err = ioctl(fd, JAILHOUSE_DISABLE); + if (err) + virReportSystemError(errno, + "%s", + _("Failed to disable jailhouse: %s")); + + VIR_DEBUG("Jailhouse hypervisor is disabled"); + + return err; +} + +int +cell_match(const struct dirent *dirent) +{ + char *ext = strrchr(dirent->d_name, '.'); + + return dirent->d_name[0] != '.' + && (STREQ(ext, JAILHOUSE_CELL_FILE_EXTENSION) == 0); +} + +int +createJailhouseCells(const char *dir_path) +{ + + struct dirent **namelist; + int num_entries, ret = -1; + size_t i; + + if (strlen(dir_path) == 0) + return ret; + + num_entries = scandir(dir_path, &namelist, cell_match, alphasort); + if (num_entries == -1) { + if (errno == ENOENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No cells found in %s, scandir failed."), + dir_path); + goto fail; + } + + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Error reading cell configurations in %s."), + dir_path); + goto fail; + } + + + for (i = 0; i < num_entries; i++) { + g_autofree char *file_path = g_strdup_printf("%s/%s", dir_path, namelist[i]->d_name); + + if (createCell(file_path) != 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cell creation failed with conf found in %s."), + namelist[i]->d_name); + goto fail; + } + } + + ret = 0; + + fail: + VIR_FREE(namelist); + return ret; +} + +int +openDev(void) +{ + int fd; + + fd = open(JAILHOUSE_DEVICE, O_RDWR); + if (fd < 0) { + virReportSystemError(errno, + _("Error opening jailhouse device %s"), + JAILHOUSE_DEVICE); + } + return fd; +} + +int +createCell(const char *conf_file) +{ + virJailhouseCellCreate cell_create; + int err = -1, len; + g_autofree char *buffer = NULL; + VIR_AUTOCLOSE fd = -1; + + if (strlen(conf_file) == 0) + return err; + + len = virFileReadAll(conf_file, MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE, &buffer); + if (len < 0 || !buffer) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Failed to read the system configuration file")); + return err; + } + + cell_create.config_address = (unsigned long) buffer; + cell_create.config_size = len; + + fd = openDev(); + + err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create); + if (err) + virReportSystemError(errno, + "%s", + _("Cell creation failed: %s")); + + return err; +} + +void +cellInfoFree(virJailhouseCellInfoPtr cell_info) +{ + VIR_FREE(cell_info->state); + VIR_FREE(cell_info->cpus_assigned_list); + VIR_FREE(cell_info->cpus_failed_list); + VIR_FREE(cell_info); +} + +char * +readSysfsCellString(const unsigned int id, const char *entry) +{ + g_autofree char *buffer = NULL; + g_autofree char *file_path = NULL; + int len = -1; + + file_path = g_strdup_printf(JAILHOUSE_CELLS "%u/%s", id, entry); + + len = virFileReadAll(file_path, 1024, &buffer); + if (len < 0 || !buffer) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error reading cell(%u) %s from %s failed"), + id, entry, file_path); + return NULL; + } + + virTrimSpaces(buffer, NULL); + + return buffer; +} + +int +getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info_ptr) +{ + char *tmp; + + if (VIR_ALLOC(*cell_info_ptr) < 0) + return -1; + + virJailhouseCellInfoPtr cell_info = *cell_info_ptr; + + /* set cell id */ + cell_info->id.id = id; + + /* get cell name */ + tmp = readSysfsCellString(id, "name"); + if (virStrncpy(cell_info->id.name, tmp, JAILHOUSE_CELL_ID_NAMELEN, JAILHOUSE_CELL_ID_NAMELEN) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cell ID %s too long to be copied to the cell info"), + tmp); + return -1; + } + + cell_info->id.name[JAILHOUSE_CELL_ID_NAMELEN] = 0; + VIR_FREE(tmp); + + /* get cell state */ + cell_info->state = readSysfsCellString(id, "state"); + + /* get assigned cpu list */ + cell_info->cpus_assigned_list = + readSysfsCellString(id, "cpus_assigned_list"); + + /* get failed cpu list */ + cell_info->cpus_failed_list = + readSysfsCellString(id, "cpus_failed_list"); + + return 0; +} + +virJailhouseCellInfoPtr * +getJailhouseCellsInfo(void) +{ + struct dirent **namelist; + virJailhouseCellInfoPtr *cell_info_list; + unsigned int id; + int num_entries; + size_t i; + + num_entries = + scandir(JAILHOUSE_CELLS, &namelist, cell_match, alphasort); + if (num_entries == -1) { + if (errno == ENOENT) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("No cells found in %s, scandir failed."), + JAILHOUSE_CELLS); + return NULL; + } + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error reading cell IDs in %s."), + JAILHOUSE_CELLS); + return NULL; + } + + /* Allocate memory for 1 more than num_entries and make the last entry NULL. */ + if (VIR_ALLOC_N(cell_info_list, num_entries + 1) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cells info list")); + } + + /* Set the last entry to NULL. */ + cell_info_list[num_entries] = NULL; + + for (i = 0; i < num_entries; i++) { + if (virStrToLong_ui(namelist[i]->d_name, NULL, 10, &id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cell ID %s could not be converted to a long"), + namelist[i]->d_name); + continue; + } + + /* get the cell's information(name, state etc.) using sysfs */ + getCellInfo(id, &cell_info_list[i]); + VIR_FREE(namelist[i]); + } + + VIR_FREE(namelist); + return cell_info_list; +} + +int +destroyCell(virJailhouseCellId cell_id) +{ + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev(); + + err = ioctl(fd, JAILHOUSE_CELL_DESTROY, &cell_id); + if (err) + virReportSystemError(errno, + _("Destroying cell %d failed"), + cell_id.id); + + return err; +} + +int +destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list G_GNUC_UNUSED) +{ + + /* Iterate over all cells in cell_info_list and destroy each cell */ + // TODO: Not implemented yet. + + return 0; +} diff --git a/src/jailhouse/jailhouse_api.h b/src/jailhouse/jailhouse_api.h new file mode 100644 index 0000000000..8362cb3d0f --- /dev/null +++ b/src/jailhouse/jailhouse_api.h @@ -0,0 +1,74 @@ +/* + * jailhouse_api.h: Jailhouse hypervisor API implementation + * + * 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 + +#define JAILHOUSE_CELL_ID_NAMELEN 31 + +typedef struct _virJailhouseCellId virJailhouseCellId; + +struct _virJailhouseCellId { + __s32 id; + __u32 padding; + char name[JAILHOUSE_CELL_ID_NAMELEN + 1]; +}; + +typedef struct _virJailhouseCellInfo virJailhouseCellInfo; +typedef virJailhouseCellInfo *virJailhouseCellInfoPtr; + +struct _virJailhouseCellInfo { + struct _virJailhouseCellId id; + char *state; + char *cpus_assigned_list; + char *cpus_failed_list; +}; + +typedef struct _virJailhouseCellCreate virJailhouseCellCreate; + +struct _virJailhouseCellCreate { + __u64 config_address; + __u32 config_size; + __u32 padding; +}; + +// Enables the Jailhouse hypervisor by reading the hypervisor system +// configuration from the given file and calls the ioctl API to +// enable the hypervisor. +int jailhouseEnable(const char *sys_conf_file_path); + +// Disables the Jailhouse hypervisor. +int jailhouseDisable(void); + +/* Cell API methods */ + +// Creates Jailhouse cells using the cells configurations +// provided in the dir_name. +int createJailhouseCells(const char *dir_path); + +// Destroys Jailhouse cells using the cell IDs provided in +// the cell_info_list. +int destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list); + +// Returns cell's information in a null-terminated array of +// virJailhouseCellInfoPtr for all the Jailhouse cells. +virJailhouseCellInfoPtr *getJailhouseCellsInfo(void); + +// Free the cell info object. +void cellInfoFree(virJailhouseCellInfoPtr cell_info); diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 0175ba771b..ac9da4c85d 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -16,43 +16,228 @@ * 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 <string.h> +#include "configmake.h" +#include "datatypes.h" +#include "domain_conf.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 "virlog.h" #include "vircommand.h" -#include <string.h> +#include "virpidfile.h" -#define UNUSED(x) (void)(x) +#define VIR_FROM_THIS VIR_FROM_JAILHOUSE + +VIR_LOG_INIT("jailhouse.jailhouse_driver"); + +static virClassPtr virJailhouseDriverConfigClass; +static void virJailhouseDriverConfigDispose(void *obj); + +static virJailhouseDriverPtr jailhouse_driver; + +static int virJailhouseConfigOnceInit(void) +{ + if (!VIR_CLASS_NEW(virJailhouseDriverConfig, virClassForObject())) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virJailhouseConfig); + + +static virJailhouseDriverConfigPtr +virJailhouseDriverConfigNew(void) +{ + virJailhouseDriverConfigPtr cfg; + + // TODO: Check if the following has to be uncommented. + if (virJailhouseConfigInitialize() < 0) + return NULL; + + if (!(cfg = virObjectNew(virJailhouseDriverConfigClass))) + return NULL; + + cfg->stateDir = g_strdup(JAILHOUSE_STATE_DIR); + + cfg->sys_config_file_path = g_strdup(DATADIR "/jailhouse/system.cell"); + + cfg->cell_config_dir = g_strdup(DATADIR "/jailhouse/cells"); + + return cfg; +} + +static void virJailhouseDriverConfigDispose(void *obj) +{ + + virJailhouseDriverConfigPtr cfg = obj; + + VIR_FREE(cfg->stateDir); + VIR_FREE(cfg->sys_config_file_path); + VIR_FREE(cfg->cell_config_dir); +} + +static int +jailhouseLoadConf(virJailhouseDriverConfigPtr config) +{ + g_autoptr(virConf) conf = NULL; + + if (!virFileExists(JAILHOUSE_CONFIG_FILE)) + return 0; + + if (!(conf = virConfReadFile(JAILHOUSE_CONFIG_FILE, 0))) + return -1; + + if (virConfGetValueString(conf, "system_config", + &config->sys_config_file_path) < 0) + return -1; + + if (virConfGetValueString(conf, "non_root_cells_dir", + &config->cell_config_dir) < 0) + return -1; + + return 1; +} + +static int +jailhouseCreateAndLoadCells(virJailhouseDriverPtr driver) +{ + if (!driver->config || + !driver->config->cell_config_dir || + strlen(driver->config->cell_config_dir) == 0) + return -1; + + // Create all cells in the hypervisor. + if (createJailhouseCells(driver->config->cell_config_dir) < 0) + return -1; + + // Get all cells created above. + driver->cell_info_list = getJailhouseCellsInfo(); + + return 0; +} + +static void +jailhouseFreeDriver(virJailhouseDriverPtr driver) +{ + if (!driver) + return; + + virMutexDestroy(&driver->lock); + virObjectUnref(driver->config); + VIR_FREE(driver); +} static virDrvOpenStatus jailhouseConnectOpen(virConnectPtr conn, - virConnectAuthPtr auth, - virConfPtr conf, - unsigned int flags) + virConnectAuthPtr auth G_GNUC_UNUSED, + virConfPtr conf G_GNUC_UNUSED, unsigned int flags) { - UNUSED(conn); - UNUSED(auth); - UNUSED(conf); - UNUSED(flags); - return 0; + uid_t uid = geteuid(); + + virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); + + if (!virConnectValidateURIPath(conn->uri->path, "jailhouse", uid == 0)) + return VIR_DRV_OPEN_ERROR; + + if (!jailhouse_driver) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Jailhouse driver state is not initialized.")); + return VIR_DRV_OPEN_ERROR; + } + + conn->privateData = jailhouse_driver; + + return VIR_DRV_OPEN_SUCCESS; } +#define UNUSED(x) (void)(x) + static int jailhouseConnectClose(virConnectPtr conn) { - UNUSED(conn); + conn->privateData = NULL; + + return 0; +} + +static int +jailhouseStateCleanup(void) +{ + if (!jailhouse_driver) + return -1; + + if (jailhouse_driver->lockFD != -1) + virPidFileRelease(jailhouse_driver->config->stateDir, + "driver", jailhouse_driver->lockFD); + + virMutexDestroy(&jailhouse_driver->lock); + + jailhouseFreeDriver(jailhouse_driver); return 0; } +static int +jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, + const char *root G_GNUC_UNUSED, + virStateInhibitCallback callback G_GNUC_UNUSED, + void *opaque G_GNUC_UNUSED) +{ + virJailhouseDriverConfigPtr cfg = NULL; + int rc; + + jailhouse_driver = g_new0(virJailhouseDriver, 1); + jailhouse_driver->lockFD = -1; + + if (virMutexInit(&jailhouse_driver->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize mutex")); + VIR_FREE(jailhouse_driver); + return VIR_DRV_STATE_INIT_ERROR; + } + + if (!(cfg = virJailhouseDriverConfigNew())) + goto error; + + jailhouse_driver->config = cfg; + + if (jailhouseLoadConf(cfg) < 0) + goto error; + + if (virFileMakePath(cfg->stateDir) < 0) { + virReportSystemError(errno, _("Failed to create state dir %s"), + cfg->stateDir); + goto error; + } + + if ((jailhouse_driver->lockFD = virPidFileAcquire(cfg->stateDir, + "driver", false, getpid())) < 0) + goto error; + + if ((rc = jailhouseEnable(cfg->sys_config_file_path)) < 0) + goto error; + else if (rc == 0) + return VIR_DRV_STATE_INIT_SKIPPED; + + if (jailhouseCreateAndLoadCells(jailhouse_driver) < 0) + goto error; + + return VIR_DRV_STATE_INIT_COMPLETE; + + error: + jailhouseStateCleanup(); + return VIR_DRV_STATE_INIT_ERROR; + +} static const char * jailhouseConnectGetType(virConnectPtr conn) { @@ -69,36 +254,16 @@ jailhouseConnectGetHostname(virConnectPtr conn) } static int -jailhouseNodeGetInfo(virConnectPtr conn, - virNodeInfoPtr info) +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) + virDomainPtr ** domain, unsigned int flags) { UNUSED(conn); UNUSED(domain); @@ -107,8 +272,7 @@ jailhouseConnectListAllDomains(virConnectPtr conn, } static virDomainPtr -jailhouseDomainLookupByID(virConnectPtr conn, - int id) +jailhouseDomainLookupByID(virConnectPtr conn, int id) { UNUSED(conn); UNUSED(id); @@ -116,8 +280,7 @@ jailhouseDomainLookupByID(virConnectPtr conn, } static virDomainPtr -jailhouseDomainLookupByName(virConnectPtr conn, - const char *name) +jailhouseDomainLookupByName(virConnectPtr conn, const char *name) { UNUSED(conn); UNUSED(name); @@ -125,8 +288,7 @@ jailhouseDomainLookupByName(virConnectPtr conn, } static virDomainPtr -jailhouseDomainLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) +jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { UNUSED(conn); UNUSED(uuid); @@ -157,8 +319,7 @@ jailhouseDomainDestroy(virDomainPtr domain) } static int -jailhouseDomainGetInfo(virDomainPtr domain, - virDomainInfoPtr info) +jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { UNUSED(domain); UNUSED(info); @@ -167,9 +328,7 @@ jailhouseDomainGetInfo(virDomainPtr domain, static int jailhouseDomainGetState(virDomainPtr domain, - int *state, - int *reason, - unsigned int flags) + int *state, int *reason, unsigned int flags) { UNUSED(domain); UNUSED(state); @@ -179,8 +338,7 @@ jailhouseDomainGetState(virDomainPtr domain, } static char * -jailhouseDomainGetXMLDesc(virDomainPtr domain, - unsigned int flags) +jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) { UNUSED(domain); UNUSED(flags); @@ -189,31 +347,43 @@ jailhouseDomainGetXMLDesc(virDomainPtr domain, 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 */ + .connectOpen = jailhouseConnectOpen, /* 6.3.0 */ + .connectClose = jailhouseConnectClose, /* 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 = { + .localOnly = true, + .uriSchemes = (const char *[]){ "jailhouse", NULL }, .hypervisorDriver = &jailhouseHypervisorDriver, }; + +static virStateDriver jailhouseStateDriver = { + .name = "JAILHOUSE", + .stateInitialize = jailhouseStateInitialize, + .stateCleanup = jailhouseStateCleanup, +}; + int jailhouseRegister(void) { - return virRegisterConnectDriver(&jailhouseConnectDriver, false); + if (virRegisterConnectDriver(&jailhouseConnectDriver, false) < 0) + return -1; + if (virRegisterStateDriver(&jailhouseStateDriver) < 0) + return -1; + return 0; } diff --git a/src/jailhouse/jailhouse_driver.h b/src/jailhouse/jailhouse_driver.h index b0dbc8d033..8a0e111676 100644 --- a/src/jailhouse/jailhouse_driver.h +++ b/src/jailhouse/jailhouse_driver.h @@ -20,4 +20,55 @@ #pragma once +#include <linux/types.h> + +#include "jailhouse_api.h" + int jailhouseRegister(void); + +#define JAILHOUSE_CONFIG_FILE SYSCONFDIR "/libvirt/jailhouse/jailhouse.conf" +#define JAILHOUSE_STATE_DIR RUNSTATEDIR "/libvirt/jailhouse" + +#define JAILHOUSE_DEV "/dev/jailhouse" + +#define JAILHOUSE_SYSFS_DEV "/sys/devices/jailhouse/" + +typedef struct _virJailhouseDriver virJailhouseDriver; +typedef virJailhouseDriver *virJailhouseDriverPtr; + +typedef struct _virJailhouseDriverConfig virJailhouseDriverConfig; +typedef virJailhouseDriverConfig *virJailhouseDriverConfigPtr; + +struct _virJailhouseDriverConfig { + virObject parent; + + char *stateDir; + + // File path of the jailhouse system configuration + // for jailhouse enable/disable. + char *sys_config_file_path; + + // Config directory where all jailhouse cell configurations + // are stored. + char *cell_config_dir; +}; + +struct _virJailhouseDriver { + virMutex lock; + + // Jailhouse configuration read from the jailhouse.conf + virJailhouseDriverConfigPtr config; + + /* pid file FD, ensures two copies of the driver can't use the same root */ + int lockFD; + + // All the cells created during connect open on the hypervisor. + virJailhouseCellInfoPtr *cell_info_list; +}; + +struct _jailhouseCell { + __s32 id; + char *state; + char *cpus_assigned_list; + char *cpus_failed_list; +}; diff --git a/src/jailhouse/meson.build b/src/jailhouse/meson.build index 45ceeecca3..a706985169 100644 --- a/src/jailhouse/meson.build +++ b/src/jailhouse/meson.build @@ -1,5 +1,6 @@ jailhouse_sources = files( 'jailhouse_driver.c', + 'jailhouse_api.c', ) driver_source_files += jailhouse_sources diff --git a/src/libvirt.c b/src/libvirt.c index 8a78cbcf3a..0748eb2352 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -75,9 +75,6 @@ #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 @@ -274,10 +271,6 @@ 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; @@ -1052,9 +1045,6 @@ 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/remote/remote_daemon.c b/src/remote/remote_daemon.c index 2ac4f6cd2e..cbfdebfd7a 100644 --- a/src/remote/remote_daemon.c +++ b/src/remote/remote_daemon.c @@ -145,6 +145,10 @@ static int daemonInitialize(void) if (virDriverLoadModule("interface", "interfaceRegister", false) < 0) return -1; # endif +# ifdef WITH_JAILHOUSE + if (virDriverLoadModule("jailhouse", "jailhouseRegister", false) < 0) + return -1; +# endif # ifdef WITH_SECRETS if (virDriverLoadModule("secret", "secretRegister", false) < 0) return -1; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index 53d17a8f4a..06d8fe6098 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -2115,7 +2115,8 @@ remoteDispatchConnectOpen(virNetServerPtr server G_GNUC_UNUSED, STREQ(type, "VBOX") || STREQ(type, "bhyve") || STREQ(type, "vz") || - STREQ(type, "Parallels")) { + STREQ(type, "Parallels") || + STREQ(type, "JAILHOUSE")) { VIR_DEBUG("Hypervisor driver found, setting URIs for secondary drivers"); if (getuid() == 0) { priv->interfaceURI = "interface:///system"; -- 2.26.2

On Thu, Sep 17, 2020 at 04:23:52PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
--- include/libvirt/virterror.h | 1 + po/POTFILES.in | 2 + src/jailhouse/Makefile.inc.am | 34 ++- src/jailhouse/jailhouse.conf | 10 + src/jailhouse/jailhouse_api.c | 372 ++++++++++++++++++++++++++++ src/jailhouse/jailhouse_api.h | 74 ++++++ src/jailhouse/jailhouse_driver.c | 302 +++++++++++++++++----- src/jailhouse/jailhouse_driver.h | 51 ++++ src/jailhouse/meson.build | 1 + src/libvirt.c | 10 - src/remote/remote_daemon.c | 4 + src/remote/remote_daemon_dispatch.c | 3 +- 12 files changed, 783 insertions(+), 81 deletions(-) create mode 100644 src/jailhouse/jailhouse.conf create mode 100644 src/jailhouse/jailhouse_api.c create mode 100644 src/jailhouse/jailhouse_api.h
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 97f2ac16d8..9f1bca2684 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -137,6 +137,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
Should be in the previous patch.
diff --git a/src/jailhouse/Makefile.inc.am b/src/jailhouse/Makefile.inc.am index 02822b2ea1..324c3b1b16 100644 --- a/src/jailhouse/Makefile.inc.am +++ b/src/jailhouse/Makefile.inc.am
This file shouldn't exist any more.
diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c new file mode 100644 index 0000000000..cda00b50e7 --- /dev/null +++ b/src/jailhouse/jailhouse_api.c @@ -0,0 +1,372 @@ +/* + * jailhouse_api.c: Jailhouse API + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <linux/types.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" +#include "virstring.h" +#include "jailhouse_api.h" + +#define JAILHOUSE_DEVICE "/dev/jailhouse" +#define JAILHOUSE_CELLS "/sys/devices/jailhouse/cells" +#define MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE 1024*1024 +#define MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE 1024 + + +#define JAILHOUSE_ENABLE _IOW(0, 0, void *) +#define JAILHOUSE_DISABLE _IO(0, 1) +#define JAILHOUSE_CELL_CREATE _IOW(0, 2, virJailhouseCellCreate) +#define JAILHOUSE_CELL_DESTROY _IOW(0, 5, virJailhouseCellId) + +#define VIR_FROM_THIS VIR_FROM_JAILHOUSE + +VIR_LOG_INIT("jailhouse.jailhouse_api"); + +#define JAILHOUSE_CELL_FILE_EXTENSION ".cell" + +/* Forward declarations */ + +/* Open the Jailhouse device for ioctl APIs */ +int openDev(void); + +/* Reads cell's property given by 'entry' using sysfs API */ +char *readSysfsCellString(const unsigned int id, const char *entry); + +int cell_match(const struct dirent *dirent); + +int createCell(const char *conf_file); + +int destroyCell(virJailhouseCellId cell_id); + +int getCellInfo(const unsigned int id, + virJailhouseCellInfoPtr * cell_info);
We expect that all methods have a consistent name prefix. So everything in this driver should really be named with "virJailhouse" as an API prefix. This naming rule includes static methods
+ +int +jailhouseEnable(const char *sys_conf_file_path) +{ + int err = -1, len; + g_autofree char *buffer = NULL; + VIR_AUTOCLOSE fd = -1; + + if (!virFileExists(sys_conf_file_path)) + return 0; + + len = virFileReadAll(sys_conf_file_path, MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE, &buffer); + if (len < 0 || !buffer) {
buffer will be non-NULL if len >= 0, so the second test isn't needed.
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Failed to read the system configuration file")); + return -1; + } + + fd = openDev();
You need to check for error opening files...
+ + err = ioctl(fd, JAILHOUSE_ENABLE, buffer);
or this uses a closed FD.
+ if (err) { + virReportSystemError(errno, "%s", _("Failed to enable jailhouse")); + return err; + } + + VIR_DEBUG("Jailhouse hypervisor is enabled"); + + return 1; +} + +int +jailhouseDisable(void) +{ + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev();
Again check for error
+ + err = ioctl(fd, JAILHOUSE_DISABLE); + if (err) + virReportSystemError(errno, + "%s", + _("Failed to disable jailhouse: %s")); + + VIR_DEBUG("Jailhouse hypervisor is disabled"); + + return err; +} + +int +cell_match(const struct dirent *dirent) +{ + char *ext = strrchr(dirent->d_name, '.'); + + return dirent->d_name[0] != '.' + && (STREQ(ext, JAILHOUSE_CELL_FILE_EXTENSION) == 0);
You need to check for "ext" being NULL.
+} + +int +createJailhouseCells(const char *dir_path) +{ + + struct dirent **namelist; + int num_entries, ret = -1; + size_t i; + + if (strlen(dir_path) == 0) + return ret; + + num_entries = scandir(dir_path, &namelist, cell_match, alphasort); + if (num_entries == -1) { + if (errno == ENOENT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("No cells found in %s, scandir failed."), + dir_path); + goto fail; + } + + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Error reading cell configurations in %s."), + dir_path); + goto fail; + } + + + for (i = 0; i < num_entries; i++) { + g_autofree char *file_path = g_strdup_printf("%s/%s", dir_path, namelist[i]->d_name); + + if (createCell(file_path) != 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Cell creation failed with conf found in %s."), + namelist[i]->d_name); + goto fail; + } + } + + ret = 0; + + fail:
Our naming convention is "cleanup" for paths that are shared with successful exit, or "error" for exclusively failure paths. So this one should be "cleanup"
+ VIR_FREE(namelist); + return ret; +}
+int +createCell(const char *conf_file) +{ + virJailhouseCellCreate cell_create; + int err = -1, len; + g_autofree char *buffer = NULL; + VIR_AUTOCLOSE fd = -1; + + if (strlen(conf_file) == 0) + return err; + + len = virFileReadAll(conf_file, MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE, &buffer); + if (len < 0 || !buffer) {
No need for !buffer
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("Failed to read the system configuration file")); + return err; + } + + cell_create.config_address = (unsigned long) buffer; + cell_create.config_size = len; + + fd = openDev();
Check error.
+ + err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create); + if (err) + virReportSystemError(errno, + "%s", + _("Cell creation failed: %s")); + + return err; +}
+char * +readSysfsCellString(const unsigned int id, const char *entry) +{ + g_autofree char *buffer = NULL; + g_autofree char *file_path = NULL; + int len = -1; + + file_path = g_strdup_printf(JAILHOUSE_CELLS "%u/%s", id, entry); + + len = virFileReadAll(file_path, 1024, &buffer); + if (len < 0 || !buffer) {
No need for !buffer
+ virReportError(VIR_ERR_INTERNAL_ERROR, + _("Error reading cell(%u) %s from %s failed"), + id, entry, file_path); + return NULL; + } + + virTrimSpaces(buffer, NULL); + + return buffer; +}
+ + /* Allocate memory for 1 more than num_entries and make the last entry NULL. */ + if (VIR_ALLOC_N(cell_info_list, num_entries + 1) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cells info list")); + }
Don't need to check for failure as it aborts().
+ + /* Set the last entry to NULL. */ + cell_info_list[num_entries] = NULL; + + for (i = 0; i < num_entries; i++) { + if (virStrToLong_ui(namelist[i]->d_name, NULL, 10, &id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cell ID %s could not be converted to a long"), + namelist[i]->d_name); + continue; + } + + /* get the cell's information(name, state etc.) using sysfs */ + getCellInfo(id, &cell_info_list[i]); + VIR_FREE(namelist[i]); + } + + VIR_FREE(namelist); + return cell_info_list; +} + +int +destroyCell(virJailhouseCellId cell_id) +{ + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev();
Check for error
+ + err = ioctl(fd, JAILHOUSE_CELL_DESTROY, &cell_id); + if (err) + virReportSystemError(errno, + _("Destroying cell %d failed"), + cell_id.id); + + return err; +}
diff --git a/src/jailhouse/jailhouse_api.h b/src/jailhouse/jailhouse_api.h new file mode 100644 index 0000000000..8362cb3d0f --- /dev/null +++ b/src/jailhouse/jailhouse_api.h @@ -0,0 +1,74 @@ +/* + * jailhouse_api.h: Jailhouse hypervisor API implementation + * + * 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 + +#define JAILHOUSE_CELL_ID_NAMELEN 31 + +typedef struct _virJailhouseCellId virJailhouseCellId; + +struct _virJailhouseCellId { + __s32 id;
Shouldn't be using these types, instead int32_t
+ __u32 padding;
uint32_t
+ char name[JAILHOUSE_CELL_ID_NAMELEN + 1]; +}; + +typedef struct _virJailhouseCellInfo virJailhouseCellInfo; +typedef virJailhouseCellInfo *virJailhouseCellInfoPtr; + +struct _virJailhouseCellInfo { + struct _virJailhouseCellId id; + char *state; + char *cpus_assigned_list; + char *cpus_failed_list; +}; + +typedef struct _virJailhouseCellCreate virJailhouseCellCreate; + +struct _virJailhouseCellCreate { + __u64 config_address;
uint64_t ..etc
+ __u32 config_size; + __u32 padding; +}; + +// Enables the Jailhouse hypervisor by reading the hypervisor system +// configuration from the given file and calls the ioctl API to +// enable the hypervisor. +int jailhouseEnable(const char *sys_conf_file_path); + +// Disables the Jailhouse hypervisor. +int jailhouseDisable(void); + +/* Cell API methods */ + +// Creates Jailhouse cells using the cells configurations +// provided in the dir_name. +int createJailhouseCells(const char *dir_path); + +// Destroys Jailhouse cells using the cell IDs provided in +// the cell_info_list. +int destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list); + +// Returns cell's information in a null-terminated array of +// virJailhouseCellInfoPtr for all the Jailhouse cells. +virJailhouseCellInfoPtr *getJailhouseCellsInfo(void); + +// Free the cell info object. +void cellInfoFree(virJailhouseCellInfoPtr cell_info);
@@ -69,36 +254,16 @@ jailhouseConnectGetHostname(virConnectPtr conn) }
static int -jailhouseNodeGetInfo(virConnectPtr conn, - virNodeInfoPtr info) +jailhouseNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
This formatting change should be done in the original patch. Same for the changes that follow
{ 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) + virDomainPtr ** domain, unsigned int flags) { UNUSED(conn); UNUSED(domain); @@ -107,8 +272,7 @@ jailhouseConnectListAllDomains(virConnectPtr conn, }
static virDomainPtr -jailhouseDomainLookupByID(virConnectPtr conn, - int id) +jailhouseDomainLookupByID(virConnectPtr conn, int id) { UNUSED(conn); UNUSED(id); @@ -116,8 +280,7 @@ jailhouseDomainLookupByID(virConnectPtr conn, }
static virDomainPtr -jailhouseDomainLookupByName(virConnectPtr conn, - const char *name) +jailhouseDomainLookupByName(virConnectPtr conn, const char *name) { UNUSED(conn); UNUSED(name); @@ -125,8 +288,7 @@ jailhouseDomainLookupByName(virConnectPtr conn, }
static virDomainPtr -jailhouseDomainLookupByUUID(virConnectPtr conn, - const unsigned char *uuid) +jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { UNUSED(conn); UNUSED(uuid); @@ -157,8 +319,7 @@ jailhouseDomainDestroy(virDomainPtr domain) }
static int -jailhouseDomainGetInfo(virDomainPtr domain, - virDomainInfoPtr info) +jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { UNUSED(domain); UNUSED(info); @@ -167,9 +328,7 @@ jailhouseDomainGetInfo(virDomainPtr domain,
static int jailhouseDomainGetState(virDomainPtr domain, - int *state, - int *reason, - unsigned int flags) + int *state, int *reason, unsigned int flags) { UNUSED(domain); UNUSED(state); @@ -179,8 +338,7 @@ jailhouseDomainGetState(virDomainPtr domain, }
static char * -jailhouseDomainGetXMLDesc(virDomainPtr domain, - unsigned int flags) +jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) { UNUSED(domain); UNUSED(flags); @@ -189,31 +347,43 @@ jailhouseDomainGetXMLDesc(virDomainPtr domain,
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 */ + .connectOpen = jailhouseConnectOpen, /* 6.3.0 */ + .connectClose = jailhouseConnectClose, /* 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 */
Don't do this formatting change - trying to horizontally align such comments is a waste of time in the long term.
diff --git a/src/jailhouse/jailhouse_driver.h b/src/jailhouse/jailhouse_driver.h index b0dbc8d033..8a0e111676 100644 --- a/src/jailhouse/jailhouse_driver.h +++ b/src/jailhouse/jailhouse_driver.h @@ -20,4 +20,55 @@
#pragma once
+#include <linux/types.h> + +#include "jailhouse_api.h" + int jailhouseRegister(void); + +#define JAILHOUSE_CONFIG_FILE SYSCONFDIR "/libvirt/jailhouse/jailhouse.conf" +#define JAILHOUSE_STATE_DIR RUNSTATEDIR "/libvirt/jailhouse" + +#define JAILHOUSE_DEV "/dev/jailhouse" + +#define JAILHOUSE_SYSFS_DEV "/sys/devices/jailhouse/" + +typedef struct _virJailhouseDriver virJailhouseDriver; +typedef virJailhouseDriver *virJailhouseDriverPtr; + +typedef struct _virJailhouseDriverConfig virJailhouseDriverConfig; +typedef virJailhouseDriverConfig *virJailhouseDriverConfigPtr; + +struct _virJailhouseDriverConfig { + virObject parent; + + char *stateDir; + + // File path of the jailhouse system configuration + // for jailhouse enable/disable. + char *sys_config_file_path; + + // Config directory where all jailhouse cell configurations + // are stored. + char *cell_config_dir; +}; + +struct _virJailhouseDriver { + virMutex lock; + + // Jailhouse configuration read from the jailhouse.conf + virJailhouseDriverConfigPtr config; + + /* pid file FD, ensures two copies of the driver can't use the same root */ + int lockFD; + + // All the cells created during connect open on the hypervisor. + virJailhouseCellInfoPtr *cell_info_list; +}; + +struct _jailhouseCell { + __s32 id;
int32_t
+ char *state; + char *cpus_assigned_list; + char *cpus_failed_list; +};
diff --git a/src/libvirt.c b/src/libvirt.c index 8a78cbcf3a..0748eb2352 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -75,9 +75,6 @@ #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 @@ -274,10 +271,6 @@ 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; @@ -1052,9 +1045,6 @@ 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,
You just added all these lines in the previous patch. If they're not relevant, then don't add them in the first place. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- src/jailhouse/jailhouse_driver.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index ac9da4c85d..75bf41fc11 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -32,8 +32,10 @@ #include "viralloc.h" #include "virfile.h" #include "virlog.h" +#include "virutil.h" #include "vircommand.h" #include "virpidfile.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_JAILHOUSE @@ -241,16 +243,19 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, static const char * jailhouseConnectGetType(virConnectPtr conn) { - UNUSED(conn); - return NULL; + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL; + return "JAILHOUSE"; } static char * jailhouseConnectGetHostname(virConnectPtr conn) { - UNUSED(conn); - return NULL; + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + + return virGetHostname(); } static int @@ -263,7 +268,7 @@ jailhouseNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) static int jailhouseConnectListAllDomains(virConnectPtr conn, - virDomainPtr ** domain, unsigned int flags) + virDomainPtr **domain, unsigned int flags) { UNUSED(conn); UNUSED(domain); @@ -300,7 +305,6 @@ jailhouseDomainCreate(virDomainPtr domain) { UNUSED(domain); return -1; - } static int @@ -350,18 +354,18 @@ static virHypervisorDriver jailhouseHypervisorDriver = { .connectOpen = jailhouseConnectOpen, /* 6.3.0 */ .connectClose = jailhouseConnectClose, /* 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 */ + .domainCreate = jailhouseDomainCreate, /* 6.3.0 */ .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */ .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */ .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */ .domainGetState = jailhouseDomainGetState, /* 6.3.0 */ + .domainLookupByID = jailhouseDomainLookupByID, /* 6.3.0 */ + .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 6.3.0 */ + .domainLookupByName = jailhouseDomainLookupByName, /* 6.3.0 */ + .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 6.3.0 */ + .nodeGetInfo = jailhouseNodeGetInfo, /* 6.3.0 */ }; -- 2.26.2

On Thu, Sep 17, 2020 at 04:23:53PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
--- src/jailhouse/jailhouse_driver.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index ac9da4c85d..75bf41fc11 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -32,8 +32,10 @@ #include "viralloc.h" #include "virfile.h" #include "virlog.h" +#include "virutil.h" #include "vircommand.h" #include "virpidfile.h" +#include "access/viraccessapicheck.h"
#define VIR_FROM_THIS VIR_FROM_JAILHOUSE
@@ -241,16 +243,19 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, static const char * jailhouseConnectGetType(virConnectPtr conn) { - UNUSED(conn); - return NULL; + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL;
+ return "JAILHOUSE"; }
static char * jailhouseConnectGetHostname(virConnectPtr conn) { - UNUSED(conn); - return NULL; + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + + return virGetHostname(); }
static int @@ -263,7 +268,7 @@ jailhouseNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
static int jailhouseConnectListAllDomains(virConnectPtr conn, - virDomainPtr ** domain, unsigned int flags) + virDomainPtr **domain, unsigned int flags) { UNUSED(conn); UNUSED(domain); @@ -300,7 +305,6 @@ jailhouseDomainCreate(virDomainPtr domain) { UNUSED(domain); return -1; - }
Put these formatting fixes in the original patch that caused them.
static int @@ -350,18 +354,18 @@ static virHypervisorDriver jailhouseHypervisorDriver = { .connectOpen = jailhouseConnectOpen, /* 6.3.0 */ .connectClose = jailhouseConnectClose, /* 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 */ + .domainCreate = jailhouseDomainCreate, /* 6.3.0 */ .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */ .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */ .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */ .domainGetState = jailhouseDomainGetState, /* 6.3.0 */ + .domainLookupByID = jailhouseDomainLookupByID, /* 6.3.0 */ + .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 6.3.0 */ + .domainLookupByName = jailhouseDomainLookupByName, /* 6.3.0 */ + .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 6.3.0 */ + .nodeGetInfo = jailhouseNodeGetInfo, /* 6.3.0 */ };
This re-ordering should be dropped, or done in the original patch Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On a Thursday in 2020, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
--- src/jailhouse/jailhouse_driver.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index ac9da4c85d..75bf41fc11 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -32,8 +32,10 @@ #include "viralloc.h" #include "virfile.h" #include "virlog.h" +#include "virutil.h" #include "vircommand.h" #include "virpidfile.h" +#include "access/viraccessapicheck.h"
#define VIR_FROM_THIS VIR_FROM_JAILHOUSE
@@ -241,16 +243,19 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, static const char * jailhouseConnectGetType(virConnectPtr conn) { - UNUSED(conn); - return NULL; + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL;
+ return "JAILHOUSE"; }
There's no need to name it in all-caps. "Jailhouse" or "jailhouse" will do Jano

From: Prakhar Bansal <prakharbansal0910@gmail.com> Implemented Jailhouse hypervisor APIs for cell load/start/shutdown/destroy. --- src/jailhouse/jailhouse_api.c | 100 ++++++++++++-- src/jailhouse/jailhouse_api.h | 29 +++++ src/jailhouse/jailhouse_driver.c | 217 +++++++++++++++++++++++++++++-- src/jailhouse/jailhouse_driver.h | 8 ++ 4 files changed, 335 insertions(+), 19 deletions(-) diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c index cda00b50e7..783903e939 100644 --- a/src/jailhouse/jailhouse_api.c +++ b/src/jailhouse/jailhouse_api.c @@ -43,11 +43,14 @@ #define JAILHOUSE_CELLS "/sys/devices/jailhouse/cells" #define MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE 1024*1024 #define MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE 1024 +#define MAX_JAILHOUSE_CELL_IMAGE_FILE_SIZE 64*1024*1024 #define JAILHOUSE_ENABLE _IOW(0, 0, void *) #define JAILHOUSE_DISABLE _IO(0, 1) #define JAILHOUSE_CELL_CREATE _IOW(0, 2, virJailhouseCellCreate) +#define JAILHOUSE_CELL_LOAD _IOW(0, 3, virJailhouseCellLoad) +#define JAILHOUSE_CELL_START _IOW(0, 4, virJailhouseCellId) #define JAILHOUSE_CELL_DESTROY _IOW(0, 5, virJailhouseCellId) #define VIR_FROM_THIS VIR_FROM_JAILHOUSE @@ -68,8 +71,6 @@ int cell_match(const struct dirent *dirent); int createCell(const char *conf_file); -int destroyCell(virJailhouseCellId cell_id); - int getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info); @@ -254,7 +255,7 @@ readSysfsCellString(const unsigned int id, const char *entry) } int -getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info_ptr) +getCellInfo(const unsigned int id, virJailhouseCellInfoPtr *cell_info_ptr) { char *tmp; @@ -345,28 +346,105 @@ getJailhouseCellsInfo(void) } int -destroyCell(virJailhouseCellId cell_id) +loadImagesInCell(virJailhouseCellId cell_id, char **images, int num_images) +{ + virJailhousePreloadImagePtr image; + virJailhouseCellLoadPtr cell_load; + g_autofree char *buffer = NULL; + unsigned int n; + int len = -1, err = -1; + VIR_AUTOCLOSE fd = -1; + + + if (VIR_ALLOC(cell_load) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cell load")); + return -1; + } + + + if (VIR_ALLOC_N(cell_load->image, num_images) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cell load images")); + return -1; + } + + cell_load->id = cell_id; + cell_load->num_preload_images = num_images; + + for (n = 0, image = cell_load->image; n < num_images; n++, image++) { + len = virFileReadAll(images[n], MAX_JAILHOUSE_CELL_IMAGE_FILE_SIZE, &buffer); + if (len < 0 || !buffer) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Failed to read the image file %s"), + images[n]); + return -1; + } + + image->source_address = (unsigned long)buffer; + image->size = len; + + // TODO(Prakhar): Add support for target address. + image->target_address = 0; + } + + fd = openDev(); + + err = ioctl(fd, JAILHOUSE_CELL_LOAD, cell_load); + if (err) { + virReportSystemError(errno, + _("Loading cell images for %d failed"), + cell_id.id); + return -1; + } + + return 0; +} + +int +shutdownCell(virJailhouseCellId cell_id) +{ + // Loading 0 images in the cell causes cell to shutdown. + return loadImagesInCell(cell_id, NULL, 0); +} + +int +startCell(virJailhouseCellId cell_id) { int err = -1; VIR_AUTOCLOSE fd = -1; fd = openDev(); - err = ioctl(fd, JAILHOUSE_CELL_DESTROY, &cell_id); - if (err) + err = ioctl(fd, JAILHOUSE_CELL_START, &cell_id); + if (err) { virReportSystemError(errno, - _("Destroying cell %d failed"), + _("Start cell %d failed"), cell_id.id); + return -1; + } - return err; + return 0; } int -destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list G_GNUC_UNUSED) +destroyCell(virJailhouseCellId cell_id) { + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev(); - /* Iterate over all cells in cell_info_list and destroy each cell */ - // TODO: Not implemented yet. + err = ioctl(fd, JAILHOUSE_CELL_DESTROY, &cell_id); + if (err) { + virReportSystemError(errno, + _("Destroying cell %d failed"), + cell_id.id); + + return -1; + } return 0; } diff --git a/src/jailhouse/jailhouse_api.h b/src/jailhouse/jailhouse_api.h index 8362cb3d0f..ba39a4c8b7 100644 --- a/src/jailhouse/jailhouse_api.h +++ b/src/jailhouse/jailhouse_api.h @@ -48,6 +48,27 @@ struct _virJailhouseCellCreate { __u32 padding; }; +typedef struct _virJailhousePreloadImage virJailhousePreloadImage; +typedef virJailhousePreloadImage *virJailhousePreloadImagePtr; + +struct _virJailhousePreloadImage { + __u64 source_address; + __u64 size; + __u64 target_address; + __u64 padding; +}; + +typedef struct _virJailhouseCellLoad virJailhouseCellLoad; +typedef virJailhouseCellLoad *virJailhouseCellLoadPtr; + +struct _virJailhouseCellLoad { + struct _virJailhouseCellId id; + __u32 num_preload_images; + __u32 padding; + struct _virJailhousePreloadImage image[]; +}; + + // Enables the Jailhouse hypervisor by reading the hypervisor system // configuration from the given file and calls the ioctl API to // enable the hypervisor. @@ -62,6 +83,14 @@ int jailhouseDisable(void); // provided in the dir_name. int createJailhouseCells(const char *dir_path); +int loadImagesInCell(virJailhouseCellId cell_id, char **images, int num_images); + +int startCell(virJailhouseCellId cell_id); + +int shutdownCell(virJailhouseCellId cell_id); + +int destroyCell(virJailhouseCellId cell_id); + // Destroys Jailhouse cells using the cell IDs provided in // the cell_info_list. int destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list); diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 75bf41fc11..5b7bdc92d8 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -25,7 +25,6 @@ #include "configmake.h" #include "datatypes.h" #include "domain_conf.h" -#include "jailhouse_driver.h" #include "virtypedparam.h" #include "virerror.h" #include "virstring.h" @@ -36,6 +35,9 @@ #include "vircommand.h" #include "virpidfile.h" #include "access/viraccessapicheck.h" +#include "virdomainobjlist.h" + +#include "jailhouse_driver.h" #define VIR_FROM_THIS VIR_FROM_JAILHOUSE @@ -62,7 +64,6 @@ virJailhouseDriverConfigNew(void) { virJailhouseDriverConfigPtr cfg; - // TODO: Check if the following has to be uncommented. if (virJailhouseConfigInitialize() < 0) return NULL; @@ -135,6 +136,7 @@ jailhouseFreeDriver(virJailhouseDriverPtr driver) return; virMutexDestroy(&driver->lock); + virObjectUnref(driver->domains); virObjectUnref(driver->config); VIR_FREE(driver); } @@ -207,6 +209,9 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, return VIR_DRV_STATE_INIT_ERROR; } + if (!(jailhouse_driver->domains = virDomainObjListNew())) + goto error; + if (!(cfg = virJailhouseDriverConfigNew())) goto error; @@ -259,10 +264,11 @@ jailhouseConnectGetHostname(virConnectPtr conn) } static int -jailhouseNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) +jailhouseNodeGetInfo(virConnectPtr conn, + virNodeInfoPtr nodeinfo) { UNUSED(conn); - UNUSED(info); + UNUSED(nodeinfo); return -1; } @@ -300,11 +306,205 @@ jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) return NULL; } +static virDomainObjPtr +virJailhouseDomObjFromDomain(virDomainPtr domain) +{ + virDomainObjPtr cell; + virJailhouseDriverPtr driver = domain->conn->privateData; + char uuidstr[VIR_UUID_STRING_BUFLEN]; + + cell = virDomainObjListFindByUUID(driver->domains, domain->uuid); + if (!cell) { + virUUIDFormat(domain->uuid, uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s' (%s)"), + uuidstr, domain->name); + return NULL; + } + + return cell; +} + + + +static virJailhouseCellInfoPtr +virJailhouseFindCellByName(virJailhouseDriverPtr driver, + char* name) +{ + virJailhouseCellInfoPtr *cell = driver->cell_info_list; + + while (*cell) { + if (STRCASEEQ((*cell)->id.name, name)) + return *cell; + cell++; + } + + return NULL; +} + +static int +jailhouseDomainCreateWithFlags(virDomainPtr domain, + unsigned int flags) +{ + virJailhouseDriverPtr driver = domain->conn->privateData; + virDomainObjPtr cell; + virJailhouseCellInfoPtr cell_info; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_NONE, -1); + + if (!domain->name) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Error while reading the domain name")); + goto cleanup; + } + + if (!domain->id) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Error while reading the domain ID")); + goto cleanup; + } + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainCreateWithFlagsEnsureACL(domain->conn, cell->def) < 0) + goto cleanup; + + if (!(cell_info = virJailhouseFindCellByName(driver, cell->def->name))) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name %s and ID %d)"), + cell->def->name, cell->def->id); + virDomainObjListRemove(driver->domains, cell); + goto cleanup; + } + + ret = 0; + + cleanup: + virDomainObjEndAPI(&cell); + return ret; + +} + static int jailhouseDomainCreate(virDomainPtr domain) { - UNUSED(domain); - return -1; + return jailhouseDomainCreateWithFlags(domain, 0); +} + +static virDomainPtr +jailhouseDomainCreateXML(virConnectPtr conn, + const char *xml, + unsigned int flags) +{ + virJailhouseDriverPtr driver = conn->privateData; + virJailhouseCellInfoPtr cell_info; + virDomainPtr dom = NULL; + virDomainDefPtr def = NULL; + virDomainObjPtr cell = NULL; + virDomainDiskDefPtr disk = NULL; + virJailhouseCellId cell_id; + char **images = NULL; + int num_images = 0, i = 0; + unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; + + if (flags & VIR_DOMAIN_START_VALIDATE) + parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; + + if ((def = virDomainDefParseString(xml, NULL, + NULL, parse_flags)) == NULL) + goto cleanup; + + if ((cell = virDomainObjListFindByUUID(driver->domains, def->uuid))) + goto cleanup; + + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + + if (!(cell_info = virJailhouseFindCellByName(driver, def->name))) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("cell info for %s not found"), + def->name); + goto cleanup; + } + + // Assign cell Id to the domain. + def->id = cell_info->id.id; + + if (!(cell = virDomainObjListAdd(driver->domains, def, + NULL, + VIR_DOMAIN_OBJ_LIST_ADD_LIVE | + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) + goto cleanup; + + def = NULL; + + if (cell->def->ndisks < 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Domain XML doesn't contain any disk images")); + goto cleanup; + } + + if (VIR_ALLOC_N(images, cell->def->ndisks) < 0) + goto cleanup; + + for (i = 0; i < cell->def->ndisks; ++i) { + images[i] = NULL; + + if (cell->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK && + virDomainDiskGetType(cell->def->disks[i]) == VIR_STORAGE_TYPE_FILE) { + disk = cell->def->disks[i]; + const char *src = virDomainDiskGetSource(disk); + if (!src) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("First file-based harddisk has no source")); + goto cleanup; + } + + images[i] = (char *)src; + num_images++; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("A Jailhouse doamin(cell) can ONLY have FILE type disks")); + goto cleanup; + } + } + + // Initialize the cell_id. + cell_id.id = cell->def->id; + cell_id.padding = 0; + if (virStrncpy(cell_id.name, cell->def->name, JAILHOUSE_CELL_ID_NAMELEN, JAILHOUSE_CELL_ID_NAMELEN) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cell name %s length exceeded the limit"), + cell->def->name); + goto cleanup; + } + + if (loadImagesInCell(cell_id, images, num_images) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load images in the Cell %s"), + cell->def->name); + goto cleanup; + } + + VIR_DEBUG("Starting the domain..."); + + if (startCell(cell_id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to start the Cell %s"), + cell->def->name); + goto cleanup; + } + + virDomainObjSetState(cell, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED); + + dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); + + cleanup: + virDomainDefFree(def); + virDomainObjEndAPI(&cell); + return dom; } static int @@ -314,7 +514,6 @@ jailhouseDomainShutdown(virDomainPtr domain) return -1; } - static int jailhouseDomainDestroy(virDomainPtr domain) { @@ -356,7 +555,9 @@ static virHypervisorDriver jailhouseHypervisorDriver = { .connectListAllDomains = jailhouseConnectListAllDomains, /* 6.3.0 */ .connectGetType = jailhouseConnectGetType, /* 6.3.0 */ .connectGetHostname = jailhouseConnectGetHostname, /* 6.3.0 */ - .domainCreate = jailhouseDomainCreate, /* 6.3.0 */ + .domainCreate = jailhouseDomainCreate, /*6.3.0 */ + .domainCreateWithFlags = jailhouseDomainCreateWithFlags, /* 6.3.0 */ + .domainCreateXML = jailhouseDomainCreateXML, /* 6.3.0 */ .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */ .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */ .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */ diff --git a/src/jailhouse/jailhouse_driver.h b/src/jailhouse/jailhouse_driver.h index 8a0e111676..8fc99fe7d2 100644 --- a/src/jailhouse/jailhouse_driver.h +++ b/src/jailhouse/jailhouse_driver.h @@ -22,7 +22,9 @@ #include <linux/types.h> +#include "domain_event.h" #include "jailhouse_api.h" +#include "virdomainobjlist.h" int jailhouseRegister(void); @@ -64,6 +66,12 @@ struct _virJailhouseDriver { // All the cells created during connect open on the hypervisor. virJailhouseCellInfoPtr *cell_info_list; + + // XML options for domain XMLs. + virDomainXMLOptionPtr xmlopt; + virDomainObjListPtr domains; + + virObjectEventStatePtr domainEventState; }; struct _jailhouseCell { -- 2.26.2

On Thu, Sep 17, 2020 at 04:23:54PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
Implemented Jailhouse hypervisor APIs for cell load/start/shutdown/destroy. --- src/jailhouse/jailhouse_api.c | 100 ++++++++++++-- src/jailhouse/jailhouse_api.h | 29 +++++ src/jailhouse/jailhouse_driver.c | 217 +++++++++++++++++++++++++++++-- src/jailhouse/jailhouse_driver.h | 8 ++ 4 files changed, 335 insertions(+), 19 deletions(-)
diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c index cda00b50e7..783903e939 100644 --- a/src/jailhouse/jailhouse_api.c +++ b/src/jailhouse/jailhouse_api.c @@ -43,11 +43,14 @@ #define JAILHOUSE_CELLS "/sys/devices/jailhouse/cells" #define MAX_JAILHOUSE_SYS_CONFIG_FILE_SIZE 1024*1024 #define MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE 1024 +#define MAX_JAILHOUSE_CELL_IMAGE_FILE_SIZE 64*1024*1024
#define JAILHOUSE_ENABLE _IOW(0, 0, void *) #define JAILHOUSE_DISABLE _IO(0, 1) #define JAILHOUSE_CELL_CREATE _IOW(0, 2, virJailhouseCellCreate) +#define JAILHOUSE_CELL_LOAD _IOW(0, 3, virJailhouseCellLoad) +#define JAILHOUSE_CELL_START _IOW(0, 4, virJailhouseCellId) #define JAILHOUSE_CELL_DESTROY _IOW(0, 5, virJailhouseCellId)
#define VIR_FROM_THIS VIR_FROM_JAILHOUSE @@ -68,8 +71,6 @@ int cell_match(const struct dirent *dirent);
int createCell(const char *conf_file);
-int destroyCell(virJailhouseCellId cell_id); - int getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info);
@@ -254,7 +255,7 @@ readSysfsCellString(const unsigned int id, const char *entry) }
int -getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info_ptr) +getCellInfo(const unsigned int id, virJailhouseCellInfoPtr *cell_info_ptr) { char *tmp;
@@ -345,28 +346,105 @@ getJailhouseCellsInfo(void) }
int -destroyCell(virJailhouseCellId cell_id) +loadImagesInCell(virJailhouseCellId cell_id, char **images, int num_images) +{ + virJailhousePreloadImagePtr image; + virJailhouseCellLoadPtr cell_load; + g_autofree char *buffer = NULL; + unsigned int n; + int len = -1, err = -1; + VIR_AUTOCLOSE fd = -1; + + + if (VIR_ALLOC(cell_load) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cell load")); + return -1; + } + + + if (VIR_ALLOC_N(cell_load->image, num_images) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", + _("Insufficient memory for cell load images")); + return -1; + }
No need to check failure - these abort on OOM.
+ + cell_load->id = cell_id; + cell_load->num_preload_images = num_images; + + for (n = 0, image = cell_load->image; n < num_images; n++, image++) { + len = virFileReadAll(images[n], MAX_JAILHOUSE_CELL_IMAGE_FILE_SIZE, &buffer); + if (len < 0 || !buffer) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Failed to read the image file %s"), + images[n]); + return -1; + } + + image->source_address = (unsigned long)buffer; + image->size = len; + + // TODO(Prakhar): Add support for target address. + image->target_address = 0; + } + + fd = openDev();
Check error here.
+ + err = ioctl(fd, JAILHOUSE_CELL_LOAD, cell_load); + if (err) { + virReportSystemError(errno, + _("Loading cell images for %d failed"), + cell_id.id); + return -1; + } + + return 0; +}
-destroyJailhouseCells(virJailhouseCellInfoPtr *cell_info_list G_GNUC_UNUSED) +destroyCell(virJailhouseCellId cell_id) { + int err = -1; + VIR_AUTOCLOSE fd = -1; + + fd = openDev();
Check error
- /* Iterate over all cells in cell_info_list and destroy each cell */ - // TODO: Not implemented yet. + err = ioctl(fd, JAILHOUSE_CELL_DESTROY, &cell_id); + if (err) { + virReportSystemError(errno, + _("Destroying cell %d failed"), + cell_id.id); + + return -1; + }
+typedef struct _virJailhousePreloadImage virJailhousePreloadImage; +typedef virJailhousePreloadImage *virJailhousePreloadImagePtr; + +struct _virJailhousePreloadImage { + __u64 source_address;
uint64_t, etc
+ __u64 size; + __u64 target_address; + __u64 padding; +}; + +typedef struct _virJailhouseCellLoad virJailhouseCellLoad; +typedef virJailhouseCellLoad *virJailhouseCellLoadPtr; + +struct _virJailhouseCellLoad { + struct _virJailhouseCellId id; + __u32 num_preload_images; + __u32 padding; + struct _virJailhousePreloadImage image[]; +}; + +
jailhouseDomainCreate(virDomainPtr domain) { - UNUSED(domain); - return -1; + return jailhouseDomainCreateWithFlags(domain, 0); +} + +static virDomainPtr +jailhouseDomainCreateXML(virConnectPtr conn, + const char *xml, + unsigned int flags) +{ + virJailhouseDriverPtr driver = conn->privateData; + virJailhouseCellInfoPtr cell_info; + virDomainPtr dom = NULL; + virDomainDefPtr def = NULL; + virDomainObjPtr cell = NULL; + virDomainDiskDefPtr disk = NULL; + virJailhouseCellId cell_id; + char **images = NULL; + int num_images = 0, i = 0; + unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; + + if (flags & VIR_DOMAIN_START_VALIDATE) + parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; + + if ((def = virDomainDefParseString(xml, NULL, + NULL, parse_flags)) == NULL) + goto cleanup; + + if ((cell = virDomainObjListFindByUUID(driver->domains, def->uuid))) + goto cleanup; + + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + + if (!(cell_info = virJailhouseFindCellByName(driver, def->name))) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("cell info for %s not found"), + def->name); + goto cleanup; + } + + // Assign cell Id to the domain.
Forgot to mention this on previous patches, but we only want C style comments /* ... */, never C++ style.
+ def->id = cell_info->id.id; + + if (!(cell = virDomainObjListAdd(driver->domains, def, + NULL, + VIR_DOMAIN_OBJ_LIST_ADD_LIVE | + VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) + goto cleanup; + + def = NULL; + + if (cell->def->ndisks < 1) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Domain XML doesn't contain any disk images")); + goto cleanup; + } + + if (VIR_ALLOC_N(images, cell->def->ndisks) < 0) + goto cleanup; + + for (i = 0; i < cell->def->ndisks; ++i) { + images[i] = NULL; + + if (cell->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK && + virDomainDiskGetType(cell->def->disks[i]) == VIR_STORAGE_TYPE_FILE) { + disk = cell->def->disks[i]; + const char *src = virDomainDiskGetSource(disk); + if (!src) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("First file-based harddisk has no source")); + goto cleanup; + } + + images[i] = (char *)src; + num_images++; + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("A Jailhouse doamin(cell) can ONLY have FILE type disks")); + goto cleanup; + } + }
static int jailhouseDomainDestroy(virDomainPtr domain) { @@ -356,7 +555,9 @@ static virHypervisorDriver jailhouseHypervisorDriver = { .connectListAllDomains = jailhouseConnectListAllDomains, /* 6.3.0 */ .connectGetType = jailhouseConnectGetType, /* 6.3.0 */ .connectGetHostname = jailhouseConnectGetHostname, /* 6.3.0 */ - .domainCreate = jailhouseDomainCreate, /* 6.3.0 */ + .domainCreate = jailhouseDomainCreate, /*6.3.0 */
Introduced a whitespace bug
+ .domainCreateWithFlags = jailhouseDomainCreateWithFlags, /* 6.3.0 */ + .domainCreateXML = jailhouseDomainCreateXML, /* 6.3.0 */ .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */ .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */ .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- src/jailhouse/jailhouse_driver.c | 102 +++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 19 deletions(-) diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 5b7bdc92d8..2bb249f996 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -267,19 +267,26 @@ static int jailhouseNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { - UNUSED(conn); - UNUSED(nodeinfo); - return -1; + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + + return virCapabilitiesGetNodeInfo(nodeinfo); } static int jailhouseConnectListAllDomains(virConnectPtr conn, - virDomainPtr **domain, unsigned int flags) + virDomainPtr **domains, + unsigned int flags) { - UNUSED(conn); - UNUSED(domain); - UNUSED(flags); - return -1; + virJailhouseDriverPtr driver = conn->privateData; + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + + if (virConnectListAllDomainsEnsureACL(conn) < 0) + return -1; + + return virDomainObjListExport(driver->domains, conn, domains, + virConnectListAllDomainsCheckACL, flags); } static virDomainPtr @@ -522,30 +529,87 @@ jailhouseDomainDestroy(virDomainPtr domain) } static int -jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) +virjailhouseGetDomainTotalCpuStats(virDomainObjPtr cell, + unsigned long long *cpustats) { - UNUSED(domain); - UNUSED(info); + // TODO(Prakhar): Not implemented yet. + UNUSED(cell); + UNUSED(cpustats); return -1; } +static int +jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) +{ + virDomainObjPtr cell; + int ret = -1; + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainGetInfoEnsureACL(domain->conn, cell->def) < 0) + goto cleanup; + + if (virDomainObjIsActive(cell)) { + if (virjailhouseGetDomainTotalCpuStats(cell, &(info->cpuTime)) < 0) + goto cleanup; + } else { + info->cpuTime = 0; + } + + info->state = virDomainObjGetState(cell, NULL); + info->maxMem = virDomainDefGetMemoryTotal(cell->def); + info->nrVirtCpu = virDomainDefGetVcpus(cell->def); + ret = 0; + + cleanup: + virDomainObjEndAPI(&cell); + return ret; +} + static int jailhouseDomainGetState(virDomainPtr domain, int *state, int *reason, unsigned int flags) { - UNUSED(domain); - UNUSED(state); - UNUSED(reason); - UNUSED(flags); - return -1; + virDomainObjPtr cell; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainGetStateEnsureACL(domain->conn, cell->def) < 0) + goto cleanup; + + *state = virDomainObjGetState(cell, reason); + ret = 0; + + cleanup: + virDomainObjEndAPI(&cell); + return ret; } static char * jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) { - UNUSED(domain); - UNUSED(flags); - return NULL; + virDomainObjPtr cell; + char *ret = NULL; + + virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL); + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainGetXMLDescEnsureACL(domain->conn, cell->def, flags) < 0) + goto cleanup; + + ret = virDomainDefFormat(cell->def, NULL /* xmlopt */, + virDomainDefFormatConvertXMLFlags(flags)); + + cleanup: + virDomainObjEndAPI(&cell); + return ret; } static virHypervisorDriver jailhouseHypervisorDriver = { -- 2.26.2

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- src/jailhouse/jailhouse_driver.c | 70 ++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 2bb249f996..8c84a23388 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -292,25 +292,77 @@ jailhouseConnectListAllDomains(virConnectPtr conn, static virDomainPtr jailhouseDomainLookupByID(virConnectPtr conn, int id) { - UNUSED(conn); - UNUSED(id); - return NULL; +virJailhouseDriverPtr driver = conn->privateData; + virDomainObjPtr cell; + virDomainPtr dom = NULL; + + cell = virDomainObjListFindByID(driver->domains, id); + + if (!cell) { + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching ID '%d'"), id); + goto cleanup; + } + + if (virDomainLookupByIDEnsureACL(conn, cell->def) < 0) + goto cleanup; + + dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); + cleanup: + virDomainObjEndAPI(&cell); + return dom; } static virDomainPtr jailhouseDomainLookupByName(virConnectPtr conn, const char *name) { - UNUSED(conn); - UNUSED(name); - return NULL; + virJailhouseDriverPtr driver = conn->privateData; + virDomainObjPtr cell; + virDomainPtr dom = NULL; + + cell = virDomainObjListFindByName(driver->domains, name); + + if (!cell) { + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching name '%s'"), name); + goto cleanup; + } + + if (virDomainLookupByNameEnsureACL(conn, cell->def) < 0) + goto cleanup; + + dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); + + cleanup: + virDomainObjEndAPI(&cell); + return dom; } static virDomainPtr jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { - UNUSED(conn); - UNUSED(uuid); - return NULL; + virJailhouseDriverPtr driver = conn->privateData; + virDomainObjPtr cell; + virDomainPtr dom = NULL; + + cell = virDomainObjListFindByUUID(driver->domains, uuid); + + if (!cell) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(uuid, uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching UUID '%s'"), uuidstr); + goto cleanup; + } + + if (virDomainLookupByUUIDEnsureACL(conn, cell->def) < 0) + goto cleanup; + + dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); + + cleanup: + virDomainObjEndAPI(&cell); + return dom; } static virDomainObjPtr -- 2.26.2

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- src/jailhouse/jailhouse_api.c | 8 +++ src/jailhouse/jailhouse_driver.c | 101 +++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c index 783903e939..510e2f5f66 100644 --- a/src/jailhouse/jailhouse_api.c +++ b/src/jailhouse/jailhouse_api.c @@ -71,6 +71,14 @@ int cell_match(const struct dirent *dirent); int createCell(const char *conf_file); +int loadImagesInCell(virJailhouseCellId cell_id, char *images, int num_images); + +int shutdownCell(virJailhouseCellId cell_id); + +int startCell(virJailhouseCellId cell_id); + +int destroyCell(virJailhouseCellId cell_id); + int getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info); diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 8c84a23388..46c7759cb8 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -406,8 +406,8 @@ jailhouseDomainCreateWithFlags(virDomainPtr domain, unsigned int flags) { virJailhouseDriverPtr driver = domain->conn->privateData; - virDomainObjPtr cell; virJailhouseCellInfoPtr cell_info; + virDomainObjPtr cell; int ret = -1; virCheckFlags(VIR_DOMAIN_NONE, -1); @@ -566,18 +566,107 @@ jailhouseDomainCreateXML(virConnectPtr conn, return dom; } +static int +jailhouseDomainShutdownFlags(virDomainPtr domain, unsigned int flags) +{ + virJailhouseDriverPtr driver = domain->conn->privateData; + virJailhouseCellInfoPtr cell_info; + virDomainObjPtr cell; + virJailhouseCellId cell_id; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainShutdownFlagsEnsureACL(domain->conn, cell->def, flags) < 0) + goto cleanup; + + if (virDomainObjGetState(cell, NULL) != VIR_DOMAIN_RUNNING) + goto cleanup; + + if (!(cell_info = virJailhouseFindCellByName(driver, cell->def->name))) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name %s and ID %d)"), + cell->def->name, cell->def->id); + virDomainObjListRemove(driver->domains, cell); + goto cleanup; + } + + // Initialize the cell_id. + cell_id.id = cell->def->id; + cell_id.padding = 0; + if (virStrcpy(cell_id.name, cell->def->name, JAILHOUSE_CELL_ID_NAMELEN) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cell name %s length exceeded the limit"), + cell->def->name); + goto cleanup; + } + + if (shutdownCell(cell_id) < 0) + goto cleanup; + + virDomainObjSetState(cell, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_SHUTDOWN); + + ret = 0; + + cleanup: + virDomainObjEndAPI(&cell); + return ret; +} + static int jailhouseDomainShutdown(virDomainPtr domain) { - UNUSED(domain); - return -1; + return jailhouseDomainShutdownFlags(domain, 0); +} + +static int +jailhouseDomainDestroyFlags(virDomainPtr domain, unsigned int flags) +{ + virJailhouseDriverPtr driver = domain->conn->privateData; + virJailhouseCellInfoPtr cell_info; + virDomainObjPtr cell; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(cell = virJailhouseDomObjFromDomain(domain))) + goto cleanup; + + if (virDomainDestroyFlagsEnsureACL(domain->conn, cell->def) < 0) + goto cleanup; + + if (virDomainObjGetState(cell, NULL) != VIR_DOMAIN_SHUTOFF) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("Domain %s is still running."), + cell->def->name); + goto cleanup; + } + + if (!(cell_info = virJailhouseFindCellByName(driver, cell->def->name))) { + virReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching name %s and ID %d)"), + cell->def->name, cell->def->id); + virDomainObjListRemove(driver->domains, cell); + goto cleanup; + } + + // Remove the cell from the domain list. + virDomainObjListRemove(driver->domains, cell); + + ret = 0; + + cleanup: + virDomainObjEndAPI(&cell); + return ret; } static int jailhouseDomainDestroy(virDomainPtr domain) { - UNUSED(domain); - return -1; + return jailhouseDomainDestroyFlags(domain, 0); } static int @@ -675,7 +764,9 @@ static virHypervisorDriver jailhouseHypervisorDriver = { .domainCreateWithFlags = jailhouseDomainCreateWithFlags, /* 6.3.0 */ .domainCreateXML = jailhouseDomainCreateXML, /* 6.3.0 */ .domainShutdown = jailhouseDomainShutdown, /* 6.3.0 */ + .domainShutdownFlags = jailhouseDomainShutdownFlags, /* 6.3.0 */ .domainDestroy = jailhouseDomainDestroy, /* 6.3.0 */ + .domainDestroyFlags = jailhouseDomainDestroyFlags, /* 6.3.0 */ .domainGetInfo = jailhouseDomainGetInfo, /* 6.3.0 */ .domainGetState = jailhouseDomainGetState, /* 6.3.0 */ .domainLookupByID = jailhouseDomainLookupByID, /* 6.3.0 */ -- 2.26.2

From: Prakhar Bansal <prakharbansal0910@gmail.com> - Added xmlopt to the Jailhouse driver - Added ACL check in ConnectOpen --- src/jailhouse/jailhouse_api.c | 48 +++++++++++++------------- src/jailhouse/jailhouse_driver.c | 58 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/src/jailhouse/jailhouse_api.c b/src/jailhouse/jailhouse_api.c index 510e2f5f66..bb82b5a31e 100644 --- a/src/jailhouse/jailhouse_api.c +++ b/src/jailhouse/jailhouse_api.c @@ -69,15 +69,9 @@ char *readSysfsCellString(const unsigned int id, const char *entry); int cell_match(const struct dirent *dirent); -int createCell(const char *conf_file); - -int loadImagesInCell(virJailhouseCellId cell_id, char *images, int num_images); - -int shutdownCell(virJailhouseCellId cell_id); +int cell_match_info(const struct dirent *dirent); -int startCell(virJailhouseCellId cell_id); - -int destroyCell(virJailhouseCellId cell_id); +int createCell(const char *conf_file); int getCellInfo(const unsigned int id, virJailhouseCellInfoPtr * cell_info); @@ -121,25 +115,31 @@ jailhouseDisable(void) fd = openDev(); err = ioctl(fd, JAILHOUSE_DISABLE); - if (err) + if (err) { virReportSystemError(errno, "%s", _("Failed to disable jailhouse: %s")); + return -1; + } VIR_DEBUG("Jailhouse hypervisor is disabled"); - return err; + return 0; } int cell_match(const struct dirent *dirent) { char *ext = strrchr(dirent->d_name, '.'); - return dirent->d_name[0] != '.' - && (STREQ(ext, JAILHOUSE_CELL_FILE_EXTENSION) == 0); + && STREQ(ext, JAILHOUSE_CELL_FILE_EXTENSION); } +int +cell_match_info(const struct dirent *dirent) +{ + return dirent->d_name[0] != '.'; +} int createJailhouseCells(const char *dir_path) { @@ -150,7 +150,6 @@ createJailhouseCells(const char *dir_path) if (strlen(dir_path) == 0) return ret; - num_entries = scandir(dir_path, &namelist, cell_match, alphasort); if (num_entries == -1) { if (errno == ENOENT) { @@ -170,7 +169,8 @@ createJailhouseCells(const char *dir_path) for (i = 0; i < num_entries; i++) { g_autofree char *file_path = g_strdup_printf("%s/%s", dir_path, namelist[i]->d_name); - if (createCell(file_path) != 0) { + + if (createCell(file_path) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Cell creation failed with conf found in %s."), namelist[i]->d_name); @@ -208,13 +208,13 @@ createCell(const char *conf_file) VIR_AUTOCLOSE fd = -1; if (strlen(conf_file) == 0) - return err; + return -1; len = virFileReadAll(conf_file, MAX_JAILHOUSE_CELL_CONFIG_FILE_SIZE, &buffer); if (len < 0 || !buffer) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Failed to read the system configuration file")); - return err; + return -1; } cell_create.config_address = (unsigned long) buffer; @@ -223,12 +223,14 @@ createCell(const char *conf_file) fd = openDev(); err = ioctl(fd, JAILHOUSE_CELL_CREATE, &cell_create); - if (err) + if (err) { virReportSystemError(errno, "%s", _("Cell creation failed: %s")); + return -1; + } - return err; + return 0; } void @@ -243,11 +245,11 @@ cellInfoFree(virJailhouseCellInfoPtr cell_info) char * readSysfsCellString(const unsigned int id, const char *entry) { - g_autofree char *buffer = NULL; + char *buffer = NULL; g_autofree char *file_path = NULL; int len = -1; - file_path = g_strdup_printf(JAILHOUSE_CELLS "%u/%s", id, entry); + file_path = g_strdup_printf(JAILHOUSE_CELLS "/%u/%s", id, entry); len = virFileReadAll(file_path, 1024, &buffer); if (len < 0 || !buffer) { @@ -277,13 +279,12 @@ getCellInfo(const unsigned int id, virJailhouseCellInfoPtr *cell_info_ptr) /* get cell name */ tmp = readSysfsCellString(id, "name"); - if (virStrncpy(cell_info->id.name, tmp, JAILHOUSE_CELL_ID_NAMELEN, JAILHOUSE_CELL_ID_NAMELEN) < 0) { + if (virStrcpy(cell_info->id.name, tmp, JAILHOUSE_CELL_ID_NAMELEN) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Cell ID %s too long to be copied to the cell info"), tmp); return -1; } - cell_info->id.name[JAILHOUSE_CELL_ID_NAMELEN] = 0; VIR_FREE(tmp); @@ -310,8 +311,7 @@ getJailhouseCellsInfo(void) int num_entries; size_t i; - num_entries = - scandir(JAILHOUSE_CELLS, &namelist, cell_match, alphasort); + num_entries = scandir(JAILHOUSE_CELLS, &namelist, cell_match_info, alphasort); if (num_entries == -1) { if (errno == ENOENT) { virReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 46c7759cb8..45b1f35896 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -122,7 +122,6 @@ jailhouseCreateAndLoadCells(virJailhouseDriverPtr driver) // Create all cells in the hypervisor. if (createJailhouseCells(driver->config->cell_config_dir) < 0) return -1; - // Get all cells created above. driver->cell_info_list = getJailhouseCellsInfo(); @@ -136,6 +135,7 @@ jailhouseFreeDriver(virJailhouseDriverPtr driver) return; virMutexDestroy(&driver->lock); + virObjectUnref(driver->xmlopt); virObjectUnref(driver->domains); virObjectUnref(driver->config); VIR_FREE(driver); @@ -147,7 +147,6 @@ jailhouseConnectOpen(virConnectPtr conn, virConfPtr conf G_GNUC_UNUSED, unsigned int flags) { uid_t uid = geteuid(); - virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); if (!virConnectValidateURIPath(conn->uri->path, "jailhouse", uid == 0)) @@ -159,8 +158,10 @@ jailhouseConnectOpen(virConnectPtr conn, return VIR_DRV_OPEN_ERROR; } - conn->privateData = jailhouse_driver; + if (virConnectOpenEnsureACL(conn) < 0) + return VIR_DRV_OPEN_ERROR; + conn->privateData = jailhouse_driver; return VIR_DRV_OPEN_SUCCESS; } @@ -169,16 +170,19 @@ jailhouseConnectOpen(virConnectPtr conn, static int jailhouseConnectClose(virConnectPtr conn) { - conn->privateData = NULL; + conn->privateData = NULL; - return 0; + return 0; } static int jailhouseStateCleanup(void) { if (!jailhouse_driver) - return -1; + return -1; + + if (jailhouseDisable() < 0) + return -1; if (jailhouse_driver->lockFD != -1) virPidFileRelease(jailhouse_driver->config->stateDir, @@ -187,6 +191,9 @@ jailhouseStateCleanup(void) virMutexDestroy(&jailhouse_driver->lock); jailhouseFreeDriver(jailhouse_driver); + + jailhouse_driver = NULL; + return 0; } @@ -199,6 +206,9 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, virJailhouseDriverConfigPtr cfg = NULL; int rc; + if (jailhouse_driver) + return VIR_DRV_STATE_INIT_COMPLETE; + jailhouse_driver = g_new0(virJailhouseDriver, 1); jailhouse_driver->lockFD = -1; @@ -220,6 +230,10 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, if (jailhouseLoadConf(cfg) < 0) goto error; + if (!(jailhouse_driver->xmlopt = virDomainXMLOptionNew(NULL, NULL, + NULL, NULL, NULL))) + goto error; + if (virFileMakePath(cfg->stateDir) < 0) { virReportSystemError(errno, _("Failed to create state dir %s"), cfg->stateDir); @@ -292,7 +306,7 @@ jailhouseConnectListAllDomains(virConnectPtr conn, static virDomainPtr jailhouseDomainLookupByID(virConnectPtr conn, int id) { -virJailhouseDriverPtr driver = conn->privateData; + virJailhouseDriverPtr driver = conn->privateData; virDomainObjPtr cell; virDomainPtr dom = NULL; @@ -409,7 +423,6 @@ jailhouseDomainCreateWithFlags(virDomainPtr domain, virJailhouseCellInfoPtr cell_info; virDomainObjPtr cell; int ret = -1; - virCheckFlags(VIR_DOMAIN_NONE, -1); if (!domain->name) { @@ -462,23 +475,23 @@ jailhouseDomainCreateXML(virConnectPtr conn, virDomainPtr dom = NULL; virDomainDefPtr def = NULL; virDomainObjPtr cell = NULL; - virDomainDiskDefPtr disk = NULL; virJailhouseCellId cell_id; char **images = NULL; int num_images = 0, i = 0; unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; + bool removeInactive = false; if (flags & VIR_DOMAIN_START_VALIDATE) parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; - if ((def = virDomainDefParseString(xml, NULL, - NULL, parse_flags)) == NULL) + if (!(def = virDomainDefParseString(xml, driver->xmlopt, + NULL, parse_flags))) goto cleanup; - if ((cell = virDomainObjListFindByUUID(driver->domains, def->uuid))) + if (virDomainCreateXMLEnsureACL(conn, def) < 0) goto cleanup; - if (virDomainCreateXMLEnsureACL(conn, def) < 0) + if ((cell = virDomainObjListFindByUUID(driver->domains, def->uuid))) goto cleanup; if (!(cell_info = virJailhouseFindCellByName(driver, def->name))) { @@ -492,13 +505,13 @@ jailhouseDomainCreateXML(virConnectPtr conn, def->id = cell_info->id.id; if (!(cell = virDomainObjListAdd(driver->domains, def, - NULL, - VIR_DOMAIN_OBJ_LIST_ADD_LIVE | - VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, NULL))) + driver->xmlopt, 0, NULL))) goto cleanup; def = NULL; + removeInactive = true; + if (cell->def->ndisks < 1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Domain XML doesn't contain any disk images")); @@ -513,7 +526,7 @@ jailhouseDomainCreateXML(virConnectPtr conn, if (cell->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK && virDomainDiskGetType(cell->def->disks[i]) == VIR_STORAGE_TYPE_FILE) { - disk = cell->def->disks[i]; + virDomainDiskDefPtr disk = cell->def->disks[i]; const char *src = virDomainDiskGetSource(disk); if (!src) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -525,7 +538,7 @@ jailhouseDomainCreateXML(virConnectPtr conn, num_images++; } else { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("A Jailhouse doamin(cell) can ONLY have FILE type disks")); + _("A Jailhouse domain(cell) can ONLY have FILE type disks")); goto cleanup; } } @@ -533,7 +546,7 @@ jailhouseDomainCreateXML(virConnectPtr conn, // Initialize the cell_id. cell_id.id = cell->def->id; cell_id.padding = 0; - if (virStrncpy(cell_id.name, cell->def->name, JAILHOUSE_CELL_ID_NAMELEN, JAILHOUSE_CELL_ID_NAMELEN) < 0) { + if (virStrcpy(cell_id.name, cell->def->name, JAILHOUSE_CELL_ID_NAMELEN) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Cell name %s length exceeded the limit"), cell->def->name); @@ -561,6 +574,9 @@ jailhouseDomainCreateXML(virConnectPtr conn, dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); cleanup: + if (!dom && removeInactive && !cell->persistent) + virDomainObjListRemove(driver->domains, cell); + virDomainDefFree(def); virDomainObjEndAPI(&cell); return dom; @@ -671,7 +687,7 @@ jailhouseDomainDestroy(virDomainPtr domain) static int virjailhouseGetDomainTotalCpuStats(virDomainObjPtr cell, - unsigned long long *cpustats) + unsigned long long *cpustats) { // TODO(Prakhar): Not implemented yet. UNUSED(cell); @@ -721,7 +737,7 @@ jailhouseDomainGetState(virDomainPtr domain, goto cleanup; if (virDomainGetStateEnsureACL(domain->conn, cell->def) < 0) - goto cleanup; + goto cleanup; *state = virDomainObjGetState(cell, reason); ret = 0; -- 2.26.2

On Thu, Sep 17, 2020 at 04:23:58PM +0100, Daniel P. Berrangé wrote:
From: Prakhar Bansal <prakharbansal0910@gmail.com>
- Added xmlopt to the Jailhouse driver - Added ACL check in ConnectOpen --- src/jailhouse/jailhouse_api.c | 48 +++++++++++++------------- src/jailhouse/jailhouse_driver.c | 58 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 45 deletions(-)
This patch essentially shoudn't exist. Use "git rebase -i master" to go back and put the fixes into the appropriate patch that has the original problem. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

From: Prakhar Bansal <prakharbansal0910@gmail.com> --- src/jailhouse/jailhouse_driver.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 45b1f35896..70f0f365cb 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -122,6 +122,7 @@ jailhouseCreateAndLoadCells(virJailhouseDriverPtr driver) // Create all cells in the hypervisor. if (createJailhouseCells(driver->config->cell_config_dir) < 0) return -1; + // Get all cells created above. driver->cell_info_list = getJailhouseCellsInfo(); @@ -137,6 +138,7 @@ jailhouseFreeDriver(virJailhouseDriverPtr driver) virMutexDestroy(&driver->lock); virObjectUnref(driver->xmlopt); virObjectUnref(driver->domains); + virObjectUnref(driver->domainEventState); virObjectUnref(driver->config); VIR_FREE(driver); } @@ -222,6 +224,9 @@ jailhouseStateInitialize(bool privileged G_GNUC_UNUSED, if (!(jailhouse_driver->domains = virDomainObjListNew())) goto error; + if (!(jailhouse_driver->domainEventState = virObjectEventStateNew())) + goto error; + if (!(cfg = virJailhouseDriverConfigNew())) goto error; @@ -476,6 +481,7 @@ jailhouseDomainCreateXML(virConnectPtr conn, virDomainDefPtr def = NULL; virDomainObjPtr cell = NULL; virJailhouseCellId cell_id; + virObjectEventPtr event = NULL; char **images = NULL; int num_images = 0, i = 0; unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; @@ -573,12 +579,16 @@ jailhouseDomainCreateXML(virConnectPtr conn, dom = virGetDomain(conn, cell->def->name, cell->def->uuid, cell->def->id); + event = virDomainEventLifecycleNewFromObj(cell, + VIR_DOMAIN_EVENT_STARTED, + VIR_DOMAIN_EVENT_STARTED_BOOTED); cleanup: if (!dom && removeInactive && !cell->persistent) virDomainObjListRemove(driver->domains, cell); virDomainDefFree(def); virDomainObjEndAPI(&cell); + virObjectEventStateQueue(driver->domainEventState, event); return dom; } @@ -589,6 +599,7 @@ jailhouseDomainShutdownFlags(virDomainPtr domain, unsigned int flags) virJailhouseCellInfoPtr cell_info; virDomainObjPtr cell; virJailhouseCellId cell_id; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -627,8 +638,12 @@ jailhouseDomainShutdownFlags(virDomainPtr domain, unsigned int flags) ret = 0; + event = virDomainEventLifecycleNewFromObj(cell, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN); cleanup: virDomainObjEndAPI(&cell); + virObjectEventStateQueue(driver->domainEventState, event); return ret; } @@ -644,6 +659,7 @@ jailhouseDomainDestroyFlags(virDomainPtr domain, unsigned int flags) virJailhouseDriverPtr driver = domain->conn->privateData; virJailhouseCellInfoPtr cell_info; virDomainObjPtr cell; + virObjectEventPtr event = NULL; int ret = -1; virCheckFlags(0, -1); @@ -674,8 +690,12 @@ jailhouseDomainDestroyFlags(virDomainPtr domain, unsigned int flags) ret = 0; + event = virDomainEventLifecycleNewFromObj(cell, + VIR_DOMAIN_EVENT_STOPPED, + VIR_DOMAIN_EVENT_STOPPED_DESTROYED); cleanup: virDomainObjEndAPI(&cell); + virObjectEventStateQueue(driver->domainEventState, event); return ret; } -- 2.26.2

On Thu, Sep 17, 2020 at 04:23:50PM +0100, Daniel P. Berrangé wrote:
I'm sending this series on behalf of Prakhar Bansal who has been unable to sucessfully send the whole series. GMail is blocking sending of certain patches for unknown reasons.
https://www.redhat.com/archives/libvir-list/2020-September/msg00309.html
It is also available at
I've had a look through the patches, and given some comments. Overall the driver looks like a pretty good initial effort. Most of the comments are more on the style / codiing patterns side.
Prakhar Bansal (9): Jailhouse driver: first commit with skeleton code Jailhouse driver: Implementation of ConnectOpen Jailhouse driver: Implementation of ConnectGetType Jailhouse driver: Implementation of DomainCreate* callbacks Jailhouse driver: Implementation of DomainInfo/State/List Jailhouse driver: Implementation of DomainLookup* callbacks Jailhouse driver: Implementation of DomainShutdown/Destroy callbacks Jailhouse driver: Fixes for creation of cells, fetching cell info, disabling jailhouse hypervisor Jailhouse driver: Add events to events queue in DomainCreate/Shutdown/Destroy
include/libvirt/virterror.h | 1 + libvirt.spec.in | 7 + m4/virt-driver-jailhouse.m4 | 42 ++ meson.build | 4 + meson_options.txt | 1 + po/POTFILES.in | 2 + src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/jailhouse/Makefile.inc.am | 47 ++ src/jailhouse/jailhouse.conf | 10 + src/jailhouse/jailhouse_api.c | 458 +++++++++++++++ src/jailhouse/jailhouse_api.h | 103 ++++ src/jailhouse/jailhouse_driver.c | 837 +++++++++++++++++++++++++++ src/jailhouse/jailhouse_driver.h | 82 +++ src/jailhouse/libvirtd_jailhouse.aug | 43 ++ src/jailhouse/meson.build | 49 ++ src/meson.build | 1 + src/qemu/qemu_command.c | 1 + src/remote/remote_daemon.c | 4 + src/remote/remote_daemon_dispatch.c | 3 +- src/util/virerror.c | 1 + 21 files changed, 1697 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.conf create mode 100644 src/jailhouse/jailhouse_api.c create mode 100644 src/jailhouse/jailhouse_api.h 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
-- 2.26.2
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
participants (3)
-
Daniel P. Berrangé
-
Ján Tomko
-
Pavel Hrdina