From 0501c997a0aa647ec6995a6e662b677db037ee5c Mon Sep 17 00:00:00 2001 From: Andrii Chepurnyi Date: Tue, 3 Oct 2023 08:58:28 +0000 Subject: [PATCH] board: xen: introduce virtio-blk support 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 --- board/xen/xenguest_arm64/MAINTAINERS | 1 + board/xen/xenguest_arm64/xenguest_arm64.c | 108 +++++++++++++++++++++- configs/xenguest_arm64_virtio_defconfig | 63 +++++++++++++ doc/board/xen/xenguest_arm64.rst | 2 + include/configs/xenguest_arm64.h | 10 +- 5 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 configs/xenguest_arm64_virtio_defconfig diff --git a/board/xen/xenguest_arm64/MAINTAINERS b/board/xen/xenguest_arm64/MAINTAINERS index 264920e240..7a317366ec 100644 --- a/board/xen/xenguest_arm64/MAINTAINERS +++ b/board/xen/xenguest_arm64/MAINTAINERS @@ -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 diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c index 6e10bba76b..244070a242 100644 --- a/board/xen/xenguest_arm64/xenguest_arm64.c +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -8,12 +8,15 @@ */ #include +#include #include #include #include #include #include #include +#include +#include #include #include @@ -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, ®_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(®_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, ®_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(®_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 index 0000000000..b812cf4fe8 --- /dev/null +++ b/configs/xenguest_arm64_virtio_defconfig @@ -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 diff --git a/doc/board/xen/xenguest_arm64.rst b/doc/board/xen/xenguest_arm64.rst index e9bdaf7ffb..92be9d4376 100644 --- a/doc/board/xen/xenguest_arm64.rst +++ b/doc/board/xen/xenguest_arm64.rst @@ -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 diff --git a/include/configs/xenguest_arm64.h b/include/configs/xenguest_arm64.h index bc268d25dc..3dce25b60e 100644 --- a/include/configs/xenguest_arm64.h +++ b/include/configs/xenguest_arm64.h @@ -14,9 +14,15 @@ #undef CFG_SYS_SDRAM_BASE #undef CFG_EXTRA_ENV_SETTINGS + +#ifdef CONFIG_VIRTIO_BLK #define CFG_EXTRA_ENV_SETTINGS \ - "loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \ - "pvblockboot=run loadimage;" \ + "virtioboot=virtio scan; ext4load virtio 0 0x90000000 /boot/Image;" \ + "booti 0x90000000 - ${fdtcontroladdr};\0" +#else +#define CFG_EXTRA_ENV_SETTINGS \ + "pvblockboot=ext4load pvblock 0 0x90000000 /boot/Image;" \ "booti 0x90000000 - 0x88000000;\0" +#endif #endif /* __XENGUEST_ARM64_H */