diff mbox series

[11/15] tools/helpers: Add get_overlay

Message ID 20240424033449.168398-12-xin.wang2@amd.com (mailing list archive)
State Superseded
Headers show
Series Remaining patches for dynamic node programming using overlay dtbo | expand

Commit Message

Henry Wang April 24, 2024, 3:34 a.m. UTC
From: Vikram Garhwal <fnu.vikram@xilinx.com>

This user level application copies the overlay dtbo shared by dom0 while doing
overlay node assignment operation. It uses xenstore to communicate with dom0.
More information on the protocol is writtien in docs/misc/overlay.txt file.

Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
Signed-off-by: Henry Wang <xin.wang2@amd.com>
---
 tools/helpers/Makefile      |   8 +
 tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++
 2 files changed, 401 insertions(+)
 create mode 100644 tools/helpers/get_overlay.c

Comments

Jan Beulich April 24, 2024, 6:08 a.m. UTC | #1
On 24.04.2024 05:34, Henry Wang wrote:
> From: Vikram Garhwal <fnu.vikram@xilinx.com>
> 
> This user level application copies the overlay dtbo shared by dom0 while doing
> overlay node assignment operation. It uses xenstore to communicate with dom0.
> More information on the protocol is writtien in docs/misc/overlay.txt file.
> 
> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
> Signed-off-by: Henry Wang <xin.wang2@amd.com>
> ---
>  tools/helpers/Makefile      |   8 +
>  tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 401 insertions(+)
>  create mode 100644 tools/helpers/get_overlay.c

As mentioned before on various occasions - new files preferably use dashes as
separators in preference to underscores. You not doing so is particularly
puzzling seeing ...

> --- a/tools/helpers/Makefile
> +++ b/tools/helpers/Makefile
> @@ -12,6 +12,7 @@ TARGETS += init-xenstore-domain
>  endif
>  ifeq ($(CONFIG_ARM),y)
>  TARGETS += init-dom0less
> +TARGETS += get_overlay

... patch context here (demonstrating a whopping 3 dashes used in similar
cases).

Jan
Henry Wang April 25, 2024, 12:43 a.m. UTC | #2
Hi Jan,

On 4/24/2024 2:08 PM, Jan Beulich wrote:
> On 24.04.2024 05:34, Henry Wang wrote:
>> From: Vikram Garhwal <fnu.vikram@xilinx.com>
>>
>> This user level application copies the overlay dtbo shared by dom0 while doing
>> overlay node assignment operation. It uses xenstore to communicate with dom0.
>> More information on the protocol is writtien in docs/misc/overlay.txt file.
>>
>> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
>> Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
>> Signed-off-by: Henry Wang <xin.wang2@amd.com>
>> ---
>>   tools/helpers/Makefile      |   8 +
>>   tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++
>>   2 files changed, 401 insertions(+)
>>   create mode 100644 tools/helpers/get_overlay.c
> As mentioned before on various occasions - new files preferably use dashes as
> separators in preference to underscores. You not doing so is particularly
> puzzling seeing ...
>
>> --- a/tools/helpers/Makefile
>> +++ b/tools/helpers/Makefile
>> @@ -12,6 +12,7 @@ TARGETS += init-xenstore-domain
>>   endif
>>   ifeq ($(CONFIG_ARM),y)
>>   TARGETS += init-dom0less
>> +TARGETS += get_overlay
> ... patch context here (demonstrating a whopping 3 dashes used in similar
> cases).

I am not very sure why Vikram used "_" in the original patch. However I 
agree you are correct. Since I am currently doing the follow up of this 
series, I will use "-" in v2 as suggested. Thanks.

Kind regards,
Henry

>
> Jan
Stewart Hildebrand April 26, 2024, 1:45 a.m. UTC | #3
On 4/24/24 20:43, Henry Wang wrote:
> Hi Jan,
> 
> On 4/24/2024 2:08 PM, Jan Beulich wrote:
>> On 24.04.2024 05:34, Henry Wang wrote:
>>> From: Vikram Garhwal <fnu.vikram@xilinx.com>
>>>
>>> This user level application copies the overlay dtbo shared by dom0 while doing
>>> overlay node assignment operation. It uses xenstore to communicate with dom0.
>>> More information on the protocol is writtien in docs/misc/overlay.txt file.
>>>
>>> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
>>> Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
>>> Signed-off-by: Henry Wang <xin.wang2@amd.com>
>>> ---
>>>   tools/helpers/Makefile      |   8 +
>>>   tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++
>>>   2 files changed, 401 insertions(+)
>>>   create mode 100644 tools/helpers/get_overlay.c
>> As mentioned before on various occasions - new files preferably use dashes as
>> separators in preference to underscores. You not doing so is particularly
>> puzzling seeing ...
>>
>>> --- a/tools/helpers/Makefile
>>> +++ b/tools/helpers/Makefile
>>> @@ -12,6 +12,7 @@ TARGETS += init-xenstore-domain
>>>   endif
>>>   ifeq ($(CONFIG_ARM),y)
>>>   TARGETS += init-dom0less
>>> +TARGETS += get_overlay
>> ... patch context here (demonstrating a whopping 3 dashes used in similar
>> cases).
> 
> I am not very sure why Vikram used "_" in the original patch. However I agree you are correct. Since I am currently doing the follow up of this series, I will use "-" in v2 as suggested. Thanks.

Please also add tools/helpers/get-overlay to .gitignore
Henry Wang April 26, 2024, 1:48 a.m. UTC | #4
Hi Stewart,

On 4/26/2024 9:45 AM, Stewart Hildebrand wrote:
> On 4/24/24 20:43, Henry Wang wrote:
>> Hi Jan,
>>
>> On 4/24/2024 2:08 PM, Jan Beulich wrote:
>>> On 24.04.2024 05:34, Henry Wang wrote:
>>>> From: Vikram Garhwal <fnu.vikram@xilinx.com>
>>>>
>>>> This user level application copies the overlay dtbo shared by dom0 while doing
>>>> overlay node assignment operation. It uses xenstore to communicate with dom0.
>>>> More information on the protocol is writtien in docs/misc/overlay.txt file.
>>>>
>>>> Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
>>>> Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com>
>>>> Signed-off-by: Henry Wang <xin.wang2@amd.com>
>>>> ---
>>>>    tools/helpers/Makefile      |   8 +
>>>>    tools/helpers/get_overlay.c | 393 ++++++++++++++++++++++++++++++++++++
>>>>    2 files changed, 401 insertions(+)
>>>>    create mode 100644 tools/helpers/get_overlay.c
>>> As mentioned before on various occasions - new files preferably use dashes as
>>> separators in preference to underscores. You not doing so is particularly
>>> puzzling seeing ...
>>>
>>>> --- a/tools/helpers/Makefile
>>>> +++ b/tools/helpers/Makefile
>>>> @@ -12,6 +12,7 @@ TARGETS += init-xenstore-domain
>>>>    endif
>>>>    ifeq ($(CONFIG_ARM),y)
>>>>    TARGETS += init-dom0less
>>>> +TARGETS += get_overlay
>>> ... patch context here (demonstrating a whopping 3 dashes used in similar
>>> cases).
>> I am not very sure why Vikram used "_" in the original patch. However I agree you are correct. Since I am currently doing the follow up of this series, I will use "-" in v2 as suggested. Thanks.
> Please also add tools/helpers/get-overlay to .gitignore

Thanks for the reminder! Yes sure I will add it.

Kind regards,
Henry
diff mbox series

Patch

diff --git a/tools/helpers/Makefile b/tools/helpers/Makefile
index 09590eb5b6..dfe17ef269 100644
--- a/tools/helpers/Makefile
+++ b/tools/helpers/Makefile
@@ -12,6 +12,7 @@  TARGETS += init-xenstore-domain
 endif
 ifeq ($(CONFIG_ARM),y)
 TARGETS += init-dom0less
+TARGETS += get_overlay
 endif
 endif
 
@@ -39,6 +40,9 @@  $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenctrl)
 $(INIT_DOM0LESS_OBJS): CFLAGS += $(CFLAGS_libxenevtchn)
 init-dom0less: LDLIBS += $(call xenlibs-ldlibs,ctrl evtchn toollog store light guest foreignmemory)
 
+SHARE_OVERLAY_OBJS = get_overlay.o
+$(SHARE_OVERLAY_OBJS): CFLAGS += $(CFLAGS_libxengnttab) $(CFLAGS_libxenstore) $(CFLAGS_libxenctrl)
+
 .PHONY: all
 all: $(TARGETS)
 
@@ -51,6 +55,10 @@  init-xenstore-domain: $(INIT_XENSTORE_DOMAIN_OBJS)
 init-dom0less: $(INIT_DOM0LESS_OBJS)
 	$(CC) $(LDFLAGS) -o $@ $(INIT_DOM0LESS_OBJS) $(LDLIBS) $(APPEND_LDFLAGS)
 
+get_overlay: $(SHARE_OVERLAY_OBJS)
+	$(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenvchan) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxengnttab) $(APPEND_LDFLAGS)
+
+
 .PHONY: install
 install: all
 	$(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
diff --git a/tools/helpers/get_overlay.c b/tools/helpers/get_overlay.c
new file mode 100644
index 0000000000..ca3007570e
--- /dev/null
+++ b/tools/helpers/get_overlay.c
@@ -0,0 +1,393 @@ 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <xenstore.h>
+#include <libxenvchan.h>
+#include <xengnttab.h>
+
+#define PAGE_SIZE 4096
+
+static int xs_create_overlay_node(int domain, const char *xs_base,
+                                  struct xs_handle *xs)
+{
+    int ret = -1;
+    struct xs_permissions perms[2];
+    char buf[64];
+    char ref[16];
+    char *domid_str = NULL;
+    int overlay_size = 0;
+
+    xs_transaction_t xs_trans = XBT_NULL;
+
+    domid_str = xs_read(xs, XBT_NULL, "domid", NULL);
+
+    if (!domid_str)
+        return ret;
+
+    /* owner domain is us */
+    perms[0].id = atoi(domid_str);
+    /* permissions for domains not listed = none. */
+    perms[0].perms = XS_PERM_NONE;
+    /* other domains i.e. domain provided by user gets r/w permissions. */
+    perms[1].id = domain;
+    perms[1].perms =  XS_PERM_READ | XS_PERM_WRITE;
+
+retry_transaction:
+
+    xs_trans = xs_transaction_start(xs);
+    if (!xs_trans)
+        goto fail_xs_transaction;
+
+    /* Create overlay-size node. */
+    snprintf(ref, sizeof(ref), "%d", overlay_size);
+    snprintf(buf, sizeof(buf), "%s/overlay-size", xs_base);
+
+    if (!xs_write(xs, xs_trans, buf, ref, strlen(ref)))
+        goto fail_xs_transaction;
+    if (!xs_set_permissions(xs, xs_trans, buf, perms, 2))
+        goto fail_xs_transaction;
+
+    /* Create domU status node. */
+    snprintf(ref, sizeof(ref), "%s", "waiting");
+    snprintf(buf, sizeof(buf), "%s/receiver-status", xs_base);
+
+    if (!xs_write(xs, xs_trans, buf, ref, strlen(ref)))
+        goto fail_xs_transaction;
+    if (!xs_set_permissions(xs, xs_trans, buf, perms, 2))
+        goto fail_xs_transaction;
+
+    /* Create dom0 status node. */
+    snprintf(ref, sizeof(ref), "%s", "not_ready");
+    snprintf(buf, sizeof(buf), "%s/sender-status", xs_base);
+
+    if (!xs_write(xs, xs_trans, buf, ref, strlen(ref)))
+        goto fail_xs_transaction;
+    if (!xs_set_permissions(xs, xs_trans, buf, perms, 2))
+        goto fail_xs_transaction;
+
+    if (!xs_transaction_end(xs, xs_trans, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else
+            goto fail_xs_transaction;
+    } else
+        ret = 0;
+
+fail_xs_transaction:
+    free(domid_str);
+
+    return ret;
+}
+
+static int get_overlay_size(struct xs_handle *xs, int domain,
+                            const char *xs_path)
+{
+    char buf[128];
+    char *ref;
+    unsigned int len;
+    int dt_size = 0;
+
+    snprintf(buf, sizeof(buf), "%s/overlay-size", xs_path);
+
+    ref = xs_read(xs, XBT_NULL, buf, &len);
+
+    if (!ref)
+        return dt_size;
+
+    dt_size = atoi(ref);
+
+    free(ref);
+
+    return dt_size;
+}
+
+static uint32_t get_num_pages(int dtbo_size)
+{
+    int num_pages = 1;
+
+    while (dtbo_size > PAGE_SIZE) {
+        dtbo_size = dtbo_size - PAGE_SIZE;
+        num_pages++;
+    }
+
+    return num_pages;
+}
+
+static void *create_shared_buffer(int domain, uint32_t *refs, uint32_t pages,
+                                  xengntshr_handle *gntshr)
+{
+    return xengntshr_share_pages(gntshr, domain, pages, refs, 1);
+}
+
+static bool wait_for_status(struct xs_handle *xs, int fd, char *status_path,
+                            const char *status)
+{
+    unsigned int num_strings;
+    char *buf = NULL;
+    char **vec = NULL;
+    bool ret = false;
+    unsigned int len;
+    int rc = 0;
+    fd_set set;
+
+    while (1)
+    {
+        FD_ZERO(&set);
+        FD_SET(fd, &set);
+
+        rc = select(fd + 1, &set, NULL, NULL, NULL);
+        /* Poll for data: Blocking. */
+        if (rc <= 0)
+            break;
+
+        if (FD_ISSET(fd, &set)) {
+            /*
+             * num_strings will be set to the number of elements in vec
+             * (2 - the watched path and the overlay_watch)
+             */
+            vec = xs_read_watch(xs, &num_strings);
+            if (!vec) {
+                break;
+            }
+
+            /* do a read. */
+            buf = xs_read(xs, XBT_NULL, status_path, &len);
+            if (buf) {
+                if (!strcmp(buf, status)) {
+                    ret = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    free(vec);
+    free(buf);
+
+    return ret;
+}
+
+static bool write_page_ref(struct xs_handle *xs, uint32_t *page_ref,
+                           uint32_t num_pages, char *path)
+{
+    xs_transaction_t xs_trans = XBT_NULL;
+    char buf[128];
+    char *ref = NULL;
+    char tmp[16];
+    int i = 0;
+    bool rc = false;
+
+    /* Caller will free this. */
+    ref = (char *)calloc(num_pages * 16, sizeof(char)); /* For each number. */
+    if (ref == NULL) {
+        fprintf(stderr, "Memory calloc for ref failed\n");
+        return rc;
+    }
+
+retry_transaction:
+    xs_trans = xs_transaction_start(xs);
+    if (!xs_trans)
+        goto out;
+
+    for (i = 0; i < num_pages; i++) {
+        snprintf(tmp, sizeof(tmp), "%d,", page_ref[i]);
+        strcat(ref, tmp);
+    }
+
+    snprintf(buf, sizeof(buf), "%s/page-ref", path);
+
+    if (!xs_write(xs, xs_trans, buf, ref, strlen(ref)))
+        goto out;
+
+    snprintf(buf, sizeof(buf), "%s/num-pages", path);
+    snprintf(tmp, sizeof(tmp), "%u", num_pages);
+    if (!xs_write(xs, xs_trans, buf, tmp, strlen(tmp)))
+        goto out;
+
+    if (!xs_transaction_end(xs, xs_trans, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else
+            goto out;
+    }
+
+    rc = true;
+
+out:
+    if (ref)
+        free(ref);
+
+    return rc;
+}
+
+static bool write_status(struct xs_handle *xs, const char *status,
+                         const char *status_path)
+{
+    xs_transaction_t xs_trans = XBT_NULL;
+
+retry_transaction:
+    xs_trans = xs_transaction_start(xs);
+    if (!xs_trans)
+        return false;
+
+    if (!xs_write(xs, xs_trans, status_path, status, strlen(status)))
+        return false;
+
+    if (!xs_transaction_end(xs, xs_trans, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else
+            return false;
+    }
+
+    return true;
+}
+
+int main(int argc, char **argv)
+{
+    void *buffer = NULL;
+    int domain ;
+    uint32_t *page_refs = NULL;
+    FILE *fptr;
+    int dtbo_size = 0;
+    const char *path = "data/overlay";
+    char receiver_status_path[64] = { };
+    char sender_status_path[64] = { };
+    struct xs_handle *xs = NULL;
+    int rc = 0;
+    int fd = 0;
+    uint32_t num_pages = 0;
+    xengntshr_handle *gntshr;
+
+    if (argc < 2) {
+       fprintf(stderr,"Please enter domain_id.\n");
+        return 0;
+    }
+
+    domain = atoi(argv[1]);
+
+    xs = xs_open(0);
+    if (xs == NULL) {
+        fprintf(stderr, "Xenstore open for domain%d failed\n", domain);
+        goto out;
+    }
+
+    rc = xs_create_overlay_node(domain, path, xs);
+    if (rc) {
+        fprintf(stderr,"Creating overlay nodes failed\n");
+        goto out;
+    }
+
+    strcpy(receiver_status_path, path);
+    strcat(receiver_status_path, "/receiver-status");
+
+    strcpy(sender_status_path, path);
+    strcat(sender_status_path, "/sender-status");
+
+    /*
+     * Watch a node for changes (poll on fd to detect).
+     * When the node changes, fd will become readable.
+     */
+    rc = xs_watch(xs, sender_status_path, "overlay_watch");
+    if (rc == 0) {
+        fprintf(stderr, "Creating watch failed\n");
+        goto out;
+    }
+
+    /* We are notified of read availability on the watch via the
+     * file descriptor.
+     */
+    fd = xs_fileno(xs);
+
+    /* Wait for ready. */
+    if (!wait_for_status(xs, fd, sender_status_path, "ready")) {
+        fprintf(stderr, "dom0 not ready.\n");
+        goto out;
+    }
+
+    dtbo_size = get_overlay_size(xs, domain, path);
+    if (dtbo_size == 0) {
+        fprintf(stderr,"Overlay data size is zero. Exiting the application\n");
+        goto out;
+    }
+
+    gntshr = xengntshr_open(NULL, 0);
+    if (!gntshr) {
+        fprintf(stderr,"Error in opening gntshr\n");
+        goto out;
+    }
+
+    num_pages = get_num_pages(dtbo_size);
+
+    page_refs =(uint32_t *)malloc(num_pages * sizeof(int));
+    if (page_refs == NULL) {
+        fprintf(stderr, "Allocating page_ref array failed\n");
+        goto out;
+    }
+
+    /* Allocate memory for data size and share with domain. */
+    buffer = create_shared_buffer(domain, page_refs, num_pages,
+                                  gntshr);
+    if (buffer == NULL) {
+        fprintf(stderr,"Buffer allocation failed\n");
+        goto out;
+    }
+
+    /* Created the buffer and got page_ref. Share the page_ref with domain. */
+    if (!write_page_ref(xs, page_refs, num_pages, path)) {
+        fprintf(stderr,"Writing page ref failed\n");
+        goto out;
+    }
+
+    /* Write the status "page_ref". */
+    if (!write_status(xs, "page_ref", receiver_status_path)) {
+        fprintf(stderr,"Writing status DONE failed\n");
+        goto out;
+    }
+
+    /* Wait for done. This means other domain done copying the dtb to buffer. */
+    if (!wait_for_status(xs, fd, sender_status_path, "done")) {
+        fprintf(stderr, "dom0 status not done\n");
+        goto out;
+    }
+
+    if ((fptr = fopen("overlay.dtbo","wb")) == NULL) {
+        fprintf(stderr,"Error! opening file");
+        goto out;
+    }
+
+    printf("Writing to file overlay.dtbo.\n");
+
+    fwrite(buffer, dtbo_size, 1, fptr);
+
+    printf("Done writing to file overlay.dtbo \n");
+
+out:
+    if (fptr)
+        fclose(fptr);
+
+    if (page_refs)
+        free(page_refs);
+
+    if (xs) {
+        close(fd);
+
+        xs_unwatch(xs, path, "overlay_watch");
+
+        xs_close(xs);
+    }
+
+    if (buffer)
+        xengntshr_unshare(gntshr, buffer, num_pages);
+
+    if (gntshr)
+         xengntshr_close(gntshr);
+
+    return 0;
+}