From patchwork Thu Mar 2 15:17:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brijesh Singh X-Patchwork-Id: 9600785 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0944360453 for ; Thu, 2 Mar 2017 16:04:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E7F8D285B9 for ; Thu, 2 Mar 2017 16:04:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE76627BE5; Thu, 2 Mar 2017 16:04:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 60A1A27B81 for ; Thu, 2 Mar 2017 16:04:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754071AbdCBPgF (ORCPT ); Thu, 2 Mar 2017 10:36:05 -0500 Received: from mail-sn1nam01on0040.outbound.protection.outlook.com ([104.47.32.40]:27407 "EHLO NAM01-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752650AbdCBPfA (ORCPT ); Thu, 2 Mar 2017 10:35:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=+Wxl/tbhIksyaeDmplnSW8gKyV9d9t54cl24PqltMjk=; b=bj1ljlAJc12ym8qtjGlYdGfjFVv/vABwm9w6hj4zoSe6rkSs30cdcjsImB1V7yTcYsndxWTuZwH5k3Fv0+bgmzJyIeYFoA1Ewtx70/HVLA3GAkWVwy19OXdNRsJkLwfG4SuAhxHumAlME804F1RbuvQH8xl0L6HDNrF10HOuu6I= Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=amd.com; Received: from [127.0.1.1] (165.204.77.1) by MWHPR12MB1616.namprd12.prod.outlook.com (10.172.56.17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.933.12; Thu, 2 Mar 2017 15:17:38 +0000 Subject: [RFC PATCH v2 25/32] kvm: svm: Add support for SEV LAUNCH_START command From: Brijesh Singh To: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Date: Thu, 2 Mar 2017 10:17:35 -0500 Message-ID: <148846785574.2349.2756610033917941226.stgit@brijesh-build-machine> In-Reply-To: <148846752022.2349.13667498174822419498.stgit@brijesh-build-machine> References: <148846752022.2349.13667498174822419498.stgit@brijesh-build-machine> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: MWHPR14CA0005.namprd14.prod.outlook.com (10.173.227.15) To MWHPR12MB1616.namprd12.prod.outlook.com (10.172.56.17) X-MS-Office365-Filtering-Correlation-Id: 1667fdbb-c540-4ccf-88f5-08d4617f4545 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(48565401081); SRVR:MWHPR12MB1616; X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1616; 3:IWase66zymWqznHsJ0iCJ0Zk3K4/DrZz4DI0zv1Z1zkLxg+6UnZbvXb7ERySYARfElmcNw3B7iMJLHIfLM2Ygr5FNEshkSQe+t9zX6oZwC/Mkz9d2qSruxiiM4o8yc67fP9hb32BHdBQDxfWY3f5CJjcbiMLO43qQ0V11rtGYQDC6fhKg6cnRXgaLNPIS0L+yBs2Aq6Jec5WBc20e/d41ybM2mcNjqkwv0R7fQlNGKunHdeeh+FenM1e9Qf0E9VXDLT/gWCsevOa4X1Y29/nLkYktojWcT0wHfANETC0/JM=; 25:IezEUPKcrQYiWu8cbLeeODXWiKbRlj5s/Ol09TAzBe7kjaf59C8ijmQMRwonZOQO/Ij1GzD8vvIwNvCkAvlSq8mEqnZC7BKR4LYeugHVDQ5ANfbBE9+5UrFPWC/qsTbcVdGy4s5CFFO/m2nGGy7wciayyqsBKM2MdAmSQLbizIXX9wBTgqaeW/T01HCCj75vTMTfwPiND+LWBVvgYc2mPHoNeVJaN1PUKrLmrWdhGx7bR4ugOkwVJE2+3+D2q26k6fuE+JHHcg9lPM3bTtsuoGcj3St4lqCiaWrE5QNtpL1pMMitjHNVmLbcqRpYNJXp0a/kXzeVY+e3vL0VqMe9aZ/lmon+UaqP3ZbbSVyv06lieUcsK6zw6l1DnwBbYX8OfP0IRQmte3V55q1C6WxtTKsy2fmxfxRHPyEA5oVW5Y2rlBYsv0hBtTLF1VHVG2db X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1616; 31:xYCHt9hfw+UuP6hIvE/P0aVUEg0F56C9mxZlcqMp1+0yDRsQGszlirZKs5C20KyYk0KDpaxQGzgDKwGiAppiHWnCum9QQ/j62odYFpmPUTArEuK0qgDqWRu2QXpgTu76J7N0AqKr+AlOCaAQUlvhm8jF6uPoEPnuopU79BOW0z+Cq0mjpIum5IJfebK1mZL/bardyXHVRE3J4ksC727l2Azgh2L+hzI8sWx0apf6kXg=; 20:2ETc+UtMkOvS3DZpVHGA3kprMtbPlhUAcrDa3H6z/E8gmANuMZfzprzClpDYPFlDIOBf9WReFicNB1dJBOL3bDOjudc/YJdAueJHstHCGh6LBHhM0j7htqeA3e8n2gSnyn9WvrtaFb//U8Ggtr4jaKS5YS5EDF+VHtivHZxNja3HRmpevrDvqVqyCEbP54q0PFrzrQVhYsV/Lc/ZdTGivOXfcqS8sRkP6Bq8oLC+OWzf0gdRMKDp+m1Ha0H3oCCcQ+oAAc1JTaxK2KMCczhHIxSFI90S+xMkWZy3hS1Jv5Q1REKCoFORGD5p1UbdNyzsJ5OGufFzGid2WUdrs/N9dyfItlK4lPp3EHD3/woc33ptaWqITHurnL1QxlgJSoctmv4yA5oHtZXiVbG2+sHZeF0rVlBwrs9jNTjOXB8I8FbD9agUcNTumesMLIHscwD7FW2iQCC9dyYdtPeCf4ynpDZgOa/pKfBs00AyEaCTjLEonfziByV95W3iRKSq2m86 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6055026)(6041248)(20161123555025)(20161123564025)(20161123562025)(20161123558025)(20161123560025)(6072148); SRVR:MWHPR12MB1616; BCL:0; PCL:0; RULEID:; SRVR:MWHPR12MB1616; X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1616; 4:r7wNBFRUCKZu4BbfSOVb/4ptxXBIehxyCG3SMZnFRXfOV+P35kqxXvcs8DEdcdpHI4p9ZQziM7w2YikKVBHYBFTWquIJVa6SzbXohnOXtHDtTuMy23wul0lFFiQCQdQYkVdQKm4cjGMDdDWe8aQwy32v9lAGHliTWc49XdnQ0sx5JCbQf2eNEt9rZk6+2/2bgZ28Oo+gE6aSXdCZ5TtLvCuiuGCjLZ7Yoymo7cw5CDQ9c4Y5Gi6C3QtBMttSGp/2V834vXVAvk+t2ikSvcsyoIyDs95Bf39Q7h0rbkyXKU1EUNjAzBvmIJKn7ugOCE2NOfhfi/VWukGg0yyoZuodMRVqxS9+7RW2+yZFfwO0xjp4nZ02otQocgJ4TAOJTwo4zXFBhIOo3Q3GoREA+WSqvSRM2q945TYRtuNVznp050JTBh8ngNA7GM6egrByPY/bxbOxjWIpnxg79EVEd2Wk5c3zHWOB5azDqFZO80q8jnRrT5Mg9URJ7OC8tSn/efdEBWrg/d9f6cnYuWEURHhbJQtsjIxdYHMyR4qPQvraC4tzyABGWgDSIc/qiOg2UKQZlOWEsEb5zQH+4yXStNQbfqgn0puOWF1Yyc36b+c/lMHowxFl4unKOwOBWZ/JN6qBMAWEIjMXu4HTJ3dgKl+8/HkSuziOIsfyh0IR7UsgF+w= X-Forefront-PRVS: 023495660C X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6049001)(6009001)(7916002)(39860400002)(39840400002)(39450400003)(39410400002)(39850400002)(1191002)(7416002)(9686003)(7406005)(189998001)(103116003)(25786008)(53936002)(42186005)(66066001)(2906002)(77096006)(3846002)(47776003)(23676002)(6486002)(7736002)(90366009)(305945005)(6116002)(4001350100001)(33716001)(81166006)(50986999)(8676002)(38730400002)(92566002)(33646002)(6666003)(2950100002)(54356999)(230700001)(83506001)(2201001)(5660300001)(50466002)(76176999)(86362001)(921003)(83996005)(84006005)(1121003)(217873001)(2101003); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR12MB1616; H:[127.0.1.1]; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtNV0hQUjEyTUIxNjE2OzIzOksrMGNUUjFnNDU3ZDI4NkJNY3d2UlpwQU53?= =?utf-8?B?K3BqUUNncTUzc3ZTaTlMOXdLNC84QnlzR0owaG1wRFE1eCtVeGhQTTg2UEkr?= =?utf-8?B?T1pldVFKZWw1OURJQ0x4UDFiQzFPV08xLzY3dGluS2pZTUxOaTF4YkFucW9o?= =?utf-8?B?MDJUMWFUcGRPQmFLZnRKRVFoOWdVZlM1ZTg1ZE4vRDRoaEFwdmZ2QzFKL3o4?= =?utf-8?B?WkJueFVoS2VmbmRVQzZoQkdQN0FMb0ZCb3hPdDdRT0hjNWp5QUIzRURnbmda?= =?utf-8?B?M2tjTEpRY2dpNmJzVjBkbXFxZ0t6dVNvL0dNaU05b0RtV2ZIU09pcU9IaURi?= =?utf-8?B?NkVRSnBsUjBkQVl1bWh2UTFZQ1NIOGlYM2JWd2RZb0Y2WU9NOWFHRnh4ZFVr?= =?utf-8?B?VVNMWHM5TXoyeDhxUFlUNVMvTDhNUUJyL0pYMU1hakphNENhSnR6N0FKMlE4?= =?utf-8?B?OW1EOE9mQnZVa0xabTQweEJRYUI4Qm9WWnV1Y3ZadWs3WTEzT1ByaFZZK1VW?= =?utf-8?B?NXZiZ1FxZUpRWUM4QkVOQ3d5anpZa2JUbFJ4WG9BRWpGVnBCbE9qSVZ3T2NV?= =?utf-8?B?dmFhbS9yL0VwUmZMZS9YYktod0E2WE9waE9FSWhWdGxyTjh5UDUwNnN2VEw1?= =?utf-8?B?c2Z6aGlLSy96ZHpBVlBsK3hYWGpYdW5ZdmdqSHFBMEhWSUo2NW1weDkyQ3dR?= =?utf-8?B?dDFGWHFNbTVHWVVORnJvWG9JVHpQcnd4NGk3WWNaZ2xhZTNSMmV5TDNIR3pi?= =?utf-8?B?NExSQnBhblZPcVNmZW9Dd0ZlUmNYQzc0UWppWlZtVEUveVFpcWRvZHY5WGZ0?= =?utf-8?B?T2Z2QmNtblpyME4vVHArbElBeEtKaFFxbjU0N2hKYU9ZOHlUajMveVhQdk9O?= =?utf-8?B?TzJLSFNOWE1jK2FEcUtxTjcwVmV6anpENmsyQ1dRdHJDSEtBWjdWb1RNSitu?= =?utf-8?B?c3RZeEpWN1l6amxoL1pkbURpdkczTkJVUVZ5OE5ibnpwSjdiWisvRmV3ME9t?= =?utf-8?B?blJEaUt4KytTNDhwT2YvaTZVN0hGcVFkTEhmYU5uSjQ3bzlYcE04cE1yWUgz?= =?utf-8?B?OW9lTWtLSXZoczdzUXQwKzBSV1FjYk84VjZ3ZnEwamRneVpBUWZEWSszZXNv?= =?utf-8?B?amFrOTFMRmNtVTZVcFY2dVNzYi8rUTVCVUgzdHAzWHR3enpSTU5yV3dWc3c3?= =?utf-8?B?VjBOdEZnVmNwTi9OKzR5QUZ5cURSQlc5aE4rd0plT0JWNzlwUHh3elk2T0s5?= =?utf-8?B?ZWRhNGpyNUkwcWk4VWwxcHdVZG1iZ2RObW0wUU5hd3dobTRlSU0xV0N5cUJ6?= =?utf-8?B?RkdYd2RzaEJyekh1TXZNWDgyNTFwbnpjTjJzeDR1WUFQWE5MVDJZMVBOWTln?= =?utf-8?B?Z0lHOXhsNlNya1l3NlZka1djOUdBV0E0L2RSNUV2RFVXcmN5aDRhb1pyQUw3?= =?utf-8?B?c0pwazBrS3lUcGhJeXZFa0plb0lFalQwWW5ia2lLMlVmMFR2K2FkR1RMNVp4?= =?utf-8?B?WEpCSG4wSWpESW5zTHVHbklVWWc3OTVGNk9xa0JTd2NEMENGeUZibkxQZFVH?= =?utf-8?B?TWFXY2RsSnFuM01OS2JiMHZKcTlJRkg2YW41dzM5c3JVT1ZwNCsxdTAvYkFl?= =?utf-8?B?OHhsWnVIVndxZFRBTGlHSmVZR1ZGQU0wdG1vQWFQa3dxbERxNUd1SWZVOGpQ?= =?utf-8?B?cWhZWUNMYXNrR29scXRDc0dxY2Q3RkJCUlRESlpJYnR5dkJycWo3UmhhbjYw?= =?utf-8?B?MzJmSjVBTXhJaElRQXkxdz09?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1616; 6:BmxsC4Vw0TIPFBKYtDxuf7MZu2pIWfMgwM+j8mr4R7TYO4RpnNkYEGPP8liyPLEvVil74t4dQMoZFMWSTbuos9z4FXmQvsyOnFNxjPSq/6JDUnQ7046ciBr9icj6khrzXW7/FQo9KCM40UQcLFNBfzAbjGwRT0/OLb7FcC5s6WG+IweOrQxp5NsxIbTXHSE/2slJ66//+lOpMLQxEWuAzryVj0cQybn4uP8Z5o4UyvHY/LxmSC95Hin2WNYw3A9KcmiQoEj3/w9SBRp8h5LTrSjZkkeEuYlcLTvkFlaISgYN/H4UXTX3j0JRjrPmZ+eMPu2AMHi6bbpvf/+JWWYiIDwQH245tSyixTbwcC6xSGXtRs62todSf+FiuQkqbnuW0icSMPdo6KAsQkjjf6PZJg==; 5:uN/qTu9sVkFbMqkMwfALaPHQ+9d9OBHruJnWwA2jG4+dJ29F9Ye1b6ODkw5bnUHW/6ysjT4Va3GJzIyALIBF+PIpfEhjROqIZ3MIRX4WnkMolFJQucSldieYloVA8SxNC+JNkYFjDy1CBi6+IofrRA==; 24:HSpWq3Pl/TffRICtgaIh5ceMnjDFRuKz2lDl48Lwtv9YreQTR9RJ862/KRXrnjW+GMW+iQT5hvdsyIhlFEdNzgHkfczhh51+JaPaEcFd+Ys= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1616; 7:xaBibI66WXRlt+ZQMeyV8x/fYVTVO441QQUv11nnZSUVyRD45+JJe3NM1hOb/bsjQOvZ7/ooxVvOumzfDNaF+a1lnqMXms8Upg4BTFTSOnN51kUS0A9aamdr8z1d/JUnu3kXkQD852LoOl6XZCpcOTxRmJOGlwxqSiard8Rxb1BZkKwqt4QO2hu8atzzWba0EJPkwaJYG80N8H9NotiQ0y4joJa1fDcAzqoUuD7vtX9arEHmOavMBsP1EuuFvz1Y7U4ridJ2TDPxlDPTathJ1C9nYbZ7YVzrvXVkAMxOd6j2B+eSozAAYSwVQQv+crWQxXLHBrwdBJTWG0idGlR5bg==; 20:11X/VeHhtGRm+6xBQdnhUq0kp7roVX3fJpxB+tFQtZXhnccUEfdq1j1mWj7Sm0Fl0qVs4yrigObmi4354y/ytKvDQsyt+MyYfltP0oA2+ToOpc/7NiRB8hcaQxk/XieGBwecne3g4mEJjTck4uNjNQJg4DxBI8QA2rvfjE27itvS2Xqqp9k4n+L/cnE7/h/q23Yqp0Ge0HqLwKB9hOsjrgAoQAej6oK/xIa1oOLpKPVd5WbLE3VJSOLzIGPIkymt X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Mar 2017 15:17:38.7320 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR12MB1616 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The command is used to bootstrap SEV guest from unencrypted boot images. The command creates a new VM encryption key (VEK) using the guest owner's public DH certificates, and session data. The VEK will be used to encrypt the guest memory. Signed-off-by: Brijesh Singh --- arch/x86/kvm/svm.c | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index fb63398..b5fa8c0 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -497,6 +498,10 @@ static inline bool gif_set(struct vcpu_svm *svm) /* Secure Encrypted Virtualization */ static unsigned int max_sev_asid; static unsigned long *sev_asid_bitmap; +static void sev_deactivate_handle(struct kvm *kvm); +static void sev_decommission_handle(struct kvm *kvm); +static int sev_asid_new(void); +static void sev_asid_free(int asid); static bool kvm_sev_enabled(void) { @@ -1534,6 +1539,17 @@ static inline int avic_free_vm_id(int id) return 0; } +static void sev_vm_destroy(struct kvm *kvm) +{ + if (!sev_guest(kvm)) + return; + + /* release the firmware resources */ + sev_deactivate_handle(kvm); + sev_decommission_handle(kvm); + sev_asid_free(sev_get_asid(kvm)); +} + static void avic_vm_destroy(struct kvm *kvm) { unsigned long flags; @@ -1551,6 +1567,12 @@ static void avic_vm_destroy(struct kvm *kvm) spin_unlock_irqrestore(&svm_vm_data_hash_lock, flags); } +static void svm_vm_destroy(struct kvm *kvm) +{ + avic_vm_destroy(kvm); + sev_vm_destroy(kvm); +} + static int avic_vm_init(struct kvm *kvm) { unsigned long flags; @@ -5502,6 +5524,282 @@ static inline void avic_post_state_restore(struct kvm_vcpu *vcpu) avic_handle_ldr_update(vcpu); } +static int sev_asid_new(void) +{ + int pos; + + if (!max_sev_asid) + return -EINVAL; + + pos = find_first_zero_bit(sev_asid_bitmap, max_sev_asid); + if (pos >= max_sev_asid) + return -EBUSY; + + set_bit(pos, sev_asid_bitmap); + return pos + 1; +} + +static void sev_asid_free(int asid) +{ + int cpu, pos; + struct svm_cpu_data *sd; + + pos = asid - 1; + clear_bit(pos, sev_asid_bitmap); + + for_each_possible_cpu(cpu) { + sd = per_cpu(svm_data, cpu); + sd->sev_vmcbs[pos] = NULL; + } +} + +static int sev_issue_cmd(struct kvm *kvm, int id, void *data, int *error) +{ + int ret; + struct fd f; + int fd = sev_get_fd(kvm); + + f = fdget(fd); + if (!f.file) + return -EBADF; + + ret = sev_issue_cmd_external_user(f.file, id, data, 0, error); + fdput(f); + + return ret; +} + +static void sev_decommission_handle(struct kvm *kvm) +{ + int ret, error; + struct sev_data_decommission *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->handle = sev_get_handle(kvm); + ret = sev_guest_decommission(data, &error); + if (ret) + pr_err("SEV: DECOMMISSION %d (%#x)\n", ret, error); + + kfree(data); +} + +static void sev_deactivate_handle(struct kvm *kvm) +{ + int ret, error; + struct sev_data_deactivate *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->handle = sev_get_handle(kvm); + ret = sev_guest_deactivate(data, &error); + if (ret) { + pr_err("SEV: DEACTIVATE %d (%#x)\n", ret, error); + goto buffer_free; + } + + wbinvd_on_all_cpus(); + + ret = sev_guest_df_flush(&error); + if (ret) + pr_err("SEV: DF_FLUSH %d (%#x)\n", ret, error); + +buffer_free: + kfree(data); +} + +static int sev_activate_asid(unsigned int handle, int asid, int *error) +{ + int ret; + struct sev_data_activate *data; + + wbinvd_on_all_cpus(); + + ret = sev_guest_df_flush(error); + if (ret) { + pr_err("SEV: DF_FLUSH %d (%#x)\n", ret, *error); + return ret; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->handle = handle; + data->asid = asid; + ret = sev_guest_activate(data, error); + if (ret) + pr_err("SEV: ACTIVATE %d (%#x)\n", ret, *error); + + kfree(data); + return ret; +} + +static int sev_pre_start(struct kvm *kvm, int *asid) +{ + int ret; + + /* If guest has active SEV handle then deactivate before creating the + * encryption context. + */ + if (sev_guest(kvm)) { + sev_deactivate_handle(kvm); + sev_decommission_handle(kvm); + *asid = sev_get_asid(kvm); /* reuse the asid */ + ret = 0; + } else { + /* Allocate new asid for this launch */ + ret = sev_asid_new(); + if (ret < 0) { + pr_err("SEV: failed to get free asid\n"); + return ret; + } + *asid = ret; + ret = 0; + } + + return ret; +} + +static int sev_post_start(struct kvm *kvm, int asid, int handle, + int sev_fd, int *error) +{ + int ret; + + /* activate asid */ + ret = sev_activate_asid(handle, asid, error); + if (ret) + return ret; + + kvm->arch.sev_info.handle = handle; + kvm->arch.sev_info.asid = asid; + kvm->arch.sev_info.sev_fd = sev_fd; + + return 0; +} + +static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) +{ + int ret, asid = 0; + void *dh_cert_addr = NULL; + void *session_addr = NULL; + struct kvm_sev_launch_start params; + struct sev_data_launch_start *start; + int *error = &argp->error; + struct fd f; + + f = fdget(argp->sev_fd); + if (!f.file) + return -EBADF; + + /* Get parameter from the user */ + ret = -EFAULT; + if (copy_from_user(¶ms, (void *)argp->data, + sizeof(struct kvm_sev_launch_start))) + goto err_1; + + ret = -ENOMEM; + start = kzalloc(sizeof(*start), GFP_KERNEL); + if (!start) + goto err_1; + + ret = sev_pre_start(kvm, &asid); + if (ret) + goto err_2; + + start->handle = params.handle; + start->policy = params.policy; + + /* Copy DH certificate from userspace */ + if (params.dh_cert_length && params.dh_cert_data) { + dh_cert_addr = kmalloc(params.dh_cert_length, GFP_KERNEL); + if (!dh_cert_addr) { + ret = -EFAULT; + goto err_3; + } + if (copy_from_user(dh_cert_addr, (void *)params.dh_cert_data, + params.dh_cert_length)) { + ret = -EFAULT; + goto err_3; + } + + start->dh_cert_address = __psp_pa(dh_cert_addr); + start->dh_cert_length = params.dh_cert_length; + } + + /* Copy session data from userspace */ + if (params.session_length && params.session_data) { + session_addr = kmalloc(params.dh_cert_length, GFP_KERNEL); + if (!session_addr) { + ret = -EFAULT; + goto err_3; + } + if (copy_from_user(session_addr, (void *)params.session_data, + params.session_length)) { + ret = -EFAULT; + goto err_3; + } + start->session_data_address = __psp_pa(session_addr); + start->session_data_length = params.session_length; + } + + /* launch start */ + ret = sev_issue_cmd_external_user(f.file, SEV_CMD_LAUNCH_START, + start, 0, error); + if (ret) { + pr_err("SEV: LAUNCH_START ret=%d (%#010x)\n", ret, *error); + goto err_3; + } + + ret = sev_post_start(kvm, asid, start->handle, argp->sev_fd, error); + if (ret) + goto err_3; + + params.handle = start->handle; + if (copy_to_user((void *) argp->data, ¶ms, + sizeof(struct kvm_sev_launch_start))) + ret = -EFAULT; +err_3: + if (ret && asid) /* free asid if we have encountered error */ + sev_asid_free(asid); + kfree(dh_cert_addr); + kfree(session_addr); +err_2: + kfree(start); +err_1: + fdput(f); + return ret; +} + +static int amd_memory_encryption_cmd(struct kvm *kvm, void __user *argp) +{ + int r = -ENOTTY; + struct kvm_sev_cmd sev_cmd; + + if (copy_from_user(&sev_cmd, argp, sizeof(struct kvm_sev_cmd))) + return -EFAULT; + + mutex_lock(&kvm->lock); + + switch (sev_cmd.id) { + case KVM_SEV_LAUNCH_START: { + r = sev_launch_start(kvm, &sev_cmd); + break; + } + default: + break; + } + + mutex_unlock(&kvm->lock); + if (copy_to_user(argp, &sev_cmd, sizeof(struct kvm_sev_cmd))) + r = -EFAULT; + return r; +} + static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .cpu_has_kvm_support = has_svm, .disabled_by_bios = is_disabled, @@ -5518,7 +5816,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .vcpu_reset = svm_vcpu_reset, .vm_init = avic_vm_init, - .vm_destroy = avic_vm_destroy, + .vm_destroy = svm_vm_destroy, .prepare_guest_switch = svm_prepare_guest_switch, .vcpu_load = svm_vcpu_load, @@ -5617,6 +5915,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .pmu_ops = &amd_pmu_ops, .deliver_posted_interrupt = svm_deliver_avic_intr, .update_pi_irte = svm_update_pi_irte, + + .memory_encryption_op = amd_memory_encryption_cmd, }; static int __init svm_init(void)