Re: [PATCH kvmtool v3 7/9] Allow the user to specify where the RAM is placed in the memory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 20, 2018 at 03:21:24PM +0000, Julien Grall wrote:
> At the moment the user is only able to give the amount of memory used by
> the guest. The placement of the RAM in the layout is left to the
> software. It would be useful to give more freedom to the user where the
> RAM regions will live in the memory layout and the size of them.
> 
> The command line to specify the size of the memory (-m/-mem) is now extended
> in a compatible way to allow specifiying the base address: <size>[@<addr>].
> 
> The <addr> is mandatory if the option is specified multiple (i.e the
> user request).
> 
> As not all the architecture will support multiple RAM region or even
> specificying the address, it is left to the architecture to enable the
> feature (see MAX_RAM_BANKS and ARCH_SUPPORT_CFG_RAM_BASE).
> 
> At the moment no-one is taking advantages of it, this will change in a
> follow-up patch.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxx>
> ---
>  arm/fdt.c                |  2 +-
>  arm/kvm.c                | 33 +++++++++---------
>  builtin-run.c            | 87 +++++++++++++++++++++++++++++++++++++++++++-----
>  include/kvm/kvm-config.h | 16 ++++++++-
>  include/kvm/kvm.h        | 21 ++++++++++--
>  kvm.c                    |  4 +++
>  mips/kvm.c               | 40 ++++++++++++----------
>  powerpc/kvm.c            | 26 ++++++++-------
>  x86/bios.c               |  8 +++--
>  x86/kvm.c                | 47 +++++++++++++++-----------
>  10 files changed, 204 insertions(+), 80 deletions(-)
> 
> diff --git a/arm/fdt.c b/arm/fdt.c
> index 980015b..6ac0b33 100644
> --- a/arm/fdt.c
> +++ b/arm/fdt.c
> @@ -116,7 +116,7 @@ static int setup_fdt(struct kvm *kvm)
>  	u8 staging_fdt[FDT_MAX_SIZE];
>  	u64 mem_reg_prop[]	= {
>  		cpu_to_fdt64(kvm->arch.memory_guest_start),
> -		cpu_to_fdt64(kvm->ram_size),
> +		cpu_to_fdt64(kvm->ram[0].size),
>  	};
>  	struct psci_fns *fns;
>  	void *fdt		= staging_fdt;
> diff --git a/arm/kvm.c b/arm/kvm.c
> index 9623aa5..2a55b41 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -27,11 +27,11 @@ bool kvm__arch_cpu_supports_vm(void)
>  static void kvm__init_ram(struct kvm *kvm)
>  {
>  	int err;
> -	u64 phys_start, phys_size;
> -	void *host_mem;
> +	u64 phys_start;
>  	unsigned long alignment;
>  	/* Convenience aliases */
>  	const char *hugetlbfs_path = kvm->cfg.hugetlbfs_path;
> +	struct kvm_ram_region *ram = &kvm->ram[0];
>  
>  	/*
>  	 * Allocate guest memory. We must align our buffer to 64K to
> @@ -45,8 +45,8 @@ static void kvm__init_ram(struct kvm *kvm)
>  		alignment = SZ_32M;
>  	else
>  		alignment = SZ_2M;
> -	kvm->ram_size = kvm->cfg.ram_size;
> -	kvm->arch.ram_alloc_size = kvm->ram_size + alignment;
> +	ram->size = kvm->cfg.ram[0].size;
> +	kvm->arch.ram_alloc_size = ram->size + alignment;
>  	kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path,
>  						kvm->arch.ram_alloc_size);
>  
> @@ -54,8 +54,8 @@ static void kvm__init_ram(struct kvm *kvm)
>  		die("Failed to map %lld bytes for guest memory (%d)",
>  		    kvm->arch.ram_alloc_size, errno);
>  
> -	kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
> -					SZ_2M);
> +	ram->start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
> +				   SZ_2M);
>  
>  	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
>  		MADV_MERGEABLE);
> @@ -64,13 +64,11 @@ static void kvm__init_ram(struct kvm *kvm)
>  		MADV_HUGEPAGE);
>  
>  	phys_start	= ARM_MEMORY_AREA;
> -	phys_size	= kvm->ram_size;
> -	host_mem	= kvm->ram_start;
>  
> -	err = kvm__register_ram(kvm, phys_start, phys_size, host_mem);
> +	err = kvm__register_ram(kvm, phys_start, ram->size, ram->start);
>  	if (err)
>  		die("Failed to register %lld bytes of memory at physical "
> -		    "address 0x%llx [err %d]", phys_size, phys_start, err);
> +		    "address 0x%llx [err %d]", ram->size, phys_start, err);
>  
>  	kvm->arch.memory_guest_start = phys_start;
>  }
> @@ -92,10 +90,13 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  
>  static void kvm__arch_sanitize_cfg(struct kvm_config *cfg)
>  {
> -	if (cfg->ram_size > ARM_MAX_MEMORY(cfg)) {
> -		cfg->ram_size = ARM_MAX_MEMORY(cfg);
> +	/* Convenience aliases */
> +	struct kvm_ram_config *bank0 = &cfg->ram[0];
> +
> +	if (bank0->size > ARM_MAX_MEMORY(cfg)) {
> +		bank0->size = ARM_MAX_MEMORY(cfg);
>  		pr_warning("sanitize: Capping memory to %lluMB",
> -			   cfg->ram_size >> 20);
> +			   bank0->size >> 20);
>  	}
>  }
>  
> @@ -118,14 +119,16 @@ bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
>  	void *pos, *kernel_end, *limit;
>  	unsigned long guest_addr;
>  	ssize_t file_size;
> +	/* Convenience aliases */
> +	struct kvm_ram_region *ram0 = &kvm->ram[0];
>  
>  	/*
>  	 * Linux requires the initrd and dtb to be mapped inside lowmem,
>  	 * so we can't just place them at the top of memory.
>  	 */
> -	limit = kvm->ram_start + min(kvm->ram_size, (u64)SZ_256M) - 1;
> +	limit = ram0->start + min(ram0->size, (u64)SZ_256M) - 1;
>  
> -	pos = kvm->ram_start + ARM_KERN_OFFSET(kvm);
> +	pos = ram0->start + ARM_KERN_OFFSET(kvm);
>  	kvm->arch.kern_guest_start = host_to_guest_flat(kvm, pos);
>  	file_size = read_file(fd_kernel, pos, limit - pos);
>  	if (file_size < 0) {
> diff --git a/builtin-run.c b/builtin-run.c
> index 443c10b..568af5c 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -87,6 +87,63 @@ void kvm_run_set_wrapper_sandbox(void)
>  	kvm_run_wrapper = KVM_RUN_SANDBOX;
>  }
>  
> +static int mem_parser(const struct option *opt, const char *arg, int unset)
> +{
> +	struct kvm_config *cfg = opt->value;
> +	const char *p = arg;
> +	char *next;
> +	u64 size, addr;
> +	int base;
> +
> +	/* parse out size */
> +	size = strtoll(p, &next, 10);
> +
> +	if (next == p)
> +		die("mem: no size specified.\n");
> +
> +	if (*next != '@' && *next != '\0')
> +		die("mem: unexpected chars after size.\n");
> +
> +	if (*next == '\0')
> +		p = next;
> +	else
> +		p = next + 1;
> +
> +	/* parse out guest addr */
> +	base = 10;
> +	if (strcasestr(p, "0x"))
> +		base = 16;
> +	addr = strtoll(p, &next, base);

I thought strtoll() already handled '0x' prefixes if you pass base = 0?

> +	if (next == p && addr == 0) {
> +		/*
> +		 * To keep backward compatibility, the <addr> is not
> +		 * mandatory for the first bank.
> +		 */
> +		if (cfg->nr_ram > 0)
> +			die("mem: <addr> must be specified\n");
> +		addr = INVALID_RAM_ADDR;
> +	}
> +
> +	if ( cfg->nr_ram == MAX_RAM_BANKS )
> +		die("mem: Too many banks\n");
> +
> +	/*
> +	 * Allow the architecture to tell whether it is possible to configure
> +	 * the RAM base address.
> +	 */
> +#ifndef ARCH_SUPPORT_CFG_RAM_BASE
> +	if (addr == INVALID_RAM_ADDR)
> +		die("mem: specifying <addr> is not allowed\n");
> +#endif
> +
> +	cfg->ram[cfg->nr_ram].base = addr;
> +	cfg->ram[cfg->nr_ram].size = size;

How do you avoid adding overlapping regions? 

Will



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux