[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 5/5] xen/arm: Support ARM standard PV time for domains created via toolstack
Implement ARM DEN 0057A PV time support for domains created via the toolstack, utilizing the newly introduced XENMAPSPACE_pv_time. Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx> --- tools/libs/light/libxl_arm.c | 185 ++++++++++++++++++++++++++++------- xen/arch/arm/mm.c | 14 +++ xen/include/public/memory.h | 1 + 3 files changed, 167 insertions(+), 33 deletions(-) diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index 4a19a8d22bdf..33251520c07a 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -684,6 +684,40 @@ static int make_memory_nodes(libxl__gc *gc, void *fdt, return 0; } +static int make_resv_memory_node(libxl__gc *gc, void *fdt, + const struct xc_dom_image *dom) +{ + int res; + + if (strcmp(dom->guest_type, "xen-3.0-aarch64")) + /* + * The stolen time shared memory region for ARM DEN 0057A is currently + * the only user of /reserved-memory node when a domain is created via + * the toolstack, and it requires both the hypervisor and the domain to + * be AArch64. + */ + return 0; + + res = fdt_begin_node(fdt, "reserved-memory"); + if (res) return res; + + res = fdt_property_cell(fdt, "#address-cells", GUEST_ROOT_ADDRESS_CELLS); + if (res) return res; + + res = fdt_property_cell(fdt, "#size-cells", GUEST_ROOT_SIZE_CELLS); + if (res) return res; + + /* reg 0 is a placeholder for PV time region */ + res = fdt_property_reg_placeholder(gc, fdt, GUEST_ROOT_ADDRESS_CELLS, + GUEST_ROOT_SIZE_CELLS, 1); + if (res) return res; + + res = fdt_end_node(fdt); + if (res) return res; + + return 0; +} + static int make_gicv2_node(libxl__gc *gc, void *fdt, uint64_t gicd_base, uint64_t gicd_size, uint64_t gicc_base, uint64_t gicc_size) @@ -1352,6 +1386,7 @@ next_resize: FDT( make_psci_node(gc, fdt) ); FDT( make_memory_nodes(gc, fdt, dom) ); + FDT( make_resv_memory_node(gc, fdt, dom) ); switch (info->arch_arm.gic_version) { case LIBXL_GIC_VERSION_V2: @@ -1519,6 +1554,9 @@ static void finalise_one_node(libxl__gc *gc, void *fdt, const char *uname, #define EXT_REGION_MIN_SIZE xen_mk_ullong(0x0004000000) /* 64MB */ +/* As per ARM DEN 0057A, stolen time memory regions are 64-byte aligned */ +#define PV_REGIONS_PER_PAGE (XC_PAGE_SIZE / 64) + static int compare_iomem(const void *a, const void *b) { const libxl_iomem_range *x = a, *y = b; @@ -1530,24 +1568,92 @@ static int compare_iomem(const void *a, const void *b) return 0; } -static int finalize_hypervisor_node(libxl__gc *gc, - libxl_domain_build_info *b_info, - struct xc_dom_image *dom) +static int get_pv_region(libxl_domain_build_info *b_info, + struct xc_dom_image *dom, + uint64_t *start, uint64_t end, + uint64_t *region_base, uint64_t *region_size) +{ + unsigned int npages = DIV_ROUNDUP(b_info->max_vcpus, PV_REGIONS_PER_PAGE); + unsigned int len = npages * XC_PAGE_SIZE; + uint32_t domid = dom->guest_domid; + xc_interface *xch = dom->xch; + unsigned long idx = 0; + uint64_t size; + int rc; + + if (*start >= end) + return -1; + size = end - *start; + if (size < len) + return -1; + + for (; npages; npages--, idx++) { + rc = xc_domain_add_to_physmap(xch, domid, XENMAPSPACE_pv_time, idx, + (*start >> XC_PAGE_SHIFT) + idx); + if (rc) + return rc; + } + + region_base[0] = *start; + region_size[0] = len; + *start += len; + return 0; +} + +static void get_ext_region(uint64_t start, uint64_t end, uint64_t *region_base, + uint64_t *region_size, unsigned int *nr_regions) +{ + uint64_t size; + + start = ALIGN_UP_TO_2MB(start); + if (start >= end) + return; + + size = end - start; + if (size < EXT_REGION_MIN_SIZE) + return; + + region_base[*nr_regions] = start; + region_size[*nr_regions] = size; + (*nr_regions)++; +} + +static int finalize_extra_regions(libxl__gc *gc, + libxl_domain_build_info *b_info, + struct xc_dom_image *dom) { void *fdt = dom->devicetree_blob; - uint64_t region_base[MAX_NR_EXT_REGIONS], region_size[MAX_NR_EXT_REGIONS]; - uint32_t regs[(GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * + + /* For extended regions */ + uint64_t ext_region_base[MAX_NR_EXT_REGIONS], ext_region_size[MAX_NR_EXT_REGIONS]; + uint32_t ext_regs[(GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * (MAX_NR_EXT_REGIONS + 1)]; - be32 *cells = ®s[0]; + be32 *ext_cells = &ext_regs[0]; + int hyp_offset; + + /* For pv regions */ + uint64_t pv_region_base[1], pv_region_size[1]; + uint32_t pv_regs[GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS]; + be32 *pv_cells = &pv_regs[0]; + int resv_offset; + const uint64_t bankbase[] = GUEST_RAM_BANK_BASES; const uint64_t banksize[] = GUEST_RAM_BANK_SIZES; unsigned int i, j, len, nr_regions = 0; + bool pv_region_pending = true; libxl_dominfo info; - int offset, rc; + int rc; - offset = fdt_path_offset(fdt, "/hypervisor"); - if (offset < 0) - return offset; + resv_offset = fdt_path_offset(fdt, "/reserved-memory"); + if (!strcmp(dom->guest_type, "xen-3.0-aarch64")) { + if (resv_offset < 0) + return resv_offset; + } else + pv_region_pending = false; + + hyp_offset = fdt_path_offset(fdt, "/hypervisor"); + if (hyp_offset < 0) + return hyp_offset; rc = libxl_domain_info(CTX, &info, dom->guest_domid); if (rc) @@ -1572,8 +1678,7 @@ static int finalize_hypervisor_node(libxl__gc *gc, } unallocated; uint64_t unallocated_size = 0; - unallocated.start = bankbase[i] + - ALIGN_UP_TO_2MB((uint64_t)dom->rambank_size[i] << XC_PAGE_SHIFT); + unallocated.start = bankbase[i] + ((uint64_t)dom->rambank_size[i] << XC_PAGE_SHIFT); unallocated.end = ~0ULL >> (64 - info.gpaddr_bits); unallocated.end = min(unallocated.end, bankbase[i] + banksize[i] - 1); @@ -1581,7 +1686,7 @@ static int finalize_hypervisor_node(libxl__gc *gc, if (unallocated.end >= unallocated.start) unallocated_size = unallocated.end - unallocated.start + 1; - if (unallocated_size < EXT_REGION_MIN_SIZE) + if (unallocated_size <= 0) continue; /* Exclude iomem */ @@ -1605,14 +1710,14 @@ static int finalize_hypervisor_node(libxl__gc *gc, if (unallocated.start > unallocated.end) break; } else { - uint64_t size = iomem.start - unallocated.start; - - if (size >= EXT_REGION_MIN_SIZE) { - region_base[nr_regions] = unallocated.start; - region_size[nr_regions] = size; - nr_regions++; + if (pv_region_pending) { + rc = get_pv_region(b_info, dom, &unallocated.start, iomem.start, + pv_region_base, pv_region_size); + if (!rc) + pv_region_pending = false; } - + get_ext_region(unallocated.start, iomem.start, ext_region_base, + ext_region_size, &nr_regions); unallocated.start = iomem.end + 1; if (unallocated.start > unallocated.end) @@ -1624,38 +1729,52 @@ static int finalize_hypervisor_node(libxl__gc *gc, if (unallocated.end >= unallocated.start && nr_regions < MAX_NR_EXT_REGIONS) { - uint64_t size = unallocated.end - unallocated.start + 1; - - if (size >= EXT_REGION_MIN_SIZE) { - region_base[nr_regions] = unallocated.start; - region_size[nr_regions] = size; - nr_regions++; + if (pv_region_pending) { + rc = get_pv_region(b_info, dom, &unallocated.start, unallocated.end, + pv_region_base, pv_region_size); + if (!rc) + pv_region_pending = false; } + get_ext_region(unallocated.start, unallocated.end, ext_region_base, + ext_region_size, &nr_regions); } } + if (!strcmp(dom->guest_type, "xen-3.0-aarch64")) { + if (pv_region_pending) { + LOG(ERROR, "The PV time region cannot be allocated, not enough space"); + return ERROR_FAIL; + } + set_range(&pv_cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, + pv_region_base[0], pv_region_size[0]); + len = sizeof(pv_regs[0]) * (GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS); + rc = fdt_setprop(fdt, resv_offset, "reg", pv_regs, len); + if (rc) + return rc; + } + /* * The region 0 for grant table space must be always present. If we managed * to allocate the extended regions then insert them as regions 1...N. */ - set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, + set_range(&ext_cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, GUEST_GNTTAB_BASE, GUEST_GNTTAB_SIZE); for (i = 0; i < nr_regions; i++) { LOG(DEBUG, "Extended region %u: %#"PRIx64"->%#"PRIx64"", - i, region_base[i], region_base[i] + region_size[i] - 1); + i, ext_region_base[i], ext_region_base[i] + ext_region_size[i] - 1); - set_range(&cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, - region_base[i], region_size[i]); + set_range(&ext_cells, GUEST_ROOT_ADDRESS_CELLS, GUEST_ROOT_SIZE_CELLS, + ext_region_base[i], ext_region_size[i]); } if (!nr_regions) LOG(WARN, "The extended regions cannot be allocated, not enough space"); - len = sizeof(regs[0]) * (GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * + len = sizeof(ext_regs[0]) * (GUEST_ROOT_ADDRESS_CELLS + GUEST_ROOT_SIZE_CELLS) * (nr_regions + 1); - return fdt_setprop(fdt, offset, "reg", regs, len); + return fdt_setprop(fdt, hyp_offset, "reg", ext_regs, len); } int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, @@ -1698,7 +1817,7 @@ int libxl__arch_domain_finalise_hw_description(libxl__gc *gc, } - res = finalize_hypervisor_node(gc, &d_config->b_info, dom); + res = finalize_extra_regions(gc, &d_config->b_info, dom); if (res) return res; diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 0613c1916936..4741472ea1a0 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -180,7 +180,21 @@ int xenmem_add_to_physmap_one( case XENMAPSPACE_dev_mmio: rc = map_dev_mmio_page(d, gfn, _mfn(idx)); return rc; + case XENMAPSPACE_pv_time: +#ifdef CONFIG_ARM_64 + ASSERT(IS_POWER_OF_TWO(sizeof(struct pv_time_region))); + if ( idx >= DIV_ROUND_UP(d->max_vcpus * sizeof(struct pv_time_region), + PAGE_SIZE) ) + return -EINVAL; + + if ( idx == 0 ) + d->arch.pv_time_regions_gfn = gfn; + mfn = virt_to_mfn(d->arch.pv_time_regions[idx]); + t = p2m_ram_ro; + + break; +#endif default: return -ENOSYS; } diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index bd9fc37b5297..4daa703e882e 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -217,6 +217,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t); Stage-2 using the Normal Memory Inner/Outer Write-Back Cacheable memory attribute. */ +#define XENMAPSPACE_pv_time 6 /* PV time shared region (ARM64 only) */ /* ` } */ /* -- 2.48.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |