]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
board: xen: introduce virtio-blk support
authorAndrii Chepurnyi <Andrii_Chepurnyi@epam.com>
Tue, 3 Oct 2023 08:58:28 +0000 (08:58 +0000)
committerTom Rini <trini@konsulko.com>
Wed, 11 Oct 2023 14:46:23 +0000 (10:46 -0400)
Added new xenguest_arm64_virtio_defconfig which
enables support for virtio-blk using various types
of transport like virtio-pci, vrtio-mmio. Currently
supported: up to 2 PCI host bridges and 10 MMIO devices.
Note: DT parsing code was partly taken from pci-uclass.c
Limitation: All memory regions should be
below 4GB address space.

Signed-off-by: Andrii Chepurnyi <andrii_chepurnyi@epam.com>
board/xen/xenguest_arm64/MAINTAINERS
board/xen/xenguest_arm64/xenguest_arm64.c
configs/xenguest_arm64_virtio_defconfig [new file with mode: 0644]
doc/board/xen/xenguest_arm64.rst
include/configs/xenguest_arm64.h

index 264920e240f7037de6c0fa14e82c36cc9b220596..7a317366ec4c48142243542858d4cd6bbd786f59 100644 (file)
@@ -6,3 +6,4 @@ F:      board/xen/xenguest_arm64/
 F:     doc/board/xen/
 F:     include/configs/xenguest_arm64.h
 F:     configs/xenguest_arm64_defconfig
+F:     configs/xenguest_arm64_virtio_defconfig
index 6e10bba76b71c83b86d15b1493ac7165e0c27dfe..244070a242da1452dc3e160c5655eeb9d327a1a5 100644 (file)
@@ -8,12 +8,15 @@
  */
 
 #include <common.h>
+#include <log.h>
 #include <cpu_func.h>
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <xen.h>
 #include <asm/global_data.h>
+#include <virtio_types.h>
+#include <virtio.h>
 
 #include <asm/io.h>
 #include <asm/armv8/mmu.h>
@@ -49,7 +52,14 @@ void *board_fdt_blob_setup(int *err)
        return (void *)rom_pointer[0];
 }
 
-#define MAX_MEM_MAP_REGIONS 5
+/*
+ * MAX_MEM_MAP_REGIONS should respect to:
+ * 3 Xen related regions
+ * 6 regions for 2 PCI Host bridges
+ * 10 regions for MMIO devices
+ * 2 memory regions
+ */
+#define MAX_MEM_MAP_REGIONS 22
 static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
 struct mm_region *mem_map = xen_mem_map;
 
@@ -63,6 +73,93 @@ static int get_next_memory_node(const void *blob, int mem)
        return mem;
 }
 
+#ifdef CONFIG_VIRTIO_BLK
+#ifdef CONFIG_VIRTIO_PCI
+static void add_pci_mem_map(const void *blob, int *cnt)
+{
+       struct fdt_resource reg_res;
+       int node = -1, len = 0, cells_per_record = 0, max_regions = 0;
+       int pci_addr_cells = 0, addr_cells = 0, size_cells = 0;
+
+       while ((node = fdt_node_offset_by_prop_value(blob, node, "compatible",
+                                                    "pci-host-ecam-generic",
+                                                    sizeof("pci-host-ecam-generic"))) >= 0) {
+               if ((*cnt) >= MAX_MEM_MAP_REGIONS ||
+                   fdt_get_resource(blob, node, "reg", 0, &reg_res) < 0)
+                       return;
+
+               xen_mem_map[*cnt].virt = reg_res.start;
+               xen_mem_map[*cnt].phys = reg_res.start;
+               xen_mem_map[*cnt].size = fdt_resource_size(&reg_res);
+               xen_mem_map[*cnt].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+                                                                  PTE_BLOCK_INNER_SHARE);
+               (*cnt)++;
+
+               const u32 *prop = fdt_getprop(blob, node, "ranges", &len);
+
+               if (!prop)
+                       return;
+
+               pci_addr_cells =  fdt_address_cells(blob, node);
+               addr_cells = fdt_address_cells(blob, 0);
+               size_cells = fdt_size_cells(blob, node);
+
+               /* PCI addresses are always 3-cells */
+               len /= sizeof(u32);
+               cells_per_record = pci_addr_cells + addr_cells + size_cells;
+               max_regions = len / cells_per_record + CONFIG_NR_DRAM_BANKS;
+
+               for (int i = 0; i < max_regions; i++, len -= cells_per_record) {
+                       u64 pci_addr, addr, size;
+                       int space_code;
+                       u32 flags;
+
+                       if (((*cnt) >= MAX_MEM_MAP_REGIONS) || len < cells_per_record)
+                               return;
+
+                       flags = fdt32_to_cpu(prop[0]);
+                       space_code = (flags >> 24) & 3;
+                       pci_addr = fdtdec_get_number(prop + 1, 2);
+                       prop += pci_addr_cells;
+                       addr = fdtdec_get_number(prop, addr_cells);
+                       prop += addr_cells;
+                       size = fdtdec_get_number(prop, size_cells);
+                       prop += size_cells;
+
+                       xen_mem_map[*cnt].virt = addr;
+                       xen_mem_map[*cnt].phys = addr;
+                       xen_mem_map[*cnt].size = size;
+                       xen_mem_map[*cnt].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+                                                  PTE_BLOCK_INNER_SHARE);
+                       (*cnt)++;
+               }
+       }
+}
+#endif
+
+#ifdef CONFIG_VIRTIO_MMIO
+static void add_mmio_mem_map(const void *blob, int *cnt)
+{
+       int node = -1;
+       struct fdt_resource reg_res;
+
+       if ((*cnt) >= MAX_MEM_MAP_REGIONS)
+               return;
+       while ((node = fdt_node_offset_by_prop_value(blob, node, "compatible", "virtio,mmio",
+                                                    sizeof("virtio,mmio"))) >= 0) {
+               if (fdt_get_resource(blob, node, "reg", 0, &reg_res) < 0)
+                       return;
+               xen_mem_map[*cnt].virt = reg_res.start;
+               xen_mem_map[*cnt].phys = reg_res.start;
+               xen_mem_map[*cnt].size = roundup(fdt_resource_size(&reg_res), PAGE_SIZE);
+               xen_mem_map[*cnt].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+                               PTE_BLOCK_INNER_SHARE);
+               (*cnt)++;
+       }
+}
+#endif
+#endif
+
 static int setup_mem_map(void)
 {
        int i = 0, ret, mem, reg = 0;
@@ -72,6 +169,7 @@ static int setup_mem_map(void)
        phys_addr_t gnttab_base;
        phys_size_t gnttab_sz;
 
+       memset(xen_mem_map, 0, sizeof(xen_mem_map));
        /*
         * Add "magic" region which is used by Xen to provide some essentials
         * for the guest: we need console and xenstore.
@@ -143,6 +241,14 @@ static int setup_mem_map(void)
                xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
                                        PTE_BLOCK_INNER_SHARE);
        }
+#ifdef CONFIG_VIRTIO_BLK
+#ifdef CONFIG_VIRTIO_PCI
+       add_pci_mem_map(blob, &i);
+#endif
+#ifdef CONFIG_VIRTIO_MMIO
+       add_mmio_mem_map(blob, &i);
+#endif
+#endif
        return 0;
 }
 
diff --git a/configs/xenguest_arm64_virtio_defconfig b/configs/xenguest_arm64_virtio_defconfig
new file mode 100644 (file)
index 0000000..b812cf4
--- /dev/null
@@ -0,0 +1,63 @@
+CONFIG_ARM=y
+CONFIG_POSITION_INDEPENDENT=y
+CONFIG_TARGET_XENGUEST_ARM64=y
+CONFIG_TEXT_BASE=0x40080000
+CONFIG_SYS_MALLOC_LEN=0x2000000
+CONFIG_SYS_MALLOC_F_LEN=0x400
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="xenguest-arm64"
+CONFIG_SYS_PROMPT="xenguest# "
+CONFIG_IDENT_STRING=" xenguest"
+CONFIG_SYS_LOAD_ADDR=0x40000000
+CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_BOOTDELAY=10
+CONFIG_SYS_MAXARGS=64
+CONFIG_SYS_PBSIZE=1051
+#CONFIG_SYS_CBSIZE=512
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_BOOTD is not set
+CONFIG_SYS_BOOTM_LEN=0x800000
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_GO is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_SAVEENV is not set
+# CONFIG_CMD_ENV_EXISTS is not set
+# CONFIG_CMD_CRC32 is not set
+# CONFIG_CMD_LZMADEC is not set
+# CONFIG_CMD_UNZIP is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_ECHO is not set
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SOURCE is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_SLEEP is not set
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+# CONFIG_NET is not set
+# CONFIG_MMC is not set
+# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
+CONFIG_DM_SERIAL=y
+CONFIG_PHYS_64BIT=y
+CONFIG_PCI=y
+CONFIG_CMD_PCI=y
+CONFIG_PCIE_ECAM_GENERIC=y
+CONFIG_PCI_REGION_MULTI_ENTRY=y
+CONFIG_PCI_INIT_R=y
+CONFIG_PCI_PNP=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_SYS_PCI_64BIT=y
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_CMD_VIRTIO=y
+# CONFIG_VIRTIO_PCI_LEGACY is not set
+# CONFIG_VIRTIO_NET is not set
+# CONFIG_VIRTIO_RNG is not set
+CONFIG_CMD_GPT=y
+CONFIG_PARTITION_TYPE_GUID=y
index e9bdaf7ffb2a49ba64cdac4daf166a6b15406971..92be9d43769a26f332014b19a6364f57974c276d 100644 (file)
@@ -23,6 +23,7 @@ previously done by NXP [4]:
 - PV block device frontend driver with XenStore based device enumeration and
   UCLASS_PVBLOCK class;
 - PV serial console device frontend driver;
+- Virtio block device support;
 - Xen hypervisor support with minimal set of the essential headers adapted from
   the Linux kernel;
 - Xen grant table support;
@@ -34,6 +35,7 @@ previously done by NXP [4]:
   define any start addresses at compile time which is up to Xen to choose at
   run-time;
 - new defconfig introduced: xenguest_arm64_defconfig.
+- new defconfig introduced: xenguest_arm64_virtio_defconfig.
 
 
 Board limitations
index bc268d25dc3a3b96f9609336a920903dcc8e81fb..3dce25b60e7eb3fab5b9521f687ca1f3c2c90d7a 100644 (file)
 #undef CFG_SYS_SDRAM_BASE
 
 #undef CFG_EXTRA_ENV_SETTINGS
+
+#ifdef CONFIG_VIRTIO_BLK
+#define CFG_EXTRA_ENV_SETTINGS \
+       "virtioboot=virtio scan; ext4load virtio 0 0x90000000 /boot/Image;" \
+               "booti 0x90000000 - ${fdtcontroladdr};\0"
+#else
 #define CFG_EXTRA_ENV_SETTINGS \
-       "loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \
-       "pvblockboot=run loadimage;" \
+       "pvblockboot=ext4load pvblock 0 0x90000000 /boot/Image;" \
                "booti 0x90000000 - 0x88000000;\0"
+#endif
 
 #endif /* __XENGUEST_ARM64_H */