xen: Port Xen bus driver from mini-os
Make required updates to run on u-boot and strip test code. Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
This commit is contained in:
parent
e87dfb0526
commit
60e49ff1f8
@ -1756,6 +1756,7 @@ config TARGET_XENGUEST_ARM64
|
||||
select OF_CONTROL
|
||||
select LINUX_KERNEL_IMAGE_HEADER
|
||||
select XEN_SERIAL
|
||||
select SSCANF
|
||||
endchoice
|
||||
|
||||
config ARCH_SUPPORT_TFABOOT
|
||||
|
@ -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__);
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
obj-y += hypervisor.o
|
||||
obj-y += events.o
|
||||
obj-y += xenbus.o
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <xen/hvm.h>
|
||||
#include <xen/events.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/interface/memory.h>
|
||||
|
||||
#define active_evtchns(cpu, sh, idx) \
|
||||
@ -236,5 +237,6 @@ void xen_init(void)
|
||||
|
||||
map_shared_info(NULL);
|
||||
init_events();
|
||||
init_xenbus();
|
||||
}
|
||||
|
||||
|
557
drivers/xen/xenbus.c
Normal file
557
drivers/xen/xenbus.c
Normal file
@ -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 <common.h>
|
||||
#include <log.h>
|
||||
|
||||
#include <asm/armv8/mmu.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/xen/system.h>
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#include <xen/events.h>
|
||||
#include <xen/hvm.h>
|
||||
#include <xen/xenbus.h>
|
||||
|
||||
#include <xen/interface/io/xs_wire.h>
|
||||
|
||||
#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__);
|
||||
}
|
@ -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);
|
||||
|
||||
|
116
include/xen/xenbus.h
Normal file
116
include/xen/xenbus.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef XENBUS_H__
|
||||
#define XENBUS_H__
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/io/xenbus.h>
|
||||
|
||||
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__ */
|
Loading…
Reference in New Issue
Block a user