From patchwork Fri Sep 27 09:00:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164091 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 582AB924 for ; Fri, 27 Sep 2019 09:02:16 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3DB3F2146E for ; Fri, 27 Sep 2019 09:02:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3DB3F2146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7R-0005Ks-QI; Fri, 27 Sep 2019 09:00:53 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7R-0005KD-6u for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:00:53 +0000 X-Inumbo-ID: 4e2a9b42-e105-11e9-b588-bc764e2007e4 Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4e2a9b42-e105-11e9-b588-bc764e2007e4; Fri, 27 Sep 2019 09:00:51 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id E52A9AF97; Fri, 27 Sep 2019 09:00:50 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:43 +0200 Message-Id: <20190927090048.28872-2-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 1/6] docs: add feature document for Xen hypervisor sysfs-like support X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" On the 2019 Xen developer summit there was agreement that the Xen hypervisor should gain support for a hierarchical name-value store similar to the Linux kernel's sysfs. In the beginning there should only be basic support: entries can be added from the hypervisor itself only, there is a simple hypercall interface to read the data. Add a feature document for setting the base of a discussion regarding the desired functionality and the entries to add. Signed-off-by: Juergen Gross --- V1: - remove the "--" prefixes of the sub-commands of the user tool (Jan Beulich) - rename xenfs to xenhypfs (Jan Beulich) - add "tree" and "write" options to user tool --- docs/features/hypervisorfs.pandoc | 119 ++++++++++++++++++++++++++++++++++++++ docs/misc/hypfs-paths.pandoc | 55 ++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 docs/features/hypervisorfs.pandoc create mode 100644 docs/misc/hypfs-paths.pandoc diff --git a/docs/features/hypervisorfs.pandoc b/docs/features/hypervisorfs.pandoc new file mode 100644 index 0000000000..3155cee7d3 --- /dev/null +++ b/docs/features/hypervisorfs.pandoc @@ -0,0 +1,119 @@ +% Hypervisor FS +% Revision 1 + +\clearpage + +# Basics +---------------- --------------------- + Status: e.g. **Supported** + + Architectures: all + + Components: Hypervisor, toolstack +---------------- --------------------- + +# Overview + +The Hypervisor FS is a hierarchical name-value store for reporting +information to guests, especially dom0. It is similar to the Linux +kernel's sysfs, but without the functionality to directly alter +entries values. Entries and directories are created by the hypervisor, +while the toolstack is able to use a hypercall to query the entry +values. + +# User details + +With: + + xenhypfs ls + +the user can list the entries of a specific path of the FS. Using: + + xenhypfs cat + +the content of an entry can be retrieved. Using: + + xenhypfs write + +a writable entry can be modified. With: + + xenhypfs tree + +the complete Hypervisor FS entry tree can be printed. + +The FS structure is: + + / + buildinfo/ directory containing build-time data + config contents of .config file used to build Xen + cpu-bugs/ x86: directory of cpu bug information + l1tf "Vulnerable" or "Not vulnerable" + mds "Vulnerable" or "Not vulnerable" + meltdown "Vulnerable" or "Not vulnerable" + spec-store-bypass "Vulnerable" or "Not vulnerable" + spectre-v1 "Vulnerable" or "Not vulnerable" + spectre-v2 "Vulnerable" or "Not vulnerable" + mitigations/ directory of mitigation settings + bti-thunk "N/A", "RETPOLINE", "LFENCE" or "JMP" + spec-ctrl "No", "IBRS+" or IBRS-" + ibpb "No" or "Yes" + l1d-flush "No" or "Yes" + md-clear "No" or "VERW" + l1tf-barrier "No" or "Yes" + active-hvm/ directory for mitigations active in hvm doamins + msr-spec-ctrl "No" or "Yes" + rsb "No" or "Yes" + eager-fpu "No" or "Yes" + md-clear "No" or "Yes" + active-pv/ directory for mitigations active in pv doamins + msr-spec-ctrl "No" or "Yes" + rsb "No" or "Yes" + eager-fpu "No" or "Yes" + md-clear "No" or "Yes" + xpti "No" or list of "dom0", "domU", "PCID on" + l1tf-shadow "No" or list of "dom0", "domU" + parameters/ directory with hypervisor parameter values + (boot/runtime parameters) + +# Technical details + +Access to the hypervisor filesystem is done via the stable new hypercall +__HYPERVISOR_filesystem_op. + +* hypercall interface specification + * `xen/include/public/filesystem.h` +* hypervisor internal files + * `xen/include/xen/filesystem.h` + * `xen/common/filesystem.c` +* `libxenhypfs` + * `tools/libs/libxenhypfs/*` +* `xenhypfs` + * `tools/misc/xenhypfs.c` +* path documentation + * `docs/misc/hypfs-paths.pandoc` + +# Testing + +Any new parameters or hardware mitigations should be verified to show up +correctly in the filesystem. + +# Areas for improvement + +* More detailed access rights +* Entries per domain and/or per cpupool + +# Known issues + +* None + +# References + +* None + +# History + +------------------------------------------------------------------------ +Date Revision Version Notes +---------- -------- -------- ------------------------------------------- +2019-09-18 1 Xen 4.13 Document written +---------- -------- -------- ------------------------------------------- diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc new file mode 100644 index 0000000000..2fe5455e6f --- /dev/null +++ b/docs/misc/hypfs-paths.pandoc @@ -0,0 +1,55 @@ +# Xenhypfs Paths + +This document attempts to define all the paths which are available +in the Xen hypervisor file system (hypfs). + +The hypervisor file system can be accessed via the xenhypfs tool. + +## Notation + +The hypervisor file system is similar to the Linux kernel's sysfs. +In this document directories are always specified with a trailing "/". + +The following notation conventions apply: + + DIRECTORY/ + + PATH = VALUES [TAGS] + +The first syntax defines a directory. It normally contains related +entries and the general scope of the directory is described. + +The second syntax defines a file entry containing values which are +either set by the hypervisor or, if the file is writable, can be set +by the user. + +PATH can contain simple regex constructs following the Perl compatible +regexp syntax described in pcre(3) or perlre(1). + +VALUES are strings and can take the following forms: + +* STRING -- an arbitrary string. +* INTEGER -- An integer, in decimal representation unless otherwise + noted. +* "a literal string" -- literal strings are contained within quotes. +* (VALUE | VALUE | ... ) -- a set of alternatives. Alternatives are + separated by a "|" and all the alternatives are enclosed in "(" and + ")". + +Additional TAGS may follow as a comma separated set of the following +tags enclosed in square brackets. + +* w -- Path is writable by the user. This capability is usually + limited to the control domain (e.g. dom0). +* ARM | ARM32 | X86: the path is available for the respective architecture + only. +* PV -- Path is valid for PV capable hypervisors only. +* HVM -- Path is valid for HVM capable hypervisors only. +* CONFIG_* -- Path is valid only in case the hypervisor was built with + the respective config option. + +## General Paths + +#### / + +The root of the hypervisor file system. From patchwork Fri Sep 27 09:00:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164097 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 76D5014DB for ; Fri, 27 Sep 2019 09:02:23 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4A5C52146E for ; Fri, 27 Sep 2019 09:02:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4A5C52146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7W-0005NZ-Im; Fri, 27 Sep 2019 09:00:58 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7V-0005N8-DQ for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:00:57 +0000 X-Inumbo-ID: 4e3a9844-e105-11e9-bf31-bc764e2007e4 Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4e3a9844-e105-11e9-bf31-bc764e2007e4; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 0FA5EAFE1; Fri, 27 Sep 2019 09:00:51 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:44 +0200 Message-Id: <20190927090048.28872-3-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 2/6] xen: add basic hypervisor filesystem support X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich , Volodymyr Babchuk , =?utf-8?q?Roger_Pau_Monn?= =?utf-8?q?=C3=A9?= MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add the infrastructure for the hypervisor filesystem. This includes the hypercall interface and the base functions for entry creation, deletion and modification. Initially we support string and unsigned integer entry types. The saved entry size is an upper bound, so for unsigned integer entries we always set the value "11". Signed-off-by: Juergen Gross --- V1: - rename files from filesystem.* to hypfs.* - add dummy write entry support - rename hypercall filesystem_op to hypfs_op - add support for unsigned integer entries --- xen/arch/arm/traps.c | 1 + xen/arch/x86/hvm/hypercall.c | 1 + xen/arch/x86/hypercall.c | 1 + xen/arch/x86/pv/hypercall.c | 1 + xen/common/Makefile | 1 + xen/common/hypfs.c | 314 +++++++++++++++++++++++++++++++++++++++++++ xen/include/public/errno.h | 1 + xen/include/public/hypfs.h | 123 +++++++++++++++++ xen/include/public/xen.h | 1 + xen/include/xen/hypercall.h | 8 ++ xen/include/xen/hypfs.h | 40 ++++++ 11 files changed, 492 insertions(+) create mode 100644 xen/common/hypfs.c create mode 100644 xen/include/public/hypfs.h create mode 100644 xen/include/xen/hypfs.h diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index a3b961bd06..4b1acd67a2 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1401,6 +1401,7 @@ static arm_hypercall_t arm_hypercall_table[] = { #ifdef CONFIG_ARGO HYPERCALL(argo_op, 5), #endif + HYPERCALL(hypfs_op, 5), }; #ifndef NDEBUG diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c index 33dd2d99d2..210dda4f38 100644 --- a/xen/arch/x86/hvm/hypercall.c +++ b/xen/arch/x86/hvm/hypercall.c @@ -144,6 +144,7 @@ static const hypercall_table_t hvm_hypercall_table[] = { #endif HYPERCALL(xenpmu_op), COMPAT_CALL(dm_op), + HYPERCALL(hypfs_op), HYPERCALL(arch_1) }; diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c index d483dbaa6b..8a8f223481 100644 --- a/xen/arch/x86/hypercall.c +++ b/xen/arch/x86/hypercall.c @@ -73,6 +73,7 @@ const hypercall_args_t hypercall_args_table[NR_hypercalls] = ARGS(hvm_op, 2), ARGS(dm_op, 3), #endif + ARGS(hypfs_op, 5), ARGS(mca, 1), ARGS(arch_1, 1), }; diff --git a/xen/arch/x86/pv/hypercall.c b/xen/arch/x86/pv/hypercall.c index 0c84c0b3a0..e6860247cc 100644 --- a/xen/arch/x86/pv/hypercall.c +++ b/xen/arch/x86/pv/hypercall.c @@ -84,6 +84,7 @@ const hypercall_table_t pv_hypercall_table[] = { HYPERCALL(hvm_op), COMPAT_CALL(dm_op), #endif + HYPERCALL(hypfs_op), HYPERCALL(mca), HYPERCALL(arch_1), }; diff --git a/xen/common/Makefile b/xen/common/Makefile index 62b34e69e9..a3f66aa0c0 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -11,6 +11,7 @@ obj-y += domain.o obj-y += event_2l.o obj-y += event_channel.o obj-y += event_fifo.o +obj-y += hypfs.o obj-$(CONFIG_CRASH_DEBUG) += gdbstub.o obj-$(CONFIG_GRANT_TABLE) += grant_table.o obj-y += guestcopy.o diff --git a/xen/common/hypfs.c b/xen/common/hypfs.c new file mode 100644 index 0000000000..7d9595dfa7 --- /dev/null +++ b/xen/common/hypfs.c @@ -0,0 +1,314 @@ +/****************************************************************************** + * + * hypfs.c + * + * Simple sysfs-like file system for the hypervisor. + */ + +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(hypfs_lock); + +struct hypfs_dir hypfs_root = { + .list = LIST_HEAD_INIT(hypfs_root.list), +}; + +static struct hypfs_entry hypfs_root_entry = { + .type = hypfs_type_dir, + .name = "", + .list = LIST_HEAD_INIT(hypfs_root_entry.list), + .parent = &hypfs_root, + .dir = &hypfs_root, +}; + +static int hypfs_add_entry(struct hypfs_dir *parent, struct hypfs_entry *new) +{ + int ret = -ENOENT; + struct list_head *l; + + if ( !new->content ) + return -EINVAL; + + spin_lock(&hypfs_lock); + + list_for_each ( l, &parent->list ) + { + struct hypfs_entry *e = list_entry(l, struct hypfs_entry, list); + int cmp = strcmp(e->name, new->name); + + if ( cmp > 0 ) + { + ret = 0; + list_add_tail(&new->list, l); + break; + } + if ( cmp == 0 ) + { + ret = -EEXIST; + break; + } + } + + if ( ret == -ENOENT ) + { + ret = 0; + list_add_tail(&new->list, &parent->list); + } + + if ( !ret ) + { + unsigned int sz = strlen(new->name) + 1; + + parent->content_size += sizeof(struct xen_hypfs_direntry) + + ROUNDUP(sz, 4); + new->parent = parent; + } + + spin_unlock(&hypfs_lock); + + return ret; +} + +int hypfs_new_entry_any(struct hypfs_dir *parent, const char *name, + enum hypfs_entry_type type, void *content) +{ + int ret = -ENOMEM; + struct hypfs_entry *new = xzalloc(struct hypfs_entry); + + if ( !new ) + return ret; + + new->name = name; + new->type = type; + new->content = content; + + ret = hypfs_add_entry(parent, new); + + if ( ret ) + xfree(new); + + return ret; +} + +int hypfs_new_entry_string(struct hypfs_dir *parent, const char *name, + char *val) +{ + return hypfs_new_entry_any(parent, name, hypfs_type_string, val); +} + +int hypfs_new_entry_uint(struct hypfs_dir *parent, const char *name, + unsigned int *val) +{ + return hypfs_new_entry_any(parent, name, hypfs_type_uint, val); +} + +int hypfs_new_dir(struct hypfs_dir *parent, const char *name, + struct hypfs_dir *dir) +{ + if ( !dir ) + dir = xzalloc(struct hypfs_dir); + + return hypfs_new_entry_any(parent, name, hypfs_type_dir, dir); +} + +static int hypfs_get_path_user(char *buf, XEN_GUEST_HANDLE_PARAM(void) uaddr, + unsigned long len) +{ + if ( len > XEN_HYPFS_MAX_PATHLEN ) + return -EINVAL; + + if ( copy_from_guest(buf, uaddr, len) ) + return -EFAULT; + + buf[len - 1] = 0; + + return 0; +} + +static struct hypfs_entry *hypfs_get_entry_rel(struct hypfs_entry *dir, + char *path) +{ + char *slash; + struct hypfs_entry *entry; + struct list_head *l; + unsigned int name_len; + + if ( *path == 0 ) + return dir; + + if ( dir->type != hypfs_type_dir ) + return NULL; + + slash = strchr(path, '/'); + if ( !slash ) + slash = strchr(path, '\0'); + name_len = slash - path; + + list_for_each ( l, &dir->dir->list ) + { + int cmp; + + entry = list_entry(l, struct hypfs_entry, list); + cmp = strncmp(path, entry->name, name_len); + if ( cmp < 0 ) + return NULL; + if ( cmp > 0 ) + continue; + if ( strlen(entry->name) == name_len ) + return *slash ? hypfs_get_entry_rel(entry, slash + 1) : entry; + } + + return NULL; +} + +struct hypfs_entry *hypfs_get_entry(char *path) +{ + if ( path[0] != '/' ) + return NULL; + + return hypfs_get_entry_rel(&hypfs_root_entry, path + 1); +} + +static unsigned int hypfs_get_entry_len(struct hypfs_entry *entry) +{ + unsigned int len = 0; + + switch ( entry->type ) + { + case hypfs_type_dir: + len = entry->dir->content_size; + break; + case hypfs_type_string: + len = strlen(entry->str_val) + 1; + break; + case hypfs_type_uint: + len = 11; /* longest possible printed value + 1 */ + break; + } + + return len; +} + +long do_hypfs_op(unsigned int cmd, + XEN_GUEST_HANDLE_PARAM(void) arg1, unsigned long arg2, + XEN_GUEST_HANDLE_PARAM(void) arg3, unsigned long arg4) +{ + int ret; + struct hypfs_entry *entry; + unsigned int len; + static char path[XEN_HYPFS_MAX_PATHLEN]; + + if ( !is_control_domain(current->domain) && + !is_hardware_domain(current->domain) ) + return -EPERM; + + spin_lock(&hypfs_lock); + + ret = hypfs_get_path_user(path, arg1, arg2); + if ( ret ) + goto out; + + entry = hypfs_get_entry(path); + if ( !entry ) + { + ret = -ENOENT; + goto out; + } + + switch ( cmd ) + { + case XEN_HYPFS_OP_read_contents: + { + char buf[12]; + char *val = buf; + + len = hypfs_get_entry_len(entry); + if ( len > arg4 ) + { + ret = len; + break; + } + + switch ( entry->type ) + { + case hypfs_type_dir: + ret = -EISDIR; + break; + case hypfs_type_string: + val = entry->str_val; + break; + case hypfs_type_uint: + len = snprintf(buf, sizeof(buf), "%u", *entry->uint_val) + 1; + break; + } + + if ( !ret && copy_to_guest(arg3, val, len) ) + ret = -EFAULT; + + break; + } + + case XEN_HYPFS_OP_read_dir: + { + struct list_head *l; + + if ( entry->type != hypfs_type_dir ) + { + ret = -ENOTDIR; + break; + } + + len = entry->dir->content_size; + if ( len > arg4 ) + { + ret = len; + break; + } + + list_for_each ( l, &entry->dir->list ) + { + struct xen_hypfs_direntry direntry; + struct hypfs_entry *e = list_entry(l, struct hypfs_entry, list); + unsigned int e_len = strlen(e->name) + 1; + + e_len = sizeof(direntry) + ROUNDUP(e_len, 4); + direntry.flags = (e->type == hypfs_type_dir) ? XEN_HYPFS_ISDIR : 0; + direntry.off_next = list_is_last(l, &entry->dir->list) ? 0 : e_len; + direntry.content_len = hypfs_get_entry_len(e); + if ( copy_to_guest(arg3, &direntry, 1) ) + { + ret = -EFAULT; + goto out; + } + + if ( copy_to_guest_offset(arg3, sizeof(direntry), e->name, + strlen(e->name) + 1) ) + { + ret = -EFAULT; + goto out; + } + + guest_handle_add_offset(arg3, e_len); + } + + break; + } + + case XEN_HYPFS_OP_write_contents: + ret = -EACCES; + break; + + default: + ret = -ENOSYS; + break; + } + + out: + spin_unlock(&hypfs_lock); + + return ret; +} diff --git a/xen/include/public/errno.h b/xen/include/public/errno.h index e1d02fcddf..5c53af6af9 100644 --- a/xen/include/public/errno.h +++ b/xen/include/public/errno.h @@ -78,6 +78,7 @@ XEN_ERRNO(EBUSY, 16) /* Device or resource busy */ XEN_ERRNO(EEXIST, 17) /* File exists */ XEN_ERRNO(EXDEV, 18) /* Cross-device link */ XEN_ERRNO(ENODEV, 19) /* No such device */ +XEN_ERRNO(ENOTDIR, 20) /* Not a directory */ XEN_ERRNO(EISDIR, 21) /* Is a directory */ XEN_ERRNO(EINVAL, 22) /* Invalid argument */ XEN_ERRNO(ENFILE, 23) /* File table overflow */ diff --git a/xen/include/public/hypfs.h b/xen/include/public/hypfs.h new file mode 100644 index 0000000000..8822e2fb15 --- /dev/null +++ b/xen/include/public/hypfs.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * Xen Hypervisor Filesystem + * + * Copyright (c) 2019, SUSE Software Solutions Germany GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __XEN_PUBLIC_HYPFS_H__ +#define __XEN_PUBLIC_HYPFS_H__ + +#include "xen.h" + +/* + * Definitions for the __HYPERVISOR_hypfs_op hypercall. + */ + +/* Maximum length of a path in the filesystem. */ +#define XEN_HYPFS_MAX_PATHLEN 1024 + +struct xen_hypfs_direntry { + uint16_t flags; +#define XEN_HYPFS_ISDIR 0x0001 +#define XEN_HYPFS_WRITEABLE 0x0002 + /* Offset in bytes to next entry (0 == this is the last entry). */ + uint16_t off_next; + uint32_t content_len; + char name[XEN_FLEX_ARRAY_DIM]; +}; + +/* + * Hypercall operations. + */ + +/* + * XEN_HYPFS_OP_read_contents + * + * Read contents of a filesystem entry. + * + * Returns the contents of an entry in the buffer supplied by the caller. + * Only text data with a trailing zero byte is returned. + * + * arg1: XEN_GUEST_HANDLE(path name) + * arg2: length of path name (including trailing zero byte) + * arg3: XEN_GUEST_HANDLE(content buffer) + * arg4: content buffer size + * + * Possible return values: + * 0: success + * -EPERM: operation not permitted + * -ENOENT: entry not found + * -EACCESS: access to entry not permitted + * -EISDIR: entry is a directory + * -EINVAL: invalid parameter + * positive value: content buffer was too small, returned value is needed size + */ +#define XEN_HYPFS_OP_read_contents 1 + +/* + * XEN_HYPFS_OP_read_dir + * + * Read directory entries of a directory. + * + * Returns a struct xen_fs_direntry for each entry in a directory. + * + * arg1: XEN_GUEST_HANDLE(path name) + * arg2: length of path name (including trailing zero byte) + * arg3: XEN_GUEST_HANDLE(content buffer) + * arg4: content buffer size + * + * Possible return values: + * 0: success + * -EPERM: operation not permitted + * -ENOENT: entry not found + * -EACCESS: access to entry not permitted + * -ENOTDIR: entry is not a directory + * -EINVAL: invalid parameter + * positive value: content buffer was too small, returned value is needed size + */ +#define XEN_HYPFS_OP_read_dir 2 + +/* + * XEN_HYPFS_OP_read_contents + * + * Write contents of a filesystem entry. + * + * Writes an entry with the contents of a buffer supplied by the caller. + * Only text data with a trailing zero byte can be written. + * + * arg1: XEN_GUEST_HANDLE(path name) + * arg2: length of path name (including trailing zero byte) + * arg3: XEN_GUEST_HANDLE(content buffer) + * arg4: content buffer size + * + * Possible return values: + * 0: success + * -EPERM: operation not permitted + * -ENOENT: entry not found + * -EACCESS: access to entry not permitted + * -EISDIR: entry is a directory + * -EINVAL: invalid parameter + * -ENOMEM: memory shortage in the hypervisor + */ +#define XEN_HYPFS_OP_write_contents 3 + +#endif /* __XEN_PUBLIC_HYPFS_H__ */ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index d2198dffad..bf80f1da8c 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -130,6 +130,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); #define __HYPERVISOR_argo_op 39 #define __HYPERVISOR_xenpmu_op 40 #define __HYPERVISOR_dm_op 41 +#define __HYPERVISOR_hypfs_op 42 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 diff --git a/xen/include/xen/hypercall.h b/xen/include/xen/hypercall.h index ad8ad27b23..349a0f6487 100644 --- a/xen/include/xen/hypercall.h +++ b/xen/include/xen/hypercall.h @@ -150,6 +150,14 @@ do_dm_op( unsigned int nr_bufs, XEN_GUEST_HANDLE_PARAM(xen_dm_op_buf_t) bufs); +extern long +do_hypfs_op( + unsigned int cmd, + XEN_GUEST_HANDLE_PARAM(void) arg1, + unsigned long arg2, + XEN_GUEST_HANDLE_PARAM(void) arg3, + unsigned long arg4); + #ifdef CONFIG_COMPAT extern int diff --git a/xen/include/xen/hypfs.h b/xen/include/xen/hypfs.h new file mode 100644 index 0000000000..d2537211f6 --- /dev/null +++ b/xen/include/xen/hypfs.h @@ -0,0 +1,40 @@ +#ifndef __XEN_HYPFS_H__ +#define __XEN_HYPFS_H__ + +#include + +struct hypfs_dir { + unsigned int content_size; + struct list_head list; +}; + +enum hypfs_entry_type { + hypfs_type_dir, + hypfs_type_string, + hypfs_type_uint +}; + +struct hypfs_entry { + enum hypfs_entry_type type; + const char *name; + struct list_head list; + struct hypfs_dir *parent; + union { + void *content; + struct hypfs_dir *dir; + char *str_val; + unsigned int *uint_val; + }; +}; + +extern struct hypfs_dir hypfs_root; + +int hypfs_new_dir(struct hypfs_dir *parent, const char *name, + struct hypfs_dir *dir); +int hypfs_new_entry_string(struct hypfs_dir *parent, const char *name, + char *val); +int hypfs_new_entry_uint(struct hypfs_dir *parent, const char *name, + unsigned int *val); +struct hypfs_entry *hypfs_get_entry(char *path); + +#endif /* __XEN_HYPFS_H__ */ From patchwork Fri Sep 27 09:00:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164099 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 188B5924 for ; Fri, 27 Sep 2019 09:02:27 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E79C02146E for ; Fri, 27 Sep 2019 09:02:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E79C02146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7T-0005Lh-3z; Fri, 27 Sep 2019 09:00:55 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7R-0005Kw-VX for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:00:54 +0000 X-Inumbo-ID: 4e3d9c75-e105-11e9-9671-12813bfff9fa Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4e3d9c75-e105-11e9-9671-12813bfff9fa; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 3CDF5AFE3; Fri, 27 Sep 2019 09:00:51 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:45 +0200 Message-Id: <20190927090048.28872-4-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 3/6] libs: add libxenhypfs X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Ian Jackson , Wei Liu MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add the new library libxenhypfs for access to the hypervisor filesystem. Signed-off-by: Juergen Gross Acked-by: Ian Jackson --- V1: - rename to libxenhypfs - add xenhypfs_write() --- tools/Rules.mk | 6 + tools/libs/Makefile | 1 + tools/libs/hypfs/Makefile | 14 ++ tools/libs/hypfs/core.c | 252 ++++++++++++++++++++++++++++++++++++ tools/libs/hypfs/include/xenhypfs.h | 60 +++++++++ tools/libs/hypfs/libxenhypfs.map | 9 ++ tools/libs/hypfs/xenhypfs.pc.in | 10 ++ 7 files changed, 352 insertions(+) create mode 100644 tools/libs/hypfs/Makefile create mode 100644 tools/libs/hypfs/core.c create mode 100644 tools/libs/hypfs/include/xenhypfs.h create mode 100644 tools/libs/hypfs/libxenhypfs.map create mode 100644 tools/libs/hypfs/xenhypfs.pc.in diff --git a/tools/Rules.mk b/tools/Rules.mk index cf8935d6a3..b1ebb4c96c 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -19,6 +19,7 @@ XEN_LIBXENGNTTAB = $(XEN_ROOT)/tools/libs/gnttab XEN_LIBXENCALL = $(XEN_ROOT)/tools/libs/call XEN_LIBXENFOREIGNMEMORY = $(XEN_ROOT)/tools/libs/foreignmemory XEN_LIBXENDEVICEMODEL = $(XEN_ROOT)/tools/libs/devicemodel +XEN_LIBXENHYPFS = $(XEN_ROOT)/tools/libs/hypfs XEN_LIBXC = $(XEN_ROOT)/tools/libxc XEN_XENLIGHT = $(XEN_ROOT)/tools/libxl # Currently libxlutil lives in the same directory as libxenlight @@ -134,6 +135,11 @@ SHDEPS_libxendevicemodel = $(SHLIB_libxentoollog) $(SHLIB_libxentoolcore) $(SHLI LDLIBS_libxendevicemodel = $(SHDEPS_libxendevicemodel) $(XEN_LIBXENDEVICEMODEL)/libxendevicemodel$(libextension) SHLIB_libxendevicemodel = $(SHDEPS_libxendevicemodel) -Wl,-rpath-link=$(XEN_LIBXENDEVICEMODEL) +CFLAGS_libxenhypfs = -I$(XEN_LIBXENHYPFS)/include $(CFLAGS_xeninclude) +SHDEPS_libxenhypfs = $(SHLIB_libxentoollog) $(SHLIB_libxentoolcore) $(SHLIB_xencall) +LDLIBS_libxenhypfs = $(SHDEPS_libxenhypfs) $(XEN_LIBXENHYPFS)/libxenhypfs$(libextension) +SHLIB_libxenhypfs = $(SHDEPS_libxenhypfs) -Wl,-rpath-link=$(XEN_LIBXENHYPFS) + # code which compiles against libxenctrl get __XEN_TOOLS__ and # therefore sees the unstable hypercall interfaces. CFLAGS_libxenctrl = -I$(XEN_LIBXC)/include $(CFLAGS_libxentoollog) $(CFLAGS_libxenforeignmemory) $(CFLAGS_libxendevicemodel) $(CFLAGS_xeninclude) -D__XEN_TOOLS__ diff --git a/tools/libs/Makefile b/tools/libs/Makefile index 88901e7341..69cdfb5975 100644 --- a/tools/libs/Makefile +++ b/tools/libs/Makefile @@ -9,6 +9,7 @@ SUBDIRS-y += gnttab SUBDIRS-y += call SUBDIRS-y += foreignmemory SUBDIRS-y += devicemodel +SUBDIRS-y += hypfs ifeq ($(CONFIG_RUMP),y) SUBDIRS-y := toolcore diff --git a/tools/libs/hypfs/Makefile b/tools/libs/hypfs/Makefile new file mode 100644 index 0000000000..c571597686 --- /dev/null +++ b/tools/libs/hypfs/Makefile @@ -0,0 +1,14 @@ +XEN_ROOT = $(CURDIR)/../../.. +include $(XEN_ROOT)/tools/Rules.mk + +MAJOR = 1 +MINOR = 0 +LIBNAME := hypfs +USELIBS := toollog toolcore call + +SRCS-y += core.c + +include ../libs.mk + +$(PKG_CONFIG_LOCAL): PKG_CONFIG_INCDIR = $(XEN_LIBXENHYPFS)/include +$(PKG_CONFIG_LOCAL): PKG_CONFIG_CFLAGS_LOCAL = $(CFLAGS_xeninclude) diff --git a/tools/libs/hypfs/core.c b/tools/libs/hypfs/core.c new file mode 100644 index 0000000000..edbf37f2c1 --- /dev/null +++ b/tools/libs/hypfs/core.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2019 SUSE Software Solutions Germany GmbH + * + * 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; + * version 2.1 of the License. + * + * 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 . + */ + +#define __XEN_TOOLS__ 1 + +#include +#include +#include + +#include +#include +#include + +#include + +struct xenhypfs_handle { + xentoollog_logger *logger, *logger_tofree; + unsigned int flags; + xencall_handle *xcall; +}; + +xenhypfs_handle *xenhypfs_open(xentoollog_logger *logger, + unsigned open_flags) +{ + xenhypfs_handle *fshdl = calloc(1, sizeof(*fshdl)); + + if (!fshdl) + return NULL; + + fshdl->flags = open_flags; + fshdl->logger = logger; + fshdl->logger_tofree = NULL; + + if (!fshdl->logger) { + fshdl->logger = fshdl->logger_tofree = + (xentoollog_logger*) + xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0); + if (!fshdl->logger) + goto err; + } + + fshdl->xcall = xencall_open(fshdl->logger, 0); + if (!fshdl->xcall) + goto err; + + + return fshdl; + +err: + xtl_logger_destroy(fshdl->logger_tofree); + xencall_close(fshdl->xcall); + free(fshdl); + return NULL; +} + +int xenhypfs_close(xenhypfs_handle *fshdl) +{ + if (!fshdl) + return 0; + + xencall_close(fshdl->xcall); + xtl_logger_destroy(fshdl->logger_tofree); + free(fshdl); + return 0; +} + +static int xenhypfs_get_pathbuf(xenhypfs_handle *fshdl, const char *path, + char **path_buf) +{ + int ret = -1; + int path_sz; + + if (!fshdl) { + errno = EBADF; + goto out; + } + + path_sz = strlen(path) + 1; + if (path_sz > XEN_HYPFS_MAX_PATHLEN) + { + errno = ENAMETOOLONG; + goto out; + } + + *path_buf = xencall_alloc_buffer(fshdl->xcall, path_sz); + if (!*path_buf) { + errno = ENOMEM; + goto out; + } + strcpy(*path_buf, path); + + ret = path_sz; + + out: + return ret; +} + +static void *xenhypfs_read_any(xenhypfs_handle *fshdl, const char *path, + unsigned int cmd) +{ + char *buf = NULL, *path_buf = NULL; + int ret; + int sz, path_sz; + + ret = xenhypfs_get_pathbuf(fshdl, path, &path_buf); + if (ret < 0) + goto out; + + path_sz = ret; + + for (sz = 4096; sz > 0; sz = ret) { + if (buf) + xencall_free_buffer(fshdl->xcall, buf); + + buf = xencall_alloc_buffer(fshdl->xcall, sz); + if (!buf) { + errno = ENOMEM; + goto out; + } + + ret = xencall5(fshdl->xcall, __HYPERVISOR_hypfs_op, cmd, + (unsigned long)path_buf, path_sz, + (unsigned long)buf, sz); + } + + if (ret < 0) { + errno = -ret; + xencall_free_buffer(fshdl->xcall, buf); + buf = NULL; + goto out; + } + + out: + ret = errno; + xencall_free_buffer(fshdl->xcall, path_buf); + errno = ret; + + return buf; +} + +char *xenhypfs_read(xenhypfs_handle *fshdl, const char *path) +{ + char *buf, *ret_buf = NULL; + int ret; + + buf = xenhypfs_read_any(fshdl, path, XEN_HYPFS_OP_read_contents); + if (buf) + ret_buf = strdup(buf); + + ret = errno; + xencall_free_buffer(fshdl->xcall, buf); + errno = ret; + + return ret_buf; +} + +struct xenhypfs_dirent *xenhypfs_readdir(xenhypfs_handle *fshdl, + const char *path, + unsigned int *num_entries) +{ + void *buf, *curr; + int ret; + char *names; + struct xenhypfs_dirent *ret_buf = NULL; + unsigned int n, name_sz = 0; + struct xen_hypfs_direntry *entry; + + buf = xenhypfs_read_any(fshdl, path, XEN_HYPFS_OP_read_dir); + if (!buf) + goto out; + + curr = buf; + for (n = 1;; n++) { + entry = curr; + name_sz += strlen(entry->name) + 1; + if (!entry->off_next) + break; + + curr += entry->off_next; + } + + ret_buf = malloc(n * sizeof(*ret_buf) + name_sz); + if (!ret_buf) + goto out; + + *num_entries = n; + names = (char *)(ret_buf + n); + curr = buf; + for (n = 0; n < *num_entries; n++) { + entry = curr; + ret_buf[n].name = names; + ret_buf[n].is_dir = entry->flags & XEN_HYPFS_ISDIR; + strcpy(names, entry->name); + names += strlen(entry->name) + 1; + curr += entry->off_next; + } + + out: + ret = errno; + xencall_free_buffer(fshdl->xcall, buf); + errno = ret; + + return ret_buf; +} + +int xenhypfs_write(xenhypfs_handle *fshdl, const char *path, const char *val) +{ + char *buf = NULL, *path_buf = NULL; + int ret, saved_errno; + int sz, path_sz; + + ret = xenhypfs_get_pathbuf(fshdl, path, &path_buf); + if (ret < 0) + goto out; + + path_sz = ret; + + sz = strlen(val) + 1; + buf = xencall_alloc_buffer(fshdl->xcall, sz); + if (!buf) { + ret = -1; + errno = ENOMEM; + goto out; + } + strcpy(buf, val); + + ret = xencall5(fshdl->xcall, __HYPERVISOR_hypfs_op, + XEN_HYPFS_OP_write_contents, + (unsigned long)path_buf, path_sz, + (unsigned long)buf, sz); + + out: + saved_errno = errno; + xencall_free_buffer(fshdl->xcall, path_buf); + xencall_free_buffer(fshdl->xcall, buf); + errno = saved_errno; + return ret; +} diff --git a/tools/libs/hypfs/include/xenhypfs.h b/tools/libs/hypfs/include/xenhypfs.h new file mode 100644 index 0000000000..443221510a --- /dev/null +++ b/tools/libs/hypfs/include/xenhypfs.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019 SUSE Software Solutions Germany GmbH + * + * 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; + * version 2.1 of the License. + * + * 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 . + */ +#ifndef XENHYPFS_H +#define XENHYPFS_H + +#include +#include + +#include +#include + +/* Callers who don't care don't need to #include */ +struct xentoollog_logger; + +typedef struct xenhypfs_handle xenhypfs_handle; + +struct xenhypfs_dirent { + char *name; + bool is_dir; +}; + +xenhypfs_handle *xenhypfs_open(struct xentoollog_logger *logger, + unsigned int open_flags); +int xenhypfs_close(xenhypfs_handle *fshdl); + +/* Returned buffer should be freed via free(). */ +char *xenhypfs_read(xenhypfs_handle *fshdl, const char *path); + +/* Returned buffer should be freed via free(). */ +struct xenhypfs_dirent *xenhypfs_readdir(xenhypfs_handle *fshdl, + const char *path, + unsigned int *num_entries); + +int xenhypfs_write(xenhypfs_handle *fshdl, const char *path, const char *val); + +#endif /* XENHYPFS_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libs/hypfs/libxenhypfs.map b/tools/libs/hypfs/libxenhypfs.map new file mode 100644 index 0000000000..39c63f4367 --- /dev/null +++ b/tools/libs/hypfs/libxenhypfs.map @@ -0,0 +1,9 @@ +VERS_1.0 { + global: + xenhypfs_open; + xenhypfs_close; + xenhypfs_read; + xenhypfs_readdir; + xenhypfs_write; + local: *; /* Do not expose anything by default */ +}; diff --git a/tools/libs/hypfs/xenhypfs.pc.in b/tools/libs/hypfs/xenhypfs.pc.in new file mode 100644 index 0000000000..9cb968f0db --- /dev/null +++ b/tools/libs/hypfs/xenhypfs.pc.in @@ -0,0 +1,10 @@ +prefix=@@prefix@@ +includedir=@@incdir@@ +libdir=@@libdir@@ + +Name: Xenhypfs +Description: The Xenhypfs library for Xen hypervisor +Version: @@version@@ +Cflags: -I${includedir} @@cflagslocal@@ +Libs: @@libsflag@@${libdir} -lxenhypfs +Requires.private: xentoolcore,xentoollog,xencall From patchwork Fri Sep 27 09:00:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164093 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 51191924 for ; Fri, 27 Sep 2019 09:02:19 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 36E052146E for ; Fri, 27 Sep 2019 09:02:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 36E052146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7b-0005Rm-8J; Fri, 27 Sep 2019 09:01:03 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7a-0005QC-CQ for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:01:02 +0000 X-Inumbo-ID: 4e7256a8-e105-11e9-bf31-bc764e2007e4 Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4e7256a8-e105-11e9-bf31-bc764e2007e4; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 86561AFCC; Fri, 27 Sep 2019 09:00:51 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:46 +0200 Message-Id: <20190927090048.28872-5-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 4/6] tools: add xenfs tool X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add the xenfs tool for accessing the hypervisor filesystem. Signed-off-by: Juergen Gross --- V1: - rename to xenhypfs - don't use "--" for subcommands - add write support --- .gitignore | 1 + tools/misc/Makefile | 6 +++ tools/misc/xenhypfs.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 tools/misc/xenhypfs.c diff --git a/.gitignore b/.gitignore index 3ada0c4f0b..954c1da2cb 100644 --- a/.gitignore +++ b/.gitignore @@ -370,6 +370,7 @@ tools/libxl/test_timedereg tools/libxl/test_fdderegrace tools/firmware/etherboot/eb-roms.h tools/firmware/etherboot/gpxe-git-snapshot.tar.gz +tools/misc/xenhypfs tools/misc/xenwatchdogd tools/misc/xen-hvmcrash tools/misc/xen-lowmemd diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 63947bfadc..9fdb13597f 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -24,6 +24,7 @@ INSTALL_SBIN-$(CONFIG_X86) += xen-lowmemd INSTALL_SBIN-$(CONFIG_X86) += xen-mfndump INSTALL_SBIN-$(CONFIG_X86) += xen-ucode INSTALL_SBIN += xencov +INSTALL_SBIN += xenhypfs INSTALL_SBIN += xenlockprof INSTALL_SBIN += xenperf INSTALL_SBIN += xenpm @@ -86,6 +87,9 @@ xenperf: xenperf.o xenpm: xenpm.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +xenhypfs: xenhypfs.o + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenhypfs) $(APPEND_LDFLAGS) + xenlockprof: xenlockprof.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) @@ -94,6 +98,8 @@ xen-hptool.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall) xen-hptool: xen-hptool.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) +xenhypfs.o: CFLAGS += $(CFLAGS_libxenhypfs) + # xen-mfndump incorrectly uses libxc internals xen-mfndump.o: CFLAGS += -I$(XEN_ROOT)/tools/libxc $(CFLAGS_libxencall) xen-mfndump: xen-mfndump.o diff --git a/tools/misc/xenhypfs.c b/tools/misc/xenhypfs.c new file mode 100644 index 0000000000..4004be57bc --- /dev/null +++ b/tools/misc/xenhypfs.c @@ -0,0 +1,120 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +static struct xenhypfs_handle *hdl; + +static int xenhypfs_cat(char *path) +{ + int ret = 0; + char *result; + + result = xenhypfs_read(hdl, path); + if (!result) { + perror("could not read"); + ret = 3; + } else { + printf("%s\n", result); + free(result); + } + + return ret; +} + +static int xenhypfs_wr(char *path, char *val) +{ + int ret; + + ret = xenhypfs_write(hdl, path, val); + if (ret) { + perror("could not write"); + ret = 3; + } + + return ret; +} + +static int xenhypfs_ls(char *path) +{ + struct xenhypfs_dirent *ent; + unsigned int n, i; + int ret = 0; + + ent = xenhypfs_readdir(hdl, path, &n); + if (!ent) { + perror("could not read dir"); + ret = 3; + } else { + for (i = 0; i < n; i++) + printf("%c %s\n", ent[i].is_dir ? 'd' : '-', ent[i].name); + + free(ent); + } + + return ret; +} + +static int xenhypfs_tree_sub(char *path, unsigned int depth) +{ + struct xenhypfs_dirent *ent; + unsigned int n, i; + int ret = 0; + char *p; + + ent = xenhypfs_readdir(hdl, path, &n); + if (!ent) + return 1; + + for (i = 0; i < n; i++) { + printf("%*s%s%s\n", depth * 2, "", ent[i].name, + ent[i].is_dir ? "/" : ""); + if (ent[i].is_dir) { + asprintf(&p, "%s%s%s", path, (depth == 1) ? "" : "/", ent[i].name); + if (xenhypfs_tree_sub(p, depth + 1)) + ret = 1; + } + } + + free(ent); + + return ret; +} + +static int xenhypfs_tree(void) +{ + printf("/\n"); + + return xenhypfs_tree_sub("/", 1); +} + +int main(int argc, char *argv[]) +{ + int ret; + + hdl = xenhypfs_open(NULL, 0); + + if (!hdl) { + fprintf(stderr, "Could not open libxenhypfs\n"); + ret = 2; + } else if (argc == 3 && !strcmp(argv[1], "cat")) + ret = xenhypfs_cat(argv[2]); + else if (argc == 3 && !strcmp(argv[1], "ls")) + ret = xenhypfs_ls(argv[2]); + else if (argc == 4 && !strcmp(argv[1], "write")) + ret = xenhypfs_wr(argv[2], argv[3]); + else if (argc == 2 && !strcmp(argv[1], "tree")) + ret = xenhypfs_tree(); + else { + fprintf(stderr, "usage: xenhypfs ls \n"); + fprintf(stderr, " xenhypfs cat \n"); + fprintf(stderr, " xenhypfs write \n"); + fprintf(stderr, " xenhypfs tree\n"); + ret = 1; + } + + xenhypfs_close(hdl); + + return ret; +} From patchwork Fri Sep 27 09:00:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164103 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D0B3114DB for ; Fri, 27 Sep 2019 09:02:41 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B633A2146E for ; Fri, 27 Sep 2019 09:02:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B633A2146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7d-0005UJ-Op; Fri, 27 Sep 2019 09:01:05 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7b-0005SW-Vv for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:01:04 +0000 X-Inumbo-ID: 4ec16aa4-e105-11e9-9671-12813bfff9fa Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4ec16aa4-e105-11e9-9671-12813bfff9fa; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D716CAFE8; Fri, 27 Sep 2019 09:00:51 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:47 +0200 Message-Id: <20190927090048.28872-6-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 5/6] xen: add /buildinfo/config entry to hypervisor filesystem X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add the /buildinfo/config entry to the hypervisor filesystem. This entry contains the .config file used to build the hypervisor. Signed-off-by: Juergen Gross --- .gitignore | 2 ++ docs/misc/hypfs-paths.pandoc | 9 +++++++++ xen/common/Makefile | 9 +++++++++ xen/common/hypfs.c | 17 +++++++++++++++++ xen/include/xen/kernel.h | 2 ++ xen/tools/Makefile | 9 +++++++-- xen/tools/bin2c.c | 28 ++++++++++++++++++++++++++++ 7 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 xen/tools/bin2c.c diff --git a/.gitignore b/.gitignore index 954c1da2cb..16dfbb8302 100644 --- a/.gitignore +++ b/.gitignore @@ -295,6 +295,7 @@ xen/arch/*/efi/boot.c xen/arch/*/efi/compat.c xen/arch/*/efi/efi.h xen/arch/*/efi/runtime.c +xen/common/config_data.c xen/include/headers*.chk xen/include/asm xen/include/asm-*/asm-offsets.h @@ -312,6 +313,7 @@ xen/test/livepatch/xen_bye_world.livepatch xen/test/livepatch/xen_hello_world.livepatch xen/test/livepatch/xen_nop.livepatch xen/test/livepatch/xen_replace_world.livepatch +xen/tools/bin2c xen/tools/kconfig/.tmp_gtkcheck xen/tools/kconfig/.tmp_qtcheck xen/tools/symbols diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc index 2fe5455e6f..56ebdcd8be 100644 --- a/docs/misc/hypfs-paths.pandoc +++ b/docs/misc/hypfs-paths.pandoc @@ -53,3 +53,12 @@ tags enclosed in square brackets. #### / The root of the hypervisor file system. + +#### /buildinfo/ + +A directory containing static information generated while building the +hypervisor. + +#### /buildinfo/config = STRING + +The contents of the `xen/.config` file at the time of the hypervisor build. diff --git a/xen/common/Makefile b/xen/common/Makefile index a3f66aa0c0..de7e0fa645 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ARGO) += argo.o obj-y += bitmap.o obj-y += bsearch.o +obj-y += config_data.o obj-$(CONFIG_CORE_PARKING) += core_parking.o obj-y += cpu.o obj-y += cpupool.o @@ -79,3 +80,11 @@ subdir-$(CONFIG_UBSAN) += ubsan subdir-$(CONFIG_NEEDS_LIBELF) += libelf subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt + +config_data.c: ../.config + ( echo "char xen_config_data[] ="; \ + ../tools/bin2c <$<; \ + echo ";" ) > $@ + +clean:: + rm config_data.c 2>/dev/null || true diff --git a/xen/common/hypfs.c b/xen/common/hypfs.c index 7d9595dfa7..11b7b36e56 100644 --- a/xen/common/hypfs.c +++ b/xen/common/hypfs.c @@ -25,6 +25,10 @@ static struct hypfs_entry hypfs_root_entry = { .dir = &hypfs_root, }; +static struct hypfs_dir hypfs_buildinfo = { + .list = LIST_HEAD_INIT(hypfs_buildinfo.list), +}; + static int hypfs_add_entry(struct hypfs_dir *parent, struct hypfs_entry *new) { int ret = -ENOENT; @@ -312,3 +316,16 @@ long do_hypfs_op(unsigned int cmd, return ret; } + +static int __init hypfs_init(void) +{ + int ret; + + ret = hypfs_new_dir(&hypfs_root, "buildinfo", &hypfs_buildinfo); + BUG_ON(ret); + ret = hypfs_new_entry_string(&hypfs_buildinfo, "config", xen_config_data); + BUG_ON(ret); + + return 0; +} +__initcall(hypfs_init); diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h index 548b64da9f..5ff2280b0f 100644 --- a/xen/include/xen/kernel.h +++ b/xen/include/xen/kernel.h @@ -100,5 +100,7 @@ extern enum system_state { bool_t is_active_kernel_text(unsigned long addr); +extern char xen_config_data[]; + #endif /* _LINUX_KERNEL_H */ diff --git a/xen/tools/Makefile b/xen/tools/Makefile index e940939d61..cd2bbbf647 100644 --- a/xen/tools/Makefile +++ b/xen/tools/Makefile @@ -1,13 +1,18 @@ include $(XEN_ROOT)/Config.mk +PROGS = symbols bin2c + .PHONY: default default: - $(MAKE) symbols + $(MAKE) $(PROGS) .PHONY: clean clean: - rm -f *.o symbols + rm -f *.o $(PROGS) symbols: symbols.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< + +bin2c: bin2c.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< diff --git a/xen/tools/bin2c.c b/xen/tools/bin2c.c new file mode 100644 index 0000000000..c332399b70 --- /dev/null +++ b/xen/tools/bin2c.c @@ -0,0 +1,28 @@ +/* + * Unloved program to convert a binary on stdin to a C include on stdout + * + * Jan 1999 Matt Mackall + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include + +int main(int argc, char *argv[]) +{ + int ch, total = 0; + + do { + printf("\t\""); + while ((ch = getchar()) != EOF) { + total++; + printf("\\x%02x", ch); + if (total % 16 == 0) + break; + } + printf("\"\n"); + } while (ch != EOF); + + return 0; +} From patchwork Fri Sep 27 09:00:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 11164101 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 04B0014DB for ; Fri, 27 Sep 2019 09:02:28 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DEDAE2146E for ; Fri, 27 Sep 2019 09:02:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DEDAE2146E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7X-0005Oc-TF; Fri, 27 Sep 2019 09:00:59 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iDm7W-0005Nu-Vd for xen-devel@lists.xenproject.org; Fri, 27 Sep 2019 09:00:59 +0000 X-Inumbo-ID: 4e3d9b85-e105-11e9-9670-12813bfff9fa Received: from mx1.suse.de (unknown [195.135.220.15]) by localhost (Halon) with ESMTPS id 4e3d9b85-e105-11e9-9670-12813bfff9fa; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 2CC5AAFF1; Fri, 27 Sep 2019 09:00:52 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Fri, 27 Sep 2019 11:00:48 +0200 Message-Id: <20190927090048.28872-7-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190927090048.28872-1-jgross@suse.com> References: <20190927090048.28872-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v1 6/6] xen: add runtime parameter reading support to hypfs X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Add support to read values of hypervisor runtime parameters via the hypervisor file system for all unsigned integer type runtime parameters. Signed-off-by: Juergen Gross --- docs/misc/hypfs-paths.pandoc | 6 ++++++ xen/common/kernel.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc index 56ebdcd8be..d710b83185 100644 --- a/docs/misc/hypfs-paths.pandoc +++ b/docs/misc/hypfs-paths.pandoc @@ -62,3 +62,9 @@ hypervisor. #### /buildinfo/config = STRING The contents of the `xen/.config` file at the time of the hypervisor build. + +#### /params/ + +A directory of runtime parameters (those can be set via xl set-parameters). +The description of the different parameters can be found in +`docs/misc/xen-command-line.pandoc`. diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 760917dab5..09787b5a34 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -320,6 +321,32 @@ int cmdline_strcmp(const char *frag, const char *name) } } +static struct hypfs_dir hypfs_params = { + .list = LIST_HEAD_INIT(hypfs_params.list), +}; + +static int __init runtime_param_hypfs_add(void) +{ + const struct kernel_param *param; + int ret; + + ret = hypfs_new_dir(&hypfs_root, "params", &hypfs_params); + BUG_ON(ret); + + for ( param = __param_start; param < __param_end; param++ ) + { + if ( param->type == OPT_UINT && param->len == sizeof(unsigned int) ) + { + ret = hypfs_new_entry_uint(&hypfs_params, param->name, + (unsigned int *)(param->par.var)); + BUG_ON(ret); + } + } + + return 0; +} +__initcall(runtime_param_hypfs_add); + unsigned int tainted; /**