Thread (1 message) 1 message, 1 author, 2017-03-16

Re: [RFC PATCH v2 26/32] kvm: svm: Add support for SEV LAUNCH_UPDATE_DATA command

From: Paolo Bonzini <pbonzini@redhat.com>
Date: 2017-03-16 10:49:04


On 02/03/2017 16:17, Brijesh Singh wrote:
+static struct page **sev_pin_memory(unsigned long uaddr, unsigned long ulen,
+				    unsigned long *n)
+{
+	struct page **pages;
+	int first, last;
+	unsigned long npages, pinned;
+
+	/* Get number of pages */
+	first = (uaddr & PAGE_MASK) >> PAGE_SHIFT;
+	last = ((uaddr + ulen - 1) & PAGE_MASK) >> PAGE_SHIFT;
+	npages = (last - first + 1);
+
+	pages = kzalloc(npages * sizeof(struct page *), GFP_KERNEL);
+	if (!pages)
+		return NULL;
+
+	/* pin the user virtual address */
+	down_read(&current->mm->mmap_sem);
+	pinned = get_user_pages_fast(uaddr, npages, 1, pages);
+	up_read(&current->mm->mmap_sem);
get_user_pages_fast, like get_user_pages_unlocked, must be called
without mmap_sem held.
+	if (pinned != npages) {
+		printk(KERN_ERR "SEV: failed to pin  %ld pages (got %ld)\n",
+				npages, pinned);
+		goto err;
+	}
+
+	*n = npages;
+	return pages;
+err:
+	if (pinned > 0)
+		release_pages(pages, pinned, 0);
+	kfree(pages);
+
+	return NULL;
+}

+	/* the array of pages returned by get_user_pages() is a page-aligned
+	 * memory. Since the user buffer is probably not page-aligned, we need
+	 * to calculate the offset within a page for first update entry.
+	 */
+	offset = uaddr & (PAGE_SIZE - 1);
+	len = min_t(size_t, (PAGE_SIZE - offset), ulen);
+	ulen -= len;
+
+	/* update first page -
+	 * special care need to be taken for the first page because we might
+	 * be dealing with offset within the page
+	 */
No need to special case the first page; just set "offset = 0" inside the
loop after the first iteration.

Paolo
+	data->handle = sev_get_handle(kvm);
+	data->length = len;
+	data->address = __sev_page_pa(inpages[0]) + offset;
+	ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_DATA,
+			data, &argp->error);
+	if (ret)
+		goto err_3;
+
+	/* update remaining pages */
+	for (i = 1; i < nr_pages; i++) {
+
+		len = min_t(size_t, PAGE_SIZE, ulen);
+		ulen -= len;
+		data->length = len;
+		data->address = __sev_page_pa(inpages[i]);
+		ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_DATA,
+					data, &argp->error);
+		if (ret)
+			goto err_3;
+	}
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help