xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] Add xl PCI daemon (server for libxl PCI)
@ 2021-08-12 14:22 Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 1/9] tools/libs/light: Add vchan support to libxl Anastasiia Lukianenko
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

This work introduces xl PCI daemon that acts as a server for the client
in the libxl PCI. The toolstack in Dom0 accesses sysfs to get information
about PCI devices and in case of Hardware Domain that sysfs lives in
Hardware Domain, so Dom0 can't read that information directly anymore.
For that reason we introduce a "proxy" which directs requests from Dom0 to
the domain which owns PCI devices, being it Dom0 itself or any other domain,
e.g. Hardware Domain. xl PCI daemon is based on vchan-node2 tool and uses
the libxenvchan library for messaging transport.

It was verified that this model works both remotely (in different domains)
and locally (within one domain) as requested by Xen community [1]. The
server processes the requests that come from the client. For better
interoperability between guest OSes, e.g. Linux vs FreeBSD, the path in the
request is not a direct sysfs entry as seen in Dom0, but instead it is a
key-word defined in the protocol. For now libxl PCI refers to sysfs in the
following functions, therefore such a subset was implemented in xl PCI
daemon commands handling:
* ‘ls’ - the server receives "dir_id" as a parameter. Xl pcid server
  transmits information about devices assigned to the PCI driver by sending
  a reply with the remote directory listing. Client cannot pass the sysfs
  path, as it is not the same on different operating systems. Therefore,
  for example, we pass parameter "pciback_driver" and on the server side
  we refer to "/sys/bus/pci/drivers/pciback" if Linux is used);
* ‘write’- the server receives the file name and value as parameters where
  and what to write;
* ‘read_hex’ - xl PCI daemon returns hex value read from the given path;
* ‘exists’ - check if path exists;
* ‘read_resources’ - returns an array of PCI device resources (start, end,
   flags) read from given path;
* ‘unbind’ - unbinds PCI device;
* ‘reset’ - resets PCI device.

Requests and responses are formed in the form of a json which is already
used by libxenlight (xl). The commands are aimed at preventing the libxl
PCI from reading / writing from / to the local sysfs directly. To do this,
the libxl PCI itself was changed, vchan and pcid support was added to
libxl - instead of working with the read and write functions from / to the
sysfs, functionality was added to send requests to the server, then receive
and process the response.

Libxl vchan is used as transport between libxl and the server side. Libxl
vchan adds support for JSON messages processing. Libxl pcid functions allow
to process the received message from PCI server and to generate a reply in
JSON format for the client. The pcid functions in the libxl allow the use
of internal libxl structures and functions, so there is no code duplications
on server side.

The issue of simultaneous access of several processes to the channel is not
resolved as well. For example, the commands “xl pci-assignable-list” and
“xl pci-assignable-add” will be sent at the same time. Due to the fact that
there is only one channel, the processing of two requests will cause
undefined behavior on the server side. In the future, it is necessary to
take into account cases when from different domains there can be several
requests from a client at the same time or from the same but xl commands are
executed concurrently.

[1] - https://www.mail-archive.com/xen-devel@lists.xenproject.org/msg84452.html

Regards,
Anastasiia

Anastasiia Lukianenko (9):
  tools/libs/light: Add vchan support to libxl
  tools/libs/light: Add functions for handling PCI messages in JSON
    format
  tools/xl: Add pcid daemon to xl
  tools/libs/light: Add "ls" command processing to xl pcid daemon and
    libxl PCI
  tools/libs/light: Add "write" command to xl pcid and libxl PCI
  tools/libs/light: Add "read" command to xl pcid and libxl PCI
  tools/libs/light: Make Libxl PCI get values from xl pcid instead of
    libxl side
  tools/libs/light: Add "unbind" and "read resources" commands to libxl
    PCI and xl pcid
  tools/libs/light: Add "reset" and "remove" PCI dev commands to xl pcid
    daemon and libxl PCI

 tools/configure                           |   5 +-
 tools/helpers/Makefile                    |   4 +-
 tools/hotplug/FreeBSD/rc.d/xlpcid.in      |  75 +++
 tools/hotplug/Linux/init.d/xlpcid.in      |  76 +++
 tools/hotplug/NetBSD/rc.d/xlpcid.in       |  75 +++
 tools/include/pcid.h                      |  73 +++
 tools/libs/light/Makefile                 |   8 +-
 tools/libs/light/libxl_pci.c              | 566 ++++++++++++++--------
 tools/libs/light/libxl_pcid.c             | 527 ++++++++++++++++++++
 tools/libs/light/libxl_types.idl          |   1 +
 tools/libs/light/libxl_types_internal.idl |   6 +
 tools/libs/light/libxl_vchan.c            | 359 ++++++++++++++
 tools/libs/light/libxl_vchan.h            |  81 ++++
 tools/xl/Makefile                         |   5 +-
 tools/xl/xl.h                             |   1 +
 tools/xl/xl_cmdtable.c                    |   7 +
 tools/xl/xl_pcid.c                        |  79 +++
 17 files changed, 1727 insertions(+), 221 deletions(-)
 create mode 100644 tools/hotplug/FreeBSD/rc.d/xlpcid.in
 create mode 100644 tools/hotplug/Linux/init.d/xlpcid.in
 create mode 100644 tools/hotplug/NetBSD/rc.d/xlpcid.in
 create mode 100644 tools/include/pcid.h
 create mode 100644 tools/libs/light/libxl_pcid.c
 create mode 100644 tools/libs/light/libxl_vchan.c
 create mode 100644 tools/libs/light/libxl_vchan.h
 create mode 100644 tools/xl/xl_pcid.c

-- 
2.17.1



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/9] tools/libs/light: Add vchan support to libxl
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 2/9] tools/libs/light: Add functions for handling PCI messages in JSON format Anastasiia Lukianenko
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Add possibility to send commands from libxl and execute them on server
side. Libxl vchan adds support for JSON messages processing.

The using of libxl vchan is preventing the client from libxl from reading
and writing from / to the local sysfs directly.To do this, the libxl vchan
was added - instead of working with the read and write functions from / to
the sysfs, functionality allows to send requests to the server, then
receive and process the response.

Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/helpers/Makefile         |   4 +-
 tools/libs/light/Makefile      |   7 +-
 tools/libs/light/libxl_vchan.c | 359 +++++++++++++++++++++++++++++++++
 tools/libs/light/libxl_vchan.h |  81 ++++++++
 tools/xl/Makefile              |   3 +-
 5 files changed, 448 insertions(+), 6 deletions(-)
 create mode 100644 tools/libs/light/libxl_vchan.c
 create mode 100644 tools/libs/light/libxl_vchan.h

diff --git a/tools/helpers/Makefile b/tools/helpers/Makefile
index 1bcc97ea8a..ad2cdf32ad 100644
--- a/tools/helpers/Makefile
+++ b/tools/helpers/Makefile
@@ -29,12 +29,12 @@ $(INIT_XENSTORE_DOMAIN_OBJS): CFLAGS += $(CFLAGS_libxenlight)
 all: $(PROGS)
 
 xen-init-dom0: $(XEN_INIT_DOM0_OBJS)
-	$(CC) $(LDFLAGS) -o $@ $(XEN_INIT_DOM0_OBJS) $(LDLIBS_libxenctrl) $(LDLIBS_libxentoollog) $(LDLIBS_libxenstore) $(LDLIBS_libxenlight) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(XEN_INIT_DOM0_OBJS) $(LDLIBS_libxenctrl) $(LDLIBS_libxentoollog) $(LDLIBS_libxenstore) $(LDLIBS_libxenlight) $(LDLIBS_libxenvchan) $(APPEND_LDFLAGS)
 
 $(INIT_XENSTORE_DOMAIN_OBJS): _paths.h
 
 init-xenstore-domain: $(INIT_XENSTORE_DOMAIN_OBJS)
-	$(CC) $(LDFLAGS) -o $@ $(INIT_XENSTORE_DOMAIN_OBJS) $(LDLIBS_libxentoollog) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenlight) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(INIT_XENSTORE_DOMAIN_OBJS) $(LDLIBS_libxentoollog) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenlight) $(LDLIBS_libxenvchan) $(APPEND_LDFLAGS)
 
 .PHONY: install
 install: all
diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
index 4a4de12610..f5d34b3371 100644
--- a/tools/libs/light/Makefile
+++ b/tools/libs/light/Makefile
@@ -76,6 +76,7 @@ SRCS-y += libxl.c
 SRCS-y += libxl_create.c
 SRCS-y += libxl_dm.c
 SRCS-y += libxl_pci.c
+SRCS-y += libxl_vchan.c
 SRCS-y += libxl_dom.c
 SRCS-y += libxl_exec.c
 SRCS-y += libxl_xshelp.c
@@ -176,7 +177,7 @@ LDUSELIBS-y += $(PTHREAD_LIBS)
 LDUSELIBS-y += -lyajl
 LDUSELIBS += $(LDUSELIBS-y)
 
-$(LIB_OBJS) $(PIC_OBJS) $(LIBXL_TEST_OBJS): CFLAGS += $(CFLAGS_LIBXL) -include $(XEN_ROOT)/tools/config.h
+$(LIB_OBJS) $(PIC_OBJS) $(LIBXL_TEST_OBJS): CFLAGS += $(CFLAGS_LIBXL) $(CFLAGS_libxenevtchn) -include $(XEN_ROOT)/tools/config.h
 $(ACPI_OBJS) $(ACPI_PIC_OBJS): CFLAGS += -I. -DLIBACPI_STDUTILS=\"$(CURDIR)/libxl_x86_acpi.h\"
 $(TEST_PROG_OBJS) _libxl.api-for-check: CFLAGS += $(CFLAGS_libxentoollog) $(CFLAGS_libxentoolcore)
 libxl_dom.o libxl_dom.opic: CFLAGS += -I$(XEN_ROOT)/tools  # include libacpi/x86.h
@@ -240,13 +241,13 @@ libxenlight_test.so: $(PIC_OBJS) $(LIBXL_TEST_OBJS)
 	$(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenlight.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(LDUSELIBS) $(APPEND_LDFLAGS)
 
 test_%: test_%.o test_common.o libxenlight_test.so
-	$(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) -lyajl $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $^ $(filter-out %libxenlight.so, $(LDLIBS_libxenlight)) $(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) $(LDLIBS_libxenvchan) -lyajl $(APPEND_LDFLAGS)
 
 libxl-save-helper: $(SAVE_HELPER_OBJS) libxenlight.so
 	$(CC) $(LDFLAGS) -o $@ $(SAVE_HELPER_OBJS) $(LDLIBS_libxentoollog) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxentoolcore) $(APPEND_LDFLAGS)
 
 testidl: testidl.o libxenlight.so
-	$(CC) $(LDFLAGS) -o $@ testidl.o $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ testidl.o $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxentoolcore) $(LDLIBS_libxenvchan) $(APPEND_LDFLAGS)
 
 install: installlocal $(LIBHEADERS)
 
diff --git a/tools/libs/light/libxl_vchan.c b/tools/libs/light/libxl_vchan.c
new file mode 100644
index 0000000000..b533243fd3
--- /dev/null
+++ b/tools/libs/light/libxl_vchan.c
@@ -0,0 +1,359 @@
+/*
+ * Vchan support for JSON messages processing
+ *
+ * Copyright (C) 2021 EPAM Systems Inc.
+ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
+ * Author: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+#include "libxl_vchan.h"
+
+/* Based on QMP Parameters Helpers */
+static void vchan_parameters_common_add(libxl__gc *gc, libxl__json_object **param,
+                                        const char *name, libxl__json_object *obj)
+{
+    libxl__json_map_node *arg = NULL;
+
+    if (!*param) {
+        *param = libxl__json_object_alloc(gc, JSON_MAP);
+    }
+
+    GCNEW(arg);
+
+    arg->map_key = libxl__strdup(gc, name);
+    arg->obj = obj;
+
+    flexarray_append((*param)->u.map, arg);
+}
+
+
+void libxl__vchan_param_add_string(libxl__gc *gc, libxl__json_object **param,
+                                   const char *name, const char *s)
+{
+    libxl__json_object *obj;
+
+    obj = libxl__json_object_alloc(gc, JSON_STRING);
+    obj->u.string = libxl__strdup(gc, s);
+
+    vchan_parameters_common_add(gc, param, name, obj);
+}
+
+void libxl__vchan_param_add_integer(libxl__gc *gc, libxl__json_object **param,
+                                    const char *name, const long long i)
+{
+    libxl__json_object *obj;
+
+    obj = libxl__json_object_alloc(gc, JSON_INTEGER);
+    obj->u.i = i;
+
+    vchan_parameters_common_add(gc, param, name, obj);
+}
+
+/* Returns 1 if path exists, 0 if not, ERROR_* (<0) on error. */
+int xs_path_exists(libxl__gc *gc, const char *xs_path)
+{
+    int rc;
+    const char *dir;
+
+    rc = libxl__xs_read_checked(gc, XBT_NULL, xs_path, &dir);
+    if (rc)
+        return rc;
+    if (dir)
+        return 1;
+    return 0;
+}
+
+libxl_domid vchan_find_server(libxl__gc *gc, char *xs_dir, char *xs_path)
+{
+    char **domains;
+    unsigned int i, n;
+    libxl_domid domid = DOMID_INVALID;
+
+    domains = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &n);
+    if (!n)
+        goto out;
+
+    for (i = 0; i < n; i++) {
+        int d;
+
+        if (sscanf(domains[i], "%d", &d) != 1)
+            continue;
+        if (xs_path_exists(gc, GCSPRINTF("%s%d%s", xs_dir, d, xs_path)) > 0) {
+            /* Found the domain where the server lives. */
+            domid = d;
+            break;
+        }
+    }
+
+out:
+    return domid;
+}
+
+static int vchan_init_client(libxl__gc *gc, struct vchan_state *state, int is_server)
+{
+	if (is_server) {
+		state->ctrl = libxenvchan_server_init(NULL, state->domid, state->xs_path, 0, 0);
+	    if (!state->ctrl) {
+	        perror("Libxenvchan server init failed\n");
+	        exit(1);
+	    }
+	} else {
+		state->ctrl = libxenvchan_client_init(CTX->lg, state->domid,
+                                          state->xs_path);
+	    if (!state->ctrl) {
+	        LOGE(ERROR, "Couldn't intialize vchan client");
+	        return ERROR_FAIL;
+	    }
+	}
+
+    state->select_fd = libxenvchan_fd_for_select(state->ctrl);
+    if (state->select_fd < 0) {
+        LOGE(ERROR, "Couldn't read file descriptor for vchan client");
+        return ERROR_FAIL;
+    }
+
+    LOG(DEBUG, "Intialized vchan client, server at %s", state->xs_path);
+
+    return 0;
+}
+
+/*
+ * TODO: Running this code in multi-threaded environment
+ * The code now assumes that there is only one client invocation process
+ * in one domain. In the future, it is necessary to take into account cases
+ * when within one domain there will be several requests from a client at the
+ * same time. Therefore, it will be necessary to regulate the multithreading
+ * of processes.
+ */
+struct vchan_state *vchan_get_instance(libxl__gc *gc, libxl_domid domid,
+                                       char *vchan_xs_path, int is_server)
+{
+    static struct vchan_state *state = NULL;
+    int ret;
+
+    if (state)
+        return state;
+
+    state = libxl__zalloc(gc, sizeof(*state));
+    state->domid = domid;
+    state->xs_path = vchan_xs_path;
+    ret = vchan_init_client(gc, state, is_server);
+    if (ret)
+        state = NULL;
+
+    return state;
+}
+
+/*
+ * Find a JSON object and store it in o_r.
+ * return ERROR_NOTFOUND if no object is found.
+ */
+static int vchan_get_next_msg(libxl__gc *gc, struct vchan_state *state,
+                              libxl__json_object **o_r)
+{
+    size_t len;
+    char *end = NULL;
+    const size_t eoml = sizeof(END_OF_MESSAGE) - 1;
+    libxl__json_object *o = NULL;
+
+    if (!state->rx_buf_used)
+        return ERROR_NOTFOUND;
+
+    /* Search for the end of a message: "\r\n" */
+    end = memmem(state->rx_buf, state->rx_buf_used, END_OF_MESSAGE, eoml);
+    if (!end)
+        return ERROR_NOTFOUND;
+    len = (end - state->rx_buf) + eoml;
+
+    LOGD(DEBUG, state->domid, "parsing %zuB: '%.*s'", len, (int)len,
+         state->rx_buf);
+
+    /* Replace \r by \0 so that libxl__json_parse can use strlen */
+    state->rx_buf[len - eoml] = '\0';
+    o = libxl__json_parse(gc, state->rx_buf);
+
+    if (!o) {
+        LOGD(ERROR, state->domid, "Parse error");
+        return ERROR_FAIL;
+    }
+
+    state->rx_buf_used -= len;
+    memmove(state->rx_buf, state->rx_buf + len, state->rx_buf_used);
+
+    LOGD(DEBUG, state->domid, "JSON object received: %s", JSON(o));
+
+    *o_r = o;
+
+    return 0;
+}
+
+static libxl__json_object *vchan_handle_message(libxl__gc *gc,
+                                                struct vchan_info *vchan,
+                                                const libxl__json_object *request)
+{
+	libxl__json_object *result = NULL;
+	const libxl__json_object *command_obj;
+	int ret;
+
+	ret = vchan->handle_msg(gc, request, &result);
+	if (ret == ERROR_FAIL) {
+		LOGE(ERROR, "Message handling failed\n");
+	} else if (ret == ERROR_NOTFOUND) {
+		command_obj = libxl__json_map_get(VCHAN_MSG_EXECUTE, request, JSON_ANY);
+		LOGE(ERROR, "Unknown command: %s\n", command_obj->u.string);
+	}
+    return result;
+}
+
+static int set_nonblocking(int fd, int nonblocking)
+{
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1)
+        return -1;
+
+    if (nonblocking)
+        flags |= O_NONBLOCK;
+    else
+        flags &= ~O_NONBLOCK;
+
+    if (fcntl(fd, F_SETFL, flags) == -1)
+        return -1;
+
+    return 0;
+}
+
+static libxl__json_object *vchan_process_request(libxl__gc *gc,
+                                                 struct vchan_info *vchan)
+{
+    int rc, ret;
+    ssize_t r;
+    fd_set rfds;
+    fd_set wfds;
+
+    while (true) {
+        FD_ZERO(&rfds);
+        FD_ZERO(&wfds);
+        FD_SET(vchan->state->select_fd, &rfds);
+        ret = select(vchan->state->select_fd + 1, &rfds, &wfds, NULL, NULL);
+        if (ret < 0) {
+            LOGE(ERROR, "Error occured during the libxenvchan fd monitoring\n");
+            return NULL;
+        }
+        if (FD_ISSET(vchan->state->select_fd, &rfds))
+            libxenvchan_wait(vchan->state->ctrl);
+        /* Check if the buffer still have space, or increase size */
+        if (vchan->state->rx_buf_size - vchan->state->rx_buf_used < vchan->receive_buf_size) {
+            size_t newsize = vchan->state->rx_buf_size * 2 + vchan->receive_buf_size;
+
+            if (newsize > vchan->max_buf_size) {
+                LOGD(ERROR, vchan->state->domid,
+                     "receive buffer is too big (%zu > %zu)",
+                     newsize, vchan->max_buf_size);
+                return NULL;
+            }
+            vchan->state->rx_buf_size = newsize;
+            vchan->state->rx_buf = libxl__realloc(gc, vchan->state->rx_buf,
+                                                  vchan->state->rx_buf_size);
+        }
+
+        while (libxenvchan_data_ready(vchan->state->ctrl)) {
+            r = libxenvchan_read(vchan->state->ctrl,
+                                 vchan->state->rx_buf + vchan->state->rx_buf_used,
+                                 vchan->state->rx_buf_size - vchan->state->rx_buf_used);
+            if (r < 0) {
+                LOGED(ERROR, vchan->state->domid, "error reading");
+                return NULL;
+            }
+
+            LOG(DEBUG, "received %zdB: '%.*s'", r,
+                (int)r, vchan->state->rx_buf + vchan->state->rx_buf_used);
+
+            vchan->state->rx_buf_used += r;
+            assert(vchan->state->rx_buf_used <= vchan->state->rx_buf_size);
+
+            libxl__json_object *o = NULL;
+            /* parse rx buffer to find one json object */
+            rc = vchan_get_next_msg(gc, vchan->state, &o);
+            if (rc == ERROR_NOTFOUND)
+                break;
+            else if (rc)
+                return NULL;
+
+            return vchan_handle_message(gc, vchan, o);
+        }
+        if ( !libxenvchan_is_open(vchan->state->ctrl)) {
+            if (set_nonblocking(1, 0))
+                return NULL;
+        }
+    }
+    return NULL;
+}
+
+static int vchan_write(libxl__gc *gc, struct vchan_state *state, char *cmd)
+{
+    size_t len;
+    int ret;
+
+    len = strlen(cmd);
+    while (len) {
+        ret = libxenvchan_write(state->ctrl, cmd, len);
+        if (ret < 0) {
+            LOGE(ERROR, "vchan write failed");
+            return ERROR_FAIL;
+        }
+        cmd += ret;
+        len -= ret;
+    }
+    return 0;
+}
+
+libxl__json_object *vchan_send_command(libxl__gc *gc, struct vchan_info *vchan,
+                                       const char *cmd, libxl__json_object *args)
+{
+    libxl__json_object *result;
+    char *json;
+    int ret;
+
+    json = vchan->prepare_cmd(gc, cmd, args, 0);
+    if (!json)
+        return NULL;
+
+    ret = vchan_write(gc, vchan->state, json);
+    if (ret < 0)
+        return NULL;
+
+    result = vchan_process_request(gc, vchan);
+    return result;
+}
+
+int vchan_process_command(libxl__gc *gc, struct vchan_info *vchan)
+{
+    libxl__json_object *result;
+    char *json;
+    int ret;
+
+    result = vchan_process_request(gc, vchan);
+
+    json = vchan->prepare_cmd(gc, NULL, result, 0);
+    if (!json)
+        return -1;
+
+    ret = vchan_write(gc, vchan->state, json);
+    if (ret < 0)
+        return -1;
+
+    return 0;
+}
diff --git a/tools/libs/light/libxl_vchan.h b/tools/libs/light/libxl_vchan.h
new file mode 100644
index 0000000000..7ded416447
--- /dev/null
+++ b/tools/libs/light/libxl_vchan.h
@@ -0,0 +1,81 @@
+/*
+    Common definitions for JSON messages processing by vchan
+    Copyright (C) 2021 EPAM Systems Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LIBXL_VCHAN_H
+#define LIBXL_VCHAN_H
+
+#include <libxenvchan.h>
+
+#define VCHAN_SERVER 1
+#define VCHAN_CLIENT 0
+
+#define END_OF_MESSAGE "\r\n"
+
+#define VCHAN_MSG_EXECUTE         "execute"
+#define VCHAN_MSG_RETURN          "return"
+#define VCHAN_MSG_ERROR           "error"
+
+struct vchan_state {
+    /* Server domain ID. */
+    libxl_domid domid;
+    /* XenStore path of the server with the ring buffer and event channel. */
+    char *xs_path;
+    struct libxenvchan *ctrl;
+    int select_fd;
+    /* receive buffer */
+    char *rx_buf;
+    size_t rx_buf_size; /* current allocated size */
+    size_t rx_buf_used; /* actual data in the buffer */
+};
+
+typedef int (*vchan_handle_t)(libxl__gc *gc, const libxl__json_object *request,
+                              libxl__json_object **result);
+typedef char* (*vchan_prepare_t)(libxl__gc *gc, const char *cmd,
+                                 libxl__json_object *args, int id);
+struct vchan_info {
+    struct vchan_state *state;
+    vchan_handle_t handle_msg;
+    vchan_prepare_t prepare_cmd;
+    /* buffer info */
+    size_t receive_buf_size;
+    size_t max_buf_size;
+};
+
+void libxl__vchan_param_add_string(libxl__gc *gc, libxl__json_object **param,
+                                   const char *name, const char *s);
+void libxl__vchan_param_add_integer(libxl__gc *gc, libxl__json_object **param,
+                                    const char *name, const long long i);
+int xs_path_exists(libxl__gc *gc, const char *xs_path);
+libxl_domid vchan_find_server(libxl__gc *gc, char *xs_dir, char *xs_path);
+struct vchan_state *vchan_get_instance(libxl__gc *gc, libxl_domid domid,
+                                       char *vchan_xs_path, int is_server);
+libxl__json_object *vchan_send_command(libxl__gc *gc, struct vchan_info *vchan,
+                                       const char *cmd, libxl__json_object *args);
+int vchan_process_command(libxl__gc *gc, struct vchan_info *vchan);
+
+#endif /* LIBXL_VCHAN_H */
+
+/*
+ * Local variables:
+ *  mode: C
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index a5d2ee4528..d35570c343 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -15,6 +15,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
 CFLAGS_XL += $(CFLAGS_libxenlight)
 CFLAGS_XL += $(CFLAGS_libxenutil)
 CFLAGS_XL += -Wshadow
+CFLAGS_XL += $(CFLAGS_libxenvchan)
 
 XL_OBJS-$(CONFIG_X86) = xl_psr.o
 XL_OBJS = xl.o xl_cmdtable.o xl_sxp.o xl_utils.o $(XL_OBJS-y)
@@ -38,7 +39,7 @@ $(XL_OBJS): _paths.h
 all: xl
 
 xl: $(XL_OBJS)
-	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxenutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) -lyajl $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxenutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxenvchan) -lyajl $(APPEND_LDFLAGS)
 
 .PHONY: install
 install: all
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/9] tools/libs/light: Add functions for handling PCI messages in JSON format
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 1/9] tools/libs/light: Add vchan support to libxl Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 3/9] tools/xl: Add pcid daemon to xl Anastasiia Lukianenko
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

These functions allow to process the received message from PCI server and
to generate a reply in JSON format for the client.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h                      |  49 ++++++++
 tools/libs/light/Makefile                 |   1 +
 tools/libs/light/libxl_pcid.c             | 134 ++++++++++++++++++++++
 tools/libs/light/libxl_types.idl          |   1 +
 tools/libs/light/libxl_types_internal.idl |   6 +
 5 files changed, 191 insertions(+)
 create mode 100644 tools/include/pcid.h
 create mode 100644 tools/libs/light/libxl_pcid.c

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
new file mode 100644
index 0000000000..59a7aad64a
--- /dev/null
+++ b/tools/include/pcid.h
@@ -0,0 +1,49 @@
+/*
+    Common definitions for Xen PCI client-server protocol.
+    Copyright (C) 2021 EPAM Systems Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PCID_H
+#define PCID_H
+
+#define PCID_XS_DIR             "/local/domain/"
+#define PCID_XS_PATH            "/data/pcid-vchan"
+
+#define PCI_RECEIVE_BUFFER_SIZE 4096
+#define PCI_MAX_SIZE_RX_BUF     MB(1)
+
+#define PCID_MSG_FIELD_ID        "id"
+#define PCID_MSG_FIELD_ARGS      "arguments"
+
+#define PCID_PCIBACK_DRIVER      "pciback_driver"
+
+#if defined(__linux__)
+#define SYSFS_PCIBACK_DRIVER   "/sys/bus/pci/drivers/pciback"
+#endif
+
+int libxl_pcid_process(libxl_ctx *ctx);
+
+#endif /* PCID_H */
+
+/*
+ * Local variables:
+ *  mode: C
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile
index f5d34b3371..40e3a7d7ce 100644
--- a/tools/libs/light/Makefile
+++ b/tools/libs/light/Makefile
@@ -76,6 +76,7 @@ SRCS-y += libxl.c
 SRCS-y += libxl_create.c
 SRCS-y += libxl_dm.c
 SRCS-y += libxl_pci.c
+SRCS-y += libxl_pcid.c
 SRCS-y += libxl_vchan.c
 SRCS-y += libxl_dom.c
 SRCS-y += libxl_exec.c
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
new file mode 100644
index 0000000000..6317c77a3c
--- /dev/null
+++ b/tools/libs/light/libxl_pcid.c
@@ -0,0 +1,134 @@
+/*
+    Utils for xl pcid daemon
+
+    Copyright (C) 2021 EPAM Systems Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE  // required for strchrnul()
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+#include "libxl_vchan.h"
+
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include <pcid.h>
+#include <xenstore.h>
+
+#include <libxl.h>
+#include <libxl_json.h>
+#include <dirent.h>
+
+#define DOM0_ID 0
+
+static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
+                               libxl__json_object **result)
+{
+    const libxl__json_object *command_obj;
+    char *command_name;
+
+    command_obj = libxl__json_map_get(VCHAN_MSG_EXECUTE, request, JSON_ANY);
+    if (!command_obj) {
+        LOGE(ERROR, "Execution command not found\n");
+        return ERROR_FAIL;
+    }
+    command_name = command_obj->u.string;
+
+    return 0;
+}
+
+static char *pcid_prepare_reply(libxl__gc *gc, const char *cmd,
+                                libxl__json_object *result, int id)
+{
+    yajl_gen hand = NULL;
+    /* memory for 'buf' is owned by 'hand' */
+    const unsigned char *buf;
+    libxl_yajl_length len;
+    yajl_gen_status s;
+    char *ret = NULL;
+    int rc;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+    if (!hand) {
+        LOGE(ERROR, "Error with hand allocation\n");
+        goto out;
+    }
+
+#if HAVE_YAJL_V2
+    /* Disable beautify for data */
+    yajl_gen_config(hand, yajl_gen_beautify, 0);
+#endif
+
+    yajl_gen_map_open(hand);
+    if ( !result )
+        libxl__yajl_gen_asciiz(hand, VCHAN_MSG_ERROR);
+    else {
+        libxl__yajl_gen_asciiz(hand, VCHAN_MSG_RETURN);
+        rc = libxl__json_object_to_yajl_gen(gc, hand, result);
+        if (rc)
+            goto get_buf_fail;
+    }
+    libxl__yajl_gen_asciiz(hand, PCID_MSG_FIELD_ID);
+    yajl_gen_integer(hand, id);
+    yajl_gen_map_close(hand);
+
+    s = yajl_gen_get_buf(hand, &buf, &len);
+    if (s != yajl_gen_status_ok) {
+        goto get_buf_fail;
+    }
+
+    ret = libxl__sprintf(gc, "%*.*s" END_OF_MESSAGE, (int)len, (int)len, buf);
+
+get_buf_fail:
+    yajl_gen_free(hand);
+out:
+
+    return ret;
+}
+
+int libxl_pcid_process(libxl_ctx *ctx)
+{
+    GC_INIT(ctx);
+    struct vchan_info *vchan;
+    char *xs_path;
+    int ret = 0;
+
+    vchan = libxl__zalloc(gc, sizeof(*vchan));
+    xs_path = GCSPRINTF(PCID_XS_DIR"%d"PCID_XS_PATH, DOM0_ID);
+
+    vchan->state = vchan_get_instance(gc, DOM0_ID, xs_path, VCHAN_SERVER);
+    if (!(vchan->state)) {
+        ret = -1;
+        goto out;
+    }
+
+    vchan->handle_msg = pcid_handle_message;
+    vchan->prepare_cmd = pcid_prepare_reply;
+    vchan->receive_buf_size = PCI_RECEIVE_BUFFER_SIZE;
+    vchan->max_buf_size = PCI_MAX_SIZE_RX_BUF;
+
+    while (true) {
+        ret = vchan_process_command(gc, vchan);
+        if (ret < 0)
+            break;
+    }
+
+out:
+    GC_FREE;
+    return ret;
+}
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 395165d801..d89c3ac1eb 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -76,6 +76,7 @@ libxl_error = Enumeration("error", [
     (-30, "QMP_DEVICE_NOT_ACTIVE"), # a device has failed to be become active
     (-31, "QMP_DEVICE_NOT_FOUND"), # the requested device has not been found
     (-32, "QEMU_API"), # QEMU's replies don't contains expected members
+    (-33, "PROTOCOL_ERROR_PCID"),
     ], value_namespace = "")
 
 libxl_domain_type = Enumeration("domain_type", [
diff --git a/tools/libs/light/libxl_types_internal.idl b/tools/libs/light/libxl_types_internal.idl
index d66da13764..b9cee64d41 100644
--- a/tools/libs/light/libxl_types_internal.idl
+++ b/tools/libs/light/libxl_types_internal.idl
@@ -58,3 +58,9 @@ libxl__device_action = Enumeration("device_action", [
     (1, "ADD"),
     (2, "REMOVE"),
     ])
+
+libxl__pcid_message_type = Enumeration("pcid_message_type", [
+    (1, "return"),
+    (2, "error"),
+    (3, "invalid"),
+    ])
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/9] tools/xl: Add pcid daemon to xl
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 1/9] tools/libs/light: Add vchan support to libxl Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 2/9] tools/libs/light: Add functions for handling PCI messages in JSON format Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 4/9] tools/libs/light: Add "ls" command processing to xl pcid daemon and libxl PCI Anastasiia Lukianenko
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Add draft version of pcid server (based on vchan-node2), which can receive
messages from the client.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/configure                      |  5 +-
 tools/hotplug/FreeBSD/rc.d/xlpcid.in | 75 ++++++++++++++++++++++++++
 tools/hotplug/Linux/init.d/xlpcid.in | 76 ++++++++++++++++++++++++++
 tools/hotplug/NetBSD/rc.d/xlpcid.in  | 75 ++++++++++++++++++++++++++
 tools/xl/Makefile                    |  4 +-
 tools/xl/xl.h                        |  1 +
 tools/xl/xl_cmdtable.c               |  7 +++
 tools/xl/xl_pcid.c                   | 79 ++++++++++++++++++++++++++++
 8 files changed, 319 insertions(+), 3 deletions(-)
 create mode 100644 tools/hotplug/FreeBSD/rc.d/xlpcid.in
 create mode 100644 tools/hotplug/Linux/init.d/xlpcid.in
 create mode 100644 tools/hotplug/NetBSD/rc.d/xlpcid.in
 create mode 100644 tools/xl/xl_pcid.c

diff --git a/tools/configure b/tools/configure
index b21ade08c0..be9fc9b1d4 100755
--- a/tools/configure
+++ b/tools/configure
@@ -2454,7 +2454,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
-ac_config_files="$ac_config_files ../config/Tools.mk hotplug/FreeBSD/rc.d/xencommons hotplug/FreeBSD/rc.d/xendriverdomain hotplug/Linux/init.d/sysconfig.xencommons hotplug/Linux/init.d/sysconfig.xendomains hotplug/Linux/init.d/xen-watchdog hotplug/Linux/init.d/xencommons hotplug/Linux/init.d/xendomains hotplug/Linux/init.d/xendriverdomain hotplug/Linux/launch-xenstore hotplug/Linux/vif-setup hotplug/Linux/xen-hotplug-common.sh hotplug/Linux/xendomains hotplug/NetBSD/rc.d/xencommons hotplug/NetBSD/rc.d/xendriverdomain ocaml/xenstored/oxenstored.conf"
+ac_config_files="$ac_config_files ../config/Tools.mk hotplug/FreeBSD/rc.d/xencommons hotplug/FreeBSD/rc.d/xendriverdomain hotplug/FreeBSD/rc.d/xlpcid hotplug/Linux/init.d/sysconfig.xencommons hotplug/Linux/init.d/sysconfig.xendomains hotplug/Linux/init.d/xlpcid hotplug/Linux/init.d/xen-watchdog hotplug/Linux/init.d/xencommons hotplug/Linux/init.d/xendomains hotplug/Linux/init.d/xendriverdomain hotplug/Linux/launch-xenstore hotplug/Linux/vif-setup hotplug/Linux/xen-hotplug-common.sh hotplug/Linux/xendomains hotplug/NetBSD/rc.d/xencommons hotplug/NetBSD/rc.d/xendriverdomain hotplug/NetBSD/rc.d/xlpcid ocaml/xenstored/oxenstored.conf"
 
 ac_config_headers="$ac_config_headers config.h"
 
@@ -10892,8 +10892,10 @@ do
     "../config/Tools.mk") CONFIG_FILES="$CONFIG_FILES ../config/Tools.mk" ;;
     "hotplug/FreeBSD/rc.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/FreeBSD/rc.d/xencommons" ;;
     "hotplug/FreeBSD/rc.d/xendriverdomain") CONFIG_FILES="$CONFIG_FILES hotplug/FreeBSD/rc.d/xendriverdomain" ;;
+    "hotplug/FreeBSD/rc.d/xlpcid") CONFIG_FILES="$CONFIG_FILES hotplug/FreeBSD/rc.d/xlpcid" ;;
     "hotplug/Linux/init.d/sysconfig.xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/sysconfig.xencommons" ;;
     "hotplug/Linux/init.d/sysconfig.xendomains") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/sysconfig.xendomains" ;;
+    "hotplug/Linux/init.d/xlpcid") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xlpcid" ;;
     "hotplug/Linux/init.d/xen-watchdog") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xen-watchdog" ;;
     "hotplug/Linux/init.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xencommons" ;;
     "hotplug/Linux/init.d/xendomains") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/init.d/xendomains" ;;
@@ -10904,6 +10906,7 @@ do
     "hotplug/Linux/xendomains") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/xendomains" ;;
     "hotplug/NetBSD/rc.d/xencommons") CONFIG_FILES="$CONFIG_FILES hotplug/NetBSD/rc.d/xencommons" ;;
     "hotplug/NetBSD/rc.d/xendriverdomain") CONFIG_FILES="$CONFIG_FILES hotplug/NetBSD/rc.d/xendriverdomain" ;;
+    "hotplug/NetBSD/rc.d/xlpcid") CONFIG_FILES="$CONFIG_FILES hotplug/NetBSD/rc.d/xlpcid" ;;
     "ocaml/xenstored/oxenstored.conf") CONFIG_FILES="$CONFIG_FILES ocaml/xenstored/oxenstored.conf" ;;
     "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
     "hotplug/Linux/systemd/proc-xen.mount") CONFIG_FILES="$CONFIG_FILES hotplug/Linux/systemd/proc-xen.mount" ;;
diff --git a/tools/hotplug/FreeBSD/rc.d/xlpcid.in b/tools/hotplug/FreeBSD/rc.d/xlpcid.in
new file mode 100644
index 0000000000..2817bfaeed
--- /dev/null
+++ b/tools/hotplug/FreeBSD/rc.d/xlpcid.in
@@ -0,0 +1,75 @@
+#! /bin/bash
+#
+# xlpcid
+#
+# description: Run xlpcid daemon
+### BEGIN INIT INFO
+# Provides:          xlpcid
+# Short-Description: Start/stop xlpcid
+# Description:       Run xlpcid daemon
+### END INIT INFO
+#
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+xencommons_config=@CONFIG_DIR@/@CONFIG_LEAF_DIR@
+
+test -f $xencommons_config/xencommons && . $xencommons_config/xencommons
+
+XLPCID_PIDFILE="@XEN_RUN_DIR@/xlpcid.pid"
+
+# Source function library.
+if [ -e  /etc/init.d/functions ] ; then
+    . /etc/init.d/functions
+elif [ -e /lib/lsb/init-functions ] ; then
+    . /lib/lsb/init-functions
+    success () {
+        log_success_msg $*
+    }
+    failure () {
+        log_failure_msg $*
+    }
+else
+    success () {
+        echo $*
+    }
+    failure () {
+        echo $*
+    }
+fi
+
+start() {
+  echo Starting xl pcid...
+  ${sbindir}/xl pcid --pidfile=$XLPCID_PIDFILE $XLPCID_ARGS
+}
+
+stop() {
+  echo Stopping xl pcid...
+  if read 2>/dev/null <$XLPCID_PIDFILE pid; then
+    kill $pid
+    while kill -9 $pid >/dev/null 2>&1; do sleep 1; done
+    rm -f $XLPCID_PIDFILE
+  fi
+}
+
+case "$1" in
+  start)
+    start
+	;;
+  stop)
+	stop
+	;;
+  restart)
+	stop
+	start
+	;;
+  status)
+	;;
+  condrestart)
+	stop
+	start
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+	exit 1
+esac
diff --git a/tools/hotplug/Linux/init.d/xlpcid.in b/tools/hotplug/Linux/init.d/xlpcid.in
new file mode 100644
index 0000000000..dce660098c
--- /dev/null
+++ b/tools/hotplug/Linux/init.d/xlpcid.in
@@ -0,0 +1,76 @@
+#! /bin/bash
+#
+# xlpcid
+#
+# description: Run xlpcid daemon
+### BEGIN INIT INFO
+# Provides:          xlpcid
+# Short-Description: Start/stop xlpcid
+# Description:       Run xlpcid daemon
+### END INIT INFO
+#
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+xencommons_config=@CONFIG_DIR@/@CONFIG_LEAF_DIR@
+
+test -f $xencommons_config/xencommons && . $xencommons_config/xencommons
+
+XLPCID_PIDFILE="@XEN_RUN_DIR@/xlpcid.pid"
+
+# Source function library.
+if [ -e  /etc/init.d/functions ] ; then
+    . /etc/init.d/functions
+elif [ -e /lib/lsb/init-functions ] ; then
+    . /lib/lsb/init-functions
+    success () {
+        log_success_msg $*
+    }
+    failure () {
+        log_failure_msg $*
+    }
+else
+    success () {
+        echo $*
+    }
+    failure () {
+        echo $*
+    }
+fi
+
+start() {
+  echo Starting xl pcid...
+  ${sbindir}/xl pcid --pidfile=$XLPCID_PIDFILE $XLPCID_ARGS
+}
+
+stop() {
+  echo Stopping xl pcid...
+  if read 2>/dev/null <$XLPCID_PIDFILE pid; then
+    kill $pid
+    while kill -9 $pid >/dev/null 2>&1; do sleep 1; done
+    rm -f $XLPCID_PIDFILE
+  fi
+}
+
+case "$1" in
+  start)
+    start
+	;;
+  stop)
+	stop
+	;;
+  restart)
+	stop
+	start
+	;;
+  status)
+	;;
+  condrestart)
+	stop
+	start
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+	exit 1
+esac
+
diff --git a/tools/hotplug/NetBSD/rc.d/xlpcid.in b/tools/hotplug/NetBSD/rc.d/xlpcid.in
new file mode 100644
index 0000000000..2817bfaeed
--- /dev/null
+++ b/tools/hotplug/NetBSD/rc.d/xlpcid.in
@@ -0,0 +1,75 @@
+#! /bin/bash
+#
+# xlpcid
+#
+# description: Run xlpcid daemon
+### BEGIN INIT INFO
+# Provides:          xlpcid
+# Short-Description: Start/stop xlpcid
+# Description:       Run xlpcid daemon
+### END INIT INFO
+#
+
+. @XEN_SCRIPT_DIR@/hotplugpath.sh
+
+xencommons_config=@CONFIG_DIR@/@CONFIG_LEAF_DIR@
+
+test -f $xencommons_config/xencommons && . $xencommons_config/xencommons
+
+XLPCID_PIDFILE="@XEN_RUN_DIR@/xlpcid.pid"
+
+# Source function library.
+if [ -e  /etc/init.d/functions ] ; then
+    . /etc/init.d/functions
+elif [ -e /lib/lsb/init-functions ] ; then
+    . /lib/lsb/init-functions
+    success () {
+        log_success_msg $*
+    }
+    failure () {
+        log_failure_msg $*
+    }
+else
+    success () {
+        echo $*
+    }
+    failure () {
+        echo $*
+    }
+fi
+
+start() {
+  echo Starting xl pcid...
+  ${sbindir}/xl pcid --pidfile=$XLPCID_PIDFILE $XLPCID_ARGS
+}
+
+stop() {
+  echo Stopping xl pcid...
+  if read 2>/dev/null <$XLPCID_PIDFILE pid; then
+    kill $pid
+    while kill -9 $pid >/dev/null 2>&1; do sleep 1; done
+    rm -f $XLPCID_PIDFILE
+  fi
+}
+
+case "$1" in
+  start)
+    start
+	;;
+  stop)
+	stop
+	;;
+  restart)
+	stop
+	start
+	;;
+  status)
+	;;
+  condrestart)
+	stop
+	start
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+	exit 1
+esac
diff --git a/tools/xl/Makefile b/tools/xl/Makefile
index d35570c343..d46a9ad24a 100644
--- a/tools/xl/Makefile
+++ b/tools/xl/Makefile
@@ -22,7 +22,7 @@ XL_OBJS = xl.o xl_cmdtable.o xl_sxp.o xl_utils.o $(XL_OBJS-y)
 XL_OBJS += xl_parse.o xl_cpupool.o xl_flask.o
 XL_OBJS += xl_vtpm.o xl_block.o xl_nic.o xl_usb.o
 XL_OBJS += xl_sched.o xl_pci.o xl_vcpu.o xl_cdrom.o xl_mem.o
-XL_OBJS += xl_info.o xl_console.o xl_misc.o
+XL_OBJS += xl_info.o xl_console.o xl_misc.o xl_pcid.o
 XL_OBJS += xl_vmcontrol.o xl_saverestore.o xl_migrate.o
 XL_OBJS += xl_vdispl.o xl_vsnd.o xl_vkb.o xl_vcamera.o
 
@@ -39,7 +39,7 @@ $(XL_OBJS): _paths.h
 all: xl
 
 xl: $(XL_OBJS)
-	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxenutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxenvchan) -lyajl $(APPEND_LDFLAGS)
+	$(CC) $(LDFLAGS) -o $@ $(XL_OBJS) $(LDLIBS_libxenstore) $(LDLIBS_libxenutil) $(LDLIBS_libxenlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxenvchan) -lyajl $(APPEND_LDFLAGS)
 
 .PHONY: install
 install: all
diff --git a/tools/xl/xl.h b/tools/xl/xl.h
index e1d5190cc8..a88f03c624 100644
--- a/tools/xl/xl.h
+++ b/tools/xl/xl.h
@@ -206,6 +206,7 @@ int main_loadpolicy(int argc, char **argv);
 int main_remus(int argc, char **argv);
 #endif
 int main_devd(int argc, char **argv);
+int main_pcid(int argc, char **argv);
 #if defined(__i386__) || defined(__x86_64__)
 int main_psr_hwinfo(int argc, char **argv);
 int main_psr_cmt_attach(int argc, char **argv);
diff --git a/tools/xl/xl_cmdtable.c b/tools/xl/xl_cmdtable.c
index c3cb515348..dfc4386b35 100644
--- a/tools/xl/xl_cmdtable.c
+++ b/tools/xl/xl_cmdtable.c
@@ -560,6 +560,13 @@ const struct cmd_spec cmd_table[] = {
       "-F                      Run in the foreground.\n"
       "-p, --pidfile [FILE]    Write PID to pidfile when daemonizing.",
     },
+    { "pcid",
+      &main_pcid, 0, 1,
+      "Daemon that acts as a server for the client in the libxl PCI",
+      "[options]",
+      "-F                      Run in the foreground.\n"
+      "-p, --pidfile [FILE]    Write PID to pidfile when daemonizing.",
+    },
 #if defined(__i386__) || defined(__x86_64__)
     { "psr-hwinfo",
       &main_psr_hwinfo, 0, 1,
diff --git a/tools/xl/xl_pcid.c b/tools/xl/xl_pcid.c
new file mode 100644
index 0000000000..f0635579ca
--- /dev/null
+++ b/tools/xl/xl_pcid.c
@@ -0,0 +1,79 @@
+/*
+    Pcid daemon that acts as a server for the client in the libxl PCI
+
+    Copyright (C) 2021 EPAM Systems Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE  // required for strchrnul()
+
+#include <libxl_utils.h>
+#include <libxlutil.h>
+
+#include "xl.h"
+#include "xl_utils.h"
+#include "xl_parse.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <pcid.h>
+#include <xenstore.h>
+
+/*
+ * TODO: Running this code in multi-threaded environment
+ * Now the code is designed so that only one request to the server
+ * from the client is made in one domain. In the future, it is necessary
+ * to take into account cases when from different domains there can be
+ * several requests from a client at the same time. Therefore, it will be
+ * necessary to regulate the multithreading of processes for global variables.
+ */
+
+int main_pcid(int argc, char *argv[])
+{
+    int opt = 0, daemonize = 1, ret;
+    const char *pidfile = NULL;
+    static const struct option opts[] = {
+        {"pidfile", 1, 0, 'p'},
+        COMMON_LONG_OPTS,
+        {0, 0, 0, 0}
+    };
+
+    SWITCH_FOREACH_OPT(opt, "Fp:", opts, "pcid", 0) {
+    case 'F':
+        daemonize = 0;
+        break;
+    case 'p':
+        pidfile = optarg;
+        break;
+    }
+
+    if (daemonize) {
+        ret = do_daemonize("xlpcid", pidfile);
+        if (ret) {
+            ret = (ret == 1) ? 0 : ret;
+            goto out_daemon;
+        }
+    }
+
+    libxl_pcid_process(ctx);
+
+out_daemon:
+    exit(1);
+}
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/9] tools/libs/light: Add "ls" command processing to xl pcid daemon and libxl PCI
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (2 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 3/9] tools/xl: Add pcid daemon to xl Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 5/9] tools/libs/light: Add "write" command to xl pcid " Anastasiia Lukianenko
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Messaging format is based on json style. Xl pcid receives "ls" command from
client and sends a reply:
1. success case - array of directory's names
2. error case - message with "error" in return

Xl pcid server transmits information about devices assigned to the PCI
driver by sending reply with directory's names. Libxl PCI processes reply
message instead of opening directory in libxl side.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |   7 ++
 tools/libs/light/libxl_pci.c  | 136 +++++++++++++++++++++++++++++-----
 tools/libs/light/libxl_pcid.c |  59 +++++++++++++++
 3 files changed, 184 insertions(+), 18 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index 59a7aad64a..e9c3c497c6 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -28,12 +28,19 @@
 #define PCID_MSG_FIELD_ID        "id"
 #define PCID_MSG_FIELD_ARGS      "arguments"
 
+#define PCID_CMD_LIST            "ls"
+#define PCID_CMD_DIR_ID          "dir_id"
+
 #define PCID_PCIBACK_DRIVER      "pciback_driver"
 
 #if defined(__linux__)
 #define SYSFS_PCIBACK_DRIVER   "/sys/bus/pci/drivers/pciback"
 #endif
 
+#define PCI_INFO_PATH "/libxl/pci"
+#define PCI_BDF_XSPATH         "%04x-%02x-%02x-%01x"
+#define PCI_BDF                "%04x:%02x:%02x.%01x"
+
 int libxl_pcid_process(libxl_ctx *ctx);
 
 #endif /* PCID_H */
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 30e203c264..6534b70777 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -17,6 +17,9 @@
 #include "libxl_osdeps.h" /* must come before any other headers */
 
 #include "libxl_internal.h"
+#include "libxl_vchan.h"
+
+#include <pcid.h>
 
 #define PCI_BDF                "%04x:%02x:%02x.%01x"
 #define PCI_BDF_SHORT          "%02x:%02x.%01x"
@@ -47,6 +50,100 @@ static void pci_struct_fill(libxl_device_pci *pci, unsigned int domain,
     pci->func = func;
 }
 
+static libxl__pcid_message_type pci_response_type(const libxl__json_object *o)
+{
+    libxl__pcid_message_type type;
+    libxl__json_map_node *node = NULL;
+    int i;
+
+    for (i = 0; (node = libxl__json_map_node_get(o, i)); i++) {
+        if (libxl__pcid_message_type_from_string(node->map_key, &type) == 0)
+            return type;
+    }
+    return LIBXL__PCID_MESSAGE_TYPE_INVALID;
+}
+
+static int pci_handle_msg(libxl__gc *gc, const libxl__json_object *request,
+                          libxl__json_object **result)
+{
+    libxl__pcid_message_type type = pci_response_type(request);
+
+    if (type == LIBXL__PCID_MESSAGE_TYPE_RETURN)
+        *result = (libxl__json_object *)libxl__json_map_get(VCHAN_MSG_RETURN,
+                                                            request, JSON_ANY);
+
+    return 0;
+}
+
+static char *pci_prepare_cmd(libxl__gc *gc, const char *cmd,
+                             libxl__json_object *args, int id)
+{
+    yajl_gen hand = NULL;
+    /* memory for 'buf' is owned by 'hand' */
+    const unsigned char *buf;
+    libxl_yajl_length len;
+    yajl_gen_status s;
+    char *ret = NULL;
+
+    hand = libxl_yajl_gen_alloc(NULL);
+
+    if (!hand)
+        return NULL;
+
+#if HAVE_YAJL_V2
+    /* Disable beautify for data */
+    yajl_gen_config(hand, yajl_gen_beautify, 0);
+#endif
+
+    yajl_gen_map_open(hand);
+    libxl__yajl_gen_asciiz(hand, VCHAN_MSG_EXECUTE);
+    libxl__yajl_gen_asciiz(hand, cmd);
+    libxl__yajl_gen_asciiz(hand, PCID_MSG_FIELD_ID);
+    yajl_gen_integer(hand, id);
+    if (args) {
+        libxl__yajl_gen_asciiz(hand, PCID_MSG_FIELD_ARGS);
+        libxl__json_object_to_yajl_gen(gc, hand, args);
+    }
+    yajl_gen_map_close(hand);
+
+    s = yajl_gen_get_buf(hand, &buf, &len);
+
+    if (s != yajl_gen_status_ok)
+        goto out;
+
+    ret = libxl__sprintf(gc, "%*.*s" END_OF_MESSAGE,
+                         (int)len, (int)len, buf);
+
+out:
+    yajl_gen_free(hand);
+    return ret;
+}
+
+static struct vchan_info *pci_prepare_vchan(libxl__gc *gc)
+{
+    struct vchan_info *vchan;
+    libxl_domid domid;
+    char *xs_path;
+
+    domid = vchan_find_server(gc, PCID_XS_DIR, PCID_XS_PATH);
+    if (domid == DOMID_INVALID) {
+        LOGE(ERROR, "Can't find vchan server");
+        return NULL;
+    }
+    vchan = libxl__zalloc(gc, sizeof(*vchan));
+    xs_path = GCSPRINTF(PCID_XS_DIR"%d"PCID_XS_PATH, domid);
+    vchan->state = vchan_get_instance(gc, domid, xs_path, VCHAN_CLIENT);
+    if (!(vchan->state))
+        return NULL;
+
+    vchan->handle_msg = pci_handle_msg;
+    vchan->prepare_cmd = pci_prepare_cmd;
+    vchan->receive_buf_size = PCI_RECEIVE_BUFFER_SIZE;
+    vchan->max_buf_size = PCI_MAX_SIZE_RX_BUF;
+
+    return vchan;
+}
+
 static void libxl_create_pci_backend_device(libxl__gc *gc,
                                             flexarray_t *back,
                                             int num,
@@ -429,33 +526,37 @@ static void pci_info_xs_remove(libxl__gc *gc, libxl_device_pci *pci,
 
 libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
 {
-    GC_INIT(ctx);
     libxl_device_pci *pcis = NULL, *new;
-    struct dirent *de;
-    DIR *dir;
 
+    GC_INIT(ctx);
     *num = 0;
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL, *dir;
+    int i;
+    const char *dir_name;
 
-    dir = opendir(SYSFS_PCIBACK_DRIVER);
-    if (NULL == dir) {
-        if (errno == ENOENT) {
-            LOG(ERROR, "Looks like pciback driver not loaded");
-        } else {
-            LOGE(ERROR, "Couldn't open %s", SYSFS_PCIBACK_DRIVER);
-        }
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
         goto out;
-    }
 
-    while((de = readdir(dir))) {
-        unsigned int dom, bus, dev, func;
-        char *name;
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID,
+                                  PCID_PCIBACK_DRIVER);
+    result = vchan_send_command(gc, vchan, PCID_CMD_LIST, args);
+    if (!result)
+        goto out;
 
-        if (sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4)
+    for (i = 0; (dir = libxl__json_array_get(result, i)); i++) {
+        dir_name = libxl__json_object_get_string(dir);
+        unsigned dom, bus, dev, func;
+        char *name;
+        if (sscanf(dir_name, PCI_BDF, &dom, &bus, &dev, &func) != 4)
             continue;
 
         new = realloc(pcis, ((*num) + 1) * sizeof(*new));
-        if (NULL == new)
-            continue;
+        if (new == NULL) {
+            LOGE(ERROR, "Couldn't realloc pcis struct for new entry");
+            break;
+        }
 
         pcis = new;
         new = pcis + *num;
@@ -472,7 +573,6 @@ libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num)
         (*num)++;
     }
 
-    closedir(dir);
 out:
     GC_FREE;
     return pcis;
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index 6317c77a3c..c897244e8a 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -36,6 +36,57 @@
 
 #define DOM0_ID 0
 
+static struct libxl__json_object *process_ls_cmd(libxl__gc *gc,
+                                                 const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const libxl__json_object *args, *dir_id;
+    struct libxl__json_object *node;
+    char *dir_name;
+    struct dirent *de;
+    DIR *dir = NULL;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    dir_id = libxl__json_map_get(PCID_CMD_DIR_ID, args, JSON_ANY);
+    if (!dir_id)
+        goto out;
+
+    dir_name = dir_id->u.string;
+
+    if (strcmp(PCID_PCIBACK_DRIVER, dir_name) == 0)
+        dir = opendir(SYSFS_PCIBACK_DRIVER);
+    else {
+        LOGE(ERROR, "Unknown directory: %s\n", dir_name);
+        goto out;
+    }
+
+    if (dir == NULL) {
+        if (errno == ENOENT)
+            LOGE(ERROR, "Looks like pciback driver not loaded\n");
+        else
+            LOGE(ERROR, "Couldn't open %s\n", dir_name);
+        goto out;
+    }
+
+    result = libxl__json_object_alloc(gc, JSON_ARRAY);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    while ((de = readdir(dir))) {
+        node = libxl__json_object_alloc(gc, JSON_STRING);
+        node->u.string = de->d_name;
+        flexarray_append(result->u.array, node);
+    }
+
+    closedir(dir);
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -49,6 +100,14 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
     }
     command_name = command_obj->u.string;
 
+    if (strcmp(command_name, PCID_CMD_LIST) == 0)
+       *result = process_ls_cmd(gc, request);
+    else
+        return ERROR_NOTFOUND;
+
+    if (!result)
+        return ERROR_FAIL;
+
     return 0;
 }
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/9] tools/libs/light: Add "write" command to xl pcid and libxl PCI
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (3 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 4/9] tools/libs/light: Add "ls" command processing to xl pcid daemon and libxl PCI Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 6/9] tools/libs/light: Add "read" " Anastasiia Lukianenko
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Add functions for handling "write" command on xl pcid side. Libxl PCI side
receives reply:
1. success - string in "return" message
2. fail - error type of reply message

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |  7 ++++
 tools/libs/light/libxl_pci.c  | 69 +++++++++++++++++++----------------
 tools/libs/light/libxl_pcid.c | 69 +++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 32 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index e9c3c497c6..935d99b186 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -31,7 +31,14 @@
 #define PCID_CMD_LIST            "ls"
 #define PCID_CMD_DIR_ID          "dir_id"
 
+#define PCID_CMD_WRITE           "write"
+#define PCID_CMD_PCI_PATH        "pci_path"
+#define PCID_CMD_PCI_INFO        "pci_info"
+
 #define PCID_PCIBACK_DRIVER      "pciback_driver"
+#define PCID_PCI_DEV             "pci_dev"
+
+#define SYSFS_DRIVER_PATH        "driver_path"
 
 #if defined(__linux__)
 #define SYSFS_PCIBACK_DRIVER   "/sys/bus/pci/drivers/pciback"
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 6534b70777..03ce42dec3 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -455,28 +455,34 @@ static bool is_pci_in_array(libxl_device_pci *pcis, int num,
 }
 
 /* Write the standard BDF into the sysfs path given by sysfs_path. */
-static int sysfs_write_bdf(libxl__gc *gc, const char * sysfs_path,
+static int sysfs_write_bdf(libxl__gc *gc, const char *sysfs_path,
+                           const char *pci_path,
                            libxl_device_pci *pci)
 {
-    int rc, fd;
     char *buf;
 
-    fd = open(sysfs_path, O_WRONLY);
-    if (fd < 0) {
-        LOGE(ERROR, "Couldn't open %s", sysfs_path);
-        return ERROR_FAIL;
-    }
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
 
-    buf = GCSPRINTF(PCI_BDF, pci->domain, pci->bus,
-                    pci->dev, pci->func);
-    rc = write(fd, buf, strlen(buf));
-    /* Annoying to have two if's, but we need the errno */
-    if (rc < 0)
-        LOGE(ERROR, "write to %s returned %d", sysfs_path, rc);
-    close(fd);
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        return ERROR_FAIL;
 
-    if (rc < 0)
+    buf = GCSPRINTF(PCI_BDF, pci->domain, pci->bus, pci->dev, pci->func);
+    if (strcmp(SYSFS_PCI_DEV, sysfs_path) == 0)
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCI_DEV);
+    else if (strcmp(SYSFS_PCIBACK_DRIVER, sysfs_path) == 0)
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCIBACK_DRIVER);
+    else if (strcmp(SYSFS_DRIVER_PATH, sysfs_path) == 0)
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, SYSFS_DRIVER_PATH);
+
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_PATH, pci_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, buf);
+    result = vchan_send_command(gc, vchan, PCID_CMD_WRITE, args);
+    if (!result) {
+        LOGE(WARN, "Write %s to %s failed\n", buf, sysfs_path);
         return ERROR_FAIL;
+    }
 
     return 0;
 }
@@ -593,14 +599,13 @@ void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num)
 static int sysfs_dev_unbind(libxl__gc *gc, libxl_device_pci *pci,
                             char **driver_path)
 {
-    char * spath, *dp = NULL;
+    char *spath, *pci_path, *dp = NULL;
     struct stat st;
 
-    spath = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/driver",
-                           pci->domain,
-                           pci->bus,
-                           pci->dev,
-                           pci->func);
+    pci_path = GCSPRINTF("/"PCI_BDF"/driver", pci->domain, pci->bus,
+                         pci->dev, pci->func);
+
+    spath = GCSPRINTF(SYSFS_PCI_DEV"%s", pci_path);
     if ( !lstat(spath, &st) ) {
         /* Find the canonical path to the driver. */
         dp = libxl__zalloc(gc, PATH_MAX);
@@ -614,7 +619,7 @@ static int sysfs_dev_unbind(libxl__gc *gc, libxl_device_pci *pci,
 
         /* Unbind from the old driver */
         spath = GCSPRINTF("%s/unbind", dp);
-        if ( sysfs_write_bdf(gc, spath, pci) < 0 ) {
+        if (sysfs_write_bdf(gc, SYSFS_PCI_DEV, pci_path, pci) < 0) {
             LOGE(ERROR, "Couldn't unbind device");
             return -1;
         }
@@ -816,14 +821,14 @@ static int pciback_dev_assign(libxl__gc *gc, libxl_device_pci *pci)
         LOGE(ERROR, "Error checking for pciback slot");
         return ERROR_FAIL;
     } else if (rc == 0) {
-        if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/new_slot",
-                             pci) < 0 ) {
+        if (sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER, "/new_slot",
+                            pci) < 0) {
             LOGE(ERROR, "Couldn't bind device to pciback!");
             return ERROR_FAIL;
         }
     }
 
-    if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/bind", pci) < 0 ) {
+    if (sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER, "/bind", pci) < 0) {
         LOGE(ERROR, "Couldn't bind device to pciback!");
         return ERROR_FAIL;
     }
@@ -840,8 +845,8 @@ static int pciback_dev_unassign(libxl__gc *gc, libxl_device_pci *pci)
 
     /* Remove slot if necessary */
     if ( pciback_dev_has_slot(gc, pci) > 0 ) {
-        if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/remove_slot",
-                             pci) < 0 ) {
+        if (sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER, "/remove_slot",
+                            pci) < 0) {
             LOGE(ERROR, "Couldn't remove pciback slot");
             return ERROR_FAIL;
         }
@@ -1022,9 +1027,9 @@ static int libxl__device_pci_assignable_remove(libxl__gc *gc,
         if ( rebind ) {
             LOG(INFO, "Rebinding to driver at %s", driver_path);
 
-            if ( sysfs_write_bdf(gc,
-                                 GCSPRINTF("%s/bind", driver_path),
-                                 pci) < 0 ) {
+            if (sysfs_write_bdf(gc, SYSFS_DRIVER_PATH,
+                                GCSPRINTF("%s/bind", driver_path),
+                                pci) < 0) {
                 LOGE(ERROR, "Couldn't bind device to %s", driver_path);
                 return -1;
             }
@@ -1565,8 +1570,8 @@ static void pci_add_dm_done(libxl__egc *egc,
 
     /* Don't restrict writes to the PCI config space from this VM */
     if (pci->permissive) {
-        if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
-                             pci) < 0 ) {
+        if (sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER, "/permissive",
+                            pci) < 0) {
             LOGD(ERROR, domainid, "Setting permissive for device");
             rc = ERROR_FAIL;
             goto out;
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index c897244e8a..ee4c832779 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -87,6 +87,73 @@ out:
     return result;
 }
 
+static int handle_write_cmd(libxl__gc *gc, char *sysfs_path, char *pci_info)
+{
+    int rc, fd;
+
+    fd = open(sysfs_path, O_WRONLY);
+    if (fd < 0) {
+        LOGE(ERROR, "Couldn't open %s\n", sysfs_path);
+        return ERROR_FAIL;
+    }
+
+    rc = write(fd, pci_info, strlen(pci_info));
+    close(fd);
+    if (rc < 0) {
+        LOGE(ERROR, "write to %s returned %d\n", sysfs_path, rc);
+        return ERROR_FAIL;
+    }
+
+    return 0;
+}
+
+static libxl__json_object *process_write_cmd(libxl__gc *gc,
+                                             const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const struct libxl__json_object *args, *dir_id, *pci_path, *pci_info;
+    char *full_path;
+    int ret;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    dir_id = libxl__json_map_get(PCID_CMD_DIR_ID, args, JSON_ANY);
+    if (!dir_id)
+        goto out;
+    pci_path = libxl__json_map_get(PCID_CMD_PCI_PATH, args, JSON_ANY);
+    if (!pci_path)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+
+    if (strcmp(dir_id->u.string, PCID_PCI_DEV) == 0)
+        full_path = libxl__sprintf(gc, SYSFS_PCI_DEV"%s", pci_path->u.string);
+    else if (strcmp(dir_id->u.string, PCID_PCIBACK_DRIVER) == 0)
+        full_path = libxl__sprintf(gc, SYSFS_PCIBACK_DRIVER"%s", pci_path->u.string);
+    else if (strcmp(dir_id->u.string, SYSFS_DRIVER_PATH) == 0)
+        full_path = pci_path->u.string;
+    else {
+        LOGE(ERROR, "Unknown write directory %s\n", dir_id->u.string);
+        goto out;
+    }
+
+    ret = handle_write_cmd(gc, full_path, pci_info->u.string);
+    if (ret != 0)
+        goto out;
+
+    result = libxl__json_object_alloc(gc, JSON_STRING);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    result->u.string = pci_path->u.string;
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -102,6 +169,8 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
 
     if (strcmp(command_name, PCID_CMD_LIST) == 0)
        *result = process_ls_cmd(gc, request);
+    else if (strcmp(PCID_CMD_WRITE, command_name) == 0)
+       *result = process_write_cmd(gc, request);
     else
         return ERROR_NOTFOUND;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/9] tools/libs/light: Add "read" command to xl pcid and libxl PCI
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (4 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 5/9] tools/libs/light: Add "write" command to xl pcid " Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 7/9] tools/libs/light: Make Libxl PCI get values from xl pcid instead of libxl side Anastasiia Lukianenko
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Libxl PCI can use xl pcid server to read integer value from the given path.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |   1 +
 tools/libs/light/libxl_pci.c  | 125 ++++++++++++++++++----------------
 tools/libs/light/libxl_pcid.c |  50 ++++++++++++++
 3 files changed, 119 insertions(+), 57 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index 935d99b186..f39011ecb8 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -32,6 +32,7 @@
 #define PCID_CMD_DIR_ID          "dir_id"
 
 #define PCID_CMD_WRITE           "write"
+#define PCID_CMD_READ_HEX        "read_hex"
 #define PCID_CMD_PCI_PATH        "pci_path"
 #define PCID_CMD_PCI_INFO        "pci_info"
 
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 03ce42dec3..d5ddca4964 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -634,83 +634,94 @@ static int sysfs_dev_unbind(libxl__gc *gc, libxl_device_pci *pci,
 static uint16_t sysfs_dev_get_vendor(libxl__gc *gc, libxl_device_pci *pci)
 {
     char *pci_device_vendor_path =
-            GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/vendor",
-                      pci->domain, pci->bus, pci->dev, pci->func);
-    uint16_t read_items;
+            GCSPRINTF("/"PCI_BDF"/vendor", pci->domain, pci->bus,
+                      pci->dev, pci->func);
     uint16_t pci_device_vendor;
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
 
-    FILE *f = fopen(pci_device_vendor_path, "r");
-    if (!f) {
-        LOGE(ERROR,
-             "pci device "PCI_BDF" does not have vendor attribute",
-             pci->domain, pci->bus, pci->dev, pci->func);
-        return 0xffff;
-    }
-    read_items = fscanf(f, "0x%hx\n", &pci_device_vendor);
-    fclose(f);
-    if (read_items != 1) {
-        LOGE(ERROR,
-             "cannot read vendor of pci device "PCI_BDF,
-             pci->domain, pci->bus, pci->dev, pci->func);
-        return 0xffff;
-    }
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        goto fail;
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO,
+                                  pci_device_vendor_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID,
+                                  PCID_PCI_DEV);
+    result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+    if (!result)
+        goto fail;
+
+    pci_device_vendor = libxl__json_object_get_integer(result);
 
     return pci_device_vendor;
+
+fail:
+    LOGE(ERROR,
+         "cannot read vendor of pci device "PCI_BDF,
+         pci->domain, pci->bus, pci->dev, pci->func);
+    return 0xffff;
 }
 
 static uint16_t sysfs_dev_get_device(libxl__gc *gc, libxl_device_pci *pci)
 {
     char *pci_device_device_path =
-            GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/device",
-                      pci->domain, pci->bus, pci->dev, pci->func);
-    uint16_t read_items;
+            GCSPRINTF("/"PCI_BDF"/device", pci->domain, pci->bus,
+                      pci->dev, pci->func);
     uint16_t pci_device_device;
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
 
-    FILE *f = fopen(pci_device_device_path, "r");
-    if (!f) {
-        LOGE(ERROR,
-             "pci device "PCI_BDF" does not have device attribute",
-             pci->domain, pci->bus, pci->dev, pci->func);
-        return 0xffff;
-    }
-    read_items = fscanf(f, "0x%hx\n", &pci_device_device);
-    fclose(f);
-    if (read_items != 1) {
-        LOGE(ERROR,
-             "cannot read device of pci device "PCI_BDF,
-             pci->domain, pci->bus, pci->dev, pci->func);
-        return 0xffff;
-    }
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        goto fail;
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO,
+                                  pci_device_device_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID,
+                                  PCID_PCI_DEV);
+    result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+    if (!result)
+        goto fail;
+
+    pci_device_device = libxl__json_object_get_integer(result);
 
     return pci_device_device;
+
+fail:
+    LOGE(ERROR,
+         "cannot read device of pci device "PCI_BDF,
+         pci->domain, pci->bus, pci->dev, pci->func);
+    return 0xffff;
 }
 
 static int sysfs_dev_get_class(libxl__gc *gc, libxl_device_pci *pci,
                                unsigned long *class)
 {
-    char *pci_device_class_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/class",
-                     pci->domain, pci->bus, pci->dev, pci->func);
-    int read_items, ret = 0;
+    char *pci_device_class_path = GCSPRINTF("/"PCI_BDF"/class",
+                                            pci->domain, pci->bus,
+                                            pci->dev, pci->func);
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
 
-    FILE *f = fopen(pci_device_class_path, "r");
-    if (!f) {
-        LOGE(ERROR,
-             "pci device "PCI_BDF" does not have class attribute",
-             pci->domain, pci->bus, pci->dev, pci->func);
-        ret = ERROR_FAIL;
-        goto out;
-    }
-    read_items = fscanf(f, "0x%lx\n", class);
-    fclose(f);
-    if (read_items != 1) {
-        LOGE(ERROR,
-             "cannot read class of pci device "PCI_BDF,
-             pci->domain, pci->bus, pci->dev, pci->func);
-        ret = ERROR_FAIL;
-    }
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        goto fail;
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO,
+                                  pci_device_class_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID,
+                                  PCID_PCI_DEV);
+    result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+    if (!result)
+        goto fail;
 
-out:
-    return ret;
+    *class = libxl__json_object_get_integer(result);
+
+    return 0;
+
+fail:
+    LOGE(ERROR,
+         "cannot read class of pci device "PCI_BDF,
+         pci->domain, pci->bus, pci->dev, pci->func);
+    return ERROR_FAIL;
 }
 
 /*
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index ee4c832779..0f736c68af 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -154,6 +154,54 @@ out:
     return result;
 }
 
+static libxl__json_object *process_read_hex_cmd(libxl__gc *gc,
+                                                const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const struct libxl__json_object *args, *dir_id, *pci_info;
+    char *full_path;
+    uint16_t read_items;
+    long long read_number;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    dir_id = libxl__json_map_get(PCID_CMD_DIR_ID, args, JSON_ANY);
+    if (!dir_id)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+
+    if (strcmp(PCID_PCI_DEV, dir_id->u.string) == 0)
+        full_path = libxl__sprintf(gc, SYSFS_PCI_DEV"%s", pci_info->u.string);
+    else
+        full_path = pci_info->u.string;
+
+    FILE *f = fopen(full_path, "r");
+    if (!f) {
+        LOGE(ERROR, "PCI device %s does not have needed attribute\n",
+                full_path);
+        goto out;
+    }
+    read_items = fscanf(f, "0x%llx\n", &read_number);
+    fclose(f);
+    if (read_items != 1) {
+        LOGE(ERROR, "Cannot read attribute of pci device %s\n", full_path);
+        goto out;
+    }
+
+    result = libxl__json_object_alloc(gc, JSON_INTEGER);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    result->u.i = read_number;
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -171,6 +219,8 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
        *result = process_ls_cmd(gc, request);
     else if (strcmp(PCID_CMD_WRITE, command_name) == 0)
        *result = process_write_cmd(gc, request);
+    else if (strcmp(command_name, PCID_CMD_READ_HEX) == 0)
+        *result = process_read_hex_cmd(gc, request);
     else
         return ERROR_NOTFOUND;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/9] tools/libs/light: Make Libxl PCI get values from xl pcid instead of libxl side
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (5 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 6/9] tools/libs/light: Add "read" " Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 8/9] tools/libs/light: Add "unbind" and "read resources" commands to libxl PCI and xl pcid Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 9/9] tools/libs/light: Add "reset" and "remove" PCI dev commands to xl pcid daemon and libxl PCI Anastasiia Lukianenko
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

pci_multifunction_check needs to use "ls" and "lstat" commands to get
information from sysfs.
Add "is_exists" command processing to xl pcid daemon to make possible
pci_multifunction_check read directories and check lstat by using xl pcid.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |  1 +
 tools/libs/light/libxl_pci.c  | 47 ++++++++++++++++++-----------------
 tools/libs/light/libxl_pcid.c | 47 +++++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+), 23 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index f39011ecb8..5c8efbb435 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -33,6 +33,7 @@
 
 #define PCID_CMD_WRITE           "write"
 #define PCID_CMD_READ_HEX        "read_hex"
+#define PCID_CMD_EXISTS          "exists"
 #define PCID_CMD_PCI_PATH        "pci_path"
 #define PCID_CMD_PCI_INFO        "pci_info"
 
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index d5ddca4964..ab6709890e 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -1091,45 +1091,46 @@ int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci *pci,
 */
 static int pci_multifunction_check(libxl__gc *gc, libxl_device_pci *pci, unsigned int *func_mask)
 {
-    struct dirent *de;
-    DIR *dir;
-
     *func_mask = 0;
+    struct vchan_info *vchan;
+    libxl__json_object *result = NULL, *args = NULL;
+    const libxl__json_object *lstat_obj, *dir;
+    const char *dir_name;
+    int i;
 
-    dir = opendir(SYSFS_PCI_DEV);
-    if ( NULL == dir ) {
-        LOGE(ERROR, "Couldn't open %s", SYSFS_PCI_DEV);
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
         return -1;
-    }
 
-    while( (de = readdir(dir)) ) {
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCI_DEV);
+    result = vchan_send_command(gc, vchan, PCID_CMD_LIST, args);
+    if (!result)
+        return -1;
+
+    for (i = 0; (dir = libxl__json_array_get(result, i)); i++) {
+        dir_name = libxl__json_object_get_string(dir);
         unsigned dom, bus, dev, func;
-        struct stat st;
         char *path;
 
-        if ( sscanf(de->d_name, PCI_BDF, &dom, &bus, &dev, &func) != 4 )
+        if (sscanf(dir_name, PCI_BDF, &dom, &bus, &dev, &func) != 4)
             continue;
-        if ( pci->domain != dom )
+        if (pci->domain != dom)
             continue;
-        if ( pci->bus != bus )
+        if (pci->bus != bus)
             continue;
-        if ( pci->dev != dev )
+        if (pci->dev != dev)
             continue;
 
-        path = GCSPRINTF("%s/" PCI_BDF, SYSFS_PCIBACK_DRIVER, dom, bus, dev, func);
-        if ( lstat(path, &st) ) {
-            if ( errno == ENOENT )
-                LOG(ERROR, PCI_BDF " is not assigned to pciback driver",
-                    dom, bus, dev, func);
-            else
-                LOGE(ERROR, "Couldn't lstat %s", path);
-            closedir(dir);
+        path = GCSPRINTF("/" PCI_BDF, dom, bus, dev, func);
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCIBACK_DRIVER);
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, path);
+        lstat_obj = vchan_send_command(gc, vchan, PCID_CMD_EXISTS, args);
+        if (!lstat_obj)
             return -1;
-        }
+
         (*func_mask) |= (1 << func);
     }
 
-    closedir(dir);
     return 0;
 }
 
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index 0f736c68af..28d773f48d 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -34,6 +34,10 @@
 #include <libxl_json.h>
 #include <dirent.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #define DOM0_ID 0
 
 static struct libxl__json_object *process_ls_cmd(libxl__gc *gc,
@@ -202,6 +206,47 @@ out:
     return result;
 }
 
+static libxl__json_object *process_exists_cmd(libxl__gc *gc,
+                                              const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const struct libxl__json_object *args, *pci_path, *pci_info;
+    char *full_path;
+    struct stat st;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    pci_path = libxl__json_map_get(PCID_CMD_DIR_ID, args, JSON_ANY);
+    if (!pci_path)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+    if (strcmp(pci_path->u.string, PCID_PCIBACK_DRIVER) == 0)
+        full_path = libxl__sprintf(gc, SYSFS_PCIBACK_DRIVER"%s", pci_info->u.string);
+    else
+        full_path = pci_info->u.string;
+
+    if (lstat(full_path, &st)) {
+        if (errno == ENOENT)
+            LOGE(ERROR, "%s is not assigned to pciback driver", full_path);
+        else
+            LOGE(ERROR, "Couldn't lstat %s", full_path);
+        goto out;
+    }
+
+    result = libxl__json_object_alloc(gc, JSON_STRING);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    result->u.string = pci_path->u.string;
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -221,6 +266,8 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
        *result = process_write_cmd(gc, request);
     else if (strcmp(command_name, PCID_CMD_READ_HEX) == 0)
         *result = process_read_hex_cmd(gc, request);
+    else if (strcmp(command_name, PCID_CMD_EXISTS) == 0)
+        *result = process_exists_cmd(gc, request);
     else
         return ERROR_NOTFOUND;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 8/9] tools/libs/light: Add "unbind" and "read resources" commands to libxl PCI and xl pcid
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (6 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 7/9] tools/libs/light: Make Libxl PCI get values from xl pcid instead of libxl side Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  2021-08-12 14:22 ` [PATCH 9/9] tools/libs/light: Add "reset" and "remove" PCI dev commands to xl pcid daemon and libxl PCI Anastasiia Lukianenko
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Send requests to xl pcid from libxl PCI to prevent the libxl PCI from
reading / writing from / to the local sysfs directly.

"Unbind" command returns driver's path or "nolstat" result in success and
NULL if writing to PCI path failed.

"Read resources" command returns an array of PCI resources - start, end and
flags in success, NULL if getting resources from PCI path failed.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |   7 +++
 tools/libs/light/libxl_pci.c  |  99 ++++++++++++++++++--------------
 tools/libs/light/libxl_pcid.c | 105 ++++++++++++++++++++++++++++++++++
 3 files changed, 169 insertions(+), 42 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index 5c8efbb435..3153bafb19 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -29,11 +29,13 @@
 #define PCID_MSG_FIELD_ARGS      "arguments"
 
 #define PCID_CMD_LIST            "ls"
+#define PCID_CMD_UNBIND          "unbind"
 #define PCID_CMD_DIR_ID          "dir_id"
 
 #define PCID_CMD_WRITE           "write"
 #define PCID_CMD_READ_HEX        "read_hex"
 #define PCID_CMD_EXISTS          "exists"
+#define PCID_CMD_READ_RESOURCES  "read_resources"
 #define PCID_CMD_PCI_PATH        "pci_path"
 #define PCID_CMD_PCI_INFO        "pci_info"
 
@@ -44,12 +46,17 @@
 
 #if defined(__linux__)
 #define SYSFS_PCIBACK_DRIVER   "/sys/bus/pci/drivers/pciback"
+#define SYSFS_PCI_DEV          "/sys/bus/pci/devices"
 #endif
 
 #define PCI_INFO_PATH "/libxl/pci"
 #define PCI_BDF_XSPATH         "%04x-%02x-%02x-%01x"
 #define PCI_BDF                "%04x:%02x:%02x.%01x"
 
+#define RESOURCE_START "start"
+#define RESOURCE_END   "end"
+#define RESOURCE_FLAGS "flags"
+
 int libxl_pcid_process(libxl_ctx *ctx);
 
 #endif /* PCID_H */
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index ab6709890e..3d9bf4830b 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -599,34 +599,32 @@ void libxl_device_pci_assignable_list_free(libxl_device_pci *list, int num)
 static int sysfs_dev_unbind(libxl__gc *gc, libxl_device_pci *pci,
                             char **driver_path)
 {
-    char *spath, *pci_path, *dp = NULL;
-    struct stat st;
+    char *pci_path, *dp = NULL;
 
     pci_path = GCSPRINTF("/"PCI_BDF"/driver", pci->domain, pci->bus,
                          pci->dev, pci->func);
+    char *pci_info;
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
 
-    spath = GCSPRINTF(SYSFS_PCI_DEV"%s", pci_path);
-    if ( !lstat(spath, &st) ) {
-        /* Find the canonical path to the driver. */
-        dp = libxl__zalloc(gc, PATH_MAX);
-        dp = realpath(spath, dp);
-        if ( !dp ) {
-            LOGE(ERROR, "realpath() failed");
-            return -1;
-        }
-
-        LOG(DEBUG, "Driver re-plug path: %s", dp);
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        return ERROR_FAIL;
 
-        /* Unbind from the old driver */
-        spath = GCSPRINTF("%s/unbind", dp);
-        if (sysfs_write_bdf(gc, SYSFS_PCI_DEV, pci_path, pci) < 0) {
-            LOGE(ERROR, "Couldn't unbind device");
-            return -1;
-        }
+    pci_info = GCSPRINTF(PCI_BDF, pci->domain, pci->bus, pci->dev, pci->func);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_PATH, pci_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, pci_info);
+    result = vchan_send_command(gc, vchan, PCID_CMD_UNBIND, args);
+    if (!result) {
+        LOGE(WARN, "Write to %s%s failed\n", SYSFS_PCI_DEV, pci_path);
+        return -1;
     }
 
-    if ( driver_path )
+    if (driver_path) {
+        if (strcmp(result->u.string, "nolstat") != 0)
+            dp = (char *)libxl__json_object_get_string(result);
         *driver_path = dp;
+    }
 
     return 0;
 }
@@ -1488,8 +1486,6 @@ static void pci_add_dm_done(libxl__egc *egc,
     STATE_AO_GC(pas->aodev->ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
     libxl_domid domid = pas->pci_domid;
-    char *sysfs_path;
-    FILE *f;
     unsigned long long start, end, flags, size;
     int irq, i;
     int r;
@@ -1510,20 +1506,38 @@ static void pci_add_dm_done(libxl__egc *egc,
     if (isstubdom)
         starting = false;
 
-    sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
-                           pci->bus, pci->dev, pci->func);
-    f = fopen(sysfs_path, "r");
-    start = end = flags = size = 0;
-    irq = 0;
+    struct vchan_info *vchan;
+    libxl__json_object *result = NULL, *args = NULL;
+    const libxl__json_object *addr, *node;
+    char *resource_path, *irq_path;
 
-    if (f == NULL) {
-        LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        goto out;
+
+    resource_path = GCSPRINTF("/"PCI_BDF"/resource", pci->domain,
+                              pci->bus, pci->dev, pci->func);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, resource_path);
+    result = vchan_send_command(gc, vchan, PCID_CMD_READ_RESOURCES, args);
+    if (!result) {
+        LOGED(ERROR, domainid, "Couldn't get resources from %s", resource_path);
         rc = ERROR_FAIL;
         goto out;
     }
+
+    start = end = flags = size = 0;
+    irq = 0;
+
     for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-        if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
-            continue;
+        node = libxl__json_array_get(result, i);
+
+        addr = libxl__json_map_get(RESOURCE_START, node, JSON_INTEGER);
+        start = libxl__json_object_get_integer(addr);
+        addr = libxl__json_map_get(RESOURCE_END, node, JSON_INTEGER);
+        end = libxl__json_object_get_integer(addr);
+        addr = libxl__json_map_get(RESOURCE_FLAGS, node, JSON_INTEGER);
+        flags = libxl__json_object_get_integer(addr);
+
         size = end - start + 1;
         if (start) {
             if (flags & PCI_BAR_IO) {
@@ -1532,7 +1546,6 @@ static void pci_add_dm_done(libxl__egc *egc,
                     LOGED(ERROR, domainid,
                           "xc_domain_ioport_permission 0x%llx/0x%llx (error %d)",
                           start, size, r);
-                    fclose(f);
                     rc = ERROR_FAIL;
                     goto out;
                 }
@@ -1543,27 +1556,30 @@ static void pci_add_dm_done(libxl__egc *egc,
                     LOGED(ERROR, domainid,
                           "xc_domain_iomem_permission 0x%llx/0x%llx (error %d)",
                           start, size, r);
-                    fclose(f);
                     rc = ERROR_FAIL;
                     goto out;
                 }
             }
         }
     }
-    fclose(f);
-    sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
-                                pci->bus, pci->dev, pci->func);
-    f = fopen(sysfs_path, "r");
-    if (f == NULL) {
-        LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+
+    irq_path = GCSPRINTF("/"PCI_BDF"/irq", pci->domain,
+                         pci->bus, pci->dev, pci->func);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, irq_path);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCI_DEV);
+    result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+    if (!result) {
+        LOGED(ERROR, domainid, "Couldn't get irq from %s", irq_path);
+        rc = ERROR_FAIL;
         goto out_no_irq;
     }
-    if ((fscanf(f, "%u", &irq) == 1) && irq) {
+
+    irq = libxl__json_object_get_integer(result);
+    if (irq) {
         r = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
         if (r < 0) {
             LOGED(ERROR, domainid, "xc_physdev_map_pirq irq=%d (error=%d)",
                   irq, r);
-            fclose(f);
             rc = ERROR_FAIL;
             goto out;
         }
@@ -1578,7 +1594,6 @@ static void pci_add_dm_done(libxl__egc *egc,
         }
 #endif
     }
-    fclose(f);
 
     /* Don't restrict writes to the PCI config space from this VM */
     if (pci->permissive) {
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index 28d773f48d..7dd8f53f78 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -247,6 +247,107 @@ out:
     return result;
 }
 
+static libxl__json_object *process_read_rsc_cmd(libxl__gc *gc,
+                                                const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const libxl__json_object *args, *pci_info;
+    libxl__json_object *node;
+    unsigned long long start, end, flags;
+    int i;
+    char *sysfs_path;
+    FILE *f;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+
+    sysfs_path = libxl__sprintf(gc, SYSFS_PCI_DEV"%s", pci_info->u.string);
+    f = fopen(sysfs_path, "r");
+    if (!f) {
+        LOGE(ERROR, "Failed to open %s\n", sysfs_path);
+        goto out;
+    }
+
+    result = libxl__json_object_alloc(gc, JSON_ARRAY);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto fail_mem_alloc;
+    }
+
+    for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
+        if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
+            continue;
+
+        node = libxl__json_object_alloc(gc, JSON_MAP);
+        if (!node) {
+            LOGE(ERROR, "Memory allocation failed\n");
+            goto fail_mem_alloc;
+        }
+        libxl__vchan_param_add_integer(gc, &node, RESOURCE_START, start);
+        libxl__vchan_param_add_integer(gc, &node, RESOURCE_END, end);
+        libxl__vchan_param_add_integer(gc, &node, RESOURCE_FLAGS, flags);
+        flexarray_append(result->u.array, node);
+    }
+
+fail_mem_alloc:
+    fclose(f);
+out:
+    return result;
+}
+
+static libxl__json_object *process_unbind_cmd(libxl__gc *gc,
+                                              const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const struct libxl__json_object *args, *pci_path, *pci_info;
+    char *msg, *spath, *new_path, *dp = NULL;
+    struct stat st;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+    pci_path = libxl__json_map_get(PCID_CMD_PCI_PATH, args, JSON_ANY);
+    if (!pci_path)
+        goto out;
+
+    spath = libxl__sprintf(gc, SYSFS_PCI_DEV"%s", pci_path->u.string);
+
+    if (!lstat(spath, &st)) {
+        /* Find the canonical path to the driver. */
+        dp = libxl__zalloc(gc, PATH_MAX);
+        if (!(realpath(spath, dp))) {
+            LOGE(ERROR, "realpath() failed\n");
+            goto out;
+        }
+        msg = dp;
+        /* Unbind from the old driver */
+        new_path = libxl__sprintf(gc, "%s/unbind", dp);
+
+        if (handle_write_cmd(gc, new_path, pci_info->u.string) != 0) {
+            LOGE(ERROR, "Couldn't unbind device\n");
+            goto out;
+        }
+    } else {
+        msg = libxl__sprintf(gc, "nolstat");
+    }
+    result = libxl__json_object_alloc(gc, JSON_STRING);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    result->u.string = msg;
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -268,6 +369,10 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
         *result = process_read_hex_cmd(gc, request);
     else if (strcmp(command_name, PCID_CMD_EXISTS) == 0)
         *result = process_exists_cmd(gc, request);
+    else if (strcmp(command_name, PCID_CMD_READ_RESOURCES) == 0)
+        *result = process_read_rsc_cmd(gc, request);
+    else if (strcmp(command_name, PCID_CMD_UNBIND) == 0)
+        *result = process_unbind_cmd(gc, request);
     else
         return ERROR_NOTFOUND;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 9/9] tools/libs/light: Add "reset" and "remove" PCI dev commands to xl pcid daemon and libxl PCI
  2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
                   ` (7 preceding siblings ...)
  2021-08-12 14:22 ` [PATCH 8/9] tools/libs/light: Add "unbind" and "read resources" commands to libxl PCI and xl pcid Anastasiia Lukianenko
@ 2021-08-12 14:22 ` Anastasiia Lukianenko
  8 siblings, 0 replies; 10+ messages in thread
From: Anastasiia Lukianenko @ 2021-08-12 14:22 UTC (permalink / raw)
  To: xen-devel
  Cc: oleksandr_tyshchenko, artem_mygaiev, rahul.singh,
	bertrand.marquis, oleksandr_andrushchenko, roger.pau, julien,
	sstabellini, andr2000, vicooodin, Anastasiia Lukianenko

From: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>

Add "reset" command processing to xl pcid daemon.
Make possible sending "reset"/"remove" PCI device requests from libxl PCI
to xl pcid daemon instead of using sysfs on libxl side.

Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
---
 tools/include/pcid.h          |  1 +
 tools/libs/light/libxl_pci.c  | 94 +++++++++++++++++++----------------
 tools/libs/light/libxl_pcid.c | 63 +++++++++++++++++++++++
 3 files changed, 115 insertions(+), 43 deletions(-)

diff --git a/tools/include/pcid.h b/tools/include/pcid.h
index 3153bafb19..38ea06c602 100644
--- a/tools/include/pcid.h
+++ b/tools/include/pcid.h
@@ -30,6 +30,7 @@
 
 #define PCID_CMD_LIST            "ls"
 #define PCID_CMD_UNBIND          "unbind"
+#define PCID_CMD_RESET           "reset"
 #define PCID_CMD_DIR_ID          "dir_id"
 
 #define PCID_CMD_WRITE           "write"
diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
index 3d9bf4830b..0498baa47e 100644
--- a/tools/libs/light/libxl_pci.c
+++ b/tools/libs/light/libxl_pci.c
@@ -1635,37 +1635,26 @@ static int libxl__device_pci_reset(libxl__gc *gc, unsigned int domain, unsigned
                                    unsigned int dev, unsigned int func)
 {
     char *reset;
-    int fd, rc;
-
-    reset = GCSPRINTF("%s/do_flr", SYSFS_PCIBACK_DRIVER);
-    fd = open(reset, O_WRONLY);
-    if (fd >= 0) {
-        char *buf = GCSPRINTF(PCI_BDF, domain, bus, dev, func);
-        rc = write(fd, buf, strlen(buf));
-        if (rc < 0)
-            LOGD(ERROR, domain, "write to %s returned %d", reset, rc);
-        close(fd);
-        return rc < 0 ? rc : 0;
-    }
-    if (errno != ENOENT)
-        LOGED(ERROR, domain, "Failed to access pciback path %s", reset);
-    reset = GCSPRINTF("%s/"PCI_BDF"/reset", SYSFS_PCI_DEV, domain, bus, dev, func);
-    fd = open(reset, O_WRONLY);
-    if (fd >= 0) {
-        rc = write(fd, "1", 1);
-        if (rc < 0)
-            LOGED(ERROR, domain, "write to %s returned %d", reset, rc);
-        close(fd);
-        return rc < 0 ? rc : 0;
-    }
-    if (errno == ENOENT) {
-        LOGD(ERROR, domain,
-             "The kernel doesn't support reset from sysfs for PCI device "PCI_BDF,
-             domain, bus, dev, func);
-    } else {
-        LOGED(ERROR, domain, "Failed to access reset path %s", reset);
+    char *buf;
+    struct vchan_info *vchan;
+    libxl__json_object *args = NULL, *result = NULL;
+
+    vchan = pci_prepare_vchan(gc);
+    if (!vchan)
+        return -1;
+
+    reset = GCSPRINTF("%s", "/do_flr");
+    buf = GCSPRINTF(PCI_BDF, domain, bus, dev, func);
+
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_PATH, reset);
+    libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, buf);
+    result = vchan_send_command(gc, vchan, PCID_CMD_RESET, args);
+    if (!result) {
+        LOGD(ERROR, domain, "write to %s returned error", reset);
+        return -1;
     }
-    return -1;
+
+    return 0;
 }
 
 int libxl__device_pci_setdefault(libxl__gc *gc, uint32_t domid,
@@ -2085,20 +2074,35 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
             goto out_fail;
         }
     } else {
-        char *sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/resource", pci->domain,
+        char *sysfs_path = GCSPRINTF("/"PCI_BDF"/resource", pci->domain,
                                      pci->bus, pci->dev, pci->func);
-        FILE *f = fopen(sysfs_path, "r");
         unsigned int start = 0, end = 0, flags = 0, size = 0;
         int irq = 0;
         int i;
+        struct vchan_info *vchan;
+        libxl__json_object *args = NULL, *result = NULL;
+        const libxl__json_object *addr;
+        int j = 0;
 
-        if (f == NULL) {
-            LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+        vchan = pci_prepare_vchan(gc);
+        if (!vchan)
+            goto out_fail;
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, sysfs_path);
+        result = vchan_send_command(gc, vchan, PCID_CMD_READ_RESOURCES, args);
+        if (!result) {
+            LOGED(ERROR, domainid, "Couldn't get resources from %s", sysfs_path);
+            rc = ERROR_FAIL;
             goto skip1;
         }
+
         for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
-            if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
-                continue;
+            addr = libxl__json_array_get(result, j++);
+            start = libxl__json_object_get_integer(addr);
+            addr = libxl__json_array_get(result, j++);
+            end = libxl__json_object_get_integer(addr);
+            addr = libxl__json_array_get(result, j++);
+            flags = libxl__json_object_get_integer(addr);
+
             size = end - start + 1;
             if (start) {
                 if (flags & PCI_BAR_IO) {
@@ -2119,16 +2123,21 @@ static void do_pci_remove(libxl__egc *egc, pci_remove_state *prs)
                 }
             }
         }
-        fclose(f);
+
 skip1:
-        sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
+        sysfs_path = GCSPRINTF("/"PCI_BDF"/irq", pci->domain,
                                pci->bus, pci->dev, pci->func);
-        f = fopen(sysfs_path, "r");
-        if (f == NULL) {
-            LOGED(ERROR, domainid, "Couldn't open %s", sysfs_path);
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_PCI_INFO, sysfs_path);
+        libxl__vchan_param_add_string(gc, &args, PCID_CMD_DIR_ID, PCID_PCI_DEV);
+        result = vchan_send_command(gc, vchan, PCID_CMD_READ_HEX, args);
+        if (!result) {
+            LOGED(ERROR, domainid, "Couldn't get irq from %s", sysfs_path);
+            rc = ERROR_FAIL;
             goto skip_irq;
         }
-        if ((fscanf(f, "%u", &irq) == 1) && irq) {
+
+        irq = libxl__json_object_get_integer(result);
+        if (irq) {
             rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
             if (rc < 0) {
                 LOGED(ERROR, domainid, "xc_physdev_unmap_pirq irq=%d", irq);
@@ -2138,7 +2147,6 @@ skip1:
                 LOGED(ERROR, domainid, "xc_domain_irq_permission irq=%d", irq);
             }
         }
-        fclose(f);
     }
 skip_irq:
     rc = 0;
diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c
index 7dd8f53f78..a4669b9533 100644
--- a/tools/libs/light/libxl_pcid.c
+++ b/tools/libs/light/libxl_pcid.c
@@ -348,6 +348,67 @@ out:
     return result;
 }
 
+static libxl__json_object *process_reset_cmd(libxl__gc *gc,
+                                             const struct libxl__json_object *resp)
+{
+    libxl__json_object *result = NULL;
+    const libxl__json_object *args, *pci_path, *pci_info;
+    char *reset;
+    int rc, fd;
+
+    args = libxl__json_map_get(PCID_MSG_FIELD_ARGS, resp, JSON_MAP);
+    if (!args)
+        goto out;
+    pci_info = libxl__json_map_get(PCID_CMD_PCI_INFO, args, JSON_ANY);
+    if (!pci_info)
+        goto out;
+    pci_path = libxl__json_map_get(PCID_CMD_PCI_PATH, args, JSON_ANY);
+
+    reset = libxl__sprintf(gc, SYSFS_PCIBACK_DRIVER"%s", pci_path->u.string);
+    fd = open(reset, O_WRONLY);
+    if (fd >= 0) {
+        rc = write(fd, pci_info->u.string, strlen(pci_info->u.string));
+        if (rc < 0) {
+            LOGE(ERROR, "write to %s returned %d\n", reset, rc);
+            goto out;
+        }
+        close(fd);
+        goto success;
+    }
+    if (errno != ENOENT)
+        LOGE(ERROR, "Failed to access pciback path %s\n", reset);
+
+    reset = libxl__sprintf(gc, "%s/%s/reset", SYSFS_PCI_DEV, pci_info->u.string);
+    fd = open(reset, O_WRONLY);
+    if (fd >= 0) {
+        rc = write(fd, "1", 1);
+        if (rc < 0) {
+            LOGE(ERROR, "write to %s returned %d\n", reset, rc);
+            goto out;
+        }
+        close(fd);
+        goto success;
+    }
+    if (errno == ENOENT)
+        LOGE(ERROR,
+                "The kernel doesn't support reset from sysfs for PCI device %s\n",
+                pci_info->u.string);
+    else
+        LOGE(ERROR, "Failed to access reset path %s\n", reset);
+    goto out;
+
+success:
+    result = libxl__json_object_alloc(gc, JSON_STRING);
+    if (!result) {
+        LOGE(ERROR, "Memory allocation failed\n");
+        goto out;
+    }
+    result->u.string = pci_path->u.string;
+
+out:
+    return result;
+}
+
 static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
                                libxl__json_object **result)
 {
@@ -373,6 +434,8 @@ static int pcid_handle_message(libxl__gc *gc, const libxl__json_object *request,
         *result = process_read_rsc_cmd(gc, request);
     else if (strcmp(command_name, PCID_CMD_UNBIND) == 0)
         *result = process_unbind_cmd(gc, request);
+    else if (strcmp(command_name, PCID_CMD_RESET) == 0)
+        *result = process_reset_cmd(gc, request);
     else
         return ERROR_NOTFOUND;
 
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-08-12 14:23 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-12 14:22 [PATCH 0/9] Add xl PCI daemon (server for libxl PCI) Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 1/9] tools/libs/light: Add vchan support to libxl Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 2/9] tools/libs/light: Add functions for handling PCI messages in JSON format Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 3/9] tools/xl: Add pcid daemon to xl Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 4/9] tools/libs/light: Add "ls" command processing to xl pcid daemon and libxl PCI Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 5/9] tools/libs/light: Add "write" command to xl pcid " Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 6/9] tools/libs/light: Add "read" " Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 7/9] tools/libs/light: Make Libxl PCI get values from xl pcid instead of libxl side Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 8/9] tools/libs/light: Add "unbind" and "read resources" commands to libxl PCI and xl pcid Anastasiia Lukianenko
2021-08-12 14:22 ` [PATCH 9/9] tools/libs/light: Add "reset" and "remove" PCI dev commands to xl pcid daemon and libxl PCI Anastasiia Lukianenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).