From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752382AbdJTCjU (ORCPT ); Thu, 19 Oct 2017 22:39:20 -0400 Received: from mail-bl2nam02on0071.outbound.protection.outlook.com ([104.47.38.71]:59884 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752248AbdJTCfq (ORCPT ); Thu, 19 Oct 2017 22:35:46 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=brijesh.singh@amd.com; From: Brijesh Singh To: kvm@vger.kernel.org Cc: bp@alien8.de, Brijesh Singh , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Joerg Roedel , Borislav Petkov , Tom Lendacky , x86@kernel.org, linux-kernel@vger.kernel.org Subject: [Part2 PATCH v6 28/38] KVM: SVM: Add support for KVM_SEV_LAUNCH_UPDATE_DATA command Date: Thu, 19 Oct 2017 21:34:03 -0500 Message-Id: <20171020023413.122280-29-brijesh.singh@amd.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171020023413.122280-1-brijesh.singh@amd.com> References: <20171020023413.122280-1-brijesh.singh@amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Originating-IP: [165.204.78.1] X-ClientProxiedBy: MWHPR1701CA0020.namprd17.prod.outlook.com (10.172.58.30) To SN1PR12MB0157.namprd12.prod.outlook.com (10.162.3.144) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: aa071cf5-99c7-4972-d303-08d517633aaf X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(48565401081)(4534020)(4602075)(4627075)(201703031133081)(201702281549075)(2017052603199);SRVR:SN1PR12MB0157; X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0157;3:yVdRAAoXg9H3Kkuwa3V1FFEbjgeqGsMWuLb0UOWn8R9o7E2zDsvfmPPq1jD+x2xHK3rAUfe/b81el9OveBghXCiaS2C2O7S/7bxolz1atWrm1mqLzVZJNKDZy0WagHh+OI1muAl+aqhxmqudWcIncIbdvN8fdwsOxis5IYiAfq6uGuCrb0wTP6hIHcp5eF+0r1BJwd8tB2s/SaTwpNwh0c8IbmOt9iRG3nQpoXTwT3Z0CqbyTnrMrGf4h7KcRlnx;25:eMtG6pxIcOTMw+qrdaFYvT0K6wlpL35wm61a08zvslx5PrRk89eLT5OTvxpDYykNJCg5cmZq5DeGcfY66v+yh9DV7UTiY5JVcbshCmHabKwFF1TTEFqqSvesej8+qzlX6YRpDngVcn4iDIpzMvZZMBU2A5usv61vBRqJh8T+BeITONWAh/XmvnwacSktDd0RS2kWTc2HuS/3NOrpNh0JnrTxhlxi+/57e/O//NnniRWnnStmfTEtoFqO2sbHM8y4MVcYmc5fe/ZxW1mh1psVVnPlXP1ErS9ENHWQwCUKXof0iRAHoDgsdFZtExTRqRUpkIwMkBzagzjMnW/rFhJSdg==;31:wDAovSEnZBu4DR3Wxptgv6vYVl3HqfKKJxjvC1GzOlhe/05iF5luEUM98OvqI/sDS+rmBApmlLrxttTrMl4K3Bs7ct/cSBILqrj4Xp1idGDmRjWSWH0w6KJHxus38HeZEuDL6jWyz+SOGwpNutRdIrjiGwVOClIDnyaqrFePonHcbKeD0QKWtPaBR1k7mAh5HSHr3CFEYr2P7yWV2zIQGm4wnn3GmcttNMZWdZ+k5tQ= X-MS-TrafficTypeDiagnostic: SN1PR12MB0157: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0157;20:NHTLW5XfLPxJZVORfZl2UGGXnpcrdyK2Jup+SnP2fpZrNpqjZSJ8XnstxINyFsx4UO7dNqILMQ1s73ButVhohoXgnIGoaoVupjSN7ixGPQZSS5Ii4Mxg36E7+rYT7LWIzCldIViLCvBb04KpkV8AbMxtPCdyC4M1xhzCp8QcHAFD/RdTmcmA2eUetA3RpQQUeg5p4gmHKH5dgHJf8NE3Q5Gtv9lebYFWF88V+kznutzdmNMlfmkswz5BscQRmUPG439WF3JnNPV9SBlIOd0FbyMsK03LvAvmejTJ+lT+UkWYimekebzskDzCjHSNCg3y2bPIeVUCKx0AoJRkOc9x5pPoWBHG2ZDir7z0EGp9bmfBI1Q/z817HENmWq1LAb7zBtqJjRuPnFQOgQMhjsuf11FsQgAKHhxPhIib84FczUuM+U+dobUKkUsYutaOLc/BQmghx4vjsjHEpJsR66ge1HBUER/YbwEpdFaTfC1/Sm6xrSJpRTZGp6sqeT+SAa8e;4:VsJybSFRqS7lv70OQwvSA0G44GnhTrtS/choHJ1qs/J7YhoJISD/0r4SRWUs+elfabrlT0zMEUVGxd8gLbctJNYANFSY18YZ7wdzU9w4n+8AuRssFCdfY+BVF8ZcF03kTDlXWPI/+3MVw+cyllCaRDS7M6W8nGgxaUoYv6hYwB9kR7ebR+w7VJrsbZ6qNshMZyTqHjInY45N5UMUyUCOyIoc7ym6RysfndUvpGwrVQtDB04QBQK/KoCgVpoROECU9JdaSvTg802ImT070IhQxU7eiz4/DG9EmWRmPWenQGXZ53yMNUHdUZIVDzmqTeX1QyhYUQorw5zUTmrXpC3rgg== X-Exchange-Antispam-Report-Test: UriScan:(9452136761055)(767451399110); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(8121501046)(5005006)(3231020)(100000703101)(100105400095)(10201501046)(93006095)(93001095)(3002001)(6055026)(6041248)(20161123555025)(20161123564025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123560025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:SN1PR12MB0157;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:SN1PR12MB0157; X-Forefront-PRVS: 0466CA5A45 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6009001)(346002)(376002)(39860400002)(199003)(189002)(36756003)(7736002)(68736007)(50466002)(1076002)(478600001)(4326008)(16526018)(316002)(53936002)(6486002)(86362001)(575784001)(305945005)(53416004)(54906003)(50226002)(2351001)(106356001)(101416001)(81166006)(105586002)(8676002)(2361001)(76176999)(2870700001)(2906002)(50986999)(6916009)(23676002)(66066001)(47776003)(6666003)(97736004)(6116002)(2950100002)(189998001)(8936002)(3846002)(33646002)(81156014)(7416002)(5660300001)(25786009);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR12MB0157;H:ubuntu-010236106000.amd.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtTTjFQUjEyTUIwMTU3OzIzOjhKQWZ0K3Fady9kcTgvQklicTZlaG9Ibkw1?= =?utf-8?B?R3JOdjJFWDY1R0I2bWFCVXZ3VXZmV25hdTlpMU9na1E2VmxKWUpqU0ZyRHJq?= =?utf-8?B?T21INSsyVXZHVDNiMmJHODdWUGM5YVlzci9DN29BUUFZMVB2REJUQ3BFcjBq?= =?utf-8?B?TjBrY0Era2VyRGZVVTMzQUVNMDEzaGNXbUxUcGppbUZJYnkvTHQvZU80Ykhs?= =?utf-8?B?TE5qbU5XcnkzenBIQmpzdGZIRExheVIxaTRRRVVYaDY2WGJzdjU3aDhiL3FS?= =?utf-8?B?MDhuWnU1L0dBNTBrcW1DT2dCaGdpVU9GZE8zUis0YWdCdlVGVWJqN2FZeFM2?= =?utf-8?B?NmdTN0Jyam05YVhmcnlYUE5pWnBHWWtiVnpqNVZhUGpiUHlJUk04bFhTWnJM?= =?utf-8?B?WG5GaUswam1yRVJ2TTdrN3hXRzBrNGNMTVphOW9ieUxBVVZIN2w4ZDZtNWRG?= =?utf-8?B?NjlBbytoMjM1bnRZNzJacTlFWUFOT24ydUwzUUJEVnM4LzJkNW5DUEZzUnJE?= =?utf-8?B?R3JpMmlHSXg3ODZBbWt5LzcrZGd4WHMrTjRFQjNvbURDc0FMcFVidy9EOXhV?= =?utf-8?B?M1lyYUwxT3NOOUpqNXBrT3lWY3lpWDR5YmgreWswOURIemM3d0NnUTlFWXZn?= =?utf-8?B?ei9vM2lJQlZLdVd5aDJxTS9pVllNYlIreHVGREpUeExjaDI0VFdTNmNCUW5o?= =?utf-8?B?RE44ZmR5dFpDK0hkc1dRbTBSSS9tSW9GMlJzbU5KMmhCYXdDcExHYWoyRElh?= =?utf-8?B?SW85T0diRmoram5ySHk5Q3JTUDJJcFZyNGw4bGhUN3FNNDF2OTZTdFcySHVL?= =?utf-8?B?Sk5ZZWJlanNxeEdhcFFpd2Qydm5KQzZteTZLVWg1bWt1d2s0andmTDdNLzN2?= =?utf-8?B?ekxDSXpad0ZsNWgvb2ZTdENrVkdjVmpDYlNlVjNlWFVxQ3JVQjhxRjZTK2dT?= =?utf-8?B?YWhaYTA5VjdYU0xBelg4ZDQ0TWF5VTltUjA2S2F1YlZOVTNPYnVSTk5pbHRP?= =?utf-8?B?NDg5T0RkYlgxL2QyWWphSVk0S0ZZc0ZXTzdLdWNHZStka0pVcjQvbTd6Mk1F?= =?utf-8?B?STUyTVFYeDduU3ROUkZkeGlnZUJkYjVXV09MNFhjQXFBSkg5TG5ZZ2pVRDVE?= =?utf-8?B?ZzgxNStzNkpLOGIwckZDMXladjZsakRLYW5hck9ZMVRvRmM5b2xNaGtKbjdq?= =?utf-8?B?Z1QvcWlhbWVlY3IwcUhNRkR2OHZvdnM3TkJ2SHVURjhEbkhESUlPZzI2Q2Rw?= =?utf-8?B?Q1J5aEl1b3RmdHBqb05mZm53cnR0dGkwNGU0QlJBaWpGU05uWmg3bzZicG1l?= =?utf-8?B?UjRaY1RNcHZIa2VCOFlCMkZCY0RBZ3lscm1lS1AyS2ZRQU0yY3RMVU4ySFEx?= =?utf-8?B?SjVWUkhTajhoR1ZzSm9xK1lENEdhRzNxcSttT2h4TkswTlpJOWZDemh5UU1F?= =?utf-8?B?dWR0YUVidThNRFVCUzU1dmY0MmNPZTZabmMxaGRRVkhuN3RMeUozREIrY2VL?= =?utf-8?B?RXlyUHk0R0NRQ0NpKzNHL1haTWU1dnUzRnpOL0RPTGFrMFNqcmttajFEanFJ?= =?utf-8?B?aDByRG9HcnpqWmhwRUxqU2lQcVhlRFE9PQ==?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0157;6:3kfHNCvZOHAhDcwwQMEH3YQoRuXABp3gGBMh5ItRqKUNILERWCoqZMcv3u7L8RcQ1xUtvENUY4xUw56zfHh/ngnYCv/DQ/fqMozfLsClCFvJBvGsHo1mPz+oGOjqo8zwvbrH53pmc7d/JQVdZHu2O8ZbJ9EwAcmxNkVYN8JQZkoiZ9TOkk1La8JBAzHsDKKOVxKHOVfqv7Jp/CRyiWATAcIqbks0WwykUGKPb7Q5aOh6KpvRoYa6lXR+IcegywiuPvqx3vbSDzBz8OQ6Afwl+057KHKgFkI/Es24js/PFLcyDEiIzFkLzmZrt+yIohrjXbP7htMfBzWemTZTLCsirQ==;5:Pf0QQL9C11Ed5CGQOzUk5BfPYHUXdBJCWXl+HJVUar/8R/LxK1/aPK41+3t+8AcTbOVykPkpw/HbYp09v9A9H/Yx25iHM9AVghUN5WOu/m9Shh4/NbagbrbXk2d5KCGgbsIb0dETlUB7qf9L2k1CkQ==;24:Nz0weEKjdUyrA2KAkKXQt06avD6BrchDTA9+fItXMwzchuENS8ygvNUaT/RnW1QaN8qoUYiMnnha2NiuZ8h6GJA5M0OVsqgXKtMIo1cLino=;7:UT7Bnb1JL9vAewJ0FTmLWWQyOC7oZAzaLuWk3cKC8L3JyD8AkXyuNr7UePduSoCzLgUeXvmBmu2lARoKjfQ1Bk3sJcdTxE0dBHBrUw0xcX5CsnKZYdhosXJH8v8hwX9rrHdYfkmsVPQJ2WY8trPNLiNoAEYDXE08UQl2Fe7CM9xuoiXyvSeUnuZuNx6yEVeWRqkU5bEdFjuV8y5iMKhLdLtLuH9z1s0+6EKnQ7kCJOg= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0157;20:aFw4gdLQsaO6Xz4nSmyOG0BHcjqBFJMtc1A3PQlSOXf9D2vO3TXboYgEXejEuwgqywoNNICgp1xYRrSPWZoZW8bhgpb53v4xnMOCYQhahd2LpHc7KHkJ5NAXnHYvcwCKceR3semdVKk5fVt7xw11sH37KoxssEpl9lYFhXnUnA8EDE7UsgEHkjrpxsGmpIwVqvx8/cCw+u8x6gxvuYW7tbFEjfhEAQqIAhRsQI/udW+32Y2TNURAR37gke6W1j8Z X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Oct 2017 02:35:27.9407 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: aa071cf5-99c7-4972-d303-08d517633aaf X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0157 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The command is used for encrypting the guest memory region using the VM encryption key (VEK) created during KVM_SEV_LAUNCH_START. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Paolo Bonzini Cc: "Radim Krčmář" Cc: Joerg Roedel Cc: Borislav Petkov Cc: Tom Lendacky Cc: x86@kernel.org Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Brijesh Singh --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm.c | 191 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 190 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f2654486b9a6..924ce807c76c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -752,6 +752,7 @@ struct kvm_sev_info { unsigned int asid; /* ASID used for this guest */ unsigned int handle; /* SEV firmware handle */ int fd; /* SEV device fd */ + unsigned long pages_locked; /* Number of pages locked */ }; struct kvm_arch { diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 3bc0d4013aa6..7f13bb8a7078 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -330,6 +332,7 @@ enum { static unsigned int max_sev_asid; static unsigned long *sev_asid_bitmap; +#define __sme_page_pa(x) __sme_set(page_to_pfn(x) << PAGE_SHIFT) static inline bool svm_sev_enabled(void) { @@ -1545,6 +1548,83 @@ static void sev_unbind_asid(struct kvm *kvm, unsigned int handle) kfree(decommission); } +static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, + unsigned long ulen, unsigned long *n, + int write) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + unsigned long npages, npinned, size; + unsigned long locked, lock_limit; + struct page **pages; + int first, last; + + /* Calculate number of pages. */ + first = (uaddr & PAGE_MASK) >> PAGE_SHIFT; + last = ((uaddr + ulen - 1) & PAGE_MASK) >> PAGE_SHIFT; + npages = (last - first + 1); + + locked = sev->pages_locked + npages; + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { + pr_err("SEV: %lu locked pages exceed the lock limit of %lu.\n", locked, lock_limit); + return NULL; + } + + /* Avoid using vmalloc for smaller buffers. */ + size = npages * sizeof(struct page *); + if (size > PAGE_SIZE) + pages = vmalloc(size); + else + pages = kmalloc(size, GFP_KERNEL); + + if (!pages) + return NULL; + + /* Pin the user virtual address. */ + npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages); + if (npinned != npages) { + pr_err("SEV: Failure locking %lu pages.\n", npages); + goto err; + } + + *n = npages; + sev->pages_locked = locked; + + return pages; + +err: + if (npinned > 0) + release_pages(pages, npinned, 0); + + kvfree(pages); + return NULL; +} + +static void sev_unpin_memory(struct kvm *kvm, struct page **pages, + unsigned long npages) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + + release_pages(pages, npages, 0); + kvfree(pages); + sev->pages_locked -= npages; +} + +static void sev_clflush_pages(struct page *pages[], unsigned long npages) +{ + uint8_t *page_virtual; + unsigned long i; + + if (npages == 0 || pages == NULL) + return; + + for (i = 0; i < npages; i++) { + page_virtual = kmap_atomic(pages[i]); + clflush_cache_range(page_virtual, PAGE_SIZE); + kunmap_atomic(page_virtual); + } +} + static void sev_vm_destroy(struct kvm *kvm) { struct kvm_sev_info *sev = &kvm->arch.sev_info; @@ -5638,7 +5718,7 @@ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error) return ret; } -static int sev_issue_cmd(int fd, int id, void *data, int *error) +static int __sev_issue_cmd(int fd, int id, void *data, int *error) { struct fd f; int ret; @@ -5653,6 +5733,13 @@ static int sev_issue_cmd(int fd, int id, void *data, int *error) return ret; } +static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + + return __sev_issue_cmd(sev->fd, id, data, error); +} + static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) { struct kvm_sev_info *sev = &kvm->arch.sev_info; @@ -5700,7 +5787,7 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) start->policy = params.policy; /* create memory encryption context */ - ret = sev_issue_cmd(argp->sev_fd, SEV_CMD_LAUNCH_START, start, error); + ret = __sev_issue_cmd(argp->sev_fd, SEV_CMD_LAUNCH_START, start, error); if (ret) goto e_free_session; @@ -5729,6 +5816,103 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) return ret; } +static int get_num_contig_pages(int idx, struct page **inpages, + unsigned long npages) +{ + int i = idx + 1, pages = 1; + unsigned long paddr, next_paddr; + + /* find the number of contiguous pages starting from idx */ + paddr = __sme_page_pa(inpages[idx]); + while (i < npages) { + next_paddr = __sme_page_pa(inpages[i++]); + if ((paddr + PAGE_SIZE) == next_paddr) { + pages++; + paddr = next_paddr; + continue; + } + break; + } + + return pages; +} + +static int sev_launch_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp) +{ + unsigned long vaddr, vaddr_end, next_vaddr, npages, size; + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct kvm_sev_launch_update_data params; + struct sev_data_launch_update_data *data; + struct page **inpages; + int i, ret, pages; + + if (!sev_guest(kvm)) + return -ENOTTY; + + if (copy_from_user(¶ms, (void __user *)(uintptr_t)argp->data, sizeof(params))) + return -EFAULT; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + vaddr = params.uaddr; + size = params.len; + vaddr_end = vaddr + size; + + /* Lock the user memory. */ + inpages = sev_pin_memory(kvm, vaddr, size, &npages, 1); + if (!inpages) { + ret = -ENOMEM; + goto e_free; + } + + /* + * The LAUNCH_UPDATE command will perform in-place encryption of the + * memory content (i.e it will write the same memory region with C=1). + * It's possible that the cache may contain the data with C=0, i.e., + * unencrypted so invalidate it first. + */ + sev_clflush_pages(inpages, npages); + + for (i = 0; vaddr < vaddr_end; vaddr = next_vaddr, i += pages) { + int offset, len; + + /* + * If the user buffer is not page-aligned, calculate the offset + * within the page. + */ + offset = vaddr & (PAGE_SIZE - 1); + + /* Calculate the number of pages that can be encrypted in one go. */ + pages = get_num_contig_pages(i, inpages, npages); + + len = min_t(size_t, ((pages * PAGE_SIZE) - offset), size); + + data->handle = sev->handle; + data->len = len; + data->address = __sme_page_pa(inpages[i]) + offset; + ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_DATA, data, &argp->error); + if (ret) + goto e_unpin; + + size -= len; + next_vaddr = vaddr + len; + } + +e_unpin: + /* content of memory is updated, mark pages dirty */ + for (i = 0; i < npages; i++) { + set_page_dirty_lock(inpages[i]); + mark_page_accessed(inpages[i]); + } + /* unlock the user pages */ + sev_unpin_memory(kvm, inpages, npages); +e_free: + kfree(data); + return ret; +} + static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) { struct kvm_sev_cmd sev_cmd; @@ -5749,6 +5933,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) case KVM_SEV_LAUNCH_START: r = sev_launch_start(kvm, &sev_cmd); break; + case KVM_SEV_LAUNCH_UPDATE_DATA: + r = sev_launch_update_data(kvm, &sev_cmd); + break; default: r = -EINVAL; goto out; -- 2.9.5