]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
PR #610.0: Introduce network support for Firecracker
authorMarco Schlumpp <marco@unikraft.io>
Thu, 9 Feb 2023 16:14:40 +0000 (17:14 +0100)
committerMichalis Pappas <michalis@unikraft.io>
Tue, 22 Aug 2023 09:04:44 +0000 (11:04 +0200)
16 files changed:
lib/Makefile.uk
lib/ukboot/boot.c
lib/ukmmio/Config.uk [new file with mode: 0644]
lib/ukmmio/Makefile.uk [new file with mode: 0644]
lib/ukmmio/exportsyms.uk [new file with mode: 0644]
lib/ukmmio/include/uk/mmio.h [new file with mode: 0644]
lib/ukmmio/mmio.c [new file with mode: 0644]
plat/common/include/x86/cpu.h
plat/common/platform_bus.c
plat/drivers/include/virtio/virtio_bus.h
plat/drivers/include/virtio/virtio_config.h
plat/drivers/virtio/virtio_bus.c
plat/drivers/virtio/virtio_mmio.c
plat/drivers/virtio/virtio_net.c
plat/kvm/Config.uk
plat/kvm/Makefile.uk

index 625002c653f20fe3fbd025194c9a4d8a3a76e7c7..d60e38fe3f4565d6b9c0bcf8c6af0503da5cd2d9 100644 (file)
@@ -39,6 +39,7 @@ $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uklibid))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uklibparam))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uklock))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukmmap))
+$(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukmmio))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/ukmpi))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uknetdev))
 $(eval $(call _import_lib,$(CONFIG_UK_BASE)/lib/uknofault))
index 836d0456fbef8621c77c4fe8b56e0bfbe999e205..fb39e01cf76a5f4e17bdeb93ca467e68d52b9f14 100644 (file)
@@ -36,6 +36,7 @@
 #include <uk/config.h>
 
 #include <stddef.h>
+#include <string.h>
 #include <stdio.h>
 #include <errno.h>
 
@@ -69,6 +70,9 @@
 #if CONFIG_LIBUKBOOT_INITSCHEDCOOP
 #include <uk/schedcoop.h>
 #endif /* CONFIG_LIBUKBOOT_INITSCHEDCOOP */
+#if CONFIG_LIBUKMMIO
+#include <uk/mmio.h>
+#endif
 #include <uk/arch/lcpu.h>
 #include <uk/plat/bootstrap.h>
 #include <uk/plat/memory.h>
@@ -320,6 +324,15 @@ void ukplat_entry(int argc, char *argv[])
        uk_pr_info("Initialize platform time...\n");
        ukplat_time_init();
 
+#if CONFIG_LIBUKMMIO
+       uk_pr_info("Searching for MMIO devices\n");
+       for (int i = 1; i < argc; i++) {
+               if (!strncmp(argv[i], "virtio_mmio.device=", 19)) {
+                       uk_mmio_add_dev(argv[i]);
+               }
+       }
+#endif
+
 #if !CONFIG_LIBUKBOOT_NOSCHED
        uk_pr_info("Initialize scheduling...\n");
 #if CONFIG_LIBUKBOOT_INITSCHEDCOOP
diff --git a/lib/ukmmio/Config.uk b/lib/ukmmio/Config.uk
new file mode 100644 (file)
index 0000000..6a765f1
--- /dev/null
@@ -0,0 +1,5 @@
+config LIBUKMMIO
+       bool "ukmmio: mmio support"
+       default n
+       select LIBNOLIBC if !HAVE_LIBC
+       select LIBUKDEBUG
diff --git a/lib/ukmmio/Makefile.uk b/lib/ukmmio/Makefile.uk
new file mode 100644 (file)
index 0000000..e07337a
--- /dev/null
@@ -0,0 +1,10 @@
+$(eval $(call addlib_s,libukmmio,$(CONFIG_LIBUKMMIO)))
+
+# Register to uklibparam, sets "virtio_mmio" as parameter prefix (virtio_mmio.*)
+# $(eval $(call addlib_paramprefix,libukmmio,virtio_mmio))
+
+CINCLUDES-y += -I$(LIBUKMMIO_BASE)/include
+
+LIBUKMMIO_CFLAGS-$(call gcc_version_ge,8,0) += -Wno-cast-function-type
+
+LIBUKMMIO_SRCS-y += $(LIBUKMMIO_BASE)/mmio.c
diff --git a/lib/ukmmio/exportsyms.uk b/lib/ukmmio/exportsyms.uk
new file mode 100644 (file)
index 0000000..849a279
--- /dev/null
@@ -0,0 +1,3 @@
+uk_mmio_dev_count
+uk_mmio_dev_get
+uk_mmio_add_dev
diff --git a/lib/ukmmio/include/uk/mmio.h b/lib/ukmmio/include/uk/mmio.h
new file mode 100644 (file)
index 0000000..47810ae
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __UK_MMIODEV__
+#define __UK_MMIODEV__
+
+#include <sys/types.h>
+#include <uk/list.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct uk_mmio_device {
+       unsigned int id;
+       UK_TAILQ_ENTRY(struct uk_mmio_device) _list;
+
+       __u64 size;
+       __u64 base_addr;
+       unsigned long irq;
+       unsigned long dev_id;
+};
+
+/* List of MMIO devices */
+UK_TAILQ_HEAD(uk_mmio_device_list, struct uk_mmio_device);
+
+/**
+ * Get number of mmio devices.
+ *
+ * @return
+ *     - int: total number of mmio devices
+ */
+unsigned int uk_mmio_dev_count(void);
+
+/**
+ * Get a reference to a Unikraft MMIO Device, based on its ID.
+ *
+ * @param id
+ *     The identifier of the Unikraft MMIO device.
+ * @return
+ *     - NULL: device not found in list
+ *     - (struct uk_mmio_device *): reference to an Unikraft MMIO Device
+ */
+struct uk_mmio_device * uk_mmio_dev_get(unsigned int id);
+
+/**
+ * Add a Unikraft MMIO device
+ *
+ * @param device
+ *     Cmdline argument represnting a virtio_mmio device.
+ * @return
+ *     - 0: succesfully registered the device
+ *     - != 0: error on registering the device
+ */
+int uk_mmio_add_dev(char *device);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UK_MMIODEV__ */
diff --git a/lib/ukmmio/mmio.c b/lib/ukmmio/mmio.c
new file mode 100644 (file)
index 0000000..39c0ae3
--- /dev/null
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uk/alloc.h>
+#include <uk/mmio.h>
+
+#define MAX_DEV_STR 255
+const char virtio_mmio_identifier[] = "virtio_mmio.device=";
+
+struct uk_alloc *a;
+struct uk_mmio_device_list uk_mmio_device_list =
+UK_TAILQ_HEAD_INITIALIZER(uk_mmio_device_list);
+int uk_mmio_device_count = 0;
+
+unsigned int uk_mmio_dev_count(void)
+{
+       return (unsigned int) uk_mmio_device_count;
+}
+
+struct uk_mmio_device * uk_mmio_dev_get(unsigned int id)
+{
+       struct uk_mmio_device *dev;
+
+       UK_TAILQ_FOREACH(dev, &uk_mmio_device_list, _list) {
+               if (dev->id == id)
+                       return dev;
+       }
+
+       return NULL;
+}
+
+__u64 get_token_until(char *str, char c, int base, char **pEnd)
+{
+       __u64 multiplier = 1;
+       char *p;
+
+       for (p = str; *p && *p != c; p++) {
+               if (*p == 'K') {
+                       multiplier = 1024;
+                       *p = ' ';
+               }
+       }
+       if (*p) {
+               *p = ' ';
+       }
+
+       return strtol(str, pEnd, base) * multiplier;
+}
+
+int uk_mmio_add_dev(char *device)
+{
+       __u64 size, base_addr;
+       unsigned long irq, plat_dev_id = 0;
+       char devStr[MAX_DEV_STR];
+       char *pEnd;
+       struct uk_mmio_device *dev;
+
+       if (!(a = uk_alloc_get_default())) {
+               uk_pr_err("No allocator\n");
+               return -1;
+       }
+
+       if (strncmp(device, virtio_mmio_identifier, sizeof(virtio_mmio_identifier) - 1)) {
+               uk_pr_err("Invalid mmio device cmdline argument\n");
+               return -1;
+       }
+
+       strcpy(devStr, device + sizeof(virtio_mmio_identifier) - 1);
+       
+       size = get_token_until(devStr, '@', 0, &pEnd);
+       if (!size) {
+               uk_pr_err("Couldn't parse mmio device size\n");
+               return -1;
+       }
+
+       base_addr = get_token_until(pEnd, ':', 0, &pEnd);
+       if (!base_addr) {
+               uk_pr_err("Couldn't parse mmio device base addr\n");
+               return -1;
+       }
+
+       irq = get_token_until(pEnd, ':', 10, &pEnd);
+       if (!irq) {
+               uk_pr_err("Couldn't parse mmio device base irq\n");
+               return -1;
+       }
+
+       if (*pEnd) {
+               plat_dev_id = get_token_until(pEnd, 0, 10, NULL);
+       }
+
+       dev = uk_calloc(a, 1, sizeof(*dev));
+       if (!dev) {
+               return -1;
+       }
+
+       dev->id = uk_mmio_device_count++;
+       dev->base_addr = base_addr;
+       dev->size = size;
+       dev->irq = irq;
+       dev->dev_id = plat_dev_id;
+       UK_TAILQ_INSERT_TAIL(&uk_mmio_device_list, dev, _list);
+
+       uk_pr_info("New mmio device at %#lx of size %#lx and irq %lu\n", base_addr, size, irq);
+       return 0;
+}
index 535c9043cd628bcc05df161305bc3897a47a7e0b..bdf4fc901bc4a7e4a705612c2afc275fc7f6e1e6 100644 (file)
@@ -97,6 +97,53 @@ static inline __u64 rdtsc(void)
        return (h << 32) | l;
 }
 
+/* accessing devices via memory */
+static inline __u8 readb(__u8 *addr)
+{
+       __u8 v;
+
+       __asm__ __volatile__("movb %1, %0" : "=q"(v) : "m"(*addr));
+       return v;
+}
+
+static inline __u16 readw(__u16 *addr)
+{
+       __u16 v;
+
+       __asm__ __volatile__("movw %1, %0" : "=r"(v) : "m"(*addr));
+       return v;
+}
+
+static inline __u32 readl(__u32 *addr)
+{
+       __u32 v;
+
+       __asm__ __volatile__("movl %1, %0" : "=r"(v) : "m"(*addr));
+       return v;
+}
+
+static inline __u64 readq(__u64 *addr)
+{
+       __u64 v;
+
+       __asm__ __volatile__("movq %1, %0" : "=r"(v) : "m"(*addr));
+       return v;
+}
+
+static inline void writeb(__u8 *addr, __u8 v)
+{
+       __asm__ __volatile__("movb %0, %1" : : "q"(v), "m"(*addr));
+}
+
+static inline void writew(__u16 *addr, __u16 v)
+{
+       __asm__ __volatile__("movw %0, %1" : : "r"(v), "m"(*addr));
+}
+
+static inline void writel(__u32 *addr, __u32 v)
+{
+       __asm__ __volatile__("movl %0, %1" : : "r"(v), "m"(*addr));
+}
 
 /* accessing devices via port space */
 static inline __u8 inb(__u16 port)
index c34a32931b38313edb732fce019219bf8424dc86..5753230b449d1ffb8c40f07ee6b35eed6aacd1b0 100644 (file)
 #include <uk/plat/memory.h>
 #include <uk/plat/common/cpu.h>
 #include <platform_bus.h>
+#ifdef CONFIG_ARCH_ARM_64
 #include <libfdt.h>
+#endif
+#ifdef CONFIG_ARCH_ARM_64
 #include <gic/gic-v2.h>
 #include <ofw/fdt.h>
+#endif
 #include <uk/plat/common/bootinfo.h>
 
 static void *dtb;
@@ -53,7 +57,9 @@ static struct pf_bus_handler pfh;
 
 static const char *pf_device_compatible_list[] = {
        "virtio,mmio",
+#ifdef CONFIG_ARCH_ARM_64
        "pci-host-ecam-generic",
+#endif
        NULL
 };
 
@@ -145,12 +151,14 @@ static int pf_probe(void)
 
        /* Search all the platform bus devices provided by fdt */
        do {
+               #ifdef CONFIG_ARCH_ARM_64
                fdt_pf = fdt_node_offset_idx_by_compatible_list(dtb,
                                                fdt_pf, pf_device_compatible_list, &idx);
                if (fdt_pf < 0) {
                        uk_pr_info("End of searching platform devices\n");
                        break;
                }
+               #endif
 
                /* Alloc dev */
                dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev));
@@ -159,7 +167,9 @@ static int pf_probe(void)
                        return -ENOMEM;
                }
 
+               #ifdef CONFIG_ARCH_ARM_64
                dev->fdt_offset = fdt_pf;
+               #endif
 
                /* Find drv with compatible-id match table */
                drv = pf_find_driver(pf_device_compatible_list[idx]);
@@ -180,6 +190,7 @@ static int pf_probe(void)
                ret = pf_driver_add_device(drv, dev);
                if (ret < 0)
                        uk_free(pfh.a, dev);
+               return 0;
        } while (1);
 
        return ret;
index 9187fd072c04bd940cac290fc5af28faed2a44a5..5530eb123e6f5b8748eb0a492e1e81a8a294fc3f 100644 (file)
@@ -347,7 +347,7 @@ static inline void virtio_vqueue_release(struct virtio_dev *vdev,
 
 static inline void virtio_dev_drv_up(struct virtio_dev *vdev)
 {
-       virtio_dev_status_update(vdev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
+       virtio_dev_status_update(vdev, (VIRTIO_CONFIG_STATUS_ACK | VIRTIO_CONFIG_STATUS_DRIVER | VIRTIO_CONFIG_STATUS_FEATURES_OK | VIRTIO_CONFIG_STATUS_DRIVER_OK));
 }
 
 #define VIRTIO_BUS_REGISTER_DRIVER(b)  \
index f38ab11c847d4f58e5ced40af08ba81c6aaef251..a41f97be462f8089cde0b29765fd424edce07b4f 100644 (file)
@@ -46,6 +46,7 @@ extern "C" {
 #define VIRTIO_CONFIG_STATUS_ACK           0x1  /* recognize device as virtio */
 #define VIRTIO_CONFIG_STATUS_DRIVER        0x2  /* driver for the device found*/
 #define VIRTIO_CONFIG_STATUS_DRIVER_OK     0x4  /* initialization is complete */
+#define VIRTIO_CONFIG_STATUS_FEATURES_OK     0x8
 #define VIRTIO_CONFIG_STATUS_NEEDS_RESET   0x40 /* device needs reset */
 #define VIRTIO_CONFIG_STATUS_FAIL          0x80 /* device something's wrong*/
 
@@ -110,6 +111,61 @@ static inline void _virtio_cread_bytes(const void *addr, const __u8 offset,
                }
        }
 }
+
+static inline void _virtio_mem_cwrite_bytes(const void *addr, const __u8 offset,
+                                       const void *buf, int len, int type_len)
+{
+       int i = 0;
+       __u64 io_addr;
+       int count;
+
+       count  = len / type_len;
+       for (i = 0; i < count; i++) {
+               io_addr = ((unsigned long)addr) + offset + (i * type_len);
+               switch (type_len) {
+               case 1:
+                       writeb((__u8 *) io_addr, ((__u8 *)buf)[i * type_len]);
+                       break;
+               case 2:
+                       writew((__u16 *) io_addr, ((__u16 *)buf)[i * type_len]);
+                       break;
+               case 4:
+                       writel((__u32 *) io_addr, ((__u32 *)buf)[i * type_len]);
+                       break;
+               default:
+                       UK_CRASH("Unsupported virtio write operation\n");
+               }
+       }
+}
+
+static inline void _virtio_mem_cread_bytes(const void *addr, const __u8 offset,
+                                      void *buf, int len, int type_len)
+{
+       int i = 0;
+       __u64 io_addr;
+       int count;
+
+       count = len / type_len;
+       for (i = 0; i < count; i++) {
+               io_addr = ((unsigned long)addr) + offset + (i * type_len);
+               switch (type_len) {
+               case 1:
+                       ((__u8 *)buf)[i * type_len] = readb((__u8 *) io_addr);
+                       break;
+               case 2:
+                       ((__u16 *)buf)[i * type_len] = readw((__u16 *) io_addr);
+                       break;
+               case 4:
+                       ((__u32 *)buf)[i * type_len] = readl((__u32 *) io_addr);
+                       break;
+               case 8:
+                       ((__u64  *)buf)[i * type_len] = readq((__u64  *) io_addr);
+                       break;
+               default:
+                       UK_CRASH("Unsupported virtio read operation\n");
+               }
+       }
+}
 #else  /* __X86_64__ */
 
 /* IO barriers */
@@ -170,6 +226,18 @@ static inline void _virtio_cread_bytes(const void *addr, const __u8 offset,
        }
 }
 
+static inline void _virtio_mem_cwrite_bytes(const void *addr, const __u8 offset,
+                                       const void *buf, int len, int type_len)
+{
+       _virtio_cwrite_bytes(addr, offset, buf, len, type_len);
+}
+
+static inline void _virtio_mem_cread_bytes(const void *addr, const __u8 offset,
+                                      void *buf, int len, int type_len)
+{
+       _virtio_cread_bytes(addr, offset, buf, len, type_len);
+}
+
 #endif /* __X86_64__ */
 
 /**
@@ -311,6 +379,145 @@ static inline void virtio_cwrite32(const void *addr, const __u8 offset,
        _virtio_cwrite_bytes(addr, offset, &data, sizeof(data), sizeof(data));
 }
 
+/**
+ * Read the virtio device configuration of specified length.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @param buf
+ *    The destination buffer to which the value has to be copied.
+ * @param len
+ *    The length of the destination buffer.
+ */
+static inline int virtio_mem_cread_bytes_many(const void *addr, const __u8 offset,
+                                         __u8 *buf, __u32 len)
+{
+       __u8 old_buf[len];
+       int check = -1;
+       int cnt = 0;
+       __u32 i = 0;
+
+       do {
+               check = len;
+               _virtio_mem_cread_bytes(addr, offset, &old_buf[0], len, 1);
+               _virtio_mem_cread_bytes(addr, offset, buf, len, 1);
+
+               for (i = 0; i < len; i++) {
+                       if (unlikely(buf[i] != old_buf[i])) {
+                               check = -1; /* Need to retry configuration */
+                               break;
+                       }
+               }
+               cnt++;
+       } while (check == -1 && cnt < MAX_TRY_COUNT);
+
+       return check;
+}
+
+/**
+ * Read the single byte configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @return __u8
+ *   Returns the value configuration register.
+ */
+static inline __u8 virtio_mem_cread8(const void *addr, const __u8 offset)
+{
+       __u8 buf = 0;
+
+       _virtio_mem_cread_bytes(addr, offset, &buf, sizeof(buf), sizeof(buf));
+       return buf;
+}
+
+/**
+ * Read the single word configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @return __u16
+ *   Returns the value configuration register.
+ */
+static inline __u16 virtio_mem_cread16(const void *addr, const __u8 offset)
+{
+       __u16 buf = 0;
+
+       _virtio_mem_cread_bytes(addr, offset, &buf, sizeof(buf), sizeof(buf));
+       return buf;
+}
+
+/**
+ * Read the single long word configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @return __u32
+ *   Returns the value configuration register.
+ */
+static inline __u32 virtio_mem_cread32(const void *addr, const __u8 offset)
+{
+       __u32 buf = 0;
+
+       _virtio_mem_cread_bytes(addr, offset, &buf, sizeof(buf), sizeof(buf));
+       return buf;
+}
+
+/**
+ * Write the configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @param data
+ *   The value to write to the configuration.
+ */
+static inline void virtio_mem_cwrite8(const void *addr, const __u8 offset,
+                                 const __u8 data)
+{
+       _virtio_mem_cwrite_bytes(addr, offset, &data, sizeof(data), sizeof(data));
+}
+
+/**
+ * Write the configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @param data
+ *   The value to write to the configuration.
+ */
+static inline void virtio_mem_cwrite16(const void *addr, const __u8 offset,
+                                  const __u16 data)
+{
+       _virtio_mem_cwrite_bytes(addr, offset, &data, sizeof(data), sizeof(data));
+}
+
+/**
+ * Write the configuration.
+ *
+ * @param addr
+ *   The base address of the device.
+ * @param offset
+ *   The offset with the device address space.
+ * @param data
+ *   The value to write to the configuration.
+ */
+static inline void virtio_mem_cwrite32(const void *addr, const __u8 offset,
+                                  const __u32 data)
+{
+       _virtio_mem_cwrite_bytes(addr, offset, &data, sizeof(data), sizeof(data));
+}
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus __ */
index f41c75435eea4b6b16241f2bbfcfde4c885a3388..f9aa0ef41690f1b82e438307b93c9ea623a31be4 100644 (file)
@@ -117,7 +117,7 @@ static int virtio_device_reinit(struct virtio_dev *vdev)
        }
 
        /* Acknowledge the virtio driver */
-       rc = virtio_dev_status_update(vdev, VIRTIO_CONFIG_STATUS_DRIVER);
+       rc = virtio_dev_status_update(vdev, (VIRTIO_CONFIG_STATUS_ACK | VIRTIO_CONFIG_STATUS_DRIVER));
        if (rc != 0) {
                uk_pr_err("Failed to acknowledge the virtio driver %p: %d\n",
                          vdev, rc);
index 969605be23a273d529f83d0028593e996d518c7c..e0f72573ac0ac6960c1e185a52a3c1d3f144ebb2 100644 (file)
 #include <uk/plat/irq.h>
 #include <uk/bus.h>
 #include <uk/bitops.h>
+#ifdef CONFIG_ARCH_ARM_64
 #include <libfdt.h>
 #include <ofw/fdt.h>
+#endif
 #include <uk/plat/common/bootinfo.h>
 
 #include <platform_bus.h>
 #include <virtio/virtio_bus.h>
 #include <virtio/virtqueue.h>
 #include <virtio/virtio_mmio.h>
+#ifdef CONFIG_ARCH_ARM_64
 #include <gic/gic-v2.h>
+#endif
+
+#if CONFIG_LIBUKMMIO
+#include <uk/mmio.h>
+#endif
 
 /*
  * The alignment to use between consumer and producer parts of vring.
@@ -90,12 +98,12 @@ static __u64 vm_get_features(struct virtio_dev *vdev)
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
        __u64 features = 0;
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 1);
-       features = virtio_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 1);
+       features = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
        features <<= 32;
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 0);
-       features |= virtio_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES_SEL, 0);
+       features |= virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_FEATURES);
 
        return features;
 }
@@ -115,12 +123,12 @@ static void vm_set_features(struct virtio_dev *vdev,
                return;
        }
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 1);
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 1);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
                                                (__u32)(vdev->features >> 32));
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 0);
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES_SEL, 0);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_DRIVER_FEATURES,
                                                (__u32)vdev->features);
 }
 
@@ -133,32 +141,32 @@ static int vm_get(struct virtio_dev *vdev, __u16 offset,
        __u16 w;
        __u32 l;
 
-       if (vm_dev->version == 1) {
+       if (vm_dev->version <= 2) {
                __u8 *ptr = buf;
-               unsigned int i;
+               __u8 i;
 
                for (i = 0; i < len; i++)
-                       ptr[i] = virtio_cread8(base, offset + i);
+                       ptr[i] = virtio_mem_cread8(base, offset + i);
                return len;
        }
 
        switch (len) {
        case 1:
-               b = virtio_cread8(base, offset);
+               b = virtio_mem_cread8(base, offset);
                memcpy(buf, &b, sizeof(b));
                break;
        case 2:
-               w = (virtio_cread16(base, offset));
+               w = (virtio_mem_cread16(base, offset));
                memcpy(buf, &w, sizeof(w));
                break;
        case 4:
-               l = (virtio_cread32(base, offset));
+               l = (virtio_mem_cread32(base, offset));
                memcpy(buf, &l, sizeof(l));
                break;
        case 8:
-               l = (virtio_cread32(base, offset));
+               l = (virtio_mem_cread32(base, offset));
                memcpy(buf, &l, sizeof(l));
-               l = (virtio_cread32(base, offset + sizeof(l)));
+               l = (virtio_mem_cread32(base, offset + sizeof(l)));
                memcpy(buf + sizeof(l), &l, sizeof(l));
                break;
        default:
@@ -183,28 +191,28 @@ static int vm_set(struct virtio_dev *vdev, __u16 offset,
                __u32 i;
 
                for (i = 0; i < len; i++)
-                       virtio_cwrite8(base, offset + i, ptr[i]);
+                       virtio_mem_cwrite8(base, offset + i, ptr[i]);
                return 0;
        }
 
        switch (len) {
        case 1:
                memcpy(&b, buf, sizeof(b));
-               virtio_cwrite8(base, offset, b);
+               virtio_mem_cwrite8(base, offset, b);
                break;
        case 2:
                memcpy(&w, buf, sizeof(w));
-               virtio_cwrite16(base, offset, w);
+               virtio_mem_cwrite16(base, offset, w);
                break;
        case 4:
                memcpy(&l, buf, sizeof(l));
-               virtio_cwrite32(base, offset, l);
+               virtio_mem_cwrite32(base, offset, l);
                break;
        case 8:
                memcpy(&l, buf, sizeof(l));
-               virtio_cwrite32(base, offset, l);
+               virtio_mem_cwrite32(base, offset, l);
                memcpy(&l, buf + sizeof(l), sizeof(l));
-               virtio_cwrite32(base, offset + sizeof(l), l);
+               virtio_mem_cwrite32(base, offset + sizeof(l), l);
                break;
        default:
                _virtio_cwrite_bytes(base, offset, buf, len, 1);
@@ -218,7 +226,7 @@ static __u8 vm_get_status(struct virtio_dev *vdev)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 
-       return virtio_cread32(vm_dev->base, VIRTIO_MMIO_STATUS) & 0xff;
+       return virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_STATUS) & 0xff;
 }
 
 static void vm_set_status(struct virtio_dev *vdev, __u8 status)
@@ -228,7 +236,7 @@ static void vm_set_status(struct virtio_dev *vdev, __u8 status)
        /* We should never be setting status to 0. */
        UK_BUGON(status == 0);
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, status);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, status);
 }
 
 static void vm_reset(struct virtio_dev *vdev)
@@ -236,7 +244,7 @@ static void vm_reset(struct virtio_dev *vdev)
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 
        /* 0 status means a reset. */
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, 0);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_STATUS, 0);
 }
 
 /* Transport interface */
@@ -250,7 +258,8 @@ static int vm_notify(struct virtio_dev *vdev, __u16 queue_id)
         * We write the queue's selector into the notification register to
         * signal the other end
         */
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_NOTIFY, queue_id);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_NOTIFY, queue_id);
+
        return 1;
 }
 
@@ -264,8 +273,8 @@ static int vm_interrupt(void *opaque)
        struct virtqueue *vq;
 
        /* Read and acknowledge interrupts */
-       status = virtio_cread32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_STATUS);
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_ACK, status);
+       status = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_STATUS);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_INTERRUPT_ACK, status);
 
        if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) {
                uk_pr_warn("Unsupported config change interrupt received on virtio-mmio device %p\n",
@@ -306,33 +315,33 @@ static struct virtqueue *vm_setup_vq(struct virtio_dev *vdev,
        }
 
        /* Select the queue we're interested in */
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_SEL, queue_id);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_SEL, queue_id);
 
        /* Activate the queue */
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_NUM, num_desc);
+       virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_NUM, num_desc);
        if (vm_dev->version == 1) {
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_ALIGN, __PAGE_SIZE);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_PFN,
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_ALIGN, __PAGE_SIZE);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_PFN,
                                        virtqueue_physaddr(vq) >> __PAGE_SHIFT);
        } else {
                __u64 addr;
 
                addr = virtqueue_physaddr(vq);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_DESC_LOW, (__u32)addr);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_DESC_HIGH,
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_DESC_LOW, (__u32)addr);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_DESC_HIGH,
                                                                (__u32)(addr >> 32));
 
                addr = virtqueue_get_avail_addr(vq);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_AVAIL_LOW, (__u32)addr);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_AVAIL_HIGH,
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_AVAIL_LOW, (__u32)addr);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_AVAIL_HIGH,
                                                                (__u32)(addr >> 32));
 
                addr =  virtqueue_get_used_addr(vq);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_USED_LOW, (__u32)addr);
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_USED_HIGH,
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_USED_LOW, (__u32)addr);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_USED_HIGH,
                                                                (__u32)(addr >> 32));
 
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_READY, 1);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_READY, 1);
        }
 
        flags = ukplat_lcpu_save_irqf();
@@ -349,24 +358,24 @@ static int vm_find_vqs(struct virtio_dev *vdev, __u16 num_vqs, __u16 *qdesc_size
        unsigned int irq = vm_dev->pfdev->irq;
        int i, err;
        int vq_cnt = 0;
-
+       
        err = ukplat_irq_register(irq, vm_interrupt, vm_dev);
        if (err)
                return err;
 
        for (i = 0; i < num_vqs; ++i) {
                /* Select the queue we're interested in */
-               virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_SEL, i);
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_QUEUE_SEL, i);
 
                /* Queue shouldn't already be set up. */
-               if (virtio_cread32(vm_dev->base, (vm_dev->version == 1 ?
+               if (virtio_mem_cread32(vm_dev->base, (vm_dev->version == 1 ?
                                VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
                        uk_pr_err("vm_find_vqs error mmio queue not ready\n");
                        err = -ENOENT;
                        goto error_exit;
                }
 
-               qdesc_size[i] = virtio_cread32(vm_dev->base, VIRTIO_MMIO_QUEUE_NUM_MAX);
+               qdesc_size[i] = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_QUEUE_NUM_MAX);
                if (qdesc_size[i] == 0) {
                        err = -ENOENT;
                        goto error_exit;
@@ -395,13 +404,19 @@ static struct virtio_config_ops virtio_mmio_config_ops = {
 
 static int virtio_mmio_probe(struct pf_device *pfdev)
 {
+       #ifdef CONFIG_LIBUKMMIO
+       #ifdef CONFIG_ARCH_ARM_64
        const fdt32_t *prop;
        int type, hwirq, prop_len;
        int fdt_vm = pfdev->fdt_offset;
        __u64 reg_base;
        __u64 reg_size;
+       #else
+       struct uk_mmio_device *mmio_dev;
+       #endif
        void *dtb;
 
+       #ifdef CONFIG_ARCH_ARM_64
        dtb = (void *)ukplat_bootinfo_get()->dtb;
        if (fdt_vm == -FDT_ERR_NOTFOUND) {
                uk_pr_info("device not found in fdt\n");
@@ -428,12 +443,28 @@ static int virtio_mmio_probe(struct pf_device *pfdev)
 
        pfdev->base = reg_base;
        pfdev->irq = gic_irq_translate(type, hwirq);
+       #else
+
+       mmio_dev = uk_mmio_dev_get(0);
+
+       if (!mmio_dev) {
+               uk_pr_err("mmio device not found\n");
+               goto error_exit;
+       }
+       pfdev->base = mmio_dev->base_addr;
+       pfdev->irq = mmio_dev->irq;
+       
        uk_pr_info("virtio mmio probe base(0x%lx) irq(%ld)\n",
                                pfdev->base, pfdev->irq);
+       #endif
+       #endif
+       
        return 0;
-
+       
+#ifdef CONFIG_LIBUKMMIO
 error_exit:
        return -EFAULT;
+#endif
 }
 
 static int virtio_mmio_add_dev(struct pf_device *pfdev)
@@ -462,7 +493,7 @@ static int virtio_mmio_add_dev(struct pf_device *pfdev)
                goto free_vmdev;
        }
 
-       magic = virtio_cread32(vm_dev->base, VIRTIO_MMIO_MAGIC_VALUE);
+       magic = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_MAGIC_VALUE);
        if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
                uk_pr_err("Wrong magic value 0x%x!\n", magic);
                rc = -ENODEV;
@@ -470,14 +501,14 @@ static int virtio_mmio_add_dev(struct pf_device *pfdev)
        }
 
        /* Check device version */
-       vm_dev->version = virtio_cread32(vm_dev->base, VIRTIO_MMIO_VERSION);
+       vm_dev->version = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_VERSION);
        if (vm_dev->version < 1 || vm_dev->version > 2) {
                uk_pr_err("Version %ld not supported!\n", vm_dev->version);
                rc = -ENXIO;
                goto free_vmdev;
        }
 
-       vm_dev->vdev.id.virtio_device_id = virtio_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_ID);
+       vm_dev->vdev.id.virtio_device_id = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_DEVICE_ID);
        if (vm_dev->vdev.id.virtio_device_id == 0) {
                /*
                 * virtio-mmio device with an ID 0 is a (dummy) placeholder
@@ -488,9 +519,11 @@ static int virtio_mmio_add_dev(struct pf_device *pfdev)
                rc = -ENODEV;
                goto free_vmdev;
        }
-       vm_dev->id.vendor = virtio_cread32(vm_dev->base, VIRTIO_MMIO_VENDOR_ID);
+       vm_dev->id.vendor = virtio_mem_cread32(vm_dev->base, VIRTIO_MMIO_VENDOR_ID);
 
-       virtio_cwrite32(vm_dev->base, VIRTIO_MMIO_GUEST_PAGE_SIZE, __PAGE_SIZE);
+       if (vm_dev->version <= 1) {
+               virtio_mem_cwrite32(vm_dev->base, VIRTIO_MMIO_GUEST_PAGE_SIZE, __PAGE_SIZE);
+       }
 
        rc = virtio_bus_register_device(&vm_dev->vdev);
        if (rc != 0) {
index 3bc3f1c301f5817beed11ee69d4bbad4f25fe25d..01f4fbf59696b5d1d04bd41c7bd0d87f11b7c7d7 100644 (file)
@@ -40,6 +40,7 @@
 #include <virtio/virtio_bus.h>
 #include <virtio/virtqueue.h>
 #include <virtio/virtio_net.h>
+#include <uk/hexdump.h>
 
 /**
  * VIRTIO_PKT_BUFFER_LEN = VIRTIO_NET_HDR + ETH_HDR + ETH_PKT_PAYLOAD_LEN
@@ -158,6 +159,8 @@ struct virtio_net_device {
        __u8 state;
        /* RX promiscuous mode. */
        __u8 promisc : 1;
+       /* VirtIO modern network standard. */
+       __u8 modern;
 };
 
 /**
@@ -205,10 +208,12 @@ static int virtio_netdev_txq_info_get(struct uk_netdev *dev, __u16 queue_id,
 static int virtio_netdev_rxq_dequeue(struct uk_netdev_rx_queue *rxq,
                                     struct uk_netbuf **netbuf);
 static int virtio_netdev_rxq_enqueue(struct uk_netdev_rx_queue *rxq,
-                                    struct uk_netbuf *netbuf);
+                                    struct uk_netbuf *netbuf,
+                                        __u8 is_modern);
 static int virtio_netdev_recv_done(struct virtqueue *vq, void *priv);
 static int virtio_netdev_rx_fillup(struct uk_netdev_rx_queue *rxq,
-                                  __u16 num, int notify);
+                                  __u16 num, int notify,
+                                  __u8 is_modern);
 
 /**
  * Static global constants
@@ -264,7 +269,8 @@ static void virtio_netdev_xmit_free(struct uk_netdev_tx_queue *txq)
 
 static int virtio_netdev_rx_fillup(struct uk_netdev_rx_queue *rxq,
                                   __u16 nb_desc,
-                                  int notify)
+                                  int notify,
+                                  __u8 is_modern)
 {
        struct uk_netbuf *netbuf[RX_FILLUP_BATCHLEN];
        int rc = 0;
@@ -289,7 +295,7 @@ static int virtio_netdev_rx_fillup(struct uk_netdev_rx_queue *rxq,
                for (i = 0; i < cnt; i++) {
                        uk_pr_debug("Enqueue netbuf %"PRIu16"/%"PRIu16" (%p) to virtqueue %p...\n",
                                    i + 1, cnt, netbuf[i], rxq);
-                       rc = virtio_netdev_rxq_enqueue(rxq, netbuf[i]);
+                       rc = virtio_netdev_rxq_enqueue(rxq, netbuf[i], is_modern);
                        if (unlikely(rc < 0)) {
                                uk_pr_err("Failed to add a buffer to receive virtqueue %p: %d\n",
                                          rxq, rc);
@@ -331,7 +337,7 @@ static int virtio_netdev_xmit(struct uk_netdev *dev,
                              struct uk_netdev_tx_queue *queue,
                              struct uk_netbuf *pkt)
 {
-       struct virtio_net_device *vndev __unused;
+       struct virtio_net_device *vndev;
        struct virtio_net_hdr *vhdr;
        struct virtio_net_hdr_padded *padded_hdr;
        int16_t header_sz = sizeof(*padded_hdr);
@@ -357,7 +363,7 @@ static int virtio_netdev_xmit(struct uk_netdev *dev,
        /**
         * Use the preallocated header space for the virtio header.
         */
-       rc = uk_netbuf_header(pkt, header_sz);
+       rc = uk_netbuf_header(pkt, VIRTIO_HDR_LEN);
        if (unlikely(rc != 1)) {
                uk_pr_err("Failed to prepend virtio header\n");
                rc = -ENOSPC;
@@ -378,7 +384,7 @@ static int virtio_netdev_xmit(struct uk_netdev *dev,
         *       to `uk_sglist_append_netbuf()`. However, a netbuf
         *       chain can only once have set the PARTIAL_CSUM flag.
         */
-       memset(vhdr, 0, sizeof(*vhdr));
+       memset(vhdr, 0, VIRTIO_HDR_LEN);
        if (pkt->flags & UK_NETBUF_F_PARTIAL_CSUM) {
                vhdr->flags       |= VIRTIO_NET_HDR_F_NEEDS_CSUM;
                /* `csum_start` is without header size */
@@ -404,7 +410,8 @@ static int virtio_netdev_xmit(struct uk_netdev *dev,
         * 1 for the virtio header and the other for the actual network packet.
         */
        /* Appending the data to the list. */
-       rc = uk_sglist_append(&queue->sg, vhdr, sizeof(*vhdr));
+
+       rc = uk_sglist_append(&queue->sg, vhdr, vndev->modern ? VIRTIO_HDR_LEN : sizeof(struct virtio_net_hdr));
        if (unlikely(rc != 0)) {
                uk_pr_err("Failed to append to the sg list\n");
                goto err_remove_vhdr;
@@ -469,11 +476,11 @@ err_exit:
 }
 
 static int virtio_netdev_rxq_enqueue(struct uk_netdev_rx_queue *rxq,
-                                    struct uk_netbuf *netbuf)
+                                    struct uk_netbuf *netbuf,
+                                        __u8 is_modern)
 {
        int rc = 0;
        struct virtio_net_hdr_padded *rxhdr;
-       int16_t header_sz = sizeof(*rxhdr);
        __u8 *buf_start;
        size_t buf_len = 0;
        struct uk_sglist *sg;
@@ -492,7 +499,7 @@ static int virtio_netdev_rxq_enqueue(struct uk_netdev_rx_queue *rxq,
        /**
         * Retrieve the buffer header length.
         */
-       rc = uk_netbuf_header(netbuf, header_sz);
+       rc = uk_netbuf_header(netbuf, sizeof(*rxhdr));
        if (unlikely(rc != 1)) {
                uk_pr_err("Failed to allocate space to prepend virtio header\n");
                return -EINVAL;
@@ -503,7 +510,8 @@ static int virtio_netdev_rxq_enqueue(struct uk_netdev_rx_queue *rxq,
        uk_sglist_reset(sg);
 
        /* Appending the header buffer to the sglist */
-       uk_sglist_append(sg, rxhdr, sizeof(struct virtio_net_hdr));
+       // uk_sglist_append(sg, rxhdr, is_modern ? VIRTIO_HDR_LEN : sizeof(struct virtio_net_hdr));
+       uk_sglist_append(sg, rxhdr, is_modern ? VIRTIO_HDR_LEN : sizeof(struct virtio_net_hdr));
 
        /* Appending the data buffer to the sglist */
        uk_sglist_append(sg, buf_start, buf_len);
@@ -559,17 +567,18 @@ static int virtio_netdev_rxq_dequeue(struct uk_netdev_rx_queue *rxq,
         */
        buf->len = len + VTNET_RX_HEADER_PAD;
        rc = uk_netbuf_header(buf,
-                             -((int16_t)sizeof(struct virtio_net_hdr_padded)));
+                             -((uint16_t)sizeof(struct virtio_net_hdr_padded)));
        UK_ASSERT(rc == 1);
        *netbuf = buf;
 
        return ret;
 }
 
-static int virtio_netdev_recv(struct uk_netdev *dev __unused,
+static int virtio_netdev_recv(struct uk_netdev *dev,
                              struct uk_netdev_rx_queue *queue,
                              struct uk_netbuf **pkt)
 {
+       struct virtio_net_device *vndev;
        int status = 0x0;
        int rc = 0;
 
@@ -579,13 +588,14 @@ static int virtio_netdev_recv(struct uk_netdev *dev __unused,
        /* Queue interrupts have to be off when calling receive */
        UK_ASSERT(!(queue->intr_enabled & VTNET_INTR_EN));
 
+       vndev = to_virtionetdev(dev);
        rc = virtio_netdev_rxq_dequeue(queue, pkt);
        if (unlikely(rc < 0)) {
                uk_pr_err("Failed to dequeue the packet: %d\n", rc);
                goto err_exit;
        }
        status |= (*pkt) ? UK_NETDEV_STATUS_SUCCESS : 0x0;
-       status |= virtio_netdev_rx_fillup(queue, (queue->nb_desc - rc), 1);
+       status |= virtio_netdev_rx_fillup(queue, (queue->nb_desc - rc), 1, vndev->modern);
 
        /* Enable interrupt only when user had previously enabled it */
        if (queue->intr_enabled & VTNET_INTR_USR_EN_MASK) {
@@ -610,7 +620,8 @@ static int virtio_netdev_recv(struct uk_netdev *dev __unused,
                         */
                        status |= virtio_netdev_rx_fillup(queue,
                                                          (queue->nb_desc - rc),
-                                                         1);
+                                                         1,
+                                                         vndev->modern);
 
                        /* Need to enable the interrupt on the last packet */
                        rc = virtqueue_intr_enable(queue->vq);
@@ -666,7 +677,7 @@ static struct uk_netdev_rx_queue *virtio_netdev_rx_queue_setup(
        rxq->alloc_rxpkts_argp = conf->alloc_rxpkts_argp;
 
        /* Allocate receive buffers for this queue */
-       virtio_netdev_rx_fillup(rxq, rxq->nb_desc, 0);
+       virtio_netdev_rx_fillup(rxq, rxq->nb_desc, 0, vndev->modern);
 
 exit:
        return rxq;
@@ -909,11 +920,17 @@ static int virtio_netdev_feature_negotiate(struct uk_netdev *n)
        else
                VIRTIO_FEATURE_SET(drv_features, VIRTIO_NET_F_MTU);
 
+       if (VIRTIO_FEATURE_HAS(host_features, VIRTIO_NET_F_STATUS)) {
+               VIRTIO_FEATURE_SET(drv_features, VIRTIO_NET_F_STATUS);
+       }
+
        /**
         * Gratuitous ARP
         * NOTE: We tell that we will do gratuitous ARPs ourselves.
         */
-       VIRTIO_FEATURE_SET(drv_features, VIRTIO_NET_F_GUEST_ANNOUNCE);
+       if (VIRTIO_FEATURE_HAS(host_features, VIRTIO_NET_F_CTRL_VQ)) {
+               VIRTIO_FEATURE_SET(drv_features, VIRTIO_NET_F_GUEST_ANNOUNCE);
+       }
 
        /**
         * Partial checksumming
@@ -928,6 +945,12 @@ static int virtio_netdev_feature_negotiate(struct uk_netdev *n)
                VIRTIO_FEATURE_SET(drv_features, VIRTIO_NET_F_GUEST_CSUM);
        }
 
+       // VirtIO modern standard.
+       if (VIRTIO_FEATURE_HAS(host_features, VIRTIO_F_VERSION_1)) {
+               VIRTIO_FEATURE_SET(drv_features, VIRTIO_F_VERSION_1);
+               vndev->modern = 1;
+       }
+
        /**
         * Use index based event supression when it's available.
         * This allows a more fine-grained control when the hypervisor should
@@ -982,6 +1005,8 @@ static int virtio_netdev_feature_negotiate(struct uk_netdev *n)
                vndev->max_mtu = vndev->mtu = UK_ETH_PAYLOAD_MAXLEN;
        }
 
+       virtio_dev_status_update(vndev->vdev, (VIRTIO_CONFIG_STATUS_ACK | VIRTIO_CONFIG_STATUS_DRIVER | VIRTIO_CONFIG_STATUS_FEATURES_OK));
+
        return 0;
 
 err_negotiate_feature:
@@ -1233,6 +1258,7 @@ static int virtio_net_add_dev(struct virtio_dev *vdev)
        vndev->uid = rc;
        rc = 0;
        vndev->promisc = 0;
+       vndev->modern = 0;
 
        /**
         * TODO:
index 4adcb619338274192980e8754bac2c7943af01c1..2c57be22e92d1c484cb9a9d3041db4e69fdf2318 100644 (file)
@@ -213,7 +213,6 @@ config KVM_PCI
 config KVM_PF
        bool "Platform Bus Driver"
        default y
-       depends on (ARCH_ARM_64)
        select LIBUKBUS
        help
                Platform bus driver for probing and operating platform devices
@@ -239,6 +238,15 @@ config VIRTIO_PCI
        help
                Support virtio devices on PCI bus
 
+config VIRTIO_MMIO
+       bool "Virtio MMIO device support"
+       default n
+       depends on KVM_PF
+       select VIRTIO_BUS
+       select LIBUKMMIO if ARCH_X86_64
+       help
+               Support virtio devices on MMIO bus
+
 config VIRTIO_NET
        bool "Virtio Net device"
        default y if LIBUKNETDEV
index ff2bd70a65bb99c531abacab058f691ff5b3487f..9813bdff2472536e3042bc04329b59e120125604 100644 (file)
@@ -167,6 +167,10 @@ LIBKVMPF_CINCLUDES-$(CONFIG_ARCH_ARM_64)   += -I$(UK_PLAT_COMMON_BASE)/include
 LIBKVMPF_CINCLUDES-$(CONFIG_ARCH_ARM_64)   += -I$(LIBKVMPLAT_BASE)/include
 LIBKVMPF_CINCLUDES-$(CONFIG_ARCH_ARM_64)   += -I$(UK_PLAT_DRIVERS_BASE)/include
 LIBKVMPF_SRCS-$(CONFIG_KVM_PF) += $(UK_PLAT_COMMON_BASE)/platform_bus.c|common
+LIBKVMPF_ASINCLUDES-y  += -I$(UK_PLAT_COMMON_BASE)/include
+LIBKVMPF_CINCLUDES-y   += -I$(UK_PLAT_COMMON_BASE)/include
+LIBKVMPF_CINCLUDES-y   += -I$(LIBKVMPLAT_BASE)/include
+LIBKVMPF_CINCLUDES-y   += -I$(UK_PLAT_DRIVERS_BASE)/include
 
 ##
 ## Virtio library definitions
@@ -185,6 +189,8 @@ LIBKVMVIRTIO_SRCS-$(CONFIG_VIRTIO_PCI) +=\
                        $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_pci.c
 LIBKVMVIRTIO_SRCS-$(CONFIG_ARCH_ARM_64)        +=\
                        $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_mmio.c
+LIBKVMVIRTIO_SRCS-$(CONFIG_KVM_PF)     +=\
+                       $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_mmio.c
 ##
 ## Virtio Net library definition
 ##