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(¤t->mm->mmap_sem); > + pinned = get_user_pages_fast(uaddr, npages, 1, pages); > + up_read(¤t->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; > + }