From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752655AbdJDNUC (ORCPT ); Wed, 4 Oct 2017 09:20:02 -0400 Received: from mail-cys01nam02on0084.outbound.protection.outlook.com ([104.47.37.84]:31550 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752331AbdJDNPX (ORCPT ); Wed, 4 Oct 2017 09:15:23 -0400 From: Brijesh Singh To: x86@kernel.org, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: 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 Subject: [Part2 PATCH v5 20/31] KVM: SVM: Add support for KVM_SEV_LAUNCH_UPDATE_DATA command Date: Wed, 4 Oct 2017 08:14:01 -0500 Message-Id: <20171004131412.13038-21-brijesh.singh@amd.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171004131412.13038-1-brijesh.singh@amd.com> References: <20171004131412.13038-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: MWHPR2201CA0056.namprd22.prod.outlook.com (10.172.59.30) To SN1PR12MB0160.namprd12.prod.outlook.com (10.162.3.147) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c87cf9a5-baeb-4dae-25c9-08d50b29f47d X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(2017030254152)(48565401081)(2017052603199)(201703131423075)(201703031133081)(201702281549075);SRVR:SN1PR12MB0160; X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;3:tgMDAqmg/JAGrkLB7AT7oEkPmHY2MPNFLRTWRTVuU3sq3+8DBFmtGG1K2hwVANcrN2ehKpPKoeVmeB4THW37z7SK7Yxqup7qcjMYpaBbRxw//fan8SbFCWau57D/tOm9YYsJCpn6vdIETPitA9rdc/wPv/nIC70E1FTkrcTuLnJABrsM0gvNYEOEgjJCdTIoihe2YjwUgeu7Rn2CTi0FHtlYhzdvOooOwp22gH7Q7ELBtRBhLgw6Ef60781QzhVL;25:or+2/P0N3RPvI2a6tReapqGYltVrrG6iCzoCkdr50iL9vaSjwHTP2lOkJp6JwiFGoRtVlZloffUPl9al19zboEmzd99u+pBPosAdGZgjbPKjKbyZCK1CG1SErqBLZV+F7VYz+yaCBqF1Bu/MS5THVT69nR53pjs0C7PfKQg8geNm5aw5iIKgM6se7lwj6YtHk9yzpkTqo6h0r83OFy/65jFwd6Rsy0OUhDe7htxkKrvT6puuU/Vc6t++7wNjVu+xZjvmI77ufx/WFXZipURqzMF8e/a35sodjmmFSRGHmY84V21yCaOmUaRRUOFBq9J9IWGdhOzvbDrzCcXkETseSg==;31:YNbondrX5Siw/mkrsczjYhvIAGaRzH0BY+1rP5ytuejtQesvXojC9ATFRMapCVw3MswvCytrKNoByT544p4EPdmg7PYpr2/ZFyNUXpabvgBdz72IJ6UUryaY7tCQ+0HqJPv8mVJUg6/9OLxspd2+rTG3/4zWkj1TIEe6rmzwgXAZi1j0/UqPqDStz6OhKFflwVedkwB7SJOzjeotnVvPdg/NYnOsLLJrbSC2ZKqi92U= X-MS-TrafficTypeDiagnostic: SN1PR12MB0160: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;20:+iy9+o4uh7NAXH0aemNqpQzu4Qif+B8KbyIKfn3IzpuMslOTddPsgjwuHhhlOzfquPf3zuC1u2dO/+krJhL3vBUMiWE2xU1wvJcfjZ+ETTQx/m4qeJ2RL3EP2sadszPdaPNzd1MFUnI8aRhmz3WBX+FG552Ve3nPQrsOuKDWjyOkNMBz0tCA1Cug1KW4j5IVFzIzHENZ2LrQoVrEdUbA+MqRYYt1o504fJnU2u2DJ6kEQoWUbiY7xq9Z1XNt6QD/hj3aMTqO4lo1qbLjcsMj4ECzXNH9osE+X6YnXmP4BXMxGA6PDijFn8PmZVViINbLrZ00a5ijpQf+9Gd8WitjkLDVPGDrW4t+zUtLWNEqWDAJP7wPaoWn9UZYYJHWESV9QktZCnPVw6MRm7OsOofLCrsfKRM6sDIC7mvxKWIRzRWn0H67JGGIGRQuduWTYVRo3VaVtAvjEYeQnGV0X9aU6wq7Yd1YJRmCtVBykiqIsXz7aeK5jnPzxVG6/hUfXjpV;4:+s+ChB3/PVW/vbp89cSIYB3LMNP8QlMSTy8arVSSu5V8Wv9qWwfjQmWq4YJ7UZi5bCY0+xUERVEmU5y6dORDnKPcdiXVxQWn/eG3oVy9RgEHyv90EBN+INg7SOgTAe3W7fBt81bR2Yo3VU/X1SHYSUb8H9/lccjs24Ndqh8yX/XbpyvtrMSIfhQk5dKkE1JoYE8o6ZM0TOsvMgnx5b4l+EBpI9LiXK0AZG93O1wUWJjdNiVIXm/DL07+VzLj86XnJ7HO5JDnf2AHJ31dfMdknzNfNA6puk3jRwuvDM6RBQ6DeiPo4cHLImthbb1VeJRwxjiSeXjsidgYBTaT/GiveQ== 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)(100000703101)(100105400095)(3002001)(93006095)(93001095)(10201501046)(6055026)(6041248)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123564025)(20161123562025)(20161123555025)(20161123560025)(20161123558100)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:SN1PR12MB0160;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:SN1PR12MB0160; X-Forefront-PRVS: 0450A714CB X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(979002)(6009001)(39860400002)(346002)(376002)(199003)(189002)(97736004)(86362001)(23676002)(76176999)(53936002)(50986999)(1076002)(6116002)(3846002)(478600001)(36756003)(47776003)(101416001)(33646002)(6486002)(66066001)(189998001)(68736007)(105586002)(53416004)(50466002)(4326008)(54906003)(8936002)(305945005)(6666003)(2870700001)(81166006)(5660300001)(81156014)(25786009)(2906002)(8676002)(7736002)(2950100002)(7416002)(50226002)(106356001)(316002)(16526018)(969003)(989001)(999001)(1009001)(1019001);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR12MB0160;H:ubuntu-010236106000.amd.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=brijesh.singh@amd.com; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtTTjFQUjEyTUIwMTYwOzIzOm5ndmpDWVd4RCtYR01WQmlQTkRVclR4QjFr?= =?utf-8?B?b1QxcWVsRUE3TzRmV0FaS2FNeFVGbHNpT1dJZk10ZDB5UFVWdnJwOEYweU1T?= =?utf-8?B?REpHUkx3WUZaYmJDbFRuTjg2bEROdjZKVTlidDJNTlNIeDB6RDV3ckRZL1p4?= =?utf-8?B?TnZXMHdMVklBcWtqSks3YTM2OVJ1NVFoU21IYjF1WGU3YUhQbER3NUpBVlRQ?= =?utf-8?B?S25IN0hqeTJ5UElIYzVkRCtpSDhnWUVOQkN0QmxuVW80WkE0R0JVNHhhZHkv?= =?utf-8?B?ZW8wU0tQc3JvQlJCNkU1TFI5TXJqL095TGtqTDNSSCtFM1BUSzZ0TFYrWlVn?= =?utf-8?B?cnUvQjl2SFJmdWpscWdZZWVKN0VPWmlvYU41MEwvemlnMk9Raksvam03MERQ?= =?utf-8?B?OGtCd1BBR0xNbXI0bnJmVGo4VnAzQnFuNGpOWlhrUGFLbWhrZytxKzZ6RWYy?= =?utf-8?B?QTB3disrS291TlI1Qi93SUkrcnh2UWdIR3J1ekhtVVJBUHRJS1RYMEN1ZXlx?= =?utf-8?B?ejBSeW9Kb0p5WkpFQitTdE1abkR3cFhrbHRVbDcyaDdGL1JxL2VYUm84bWUw?= =?utf-8?B?OUk3Ny9zTzJ6eHhyRnlSOTZKc1lFdDZ2Tmdmcy9sZTUwTjFMMmxUaEt0Zlh2?= =?utf-8?B?ZVV1emtDS1dNeDN2RkxvU3dpa1V5M2VUb003d1NHYWRWYzYwWHRzS2JLeFB1?= =?utf-8?B?NWZEZVpPWVVKMCtheVBZWUVKYWgzeFE5OHBzMEhmOVMvSWdTSTFXM0JwbWwy?= =?utf-8?B?ZjJ4ZkRQWW16TnFzODBXK25CSDlBR0F0bE1UZHdXMDh1ZndxRjRSSFpma0I2?= =?utf-8?B?U0hISnRKNU9ialgyWkI1YnY0TWNPMXBwRUJCSTRQQjYyWVZLbDlJTzFMUWdn?= =?utf-8?B?bHFScllscnNvT2RBVDhpTExwZlBGSy9OQnQ4Z1VISzJOR21hT0R5ckpKMzVU?= =?utf-8?B?dTVCY2ppMG42dVUzTjJGdm5vcUVSUHB5a1ZpdkprV0JRenVqcS9pMmUyTzBS?= =?utf-8?B?UFIyRWc0RkZyZC9oWWtOZlE4bFpvbERNcUh4bGdlRC84dGczQkM4U0w4RjNB?= =?utf-8?B?cUM2bGFqK2VxcXhZSk9mbjJSTnluSmpyeWRSb3lKL0dwRFJXVFJlQm5TaHNa?= =?utf-8?B?V0V5VXNQVUREcHBaUkNkMGduTVJzNjdQRFZZREplVzJpUlBBTFZVRW5rMlBx?= =?utf-8?B?WmMvM2d0SzVET0RjSFlHTlFJbnN6b2krUTVjWkp4VW11SU9sdVp4TXFvSUtK?= =?utf-8?B?YVBQdUhMc3lpTGlUUGhXbHBZeitxTTZTb0dtLzhrQThJUks1WUNLKzhxQ2NE?= =?utf-8?B?Y1d0K1U2MGpqT0x5TkNZMWNURVpWZVJ5NTBDN01Keit2TGU0dXpPNnBkQjFH?= =?utf-8?B?dEkzc2hrUHR3UDRhVGxwU2VsN1JJbUdDbXFMemplTmRSME1CZmkzMGJHaHRk?= =?utf-8?B?SzNvZmRybGM3ZGpvVHBvNC82ZS9jYnlMbC9HSEdtVFhuZExmdVN1T1h6cmdx?= =?utf-8?B?R2RrdG5PaUh4ZkpGazkvN0dIa1drNlB2UnJzaTVBMzY3VnBteE9BV1FzOGhy?= =?utf-8?Q?JQ3mJ4/5tsiwotsvcF2ZxlKPEbVEn4ByPvVNgqFYs4cM=3D?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;6:/aIkP//Y9dx5QxsuT42pEdZvwNwNYVHx7oAdyHBmOGDoXMP4FvSOgIM+ELQ/hT6iASV20AEjdvCTtAR/fxdS6GwYOZ/Wb2SGcaOhSbfObrKifXQSEhoEseqGJn3U4xt0+hp0bkR/PQ/bxXIbzbvEox2MLuTiLOzqDYfCKm1dj6LwG9O3eYmVcbc92RPl60sYS22qJnGYOEC52QyJD6Zw8ysjzESKjAMB7+meWeJ5zMT61HRPMlH5Qk48BwxspgXmea5fH72Un+ByK+7i6jYFE883L9wjhHhxM5GQ6vDPAOq5I00LtsAuonCwUJ0+51nk9dZThQQxWmHUcMbJDhPi8w==;5:BhiieJrfClUb4mVy71VVXnhrW5nLMgPECZWvg4Hg1Kqq5KX/giYAguDg7E5s8G9USxaE6puJ3XDauC4VzwdSpdP3ZTVeBbcxxkzpDnCpsRItCBp2z4wmtVyjPmG2aiYkQHiTAytSQfoWOYDSuNJg6A==;24:nzA7j070T9iec5dGzP33zGQIyOVi1Pybvj2I23U7B+E2N6JINl3wQwYFWmGeVPWcgfA/mIKxqHvXumGt6vPUs/YasDzbdkKr7IxjTe2qBpI=;7:1GLbKg1IG3bstylJpGD7bWNYQF6Y+HGx7bvOsdoPOCzzrCvPifRMlwVPrJyq05KLfEn4w7hn5p3SJScRT8AcktWwT8g6bersFRXxmsV32SZEhcVSPW4ggthR0MaYphPTly5hjwjEYlo5Ali150LrqPPBOE0zbVhDKDSZzbogRgRHa6bZLPyTkW6CXyXwMvxcHOWBaKey2OQN9ub2O3PCEHIPGIcP245VtDdWF96F5e0= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;20:PkGqVWKkQjee7FdGTuP3Dx88deu0xWh04D8cls3cZf4qauv+cIeMrSZYO/h6TbMAea6oOz4ibzeDi6b5DSD1ho9agQsbmVDqjfSz9eGXqiq+4DX9ZlQtrzgugb7jXqGZXojISNTTtePhowtdJP+63YozYbf1jRwF7mA+Oe/a/DAb+18OBmAOVlmLHn3PHW8qgG1fD/YoDRvMKvrQx3sdp7OvXdSx4OENC913BNn1TuU5NHIvtCFPE9ZqwC/5FlyD X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Oct 2017 13:15:15.0263 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0160 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 | 193 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 192 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7453ef7cb487..86006dcfe574 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 locked; /* Number of pages locked */ }; struct kvm_arch { diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c599a87810af..0871d3ab9e6c 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) { @@ -1582,6 +1585,82 @@ 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, pinned, 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->locked + npages; + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { + pr_err("locked(%lu) > lock_limit(%lu)\n", locked, lock_limit); + return NULL; + } + + /* Avoid using vmalloc for smaller buffer */ + 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 */ + pinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages); + if (pinned != npages) { + pr_err("failed to lock %lu pages\n", npages); + goto err; + } + + *n = npages; + sev->locked = locked; + + return pages; +err: + if (pinned > 0) + release_pages(pages, pinned, 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->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; @@ -5697,7 +5776,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; @@ -5712,6 +5791,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 void *copy_user_blob(u64 __user uaddr, u32 len) { void *data; @@ -5785,7 +5871,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; @@ -5815,6 +5901,105 @@ 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(struct kvm_sev_launch_update_data))) + 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). + * Its possible that our cache may contain the data with C=0. Lets + * invalidate it so that we can get the recent contents after LAUNCH_UPDATE + * command completes. + */ + sev_clflush_pages(inpages, npages); + + for (i = 0; vaddr < vaddr_end; vaddr = next_vaddr, i += pages) { + int offset, len; + + /* + * since user buffer may not be 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; @@ -5837,6 +6022,10 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) r = sev_launch_start(kvm, &sev_cmd); break; } + case KVM_SEV_LAUNCH_UPDATE_DATA: { + r = sev_launch_update_data(kvm, &sev_cmd); + break; + } default: break; } -- 2.9.5