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 <andrii_chepurnyi@epam.com>
This commit is contained in:
Andrii Chepurnyi 2023-10-03 08:58:28 +00:00 committed by Tom Rini
parent 357f4fb0bd
commit 0501c997a0
5 changed files with 181 additions and 3 deletions

View file

@ -6,3 +6,4 @@ F: board/xen/xenguest_arm64/
F: doc/board/xen/ F: doc/board/xen/
F: include/configs/xenguest_arm64.h F: include/configs/xenguest_arm64.h
F: configs/xenguest_arm64_defconfig F: configs/xenguest_arm64_defconfig
F: configs/xenguest_arm64_virtio_defconfig

View file

@ -8,12 +8,15 @@
*/ */
#include <common.h> #include <common.h>
#include <log.h>
#include <cpu_func.h> #include <cpu_func.h>
#include <dm.h> #include <dm.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <xen.h> #include <xen.h>
#include <asm/global_data.h> #include <asm/global_data.h>
#include <virtio_types.h>
#include <virtio.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/armv8/mmu.h> #include <asm/armv8/mmu.h>
@ -49,7 +52,14 @@ void *board_fdt_blob_setup(int *err)
return (void *)rom_pointer[0]; 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]; static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
struct mm_region *mem_map = xen_mem_map; 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; 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) static int setup_mem_map(void)
{ {
int i = 0, ret, mem, reg = 0; int i = 0, ret, mem, reg = 0;
@ -72,6 +169,7 @@ static int setup_mem_map(void)
phys_addr_t gnttab_base; phys_addr_t gnttab_base;
phys_size_t gnttab_sz; 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 * Add "magic" region which is used by Xen to provide some essentials
* for the guest: we need console and xenstore. * 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) | xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE); 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; return 0;
} }

View file

@ -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

View file

@ -23,6 +23,7 @@ previously done by NXP [4]:
- PV block device frontend driver with XenStore based device enumeration and - PV block device frontend driver with XenStore based device enumeration and
UCLASS_PVBLOCK class; UCLASS_PVBLOCK class;
- PV serial console device frontend driver; - PV serial console device frontend driver;
- Virtio block device support;
- Xen hypervisor support with minimal set of the essential headers adapted from - Xen hypervisor support with minimal set of the essential headers adapted from
the Linux kernel; the Linux kernel;
- Xen grant table support; - 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 define any start addresses at compile time which is up to Xen to choose at
run-time; run-time;
- new defconfig introduced: xenguest_arm64_defconfig. - new defconfig introduced: xenguest_arm64_defconfig.
- new defconfig introduced: xenguest_arm64_virtio_defconfig.
Board limitations Board limitations

View file

@ -14,9 +14,15 @@
#undef CFG_SYS_SDRAM_BASE #undef CFG_SYS_SDRAM_BASE
#undef CFG_EXTRA_ENV_SETTINGS #undef CFG_EXTRA_ENV_SETTINGS
#ifdef CONFIG_VIRTIO_BLK
#define CFG_EXTRA_ENV_SETTINGS \ #define CFG_EXTRA_ENV_SETTINGS \
"loadimage=ext4load pvblock 0 0x90000000 /boot/Image;\0" \ "virtioboot=virtio scan; ext4load virtio 0 0x90000000 /boot/Image;" \
"pvblockboot=run loadimage;" \ "booti 0x90000000 - ${fdtcontroladdr};\0"
#else
#define CFG_EXTRA_ENV_SETTINGS \
"pvblockboot=ext4load pvblock 0 0x90000000 /boot/Image;" \
"booti 0x90000000 - 0x88000000;\0" "booti 0x90000000 - 0x88000000;\0"
#endif
#endif /* __XENGUEST_ARM64_H */ #endif /* __XENGUEST_ARM64_H */