Re: [PATCH 1/2] KVM: Implement kvm_copy_guest() to perform copy of guest memory in place

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

 



On Wed, Mar 06, 2019 at 05:00:15PM +1100, Suraj Jitindar Singh wrote:
> Implement the function kvm_copy_guest() to be used to perform a memory
> copy from one guest physical address to another of a variable length.
> 
> This performs similar functionality as the kvm_read_guest() and
> kvm_write_guest() functions, except both addresses point to guest memory.
> This performs a copy in place using raw_copy_in_user() to avoid having to
> buffer the data.
> 
> The guest memory can reside in different memslots and the copy length
> can span memslots.
> 
> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@xxxxxxxxx>
> 
> ---
> 
> I suspect additional checking may be required around the raw_copy_in_user()
> call.
> 
> ---
>  include/linux/kvm_host.h |  1 +
>  virt/kvm/kvm_main.c      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+)
> 

...

> +static int next_segment_many(unsigned long len, int offset1, int offset2)
> +{
> +	int size = min(PAGE_SIZE - offset1, PAGE_SIZE - offset2);
> +
> +	if (len > size)
> +		return size;
> +	else
> +		return len;
> +}
> +
> +int kvm_copy_guest(struct kvm *kvm, gpa_t to, gpa_t from, unsigned long len)
> +{
> +	struct kvm_memory_slot *to_memslot = NULL;
> +	struct kvm_memory_slot *from_memslot = NULL;
> +	gfn_t to_gfn = to >> PAGE_SHIFT;
> +	gfn_t from_gfn = from >> PAGE_SHIFT;
> +	int seg;
> +	int to_offset = offset_in_page(to);
> +	int from_offset = offset_in_page(from);
> +	int ret;
> +
> +	while ((seg = next_segment_many(len, to_offset, from_offset)) != 0) {
> +		if (!to_memslot || (to_gfn >= (to_memslot->base_gfn +
> +					       to_memslot->npages)))
> +			to_memslot = gfn_to_memslot(kvm, to_gfn);
> +		if (!from_memslot || (from_gfn >= (from_memslot->base_gfn +
> +						   from_memslot->npages)))
> +			from_memslot = gfn_to_memslot(kvm, from_gfn);
> +
> +		ret = __kvm_copy_guest_page(to_memslot, to_gfn, to_offset,
> +					    from_memslot, from_gfn, from_offset,
> +					    seg);
> +		if (ret < 0)
> +			return ret;
> +
> +		to_offset = (to_offset + seg) & (PAGE_SIZE - 1);
> +		from_offset = (from_offset + seg) & (PAGE_SIZE - 1);
> +		len -= seg;
> +		if (!to_offset)
> +			to_gfn += 1;
> +		if (!from_offset)
> +			from_gfn += 1;
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(kvm_copy_guest);

Is there a need to support spanning multiple pages at this time?  Your use
case always accesses exactly a page and requires both dst and src to be
page aligned.  I.e. provide just kvm_copy_guest_page() for simplicity.

> +
>  static int __kvm_gfn_to_hva_cache_init(struct kvm_memslots *slots,
>  				       struct gfn_to_hva_cache *ghc,
>  				       gpa_t gpa, unsigned long len)
> -- 
> 2.13.6
> 



[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