From nobody Mon Feb 9 18:18:59 2026 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1579596286; cv=none; d=zohomail.com; s=zohoarc; b=HKYV7JIfArjkczuiiSDuESDL3kxPRMwkLxKultw7be6P9EoNM7GhGpZA4ShS9e9JI0ijft373RUYPi+jHt8O5p+R7gFTa3tCju0+ThoIDHw67cuwQS2nRzr2P6tmNULVRyREoAum3KzweZI7nWy91hePBy0UihV0mR408hf7j5A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1579596286; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=EWXNuhXQiz92QFELW4OcKOBJf2xmMjgF3bSxHH7+W0k=; b=bEp0+k6P7jMeKZ0txpBOrQuvnkkRK9SspGdsD5cogNoP0iL/014yfx3Q1irssOvVX3c/8B57cyYm29LmvkyfW2xYi/E4I/B8wNwMythBnRDJQrlEZiowullha7zO+P5lHSNvN6wcPyZRWWnHfT1HmMY14C/nrY4We34OW0xTSU8= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1579596286654567.1068129215449; Tue, 21 Jan 2020 00:44:46 -0800 (PST) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1itp8m-0004dm-Rm; Tue, 21 Jan 2020 08:44:04 +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 1itp8m-0004dR-6C for xen-devel@lists.xenproject.org; Tue, 21 Jan 2020 08:44:04 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 1ed01392-3c2a-11ea-ba47-12813bfff9fa; Tue, 21 Jan 2020 08:43:39 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 4143CB2BD; Tue, 21 Jan 2020 08:43:34 +0000 (UTC) X-Inumbo-ID: 1ed01392-3c2a-11ea-ba47-12813bfff9fa X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Tue, 21 Jan 2020 09:43:25 +0100 Message-Id: <20200121084330.18309-5-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200121084330.18309-1-jgross@suse.com> References: <20200121084330.18309-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v3 4/9] 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 , Julien Grall , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Jan Beulich , Volodymyr Babchuk , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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. 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 V2: - test new entry name to be valid V3: - major rework, especially by supporting binary contents of entries - addressed all comments --- 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 | 365 +++++++++++++++++++++++++++++++++++++++= ++++ xen/include/public/hypfs.h | 124 +++++++++++++++ xen/include/public/xen.h | 1 + xen/include/xen/hypercall.h | 8 + xen/include/xen/hypfs.h | 89 +++++++++++ 10 files changed, 592 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 6f9bec22d3..87af810667 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1382,6 +1382,7 @@ static arm_hypercall_t arm_hypercall_table[] =3D { #ifdef CONFIG_ARGO HYPERCALL(argo_op, 5), #endif + HYPERCALL(hypfs_op, 5), }; =20 #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[] = =3D { #endif HYPERCALL(xenpmu_op), COMPAT_CALL(dm_op), + HYPERCALL(hypfs_op), HYPERCALL(arch_1) }; =20 diff --git a/xen/arch/x86/hypercall.c b/xen/arch/x86/hypercall.c index 7f299d45c6..05a3f5e25b 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= ] =3D 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 17ddf9ea1f..83907d4f00 100644 --- a/xen/arch/x86/pv/hypercall.c +++ b/xen/arch/x86/pv/hypercall.c @@ -85,6 +85,7 @@ const hypercall_table_t pv_hypercall_table[] =3D { 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 +=3D domain.o obj-y +=3D event_2l.o obj-y +=3D event_channel.o obj-y +=3D event_fifo.o +obj-y +=3D hypfs.o obj-$(CONFIG_CRASH_DEBUG) +=3D gdbstub.o obj-$(CONFIG_GRANT_TABLE) +=3D grant_table.o obj-y +=3D guestcopy.o diff --git a/xen/common/hypfs.c b/xen/common/hypfs.c new file mode 100644 index 0000000000..6762d20dfd --- /dev/null +++ b/xen/common/hypfs.c @@ -0,0 +1,365 @@ +/*************************************************************************= ***** + * + * hypfs.c + * + * Simple sysfs-like file system for the hypervisor. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DIRENTRY_NAME_OFF offsetof(struct xen_hypfs_dirlistentry, name) +#define DIRENTRY_SIZE(name_len) \ + (DIRENTRY_NAME_OFF + ROUNDUP(name_len, alignof(struct xen_hypfs_dirent= ry))) + +static DEFINE_RWLOCK(hypfs_lock); + +HYPFS_DIR_INIT(hypfs_root, ""); + +static int add_entry(struct hypfs_entry_dir *parent, struct hypfs_entry *n= ew) +{ + int ret =3D -ENOENT; + struct hypfs_entry *e; + + write_lock(&hypfs_lock); + + list_for_each_entry ( e, &parent->dirlist, list ) + { + int cmp =3D strcmp(e->name, new->name); + + if ( cmp > 0 ) + { + ret =3D 0; + list_add_tail(&new->list, &e->list); + break; + } + if ( cmp =3D=3D 0 ) + { + ret =3D -EEXIST; + break; + } + } + + if ( ret =3D=3D -ENOENT ) + { + ret =3D 0; + list_add_tail(&new->list, &parent->dirlist); + } + + if ( !ret ) + { + unsigned int sz =3D strlen(new->name) + 1; + + parent->e.size +=3D DIRENTRY_SIZE(sz); + } + + write_unlock(&hypfs_lock); + + return ret; +} + +int hypfs_add_entry(struct hypfs_entry_dir *parent, + struct hypfs_entry *entry, bool nofault) +{ + int ret; + + ret =3D add_entry(parent, entry); + BUG_ON(nofault && ret); + + return ret; +} + +int hypfs_add_dir(struct hypfs_entry_dir *parent, + struct hypfs_entry_dir *dir, bool nofault) +{ + int ret; + + ret =3D add_entry(parent, &dir->e); + BUG_ON(nofault && ret); + + return ret; +} + +int hypfs_add_leaf(struct hypfs_entry_dir *parent, + struct hypfs_entry_leaf *leaf, bool nofault) +{ + int ret; + + if ( !leaf->content ) + ret =3D -EINVAL; + else + ret =3D add_entry(parent, &leaf->e); + BUG_ON(nofault && ret); + + return ret; +} + +static int hypfs_get_path_user(char *buf, XEN_GUEST_HANDLE_PARAM(void) uad= dr, + unsigned long len) +{ + if ( len > XEN_HYPFS_MAX_PATHLEN ) + return -EINVAL; + + if ( copy_from_guest(buf, uaddr, len) ) + return -EFAULT; + + if ( buf[len - 1] ) + return -EINVAL; + + return 0; +} + +static struct hypfs_entry *hypfs_get_entry_rel(struct hypfs_entry_dir *dir, + const char *path) +{ + const char *end; + struct hypfs_entry *entry; + unsigned int name_len; + + if ( !*path ) + return &dir->e; + + if ( dir->e.type !=3D XEN_HYPFS_TYPE_DIR ) + return NULL; + + end =3D strchr(path, '/'); + if ( !end ) + end =3D strchr(path, '\0'); + name_len =3D end - path; + + list_for_each_entry ( entry, &dir->dirlist, list ) + { + int cmp =3D strncmp(path, entry->name, name_len); + struct hypfs_entry_dir *d =3D container_of(entry, + struct hypfs_entry_dir, e= ); + + if ( cmp < 0 ) + return NULL; + if ( !cmp && strlen(entry->name) =3D=3D name_len ) + return *end ? hypfs_get_entry_rel(d, end + 1) : entry; + } + + return NULL; +} + +struct hypfs_entry *hypfs_get_entry(const char *path) +{ + if ( path[0] !=3D '/' ) + return NULL; + + return hypfs_get_entry_rel(&hypfs_root, path + 1); +} + +int hypfs_read_dir(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr) +{ + const struct hypfs_entry_dir *d; + struct hypfs_entry *e; + unsigned int size =3D entry->size; + + d =3D container_of(entry, const struct hypfs_entry_dir, e); + + list_for_each_entry ( e, &d->dirlist, list ) + { + struct xen_hypfs_dirlistentry direntry; + unsigned int e_namelen =3D strlen(e->name) + 1; + unsigned int e_len =3D DIRENTRY_SIZE(e_namelen); + + direntry.e.flags =3D e->write ? XEN_HYPFS_WRITEABLE : 0; + direntry.e.type =3D e->type; + direntry.e.encoding =3D e->encoding; + direntry.e.content_len =3D e->size; + direntry.off_next =3D list_is_last(&e->list, &d->dirlist) ? 0 : e_= len; + if ( copy_to_guest(uaddr, &direntry, 1) ) + return -EFAULT; + + if ( copy_to_guest_offset(uaddr, DIRENTRY_NAME_OFF, + e->name, e_namelen) ) + return -EFAULT; + + guest_handle_add_offset(uaddr, e_len); + + ASSERT(e_len <=3D size); + size -=3D e_len; + } + + return 0; +} + +int hypfs_read_leaf(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr) +{ + const struct hypfs_entry_leaf *l; + + l =3D container_of(entry, const struct hypfs_entry_leaf, e); + + return copy_to_guest(uaddr, l->content, entry->size) ? -EFAULT: 0; +} + +static int hypfs_read(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ul= en) +{ + struct xen_hypfs_direntry e; + long ret =3D -EINVAL; + + if ( ulen < sizeof(e) ) + goto out; + + e.flags =3D entry->write ? XEN_HYPFS_WRITEABLE : 0; + e.type =3D entry->type; + e.encoding =3D entry->encoding; + e.content_len =3D entry->size; + + ret =3D -EFAULT; + if ( copy_to_guest(uaddr, &e, 1) ) + goto out; + + ret =3D 0; + if ( ulen < entry->size + sizeof(e) ) + goto out; + + guest_handle_add_offset(uaddr, sizeof(e)); + + ret =3D entry->read(entry, uaddr); + + out: + return ret; +} + +int hypfs_write_leaf(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ule= n) +{ + char *buf; + int ret; + + if ( ulen > leaf->e.size ) + ulen =3D leaf->e.size; + + buf =3D xzalloc_array(char, ulen); + if ( !buf ) + return -ENOMEM; + + ret =3D -EFAULT; + if ( copy_from_guest(buf, uaddr, ulen) ) + goto out; + + ret =3D 0; + if ( leaf->e.type =3D=3D XEN_HYPFS_TYPE_STRING ) + buf[leaf->e.size - 1] =3D 0; + memcpy(leaf->write_ptr, buf, ulen); + + out: + xfree(buf); + return ret; +} + +int hypfs_write_bool(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ule= n) +{ + union { + char buf[8]; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + } u; + + ASSERT(leaf->e.type =3D=3D XEN_HYPFS_TYPE_UINT && leaf->e.size <=3D 8); + + if ( ulen !=3D leaf->e.size ) + return -EDOM; + + if ( copy_from_guest(u.buf, uaddr, ulen) ) + return -EFAULT; + + switch ( leaf->e.size ) + { + case 1: + *(uint8_t *)leaf->write_ptr =3D !!u.u8; + break; + case 2: + *(uint16_t *)leaf->write_ptr =3D !!u.u16; + break; + case 4: + *(uint32_t *)leaf->write_ptr =3D !!u.u32; + break; + case 8: + *(uint64_t *)leaf->write_ptr =3D !!u.u64; + break; + } + + return 0; +} + +static int hypfs_write(struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long u= len) +{ + struct hypfs_entry_leaf *l; + + if ( !entry->write ) + return -EACCES; + + l =3D container_of(entry, struct hypfs_entry_leaf, e); + + return entry->write(l, uaddr, ulen); +} + +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; + static char path[XEN_HYPFS_MAX_PATHLEN]; + + if ( !is_control_domain(current->domain) && + !is_hardware_domain(current->domain) ) + return -EPERM; + + if ( cmd =3D=3D XEN_HYPFS_OP_get_version ) + return XEN_HYPFS_VERSION; + + if ( cmd =3D=3D XEN_HYPFS_OP_write_contents ) + write_lock(&hypfs_lock); + else + read_lock(&hypfs_lock); + + ret =3D hypfs_get_path_user(path, arg1, arg2); + if ( ret ) + goto out; + + entry =3D hypfs_get_entry(path); + if ( !entry ) + { + ret =3D -ENOENT; + goto out; + } + + switch ( cmd ) + { + case XEN_HYPFS_OP_read_contents: + ret =3D hypfs_read(entry, arg3, arg4); + break; + + case XEN_HYPFS_OP_write_contents: + ret =3D hypfs_write(entry, arg3, arg4); + break; + + default: + ret =3D -ENOSYS; + break; + } + + out: + if ( cmd =3D=3D XEN_HYPFS_OP_write_contents ) + write_unlock(&hypfs_lock); + else + read_unlock(&hypfs_lock); + + return ret; +} diff --git a/xen/include/public/hypfs.h b/xen/include/public/hypfs.h new file mode 100644 index 0000000000..8351511227 --- /dev/null +++ b/xen/include/public/hypfs.h @@ -0,0 +1,124 @@ +/*************************************************************************= ***** + * 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, an= d/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. + */ + +/* Highest version number of the hypfs interface currently defined. */ +#define XEN_HYPFS_VERSION 1 + +/* Maximum length of a path in the filesystem. */ +#define XEN_HYPFS_MAX_PATHLEN 1024 + +struct xen_hypfs_direntry { + uint16_t flags; +#define XEN_HYPFS_WRITEABLE 0x0001 + uint8_t type; +#define XEN_HYPFS_TYPE_DIR 0x0000 +#define XEN_HYPFS_TYPE_BLOB 0x0001 +#define XEN_HYPFS_TYPE_STRING 0x0002 +#define XEN_HYPFS_TYPE_UINT 0x0003 +#define XEN_HYPFS_TYPE_INT 0x0004 +#define XEN_HYPFS_TYPE_BOOL 0x0005 + uint8_t encoding; +#define XEN_HYPFS_ENC_PLAIN 0x0000 +#define XEN_HYPFS_ENC_GZIP 0x0001 + uint32_t content_len; +}; + +struct xen_hypfs_dirlistentry { + struct xen_hypfs_direntry e; + /* Offset in bytes to next entry (0 =3D=3D this is the last entry). */ + uint16_t off_next; + char name[XEN_FLEX_ARRAY_DIM]; +}; + +/* + * Hypercall operations. + */ + +/* + * XEN_HYPFS_OP_get_version + * + * Read highest interface version supported by the hypervisor. + * + * Possible return values: + * >0: highest supported interface version + * <0: negative Xen errno value + */ +#define XEN_HYPFS_OP_get_version 0 + +/* + * XEN_HYPFS_OP_read_contents + * + * Read contents of a filesystem entry. + * + * Returns the direntry and contents of an entry in the buffer supplied by= the + * caller (struct xen_hypfs_direntry with the contents following directly + * after it). + * The data buffer must be at least the size of the direntry returned in o= rder + * to have success. If the data buffer was not large enough for all the da= ta + * no entry data is returned, but the direntry will contain the needed size + * for the returned data. + * The format of the contents is according to its entry type and encoding. + * + * arg1: XEN_GUEST_HANDLE(path name) + * arg2: length of path name (including trailing zero byte) + * arg3: XEN_GUEST_HANDLE(data buffer written by hypervisor) + * arg4: data buffer size + * + * Possible return values: + * 0: success (at least the direntry was returned) + * <0 : negative Xen errno value + */ +#define XEN_HYPFS_OP_read_contents 1 + +/* + * XEN_HYPFS_OP_write_contents + * + * Write contents of a filesystem entry. + * + * Writes an entry with the contents of a buffer supplied by the caller. + * The data type and encoding can't be changed. The size can be changed on= ly + * for blobs and strings. + * + * arg1: XEN_GUEST_HANDLE(path name) + * arg2: length of path name (including trailing zero byte) + * arg3: XEN_GUEST_HANDLE(content buffer read by hypervisor) + * arg4: content buffer size + * + * Possible return values: + * 0: success + * <0 : negative Xen errno value + */ +#define XEN_HYPFS_OP_write_contents 2 + +#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 =20 /* 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); =20 +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 =20 extern int diff --git a/xen/include/xen/hypfs.h b/xen/include/xen/hypfs.h new file mode 100644 index 0000000000..a1c2140398 --- /dev/null +++ b/xen/include/xen/hypfs.h @@ -0,0 +1,89 @@ +#ifndef __XEN_HYPFS_H__ +#define __XEN_HYPFS_H__ + +#include +#include +#include + +struct hypfs_entry_leaf; + +struct hypfs_entry { + unsigned short type; + unsigned short encoding; + unsigned int size; + const char *name; + struct list_head list; + int (*read)(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr); + int (*write)(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ulen); +}; + +struct hypfs_entry_leaf { + struct hypfs_entry e; + union { + const void *content; + void *write_ptr; + }; +}; + +struct hypfs_entry_dir { + struct hypfs_entry e; + struct list_head dirlist; +}; + +#define HYPFS_DIR_INIT(var, nam) \ + struct hypfs_entry_dir var =3D { \ + .e.type =3D XEN_HYPFS_TYPE_DIR, \ + .e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .e.name =3D nam, \ + .e.size =3D 0, \ + .e.list =3D LIST_HEAD_INIT(var.e.list), \ + .e.read =3D hypfs_read_dir, \ + .dirlist =3D LIST_HEAD_INIT(var.dirlist), \ + } + +/* Content and size need to be set via hypfs_string_set(). */ +#define HYPFS_STRING_INIT(var, nam) \ + struct hypfs_entry_leaf var =3D { \ + .e.type =3D XEN_HYPFS_TYPE_STRING, \ + .e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .e.name =3D nam, \ + .e.read =3D hypfs_read_leaf, \ + } + +static inline void hypfs_string_set(struct hypfs_entry_leaf *leaf, + const char *str) +{ + leaf->content =3D str; + leaf->e.size =3D strlen(str) + 1; +} + +#define HYPFS_UINT_INIT(var, nam, uint) \ + struct hypfs_entry_leaf var =3D { \ + .e.type =3D XEN_HYPFS_TYPE_UINT, \ + .e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .e.name =3D nam, \ + .e.size =3D sizeof(uint), \ + .e.read =3D hypfs_read_leaf, \ + .content =3D &uint, \ + } + + +extern struct hypfs_entry_dir hypfs_root; + +struct hypfs_entry *hypfs_get_entry(const char *path); +int hypfs_add_dir(struct hypfs_entry_dir *parent, + struct hypfs_entry_dir *dir, bool nofault); +int hypfs_add_leaf(struct hypfs_entry_dir *parent, + struct hypfs_entry_leaf *leaf, bool nofault); +int hypfs_read_dir(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr); +int hypfs_read_leaf(const struct hypfs_entry *entry, + XEN_GUEST_HANDLE_PARAM(void) uaddr); +int hypfs_write_leaf(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ule= n); +int hypfs_write_bool(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long ule= n); + +#endif /* __XEN_HYPFS_H__ */ --=20 2.16.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel