From patchwork Thu Aug 6 09:42:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nastya Vicodin X-Patchwork-Id: 1341550 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=EJjXkuUt; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BMk9n0jjXz9sR4 for ; Thu, 6 Aug 2020 19:45:00 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 242D682228; Thu, 6 Aug 2020 11:43:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EJjXkuUt"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8CE2982214; Thu, 6 Aug 2020 11:43:30 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D150D821BE for ; Thu, 6 Aug 2020 11:43:20 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=vicooodin@gmail.com Received: by mail-lj1-x22d.google.com with SMTP id w14so21184705ljj.4 for ; Thu, 06 Aug 2020 02:43:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EMiEqn4riypqpjjIIeNrvjp0j8ZTmaDkEYp6ZM+2vMg=; b=EJjXkuUt2hDE/uGsskVWf+jXcGCFT4bTLaty8CmB6DsqFQqTMx60zxbUzQ4b3JI6VZ BmdjC3r75oHWkqVEX8P9c3ibMhyuZNzctk42auQRtRRCjqQjZsG6ieWQ3ZE/qROf7ZH7 ZPQPeKejxIGY6DcKogCTi7pUu+i9iruiUqs6SGFaSPFj5m+utj3Xce3WL5SUbTUL7TXH SQOuscqOvcCq/ddxTcuBsjGlSoltICTJ0aa0kZwNDBrZUrWhgN5YWMLXYWm0a39MFYqI YUJIjzWs4LamfpzmHiQDyCsHgEBMcemama3x9px9KJfzu3HtU7fLusuwDF2UJmxVFxfG P+VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EMiEqn4riypqpjjIIeNrvjp0j8ZTmaDkEYp6ZM+2vMg=; b=b4VQnOZfge+u1uPt5iqY/sOcHIWJdADGF+VXW4fKh9yJ9mAvqIgzvfR3Ly4Vgy5DvL U7YTuiAjZbAfky1YfLbYvdmO2HbmFhlkngwLiBY7Ubu0tt1sy7flL0PFFtHyvPiUxTba 1gSr4KsXGjmOYWFYbHlUPjvXJfJcXwlt4yaImK+PMEj+xAOxAwCDK0hvH1cxmaL8OSE7 HK4zpxTkuVsyyNi4a94xC2XP1Ihe9NLo1vWfl17dmy8AxqfW2lMr1okzTiYzNVM34gu0 /iqpp1KPlYDpgQl6Tdgyd8DD2Gkz+8Ksnz9oce+4G4QAxZ+9iqc+ZAtq7EtCHpVLmmyf l9Wg== X-Gm-Message-State: AOAM531O9mPktsxoZvqwxyYABjJ9/YcepxjpROcY2vd1hNSARCgtLBb4 9jsykvanl2SO4CXJToHmzGw/0uEqf/Jg6w== X-Google-Smtp-Source: ABdhPJzFMfeeGKOlwexLrQo9fxIw0aXWy+yF4/81FCJ5Hgo8+pcpc0lJmLYuuxm8WuRo8fAbk8GEww== X-Received: by 2002:a2e:b0d2:: with SMTP id g18mr3179114ljl.136.1596706999342; Thu, 06 Aug 2020 02:43:19 -0700 (PDT) Received: from localhost.localdomain (host-176-36-213-80.la.net.ua. [176.36.213.80]) by smtp.gmail.com with ESMTPSA id j13sm2151866ljh.83.2020.08.06.02.43.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2020 02:43:18 -0700 (PDT) From: Anastasiia Lukianenko To: u-boot@lists.denx.de, sjg@chromium.org, ye.li@nxp.com, bmeng.cn@gmail.com, xypron.glpk@gmx.de Cc: julien@xen.org, sstabellini@kernel.org, peng.fan@nxp.com, roman@zededa.com, volodymyr_babchuk@epam.com, andr2000@gmail.com, vicooodin@gmail.com, Oleksandr Andrushchenko , Anastasiia Lukianenko Subject: [RESEND PATCH v2 10/18] xen: Port Xen bus driver from mini-os Date: Thu, 6 Aug 2020 12:42:53 +0300 Message-Id: <20200806094301.4999-11-vicooodin@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200806094301.4999-1-vicooodin@gmail.com> References: <20200806094301.4999-1-vicooodin@gmail.com> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean From: Oleksandr Andrushchenko Make required updates to run on u-boot and strip test code. Signed-off-by: Anastasiia Lukianenko Signed-off-by: Oleksandr Andrushchenko --- Changes since v1: - add comments - correct code style arch/arm/Kconfig | 1 + board/xen/xenguest_arm64/xenguest_arm64.c | 16 +- drivers/xen/Makefile | 1 + drivers/xen/hypervisor.c | 2 + drivers/xen/xenbus.c | 557 ++++++++++++++++++++++ include/xen.h | 2 +- include/xen/xenbus.h | 116 +++++ 7 files changed, 693 insertions(+), 2 deletions(-) create mode 100644 drivers/xen/xenbus.c create mode 100644 include/xen/xenbus.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 124d3eb3aa..497f540019 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1746,6 +1746,7 @@ config TARGET_XENGUEST_ARM64 select OF_CONTROL select LINUX_KERNEL_IMAGE_HEADER select XEN_SERIAL + select SSCANF endchoice config ARCH_SUPPORT_TFABOOT diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c index 488b238f02..18e12c404e 100644 --- a/board/xen/xenguest_arm64/xenguest_arm64.c +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -66,7 +66,7 @@ static int setup_mem_map(void) /* * Add "magic" region which is used by Xen to provide some essentials - * for the guest: we need console. + * for the guest: we need console and xenstore. */ ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn); if (ret < 0) { @@ -82,6 +82,20 @@ static int setup_mem_map(void) PTE_BLOCK_INNER_SHARE); i++; + ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_STORE_PFN, &gfn); + if (ret < 0) { + printf("%s: Can't get HVM_PARAM_STORE_PFN, ret %d\n", + __func__, ret); + return -EINVAL; + } + + xen_mem_map[i].virt = PFN_PHYS(gfn); + xen_mem_map[i].phys = PFN_PHYS(gfn); + xen_mem_map[i].size = PAGE_SIZE; + xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE); + i++; + mem = get_next_memory_node(blob, -1); if (mem < 0) { printf("%s: Missing /memory node\n", __func__); diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0ad35edefb..9d0f604aaa 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -4,3 +4,4 @@ obj-y += hypervisor.o obj-y += events.o +obj-y += xenbus.o diff --git a/drivers/xen/hypervisor.c b/drivers/xen/hypervisor.c index 63fed6074f..1c7ae94bdf 100644 --- a/drivers/xen/hypervisor.c +++ b/drivers/xen/hypervisor.c @@ -21,6 +21,7 @@ #include #include +#include #include #define active_evtchns(cpu, sh, idx) \ @@ -236,5 +237,6 @@ void xen_init(void) map_shared_info(NULL); init_events(); + init_xenbus(); } diff --git a/drivers/xen/xenbus.c b/drivers/xen/xenbus.c new file mode 100644 index 0000000000..177d144723 --- /dev/null +++ b/drivers/xen/xenbus.c @@ -0,0 +1,557 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) 2006 - Cambridge University + * (C) 2020 - EPAM Systems Inc. + * + * File: xenbus.c [1] + * Author: Steven Smith (sos22@cam.ac.uk) + * Changes: Grzegorz Milos (gm281@cam.ac.uk) + * Changes: John D. Ramsdell + * + * Date: Jun 2006, changes Aug 2006 + * + * Description: Minimal implementation of xenbus + * + * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary + */ + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#define map_frame_virt(v) (v << PAGE_SHIFT) + +#define SCNd16 "d" + +/* Wait for reply time out, ms */ +#define WAIT_XENBUS_TO_MS 5000 +/* Polling time out, ms */ +#define WAIT_XENBUS_POLL_TO_MS 1 + +static struct xenstore_domain_interface *xenstore_buf; + +static char *errmsg(struct xsd_sockmsg *rep); + +u32 xenbus_evtchn; + +struct write_req { + const void *data; + unsigned int len; +}; + +static void memcpy_from_ring(const void *r, void *d, int off, int len) +{ + int c1, c2; + const char *ring = r; + char *dest = d; + + c1 = min(len, XENSTORE_RING_SIZE - off); + c2 = len - c1; + memcpy(dest, ring + off, c1); + memcpy(dest + c1, ring, c2); +} + +/** + * xenbus_get_reply() - Receive reply from xenbus + * @req_reply: reply message structure + * + * Wait for reply message event from the ring and copy received message + * to input xsd_sockmsg structure. Repeat until full reply is + * proceeded. + * + * Return: false - timeout + * true - reply is received + */ +static bool xenbus_get_reply(struct xsd_sockmsg **req_reply) +{ + struct xsd_sockmsg msg; + unsigned int prod = xenstore_buf->rsp_prod; + +again: + if (!wait_event_timeout(NULL, prod != xenstore_buf->rsp_prod, + WAIT_XENBUS_TO_MS)) { + printk("%s: wait_event timeout\n", __func__); + return false; + } + + prod = xenstore_buf->rsp_prod; + if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg)) + goto again; + + rmb(); + memcpy_from_ring(xenstore_buf->rsp, &msg, + MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), + sizeof(msg)); + + if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg) + msg.len) + goto again; + + /* We do not support and expect any Xen bus wathes. */ + BUG_ON(msg.type == XS_WATCH_EVENT); + + *req_reply = malloc(sizeof(msg) + msg.len); + memcpy_from_ring(xenstore_buf->rsp, *req_reply, + MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), + msg.len + sizeof(msg)); + mb(); + xenstore_buf->rsp_cons += msg.len + sizeof(msg); + + wmb(); + notify_remote_via_evtchn(xenbus_evtchn); + return true; +} + +char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path, + XenbusState state) +{ + char *current_state; + char *msg = NULL; + char *msg2 = NULL; + char value[2]; + XenbusState rs; + int xbt_flag = 0; + int retry = 0; + + do { + if (xbt == XBT_NIL) { + msg = xenbus_transaction_start(&xbt); + if (msg) + goto exit; + xbt_flag = 1; + } + + msg = xenbus_read(xbt, path, ¤t_state); + if (msg) + goto exit; + + rs = (XenbusState)(current_state[0] - '0'); + free(current_state); + if (rs == state) { + msg = NULL; + goto exit; + } + + snprintf(value, 2, "%d", state); + msg = xenbus_write(xbt, path, value); + +exit: + if (xbt_flag) { + msg2 = xenbus_transaction_end(xbt, 0, &retry); + xbt = XBT_NIL; + } + if (msg == NULL && msg2 != NULL) + msg = msg2; + else + free(msg2); + } while (retry); + + return msg; +} + +char *xenbus_wait_for_state_change(const char *path, XenbusState *state) +{ + for (;;) { + char *res, *msg; + XenbusState rs; + + msg = xenbus_read(XBT_NIL, path, &res); + if (msg) + return msg; + + rs = (XenbusState)(res[0] - 48); + free(res); + + if (rs == *state) { + wait_event_timeout(NULL, false, WAIT_XENBUS_POLL_TO_MS); + } else { + *state = rs; + break; + } + } + return NULL; +} + +/* Send data to xenbus. This can block. All of the requests are seen + * by xenbus as if sent atomically. The header is added + * automatically, using type %type, req_id %req_id, and trans_id + * %trans_id. + */ +static void xb_write(int type, int req_id, xenbus_transaction_t trans_id, + const struct write_req *req, int nr_reqs) +{ + XENSTORE_RING_IDX prod; + int r; + int len = 0; + const struct write_req *cur_req; + int req_off; + int total_off; + int this_chunk; + struct xsd_sockmsg m = { + .type = type, + .req_id = req_id, + .tx_id = trans_id + }; + struct write_req header_req = { + &m, + sizeof(m) + }; + + for (r = 0; r < nr_reqs; r++) + len += req[r].len; + m.len = len; + len += sizeof(m); + + cur_req = &header_req; + + BUG_ON(len > XENSTORE_RING_SIZE); + prod = xenstore_buf->req_prod; + /* We are running synchronously, so it is a bug if we do not + * have enough room to send a message: please note that a message + * can occupy multiple slots in the ring buffer. + */ + BUG_ON(prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE); + + total_off = 0; + req_off = 0; + while (total_off < len) { + this_chunk = min(cur_req->len - req_off, + XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); + memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod), + (char *)cur_req->data + req_off, this_chunk); + prod += this_chunk; + req_off += this_chunk; + total_off += this_chunk; + if (req_off == cur_req->len) { + req_off = 0; + if (cur_req == &header_req) + cur_req = req; + else + cur_req++; + } + } + + BUG_ON(req_off != 0); + BUG_ON(total_off != len); + BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE); + + /* Remote must see entire message before updating indexes */ + wmb(); + + xenstore_buf->req_prod += len; + + /* Send evtchn to notify remote */ + notify_remote_via_evtchn(xenbus_evtchn); +} + +/* Send a message to xenbus, in the same fashion as xb_write, and + * block waiting for a reply. The reply is malloced and should be + * freed by the caller. + */ +struct xsd_sockmsg *xenbus_msg_reply(int type, + xenbus_transaction_t trans, + struct write_req *io, + int nr_reqs) +{ + struct xsd_sockmsg *rep; + + /* We do not use request identifier which is echoed in daemon's response. */ + xb_write(type, 0, trans, io, nr_reqs); + /* Now wait for the message to arrive. */ + if (!xenbus_get_reply(&rep)) + return NULL; + return rep; +} + +static char *errmsg(struct xsd_sockmsg *rep) +{ + char *res; + + if (!rep) { + char msg[] = "No reply"; + size_t len = strlen(msg) + 1; + + return memcpy(malloc(len), msg, len); + } + if (rep->type != XS_ERROR) + return NULL; + res = malloc(rep->len + 1); + memcpy(res, rep + 1, rep->len); + res[rep->len] = 0; + free(rep); + return res; +} + +/* List the contents of a directory. Returns a malloc()ed array of + * pointers to malloc()ed strings. The array is NULL terminated. May + * block. + */ +char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents) +{ + struct xsd_sockmsg *reply, *repmsg; + struct write_req req[] = { { pre, strlen(pre) + 1 } }; + int nr_elems, x, i; + char **res, *msg; + + repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(repmsg); + if (msg) { + *contents = NULL; + return msg; + } + reply = repmsg + 1; + for (x = nr_elems = 0; x < repmsg->len; x++) + nr_elems += (((char *)reply)[x] == 0); + res = malloc(sizeof(res[0]) * (nr_elems + 1)); + for (x = i = 0; i < nr_elems; i++) { + int l = strlen((char *)reply + x); + + res[i] = malloc(l + 1); + memcpy(res[i], (char *)reply + x, l + 1); + x += l + 1; + } + res[i] = NULL; + free(repmsg); + *contents = res; + return NULL; +} + +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value) +{ + struct write_req req[] = { {path, strlen(path) + 1} }; + struct xsd_sockmsg *rep; + char *res, *msg; + + rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(rep); + if (msg) { + *value = NULL; + return msg; + } + res = malloc(rep->len + 1); + memcpy(res, rep + 1, rep->len); + res[rep->len] = 0; + free(rep); + *value = res; + return NULL; +} + +char *xenbus_write(xenbus_transaction_t xbt, const char *path, + const char *value) +{ + struct write_req req[] = { + {path, strlen(path) + 1}, + {value, strlen(value)}, + }; + struct xsd_sockmsg *rep; + char *msg; + + rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(rep); + if (msg) + return msg; + free(rep); + return NULL; +} + +char *xenbus_rm(xenbus_transaction_t xbt, const char *path) +{ + struct write_req req[] = { {path, strlen(path) + 1} }; + struct xsd_sockmsg *rep; + char *msg; + + rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(rep); + if (msg) + return msg; + free(rep); + return NULL; +} + +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value) +{ + struct write_req req[] = { {path, strlen(path) + 1} }; + struct xsd_sockmsg *rep; + char *res, *msg; + + rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(rep); + if (msg) { + *value = NULL; + return msg; + } + res = malloc(rep->len + 1); + memcpy(res, rep + 1, rep->len); + res[rep->len] = 0; + free(rep); + *value = res; + return NULL; +} + +#define PERM_MAX_SIZE 32 +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, + domid_t dom, char perm) +{ + char value[PERM_MAX_SIZE]; + struct write_req req[] = { + {path, strlen(path) + 1}, + {value, 0}, + }; + struct xsd_sockmsg *rep; + char *msg; + + snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom); + req[1].len = strlen(value) + 1; + rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req)); + msg = errmsg(rep); + if (msg) + return msg; + free(rep); + return NULL; +} + +char *xenbus_transaction_start(xenbus_transaction_t *xbt) +{ + /* Xenstored becomes angry if you send a length 0 message, so just + * shove a nul terminator on the end + */ + struct write_req req = { "", 1}; + struct xsd_sockmsg *rep; + char *err; + + rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1); + err = errmsg(rep); + if (err) + return err; + sscanf((char *)(rep + 1), "%lu", xbt); + free(rep); + return NULL; +} + +char *xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry) +{ + struct xsd_sockmsg *rep; + struct write_req req; + char *err; + + *retry = 0; + + req.data = abort ? "F" : "T"; + req.len = 2; + rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1); + err = errmsg(rep); + if (err) { + if (!strcmp(err, "EAGAIN")) { + *retry = 1; + free(err); + return NULL; + } else { + return err; + } + } + free(rep); + return NULL; +} + +int xenbus_read_integer(const char *path) +{ + char *res, *buf; + int t; + + res = xenbus_read(XBT_NIL, path, &buf); + if (res) { + printk("Failed to read %s.\n", path); + free(res); + return -1; + } + sscanf(buf, "%d", &t); + free(buf); + return t; +} + +int xenbus_read_uuid(const char *path, unsigned char uuid[16]) +{ + char *res, *buf; + + res = xenbus_read(XBT_NIL, path, &buf); + if (res) { + printk("Failed to read %s.\n", path); + free(res); + return 0; + } + if (strlen(buf) != ((2 * 16) + 4) /* 16 hex bytes and 4 hyphens */ + || sscanf(buf, + "%2hhx%2hhx%2hhx%2hhx-" + "%2hhx%2hhx-" + "%2hhx%2hhx-" + "%2hhx%2hhx-" + "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + uuid, uuid + 1, uuid + 2, uuid + 3, + uuid + 4, uuid + 5, uuid + 6, uuid + 7, + uuid + 8, uuid + 9, uuid + 10, uuid + 11, + uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) { + printk("Xenbus path %s value %s is not a uuid!\n", path, buf); + free(buf); + return 0; + } + free(buf); + return 1; +} + +char *xenbus_printf(xenbus_transaction_t xbt, + const char *node, const char *path, + const char *fmt, ...) +{ +#define BUFFER_SIZE 256 + char fullpath[BUFFER_SIZE]; + char val[BUFFER_SIZE]; + va_list args; + + BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE); + sprintf(fullpath, "%s/%s", node, path); + va_start(args, fmt); + vsprintf(val, fmt, args); + va_end(args); + return xenbus_write(xbt, fullpath, val); +} + +domid_t xenbus_get_self_id(void) +{ + char *dom_id; + domid_t ret; + + BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id)); + sscanf(dom_id, "%"SCNd16, &ret); + + return ret; +} + +void init_xenbus(void) +{ + u64 v; + + debug("%s\n", __func__); + if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v)) + BUG(); + xenbus_evtchn = v; + + if (hvm_get_parameter(HVM_PARAM_STORE_PFN, &v)) + BUG(); + xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v); +} + +void fini_xenbus(void) +{ + debug("%s\n", __func__); +} diff --git a/include/xen.h b/include/xen.h index 64ed3f0654..6fe30b83a2 100644 --- a/include/xen.h +++ b/include/xen.h @@ -8,7 +8,7 @@ /** * xen_init() - Xen initialization * - * Map Xen memory pages, initialize event handler. + * Map Xen memory pages, initialize event handler and xenbus. */ void xen_init(void); diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h new file mode 100644 index 0000000000..3ed7fd5733 --- /dev/null +++ b/include/xen/xenbus.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef XENBUS_H__ +#define XENBUS_H__ + +#include +#include + +typedef unsigned long xenbus_transaction_t; +#define XBT_NIL ((xenbus_transaction_t)0) + +extern u32 xenbus_evtchn; + +/* Initialize the XenBus system. */ +void init_xenbus(void); +/* Finalize the XenBus system. */ +void fini_xenbus(void); + +/** + * xenbus_read() - Read the value associated with a path. + * + * Returns a malloc'd error string on failure and sets *value to NULL. + * On success, *value is set to a malloc'd copy of the value. + */ +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value); + +char *xenbus_wait_for_state_change(const char *path, XenbusState *state); +char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path, + XenbusState state); + +/** + * xenbus_write() - Associates a value with a path. + * + * Returns a malloc'd error string on failure. + */ +char *xenbus_write(xenbus_transaction_t xbt, const char *path, + const char *value); + +/** + * xenbus_rm() - Removes the value associated with a path. + * + * Returns a malloc'd error string on failure. + */ +char *xenbus_rm(xenbus_transaction_t xbt, const char *path); + +/** + * xenbus_ls() - List the contents of a directory. + * + * Returns a malloc'd error string on failure and sets *contents to NULL. + * On success, *contents is set to a malloc'd array of pointers to malloc'd + * strings. The array is NULL terminated. May block. + */ +char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents); + +/** + * xenbus_get_perms() - Reads permissions associated with a path. + * + * Returns a malloc'd error string on failure and sets *value to NULL. + * On success, *value is set to a malloc'd copy of the value. + */ +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value); + +/** + * xenbus_set_perms() - Sets the permissions associated with a path. + * + * Returns a malloc'd error string on failure. + */ +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, + char perm); + +/** + * xenbus_transaction_start() - Start a xenbus transaction. + * + * Returns the transaction in xbt on success or a malloc'd error string + * otherwise. + */ +char *xenbus_transaction_start(xenbus_transaction_t *xbt); + +/** + * xenbus_transaction_end() - End a xenbus transaction. + * + * Returns a malloc'd error string if it fails. Abort says whether the + * transaction should be aborted. + * Returns 1 in *retry if the transaction should be retried. + */ +char *xenbus_transaction_end(xenbus_transaction_t xbt, int abort, + int *retry); + +/** + * xenbus_read_integer() - Read path and parse it as an integer. + * + * Returns -1 on error. + */ +int xenbus_read_integer(const char *path); + +/** + * xenbus_read_uuid() - Read path and parse it as 16 byte uuid. + * + * Returns 1 if read and parsing were successful, 0 if not + */ +int xenbus_read_uuid(const char *path, unsigned char uuid[16]); + +/** + * xenbus_printf() - Contraction of snprintf and xenbus_write(path/node). + */ +char *xenbus_printf(xenbus_transaction_t xbt, + const char *node, const char *path, + const char *fmt, ...) + __attribute__((__format__(printf, 4, 5))); + +/** + * xenbus_get_self_id() - Utility function to figure out our domain id + */ +domid_t xenbus_get_self_id(void); + +#endif /* XENBUS_H__ */