From nobody Sat Feb 7 04:40:15 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 Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1580897560609258.8928074956716; Wed, 5 Feb 2020 02:12:40 -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 1izHf9-0003OQ-87; Wed, 05 Feb 2020 10:12: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 1izHf7-0003NZ-UO for xen-devel@lists.xenproject.org; Wed, 05 Feb 2020 10:12:01 +0000 Received: from mx2.suse.de (unknown [195.135.220.15]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id ead25fc8-47ff-11ea-8396-bc764e2007e4; Wed, 05 Feb 2020 10:11:47 +0000 (UTC) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 5E6E0B02C; Wed, 5 Feb 2020 10:11:46 +0000 (UTC) X-Inumbo-ID: ead25fc8-47ff-11ea-8396-bc764e2007e4 X-Virus-Scanned: by amavisd-new at test-mx.suse.de From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Wed, 5 Feb 2020 11:11:41 +0100 Message-Id: <20200205101141.24769-9-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200205101141.24769-1-jgross@suse.com> References: <20200205101141.24769-1-jgross@suse.com> Subject: [Xen-devel] [PATCH v4 8/8] xen: add runtime parameter access 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 , Kevin Tian , Stefano Stabellini , Julien Grall , Jun Nakajima , 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 support to read and modify values of hypervisor runtime parameters via the hypervisor file system. As runtime parameters can be modified via a sysctl, too, this path has to take the hypfs rw_lock as writer. For custom runtime parameters the resulting parameter value needs to be stored in a string buffer for being consumable by the file system. Signed-off-by: Juergen Gross --- V3: - complete rework - support custom parameters, too - support parameter writing --- docs/misc/hypfs-paths.pandoc | 9 ++++++ xen/arch/arm/xen.lds.S | 5 +++ xen/arch/x86/hvm/vmx/vmcs.c | 17 +++++++++- xen/arch/x86/pv/domain.c | 7 ++++- xen/arch/x86/xen.lds.S | 5 +++ xen/common/grant_table.c | 17 +++++++--- xen/common/hypfs.c | 38 +++++++++++++++++++++++ xen/common/kernel.c | 23 +++++++++++++- xen/drivers/char/console.c | 49 +++++++++++++++++++++++++---- xen/include/xen/hypfs.h | 4 +++ xen/include/xen/param.h | 74 +++++++++++++++++++++++++++++++++++++++-= ---- 11 files changed, 226 insertions(+), 22 deletions(-) diff --git a/docs/misc/hypfs-paths.pandoc b/docs/misc/hypfs-paths.pandoc index 1faebcccbc..7d03852ccd 100644 --- a/docs/misc/hypfs-paths.pandoc +++ b/docs/misc/hypfs-paths.pandoc @@ -152,3 +152,12 @@ The major version of Xen. #### /buildinfo/version/minor =3D INTEGER =20 The minor version of Xen. + +#### /params/ + +A directory of runtime parameters. + +#### /params/* + +The single parameters. The description of the different parameters can be +found in `docs/misc/xen-command-line.pandoc`. diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index a497f6a48d..0061a8dfea 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -89,6 +89,11 @@ SECTIONS __start_schedulers_array =3D .; *(.data.schedulers) __end_schedulers_array =3D .; + + . =3D ALIGN(8); + __paramhypfs_start =3D .; + *(.data.paramhypfs) + __paramhypfs_end =3D .; *(.data.rel) *(.data.rel.*) CONSTRUCTORS diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 65445afeb0..36ddccfb73 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -70,6 +70,17 @@ integer_param("ple_window", ple_window); static bool __read_mostly opt_ept_pml =3D true; static s8 __read_mostly opt_ept_ad =3D -1; int8_t __read_mostly opt_ept_exec_sp =3D -1; +static char opt_ept_setting[16] =3D "pml=3D1"; + + +static void update_ept_param(void) +{ + snprintf(opt_ept_setting, sizeof(opt_ept_setting), "pml=3D%d", opt_ept= _pml); + if ( opt_ept_ad >=3D 0 ) + param_append_str(opt_ept_setting, ",ad=3D%d", opt_ept_ad); + if ( opt_ept_exec_sp >=3D 0 ) + param_append_str(opt_ept_setting, ",exec-sp=3D%d", opt_ept_exec_sp= ); +} =20 static int __init parse_ept_param(const char *s) { @@ -93,6 +104,8 @@ static int __init parse_ept_param(const char *s) s =3D ss + 1; } while ( *ss ); =20 + update_ept_param(); + return rc; } custom_param("ept", parse_ept_param); @@ -115,6 +128,8 @@ static int parse_ept_param_runtime(const char *s) =20 opt_ept_exec_sp =3D val; =20 + update_ept_param(); + rcu_read_lock(&domlist_read_lock); for_each_domain ( d ) { @@ -144,7 +159,7 @@ static int parse_ept_param_runtime(const char *s) =20 return 0; } -custom_runtime_only_param("ept", parse_ept_param_runtime); +custom_runtime_only_param("ept", parse_ept_param_runtime, opt_ept_setting); =20 /* Dynamic (run-time adjusted) execution control flags. */ u32 vmx_pin_based_exec_control __read_mostly; diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c index c3473b9a47..9e0d24ce81 100644 --- a/xen/arch/x86/pv/domain.c +++ b/xen/arch/x86/pv/domain.c @@ -22,6 +22,7 @@ static __read_mostly enum { PCID_XPTI, PCID_NOXPTI } opt_pcid =3D PCID_XPTI; +static char opt_pcid_val[7] =3D "xpti"; =20 static int parse_pcid(const char *s) { @@ -31,10 +32,12 @@ static int parse_pcid(const char *s) { case 0: opt_pcid =3D PCID_OFF; + snprintf(opt_pcid_val, sizeof(opt_pcid_val), "off"); break; =20 case 1: opt_pcid =3D PCID_ALL; + snprintf(opt_pcid_val, sizeof(opt_pcid_val), "on"); break; =20 default: @@ -42,10 +45,12 @@ static int parse_pcid(const char *s) { case 0: opt_pcid =3D PCID_NOXPTI; + snprintf(opt_pcid_val, sizeof(opt_pcid_val), "noxpti"); break; =20 case 1: opt_pcid =3D PCID_XPTI; + snprintf(opt_pcid_val, sizeof(opt_pcid_val), "xpti"); break; =20 default: @@ -57,7 +62,7 @@ static int parse_pcid(const char *s) =20 return rc; } -custom_runtime_param("pcid", parse_pcid); +custom_runtime_param("pcid", parse_pcid, opt_pcid_val); =20 static void noreturn continue_nonidle_domain(struct vcpu *v) { diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index f5730ffe93..b4b12a3111 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -279,6 +279,11 @@ SECTIONS __start_schedulers_array =3D .; *(.data.schedulers) __end_schedulers_array =3D .; + + . =3D ALIGN(8); + __paramhypfs_start =3D .; + *(.data.paramhypfs) + __paramhypfs_end =3D .; } :text =20 DECL_SECTION(.data) { diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 2ecf38dfbe..2de2c7e373 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -85,8 +85,10 @@ struct grant_table { struct grant_table_arch arch; }; =20 +#define PAR_VAL_SZ 12 + static int parse_gnttab_limit(const char *param, const char *arg, - unsigned int *valp) + unsigned int *valp, char *par_val) { const char *e; unsigned long val; @@ -99,28 +101,33 @@ static int parse_gnttab_limit(const char *param, const= char *arg, return -ERANGE; =20 *valp =3D val; + snprintf(par_val, PAR_VAL_SZ, "%lu", val); =20 return 0; } =20 unsigned int __read_mostly opt_max_grant_frames =3D 64; +static char gnttab_max_frames_val[PAR_VAL_SZ] =3D "64"; =20 static int parse_gnttab_max_frames(const char *arg) { return parse_gnttab_limit("gnttab_max_frames", arg, - &opt_max_grant_frames); + &opt_max_grant_frames, gnttab_max_frames_val= ); } -custom_runtime_param("gnttab_max_frames", parse_gnttab_max_frames); +custom_runtime_param("gnttab_max_frames", parse_gnttab_max_frames, + gnttab_max_frames_val); =20 static unsigned int __read_mostly opt_max_maptrack_frames =3D 1024; +static char max_maptrack_frames_val[PAR_VAL_SZ] =3D "1024"; =20 static int parse_gnttab_max_maptrack_frames(const char *arg) { return parse_gnttab_limit("gnttab_max_maptrack_frames", arg, - &opt_max_maptrack_frames); + &opt_max_maptrack_frames, + max_maptrack_frames_val); } custom_runtime_param("gnttab_max_maptrack_frames", - parse_gnttab_max_maptrack_frames); + parse_gnttab_max_maptrack_frames, max_maptrack_frames= _val); =20 #ifndef GNTTAB_MAX_VERSION #define GNTTAB_MAX_VERSION 2 diff --git a/xen/common/hypfs.c b/xen/common/hypfs.c index c726f89ac9..9a296674fb 100644 --- a/xen/common/hypfs.c +++ b/xen/common/hypfs.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include =20 @@ -289,6 +290,33 @@ int hypfs_write_bool(struct hypfs_entry_leaf *leaf, return 0; } =20 +int hypfs_write_custom(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long u= len) +{ + struct param_hypfs *p; + char *buf; + int ret; + + buf =3D xzalloc_array(char, ulen); + if ( !buf ) + return -ENOMEM; + + ret =3D -EFAULT; + if ( copy_from_guest(buf, uaddr, ulen) ) + goto out; + + ret =3D -EDOM; + if ( buf[ulen - 1] ) + goto out; + + p =3D container_of(leaf, struct param_hypfs, hypfs); + ret =3D p->param->par.func(buf); + + out: + xfree(buf); + return ret; +} + static int hypfs_write(struct hypfs_entry *entry, XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long u= len) { @@ -356,3 +384,13 @@ long do_hypfs_op(unsigned int cmd, =20 return ret; } + +void hypfs_write_lock(void) +{ + write_lock(&hypfs_lock); +} + +void hypfs_write_unlock(void) +{ + write_unlock(&hypfs_lock); +} diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 3d496bb9e6..e62a1680c7 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -198,7 +198,13 @@ static void __init _cmdline_parse(const char *cmdline) =20 int runtime_parse(const char *line) { - return parse_params(line, __param_start, __param_end); + int ret; + + hypfs_write_lock(); + ret =3D parse_params(line, __param_start, __param_end); + hypfs_write_unlock(); + + return ret; } =20 /** @@ -428,6 +434,21 @@ static int __init buildinfo_init(void) } __initcall(buildinfo_init); =20 +static HYPFS_DIR_INIT(params, "params"); + +static int __init param_init(void) +{ + struct param_hypfs *param; + + hypfs_add_dir(&hypfs_root, ¶ms, true); + + for ( param =3D __paramhypfs_start; param < __paramhypfs_end; param++ ) + hypfs_add_leaf(¶ms, ¶m->hypfs, true); + + return 0; +} +__initcall(param_init); + # define DO(fn) long do_##fn =20 #endif diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 913ae1b66a..5440145549 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -78,9 +78,11 @@ enum con_timestamp_mode }; =20 static enum con_timestamp_mode __read_mostly opt_con_timestamp_mode =3D TS= M_NONE; +static char con_timestamp_mode_val[7] =3D "none"; =20 static int parse_console_timestamps(const char *s); -custom_runtime_param("console_timestamps", parse_console_timestamps); +custom_runtime_param("console_timestamps", parse_console_timestamps, + con_timestamp_mode_val); =20 /* conring_size: allows a large console ring than default (16kB). */ static uint32_t __initdata opt_conring_size; @@ -118,13 +120,17 @@ static DEFINE_SPINLOCK(console_lock); #ifdef NDEBUG #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */ +#define XENLOG_DEFAULT_VAL "warning/warning" #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */ +#define XENLOG_GUEST_DEFAULT_VAL "none/warning" #else #define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */ #define XENLOG_LOWER_THRESHOLD 4 /* Print everything */ +#define XENLOG_DEFAULT_VAL "all/all" #define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */ #define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */ +#define XENLOG_GUEST_DEFAULT_VAL "all/all" #endif /* * The XENLOG_DEFAULT is the default given to printks that @@ -133,16 +139,20 @@ static DEFINE_SPINLOCK(console_lock); #define XENLOG_DEFAULT 1 /* XENLOG_WARNING */ #define XENLOG_GUEST_DEFAULT 1 /* XENLOG_WARNING */ =20 +#define LOGLVL_VAL_SZ 16 static int __read_mostly xenlog_upper_thresh =3D XENLOG_UPPER_THRESHOLD; static int __read_mostly xenlog_lower_thresh =3D XENLOG_LOWER_THRESHOLD; +static char xenlog_val[LOGLVL_VAL_SZ] =3D XENLOG_DEFAULT_VAL; static int __read_mostly xenlog_guest_upper_thresh =3D XENLOG_GUEST_UPPER_THRESHOLD; static int __read_mostly xenlog_guest_lower_thresh =3D XENLOG_GUEST_LOWER_THRESHOLD; +static char xenlog_guest_val[LOGLVL_VAL_SZ] =3D XENLOG_GUEST_DEFAULT_VAL; =20 static int parse_loglvl(const char *s); static int parse_guest_loglvl(const char *s); =20 +static char *lvl2opt[] =3D { "none", "error", "warning", "info", "all" }; /* * :=3D none|error|warning|info|debug|all * loglvl=3D[/] @@ -151,8 +161,8 @@ static int parse_guest_loglvl(const char *s); * Similar definitions for guest_loglvl, but applies to guest tracing. * Defaults: loglvl=3Dwarning ; guest_loglvl=3Dnone/warning */ -custom_runtime_param("loglvl", parse_loglvl); -custom_runtime_param("guest_loglvl", parse_guest_loglvl); +custom_runtime_param("loglvl", parse_loglvl, xenlog_val); +custom_runtime_param("guest_loglvl", parse_guest_loglvl, xenlog_guest_val); =20 static atomic_t print_everything =3D ATOMIC_INIT(0); =20 @@ -173,7 +183,7 @@ static int __parse_loglvl(const char *s, const char **p= s) return 2; /* sane fallback */ } =20 -static int _parse_loglvl(const char *s, int *lower, int *upper) +static int _parse_loglvl(const char *s, int *lower, int *upper, char *val) { *lower =3D *upper =3D __parse_loglvl(s, &s); if ( *s =3D=3D '/' ) @@ -181,18 +191,21 @@ static int _parse_loglvl(const char *s, int *lower, i= nt *upper) if ( *upper < *lower ) *upper =3D *lower; =20 + snprintf(val, LOGLVL_VAL_SZ, "%s/%s", lvl2opt[*lower], lvl2opt[*upper]= ); + return *s ? -EINVAL : 0; } =20 static int parse_loglvl(const char *s) { - return _parse_loglvl(s, &xenlog_lower_thresh, &xenlog_upper_thresh); + return _parse_loglvl(s, &xenlog_lower_thresh, &xenlog_upper_thresh, + xenlog_val); } =20 static int parse_guest_loglvl(const char *s) { return _parse_loglvl(s, &xenlog_guest_lower_thresh, - &xenlog_guest_upper_thresh); + &xenlog_guest_upper_thresh, xenlog_guest_val); } =20 static char *loglvl_str(int lvl) @@ -731,22 +744,46 @@ static int parse_console_timestamps(const char *s) { case 0: opt_con_timestamp_mode =3D TSM_NONE; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "none"); return 0; case 1: opt_con_timestamp_mode =3D TSM_DATE; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "date"); return 0; } if ( *s =3D=3D '\0' || /* Compat for old booleanparam() */ !strcmp(s, "date") ) + { opt_con_timestamp_mode =3D TSM_DATE; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "date"); + } else if ( !strcmp(s, "datems") ) + { opt_con_timestamp_mode =3D TSM_DATE_MS; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "datems"); + } else if ( !strcmp(s, "boot") ) + { opt_con_timestamp_mode =3D TSM_BOOT; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "boot"); + } else if ( !strcmp(s, "raw") ) + { opt_con_timestamp_mode =3D TSM_RAW; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "raw"); + } else if ( !strcmp(s, "none") ) + { opt_con_timestamp_mode =3D TSM_NONE; + snprintf(con_timestamp_mode_val, sizeof(con_timestamp_mode_val), + "none"); + } else return -EINVAL; =20 diff --git a/xen/include/xen/hypfs.h b/xen/include/xen/hypfs.h index 5b26b2e611..2b6ed8ae23 100644 --- a/xen/include/xen/hypfs.h +++ b/xen/include/xen/hypfs.h @@ -104,5 +104,9 @@ 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); +int hypfs_write_custom(struct hypfs_entry_leaf *leaf, + XEN_GUEST_HANDLE_PARAM(void) uaddr, unsigned long u= len); +void hypfs_write_lock(void); +void hypfs_write_unlock(void); =20 #endif /* __XEN_HYPFS_H__ */ diff --git a/xen/include/xen/param.h b/xen/include/xen/param.h index 75471eb4ad..b4ef3e7a22 100644 --- a/xen/include/xen/param.h +++ b/xen/include/xen/param.h @@ -1,6 +1,7 @@ #ifndef _XEN_PARAM_H #define _XEN_PARAM_H =20 +#include #include =20 /* @@ -23,10 +24,17 @@ struct kernel_param { } par; }; =20 +struct param_hypfs { + const struct kernel_param *param; + struct hypfs_entry_leaf hypfs; +}; + extern const struct kernel_param __setup_start[], __setup_end[]; extern const struct kernel_param __param_start[], __param_end[]; +extern struct param_hypfs __paramhypfs_start[], __paramhypfs_end[]; =20 #define __dataparam __used_section(".data.param") +#define __paramhypfs __used_section(".data.paramhypfs") =20 #define __param(att) static const att \ __attribute__((__aligned__(sizeof(void *)))) struct kernel_param @@ -76,40 +84,87 @@ extern const struct kernel_param __param_start[], __par= am_end[]; .type =3D OPT_IGNORE } =20 #define __rtparam __param(__dataparam) +#define __paramfs static __paramhypfs \ + __attribute__((__aligned__(sizeof(void *)))) struct param_hypfs =20 -#define custom_runtime_only_param(_name, _var) \ +#define custom_runtime_only_param(_name, _var, contvar) \ __rtparam __rtpar_##_var =3D \ { .name =3D _name, \ .type =3D OPT_CUSTOM, \ - .par.func =3D _var } + .par.func =3D _var }; \ + __paramfs __parfs_##_var =3D \ + { .param =3D &__rtpar_##_var, \ + .hypfs.e.type =3D XEN_HYPFS_TYPE_STRING, \ + .hypfs.e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .hypfs.e.name =3D _name, \ + .hypfs.e.size =3D sizeof(contvar), \ + .hypfs.e.read =3D hypfs_read_leaf, \ + .hypfs.e.write =3D hypfs_write_custom, \ + .hypfs.content =3D &contvar } #define boolean_runtime_only_param(_name, _var) \ __rtparam __rtpar_##_var =3D \ { .name =3D _name, \ .type =3D OPT_BOOL, \ .len =3D sizeof(_var), \ - .par.var =3D &_var } + .par.var =3D &_var }; \ + __paramfs __parfs_##_var =3D \ + { .param =3D &__rtpar_##_var, \ + .hypfs.e.type =3D XEN_HYPFS_TYPE_UINT, \ + .hypfs.e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .hypfs.e.name =3D _name, \ + .hypfs.e.size =3D sizeof(_var), \ + .hypfs.e.read =3D hypfs_read_leaf, \ + .hypfs.e.write =3D hypfs_write_bool, \ + .hypfs.content =3D &_var } #define integer_runtime_only_param(_name, _var) \ __rtparam __rtpar_##_var =3D \ { .name =3D _name, \ .type =3D OPT_UINT, \ .len =3D sizeof(_var), \ - .par.var =3D &_var } + .par.var =3D &_var }; \ + __paramfs __parfs_##_var =3D \ + { .param =3D &__rtpar_##_var, \ + .hypfs.e.type =3D XEN_HYPFS_TYPE_UINT, \ + .hypfs.e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .hypfs.e.name =3D _name, \ + .hypfs.e.size =3D sizeof(_var), \ + .hypfs.e.read =3D hypfs_read_leaf, \ + .hypfs.e.write =3D hypfs_write_leaf, \ + .hypfs.content =3D &_var } #define size_runtime_only_param(_name, _var) \ __rtparam __rtpar_##_var =3D \ { .name =3D _name, \ .type =3D OPT_SIZE, \ .len =3D sizeof(_var), \ - .par.var =3D &_var } + .par.var =3D &_var }; \ + __paramfs __parfs_##_var =3D \ + { .param =3D &__rtpar_##_var, \ + .hypfs.e.type =3D XEN_HYPFS_TYPE_UINT, \ + .hypfs.e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .hypfs.e.name =3D _name, \ + .hypfs.e.size =3D sizeof(_var), \ + .hypfs.e.read =3D hypfs_read_leaf, \ + .hypfs.e.write =3D hypfs_write_leaf, \ + .hypfs.content =3D &_var } #define string_runtime_only_param(_name, _var) \ __rtparam __rtpar_##_var =3D \ { .name =3D _name, \ .type =3D OPT_STR, \ .len =3D sizeof(_var), \ - .par.var =3D &_var } + .par.var =3D &_var }; \ + __paramfs __parfs_##_var =3D \ + { .param =3D &__rtpar_##_var, \ + .hypfs.e.type =3D XEN_HYPFS_TYPE_STRING, \ + .hypfs.e.encoding =3D XEN_HYPFS_ENC_PLAIN, \ + .hypfs.e.name =3D _name, \ + .hypfs.e.size =3D sizeof(_var), \ + .hypfs.e.read =3D hypfs_read_leaf, \ + .hypfs.e.write =3D hypfs_write_leaf, \ + .hypfs.content =3D &_var } =20 -#define custom_runtime_param(_name, _var) \ +#define custom_runtime_param(_name, _var, contvar) \ custom_param(_name, _var); \ - custom_runtime_only_param(_name, _var) + custom_runtime_only_param(_name, _var, contvar) #define boolean_runtime_param(_name, _var) \ boolean_param(_name, _var); \ boolean_runtime_only_param(_name, _var) @@ -123,4 +178,7 @@ extern const struct kernel_param __param_start[], __par= am_end[]; string_param(_name, _var); \ string_runtime_only_param(_name, _var) =20 +#define param_append_str(var, fmt, val) \ + snprintf(var + strlen(var), sizeof(var) - strlen(var), fmt, val) + #endif /* _XEN_PARAM_H */ --=20 2.16.4 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel