|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 3/5] xen/domctl, tools: Introduce a new domctl to get guest memory map
Hi Henry,
On 08/03/2024 02:54, Henry Wang wrote:
> There are some use cases where the toolstack needs to know the guest
> memory map. For example, the toolstack helper application
> "init-dom0less" needs to know the guest magic page regions for 1:1
> direct-mapped dom0less DomUs to allocate magic pages.
>
> To address such needs, add XEN_DOMCTL_get_mem_map hypercall and
> related data structures to query the hypervisor for the guest memory
> map. The guest memory map is recorded in the domain structure and
> currently only guest magic page region is recorded in the guest
> memory map. The guest magic page region is initialized at the domain
> creation time as the layout in the public header, and it is updated
> for 1:1 dom0less DomUs (see the following commit) to avoid conflict
> with RAM.
>
> Take the opportunity to drop an unnecessary empty line to keep the
> coding style consistent in the file.
>
> Reported-by: Alec Kwapis <alec.kwapis@xxxxxxxxxxxxx>
> Signed-off-by: Henry Wang <xin.wang2@xxxxxxx>
> ---
> v2:
> - New patch
> RFC: I think the newly introduced "struct xen_domctl_mem_map" is
> quite duplicated with "struct xen_memory_map", any comment on reuse
> the "struct xen_memory_map" for simplicity?
> ---
> tools/include/xenctrl.h | 4 ++++
> tools/libs/ctrl/xc_domain.c | 32 +++++++++++++++++++++++++++++++
> xen/arch/arm/domain.c | 6 ++++++
> xen/arch/arm/domctl.c | 19 +++++++++++++++++-
> xen/arch/arm/include/asm/domain.h | 8 ++++++++
> xen/include/public/arch-arm.h | 4 ++++
> xen/include/public/domctl.h | 21 ++++++++++++++++++++
> 7 files changed, 93 insertions(+), 1 deletion(-)
>
> diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
> index 2ef8b4e054..b25e9772a2 100644
> --- a/tools/include/xenctrl.h
> +++ b/tools/include/xenctrl.h
> @@ -1195,6 +1195,10 @@ int xc_domain_setmaxmem(xc_interface *xch,
> uint32_t domid,
> uint64_t max_memkb);
>
> +int xc_get_domain_mem_map(xc_interface *xch, uint32_t domid,
> + struct xen_mem_region mem_regions[],
> + uint32_t *nr_regions);
> +
> int xc_domain_set_memmap_limit(xc_interface *xch,
> uint32_t domid,
> unsigned long map_limitkb);
> diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c
> index f2d9d14b4d..64b46bdfb4 100644
> --- a/tools/libs/ctrl/xc_domain.c
> +++ b/tools/libs/ctrl/xc_domain.c
> @@ -697,6 +697,38 @@ int xc_domain_setmaxmem(xc_interface *xch,
> return do_domctl(xch, &domctl);
> }
>
> +int xc_get_domain_mem_map(xc_interface *xch, uint32_t domid,
> + struct xen_mem_region mem_regions[],
> + uint32_t *nr_regions)
> +{
> + int rc;
> + struct xen_domctl domctl = {
> + .cmd = XEN_DOMCTL_get_mem_map,
> + .domain = domid,
> + .u.mem_map = {
> + .nr_mem_regions = *nr_regions,
> + },
> + };
> +
> + DECLARE_HYPERCALL_BOUNCE(mem_regions,
> + sizeof(xen_mem_region_t) * (*nr_regions),
> + XC_HYPERCALL_BUFFER_BOUNCE_OUT);
> +
> + if ( !mem_regions || xc_hypercall_bounce_pre(xch, mem_regions) ||
> + (*nr_regions) < 1 )
> + return -1;
> +
> + set_xen_guest_handle(domctl.u.mem_map.buffer, mem_regions);
> +
> + rc = do_domctl(xch, &domctl);
> +
> + xc_hypercall_bounce_post(xch, mem_regions);
> +
> + *nr_regions = domctl.u.mem_map.nr_mem_regions;
> +
> + return rc;
> +}
> +
> #if defined(__i386__) || defined(__x86_64__)
> int xc_domain_set_memory_map(xc_interface *xch,
> uint32_t domid,
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 5e7a7f3e7e..54f3601ab0 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -696,6 +696,7 @@ int arch_domain_create(struct domain *d,
> {
> unsigned int count = 0;
> int rc;
> + struct mem_map_domain *mem_map = &d->arch.mem_map;
>
> BUILD_BUG_ON(GUEST_MAX_VCPUS < MAX_VIRT_CPUS);
>
> @@ -785,6 +786,11 @@ int arch_domain_create(struct domain *d,
> d->arch.sve_vl = config->arch.sve_vl;
> #endif
>
> + mem_map->regions[mem_map->nr_mem_regions].start = GUEST_MAGIC_BASE;
You don't check for exceeding max number of regions. Is the expectation that
nr_mem_regions
is 0 at this stage? Maybe add an ASSERT here.
> + mem_map->regions[mem_map->nr_mem_regions].size = GUEST_MAGIC_SIZE;
> + mem_map->regions[mem_map->nr_mem_regions].type = GUEST_MEM_REGION_MAGIC;
> + mem_map->nr_mem_regions++;
> +
> return 0;
>
> fail:
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> index ad56efb0f5..92024bcaa0 100644
> --- a/xen/arch/arm/domctl.c
> +++ b/xen/arch/arm/domctl.c
> @@ -148,7 +148,6 @@ long arch_do_domctl(struct xen_domctl *domctl, struct
> domain *d,
>
> return 0;
> }
> -
> case XEN_DOMCTL_vuart_op:
> {
> int rc;
> @@ -176,6 +175,24 @@ long arch_do_domctl(struct xen_domctl *domctl, struct
> domain *d,
>
> return rc;
> }
> + case XEN_DOMCTL_get_mem_map:
> + {
> + int rc;
Without initialization, what will be the rc value on success?
> + /*
> + * Cap the number of regions to the minimum value between toolstack
> and
> + * hypervisor to avoid overflowing the buffer.
> + */
> + uint32_t nr_regions = min(d->arch.mem_map.nr_mem_regions,
> + domctl->u.mem_map.nr_mem_regions);
> +
> + if ( copy_to_guest(domctl->u.mem_map.buffer,
> + d->arch.mem_map.regions,
> + nr_regions) ||
> + __copy_to_guest(u_domctl, domctl, 1) )
In domctl.h, you wrote that nr_regions is IN/OUT but you don't seem to write
back the actual number
of regions.
> + rc = -EFAULT;
> +
> + return rc;
> + }
> default:
> return subarch_do_domctl(domctl, d, u_domctl);
> }
> diff --git a/xen/arch/arm/include/asm/domain.h
> b/xen/arch/arm/include/asm/domain.h
> index f1d72c6e48..a559a9e499 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -10,6 +10,7 @@
> #include <asm/gic.h>
> #include <asm/vgic.h>
> #include <asm/vpl011.h>
> +#include <public/domctl.h>
> #include <public/hvm/params.h>
>
> struct hvm_domain
> @@ -59,6 +60,11 @@ struct paging_domain {
> unsigned long p2m_total_pages;
> };
>
> +struct mem_map_domain {
> + unsigned int nr_mem_regions;
> + struct xen_mem_region regions[XEN_MAX_MEM_REGIONS];
> +};
> +
> struct arch_domain
> {
> #ifdef CONFIG_ARM_64
> @@ -77,6 +83,8 @@ struct arch_domain
>
> struct paging_domain paging;
>
> + struct mem_map_domain mem_map;
> +
> struct vmmio vmmio;
>
> /* Continuable domain_relinquish_resources(). */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index a25e87dbda..a06eaf2dab 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -420,6 +420,10 @@ typedef uint64_t xen_callback_t;
> * should instead use the FDT.
> */
>
> +/* Guest memory region types */
> +#define GUEST_MEM_REGION_DEFAULT 0
What's the purpose of this default type? It seems unusued.
> +#define GUEST_MEM_REGION_MAGIC 1
> +
> /* Physical Address Space */
>
> /* Virtio MMIO mappings */
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index a33f9ec32b..77bf999651 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -946,6 +946,25 @@ struct xen_domctl_paging_mempool {
> uint64_aligned_t size; /* Size in bytes. */
> };
>
> +#define XEN_MAX_MEM_REGIONS 1
The max number of regions can differ between arches. How are you going to
handle it?
~Michal
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |