From: Zhongze Liu Date: Wed, 5 Dec 2018 22:16:01 +0000 (-0800) Subject: libxl:xl: add parsing code to parse "libxl_static_sshm" from xl config files X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=709a359236817b61ba4dede8c4fe3a59add3a9a0;p=people%2Fsstabellini%2Fxen-unstable.git%2F.git libxl:xl: add parsing code to parse "libxl_static_sshm" from xl config files Add the parsing utils for the newly introduced libxl_static_sshm struct to the libxl/libxlu_* family. And add realated parsing code in xl to parse the struct from xl config files. This is for the proposal "Allow setting up shared memory areas between VMs from xl config file" (see [1]). [1] https://lists.xen.org/archives/html/xen-devel/2017-08/msg03242.html Signed-off-by: Zhongze Liu Signed-off-by: Stefano Stabellini Cc: Wei Liu Cc: Ian Jackson Cc: Stefano Stabellini Cc: Julien Grall Cc: xen-devel@lists.xen.org --- diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index 90a6fb4255..7c5171fea5 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -173,7 +173,7 @@ AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h _libxl_list.h _paths.h \ AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c AUTOSRCS += _libxl_save_msgs_callout.c _libxl_save_msgs_helper.c LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \ - libxlu_disk_l.o libxlu_disk.o libxlu_vif.o libxlu_pci.o + libxlu_disk_l.o libxlu_disk.o libxlu_vif.o libxlu_pci.o libxlu_sshm.o $(LIBXLU_OBJS): CFLAGS += $(CFLAGS_libxenctrl) # For xentoollog.h $(TEST_PROG_OBJS) _libxl.api-for-check: CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxentoolcore) diff --git a/tools/libxl/libxlu_sshm.c b/tools/libxl/libxlu_sshm.c new file mode 100644 index 0000000000..ed6e31dd6d --- /dev/null +++ b/tools/libxl/libxlu_sshm.c @@ -0,0 +1,206 @@ +#include "libxl_osdeps.h" /* must come before any other headers */ +#include "libxlu_internal.h" +#include "xenctrl.h" + +#include + +#define PARAM_RE(EXPR) "^\\s*" EXPR "\\s*(,|$)" +#define WORD_RE "([_a-zA-Z0-9]+)" +#define EQU_RE PARAM_RE(WORD_RE "\\s*=\\s*" WORD_RE) + +#define RET_INVAL(msg, curr_str) do { \ + xlu__sshm_err(cfg, msg, curr_str); \ + rc = EINVAL; \ + goto out; \ + } while(0) + +/* set a member in libxl_static_shm and report an error if it's respecified, + * @curr_str indicates the head of the remaining string. */ +#define SET_VAL(var, name, type, value, curr_str) do { \ + if ((var) != LIBXL_SSHM_##type##_UNKNOWN && (var) != value) { \ + RET_INVAL("\"" name "\" respecified", curr_str); \ + } \ + (var) = value; \ + } while(0) + + +static void xlu__sshm_err(XLU_Config *cfg, const char *msg, + const char *curr_str) { + fprintf(cfg->report, + "%s: config parsing error in shared_memory: %s at '%s'\n", + cfg->config_source, msg, curr_str); +} + +static int parse_prot(XLU_Config *cfg, char *str, libxl_sshm_prot *prot) +{ + int rc; + libxl_sshm_prot new_prot; + + if (!strcmp(str, "rw")) { + new_prot = LIBXL_SSHM_PROT_RW; + } else { + RET_INVAL("invalid permission flags", str); + } + + SET_VAL(*prot, "permission flags", PROT, new_prot, str); + + rc = 0; + + out: + return rc; +} + +static int parse_cachepolicy(XLU_Config *cfg, char *str, + libxl_sshm_cachepolicy *policy) +{ + int rc; + libxl_sshm_cachepolicy new_policy; + + if (!strcmp(str, "ARM_normal")) { + new_policy = LIBXL_SSHM_CACHEPOLICY_ARM_NORMAL; + } else if (!strcmp(str, "x86_normal")) { + new_policy = LIBXL_SSHM_CACHEPOLICY_X86_NORMAL; + } else { + RET_INVAL("invalid cache policy", str); + } + + SET_VAL(*policy, "cache policy", CACHEPOLICY, new_policy, str); + rc = 0; + + out: + return rc; +} + +/* handle key = value pairs */ +static int handle_equ(XLU_Config *cfg, char *key, char *val, + libxl_static_shm *sshm) +{ + int rc; + + if (!strcmp(key, "id")) { + if (sshm->id && !strcmp(sshm->id, val)) { + RET_INVAL("id respecified", val); + } + + sshm->id = strdup(val); + if (!sshm->id) { + fprintf(stderr, "sshm parser out of memory\n"); + rc = ENOMEM; + goto out; + } + } else if (!strcmp(key, "role")) { + libxl_sshm_role new_role; + + if (!strcmp("owner", val)) { + new_role = LIBXL_SSHM_ROLE_OWNER; + } else if (!strcmp("borrower", val)) { + new_role = LIBXL_SSHM_ROLE_BORROWER; + } else { + RET_INVAL("invalid role", val); + } + + SET_VAL(sshm->role, "role", ROLE, new_role, val); + } else if (!strcmp(key, "begin") || + !strcmp(key, "size") || + !strcmp(key, "offset")) { + char *endptr; + int base = 10; + uint64_t new_addr; + + /* Could be in hex form. Note that we don't need to check the length here, + * for val[] is NULL-terminated */ + if (val[0] == '0' && val[1] == 'x') { base = 16; } + new_addr = strtoull(val, &endptr, base); + if (errno == ERANGE || *endptr) + RET_INVAL("invalid begin/size/offset", val); + + if (key[0] == 'b') { + SET_VAL(sshm->begin, "beginning address", RANGE, new_addr, val); + } else if(key[0] == 's'){ + SET_VAL(sshm->size, "size", RANGE, new_addr, val); + } else { + SET_VAL(sshm->offset, "offset", RANGE, new_addr, val); + } + } else if (!strcmp(key, "prot")) { + rc = parse_prot(cfg, val, &sshm->prot); + if (rc) { goto out; } + } else if (!strcmp(key, "cache_policy")) { + rc = parse_cachepolicy(cfg, val, &sshm->cache_policy); + if (rc) { goto out; } + } else { + RET_INVAL("invalid option", key); + } + + rc = 0; + + out: + return rc; +} + +int xlu_sshm_parse(XLU_Config *cfg, const char *spec, + libxl_static_shm *sshm) +{ + int rc; + regex_t equ_rec; + char *buf2 = NULL, *ptr = NULL; + regmatch_t pmatch[3]; + + rc = regcomp(&equ_rec, EQU_RE, REG_EXTENDED); + if (rc) { + fprintf(stderr, "sshm parser failed to initialize\n"); + goto out; + } + + buf2 = ptr = strdup(spec); + if (!buf2) { + fprintf(stderr, "sshm parser out of memory\n"); + rc = ENOMEM; + goto out; + } + + /* main parsing loop */ + while (true) { + if (!*ptr) { break; } + if (regexec(&equ_rec, ptr, 3, pmatch, 0)) + RET_INVAL("unrecognized token", ptr); + + ptr[pmatch[1].rm_eo] = '\0'; + ptr[pmatch[2].rm_eo] = '\0'; + rc = handle_equ(cfg, ptr + pmatch[1].rm_so, + ptr + pmatch[2].rm_so, sshm); + if (rc) { goto out; } + + ptr += pmatch[0].rm_eo; + } + + if (*ptr) { RET_INVAL("invalid syntax", ptr); } + + /* do some early checks */ + if (!sshm->id) { + RET_INVAL("id not specified", spec); + } + if (sshm->begin == LIBXL_SSHM_RANGE_UNKNOWN) { + RET_INVAL("begin address not specified", spec); + } + if (sshm->size == LIBXL_SSHM_RANGE_UNKNOWN) { + RET_INVAL("size not specified", spec); + } + if (sshm->prot == LIBXL_SSHM_PROT_UNKNOWN) { + sshm->prot = LIBXL_SSHM_PROT_RW; + } + + rc = 0; + + out: + if (buf2) { free(buf2); } + regfree(&equ_rec); + return rc; +} + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxl/libxlutil.h b/tools/libxl/libxlutil.h index 92e35c5462..7140e76845 100644 --- a/tools/libxl/libxlutil.h +++ b/tools/libxl/libxlutil.h @@ -125,6 +125,12 @@ int xlu_rdm_parse(XLU_Config *cfg, libxl_rdm_reserve *rdm, const char *str); int xlu_vif_parse_rate(XLU_Config *cfg, const char *rate, libxl_device_nic *nic); +/* + * static shared memory specification parsing + */ +int xlu_sshm_parse(XLU_Config *cfg, const char *spec, + libxl_static_shm *sshm); + #endif /* LIBXLUTIL_H */ /* diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c index b881184804..8ae898086d 100644 --- a/tools/xl/xl_parse.c +++ b/tools/xl/xl_parse.c @@ -1212,7 +1212,8 @@ void parse_config_data(const char *config_source, long l, vcpus = 0; XLU_Config *config; XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, - *usbctrls, *usbdevs, *p9devs, *vdispls, *pvcallsifs_devs; + *usbctrls, *usbdevs, *p9devs, *vdispls, *pvcallsifs_devs, + *sshms; XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs, *mca_caps; int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian, num_mca_caps; @@ -1992,6 +1993,28 @@ void parse_config_data(const char *config_source, } } + if (!xlu_cfg_get_list (config, "static_shm", &sshms, 0, 0)) { + d_config->num_sshms = 0; + d_config->sshms = NULL; + while ((buf = xlu_cfg_get_listitem (sshms, d_config->num_sshms)) != NULL) { + libxl_static_shm *sshm; + char *buf2 = strdup(buf); + int ret; + + sshm = ARRAY_EXTEND_INIT_NODEVID(d_config->sshms, + d_config->num_sshms, + libxl_static_shm_init); + ret = xlu_sshm_parse(config, buf2, sshm); + if (ret) { + fprintf(stderr, + "xl: Invalid argument for static_shm: %s", buf2); + exit(EXIT_FAILURE); + } + + free(buf2); + } + } + if (!xlu_cfg_get_list(config, "p9", &p9devs, 0, 0)) { libxl_device_p9 *p9; char *security_model = NULL;