From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752041AbdISUxF (ORCPT ); Tue, 19 Sep 2017 16:53:05 -0400 Received: from mail-by2nam01on0052.outbound.protection.outlook.com ([104.47.34.52]:32170 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751779AbdISUrO (ORCPT ); Tue, 19 Sep 2017 16:47:14 -0400 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=brijesh.singh@amd.com; From: Brijesh Singh To: linux-kernel@vger.kernel.org, kvm@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 , x86@kernel.org Subject: [Part2 PATCH v4 16/29] KVM: SVM: Add support for SEV LAUNCH_START command Date: Tue, 19 Sep 2017 15:46:14 -0500 Message-Id: <20170919204627.3875-17-brijesh.singh@amd.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170919204627.3875-1-brijesh.singh@amd.com> References: <20170919204627.3875-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: CY4PR04CA0071.namprd04.prod.outlook.com (10.171.243.164) To SN1PR12MB0158.namprd12.prod.outlook.com (10.162.3.145) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 48ff9539-67ea-4481-a9de-08d4ff9f9633 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(48565401081)(300000503095)(300135400095)(2017052603199)(201703131423075)(201703031133081)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095);SRVR:SN1PR12MB0158; X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;3:ZSCYm3ObsLOXQkKXnCt1QNjXFAI5ePr6kGMSpNaiNidaIbL09SdqJrYzIq0w1nnDONteVTDS4TtHjmpBkEzmVPMAY7uLdzl38Tj3WwrjXF+KU2kVNX3sZfvdS5YbRuPzro5y2W7v4q219+jJoJkKPo6R6GXMquwCexu3xc4oS1mD/u3HIooYktGGgQsTxjvfjeIryNoAQ4sd8osHgD+mh414U8329vERlIr0bGwvVavHGRgsiSCb8IHHBCzbnooP;25:ABKWD0GkDjpN3ubdmSChtPKvLrZCHnSKp8xju/g9T8w9Ju66PMK4g47/1Qo/JBjho6irSyjJts+vsUt/2d/BS+mkfb//ptaP7NVK8ZMJK9Ms5CgmPRJVYg0KziCfKyqyc84UVjjsa/6xu9DN6wlL+CNXDJVzvE5wYTIBT3FqoUmY4OX1mWvT4H1kSx3jqPtYFS/+rSC02R3hFgP3PiKUTs9b1Lkd7JOc8jiq7vDjyLQQ4uovPXDKPjB3WMBRkXELA6utztphLNfLo9d4TwURJ82wTwY4sI7ExbtdnJTM4ptmW9oB1nSvAjWxKMkhtmUV34Miy1ExrwNkcrPia+zDhg==;31:BS66DnIfBqKj5AJDaHeFJF1+Nd9EBvDlU/iy5WARuRS9pHMfx954ytsCsG0LxB4j2P0paV7Ro8iiG4+8UEitw0DPRx4u0VTId4nj0aGt1aQVvhp1l4HNi2mDQFXRkSHT5ViNCurO4r/7z5Z/JDpXrjgkIIhHrA6ZzXJXiFJCRfRbC2B+u6pplyt1c5ihybDIgmH5nTIzBz+7SeZZ2WFacXDRkFDDNZkBK1ce2mJRMlk= X-MS-TrafficTypeDiagnostic: SN1PR12MB0158: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:VnkE1x47XTSsRkqjGjCWKT+zVVZqj0X8atMkZRaXINzaGhwbRtB1QTKtzHNMyCF4gSaXmbsKUtnymYCnGbG7Dcb1KXpCcWEvhPuhZZZuTMi0T9ef9ZqYVxNHPZzLNhuY3yRXs6cMr97SnI8Brlx5HCfFuzg68O3Q0+HYkMFxvtgCP1xzLJBLbAQxVexuaB/mlljYTf1TWVbBVjKW25+zp7qmzInqfiWJGUA5to2kwrm7Xzt3SO2tTBSB+AEqdIYsZOp/UbHJG+RpqHYAu+9Ltiy4vUYasE0YTCGi2ZrrXz9U7njVUJCVW7ev1hrilqD3pCnsyutser2m8X7t+eSniyIu24W1VhFXyDXE4JcGcJayoYtrJrN1L2f6GkFjDGk6udBgPGsRvAqEkVE0r4uYD/PFQoLhwnc012vWZz59SAGWKkoP1iqGYfH0MCuFjuNjUZ0zqIME1HcRKXtV0ZXY40vj1ATvHnFvq2ZTd6um04W15uue6m97edlibv0a6kTn;4:Z9RpqdLDQyFMFGQ9h4O3nJenrUgI37U36KpKYav7/MQ0nTz0yiVZV0FP3rogVyLYKmz0jb+42ZjOEqKCAUZT+kpySSEscG+uEQfl5sDlM1vEqHepquTUfYg/cgL1NpYy+aYaKWmIHeWwDm5ASIq26vEXWsf9urdXWXsBBtpucyH7CIAeL3Zkp0HY0073I1k3FffaXsxKxmEZPwlHtPtz8VantXBgbsRWxR1AfwfxWKd44OayI0NRptCLovgnAj+eVyNDnSGcM8rPI851OQx5mWRhlb4P4iGjYvSCmXOohTgb435wPU7cHpM8+R4CtGxMynVe3WnPaidB0DKd+IfX5g== 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)(93006095)(93001095)(100000703101)(100105400095)(3002001)(10201501046)(6055026)(6041248)(20161123560025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123562025)(20161123564025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:SN1PR12MB0158;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:SN1PR12MB0158; X-Forefront-PRVS: 04359FAD81 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6009001)(346002)(376002)(39860400002)(199003)(189002)(86362001)(50466002)(8936002)(97736004)(6116002)(3846002)(7416002)(81156014)(8676002)(50226002)(2950100002)(81166006)(316002)(478600001)(16526017)(6666003)(7736002)(66066001)(305945005)(47776003)(6486002)(189998001)(53416004)(25786009)(101416001)(2870700001)(50986999)(76176999)(53936002)(2906002)(68736007)(36756003)(106356001)(1076002)(4326008)(5660300001)(105586002)(33646002)(23676002)(54906003);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR12MB0158;H:ubuntu-010236106000.amd.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtTTjFQUjEyTUIwMTU4OzIzOk9mY2l0bHFlOVhHQlZrMVllSmZnTnRpdG5y?= =?utf-8?B?WUptUFhCZERaVmpYY0wvSWpGQzhybTk5L1llWUtQdHFPcGh0bSsrWHJVWVIx?= =?utf-8?B?SHY3blRydUxycXVJdEZ3STk2WTIwYll2Z0xhRXF6emxpYUFQdmdqVUdXaDdt?= =?utf-8?B?M2V5R1VPU01UU0M4OHN3MUhiOGlUTHlGMDJ3UDhoM1JWNWpQY09wUEF1LzVG?= =?utf-8?B?WTJhTXlKWU43SnVoM1BIOEVpaGJKYk1Ed0l4T2tLcXJrZ3pOYjBLblJqUjd6?= =?utf-8?B?eGd3cUdwQXY4MTYybHRiT1VhMGIrYUxlbTJXbXN6VnRXZE5NZmhxWTRvUlhE?= =?utf-8?B?UEpEaG00STdmemtqOURpekZYWWdkbDZrdGduSSs0VEYyMlduMjB1eEx5MGlo?= =?utf-8?B?d1B5cGE5NWRwdC9wWVptdURzeEdHV296VklkcHYzWXZ3MlhQOXNaS0NQSFNx?= =?utf-8?B?dlkxbUhCai8xTGNyNTBiTHlPelJLSFV1eDIwM3FDbTZYS2xlb1dpckdnNG05?= =?utf-8?B?MGFTMDcxdXNCcVBFK3BjcHgzZVc1UUluNWhZcGI0S3FHKzdZYXJ5d2k2ZFBX?= =?utf-8?B?Ly9lSnAvWWxiUmJQU3Y5QlJmR0U5S0hhWjZmeCt3dFlDY2hKdVgxc2w5S2M2?= =?utf-8?B?dUpCSFVOTFI2d0N3UUtUZVBYeEFqb05IQkppb1NlSGxxS0s3VlU5U0dXajMz?= =?utf-8?B?bzg5bjBYb2UvRXRFdWJsVFFSQ1h4dnlSbGs5UkpHcEd6WFB6cVhka01GRDNh?= =?utf-8?B?SHBzS2tTMjN0UCtUbVZEVmY5bUlMSVpKQVJrZUp5T2JnT1lFdUFhaEd3WVJS?= =?utf-8?B?VGhxdFVoYm9kbjdGT09VbklGZld1aFdOVlMxc044WXBJNDJQakx2Rk13NVkz?= =?utf-8?B?YUEyZ3VqVDNVeXBPNlRENWsxSHpqdm8vMEczQUp1NU1pVVRhRUFpSnNjSCtM?= =?utf-8?B?aG9Oa2tUazlLUkhGZ015ZzJZUmtFajlZZlJQbGVBU0p1ZWtmQkNpc1g2UVVp?= =?utf-8?B?dU55ZldySTBoSHEvY3dBdjYzbVJUZE9hYkVmREZFSFNySlQ3R0d5cG9HZnhB?= =?utf-8?B?aldydGZVTTI3WkRrZm5QRWFUY1FDNGdOMEEwN1pJWGs5Um85by9vQmtYMkVu?= =?utf-8?B?TXphSnV1ZVk4SkVTc2ttTjJyNHpKWXlOUnJrNHVCK1dJNGFMZkRzNXgwT1lz?= =?utf-8?B?ZWdYa3BnaE1UWE9yY2s3M3V2NGRnTlRzL3B0ckduS3B1anBIOGszTXNXYXJs?= =?utf-8?B?WHQvWndnbGdXN203MUJSSlZXcmxONHUxcDhaT3ZJcGlBcjU2QVN3b3ZrSWpn?= =?utf-8?B?ZHFpcUttTFlEV3oyME03VE04eG4xNzh6VGJNaHhGcndJZEFJMDRBUElBN2l6?= =?utf-8?B?UllzL2c1NStSaXlEMXVMUEhyVDhsZkh2bTlERjVReElrNUtiMm1oWEkvdkF3?= =?utf-8?Q?oNOPnS+LZxvbWXLXBUs8XIl8vGJ?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;6:RzVJWIXh6/toSNUqVUIPYFoC76zlBUEeOykF6I2tg7xRrLRP2NHDDfSBoSqtTKoyIpT8IaDjL5z7WWyt+WtmclZdFKdGrdjTArQ0KX8+mwvjKNilAjL560lvtxTvaIrYCA1KmEvmofp/y3CU0cOzvKu2vtbYnVsjOLiphiM3K/txffdVSMCEcpsQuDYACXCvM7IcPA5dSO08TNVnEINrMnUDn8gEft/Arc1+eLz02Y9CXrySe9ojoeSohHWxZjO7wqd0g3ygOqBBdMWNpzZAhGNF9z/kE+hqDF708v0B1SDCamCglw83WyGEX7akGJFVENyfzwbHXVKdsgaW4329bA==;5:yhMf2G0NGPb0/VnF34YCfj+Yhs2bC1zvn1RRVruHxhHrdWmdwu9z8vRGLZBeTTmBb31ojDcEqgC5RdlAn6++IGUDOFaaR9WW9ZknvkJC/7DuV6thiCf6oBEeRzRm217V9wcm49OKvq0VsGAU+CNunA==;24:Ih062YXQ/xQVCaDEsLqpqzyJ9rGxrl+Ba4ibusP7km2a8qa2gglMZnzJHPrbyTZ/WYIStd0hT0phOv1Lp0E3lT9MHvKLpKj4V6OY54wLjyg=;7:f57fXI+wOCRDb/umWRrmeF8VycnkXcigcgsMLcoU3MaMhTqOfk2RgCWcv6xJc0BwDthzYUpZGUv5aeNxjS19O3yh7gdzGhIqNgNUQcXLUNht6QpaQjaI0Kx5JE+UOzFuUTsLoUt2xHVuAH8jeUexlie5Z2XxnbVGl0FyaFCTUdWj82cSb7VNGtoDEkFSQ1xoDBpngIARCt5CP4OC7WblA1f6y/k5L0DjvNvDxrdD17E= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:xXNrxpe4i6aBjbS/YzFerLmcotP3y22ItgcqsMGiqzaX/+JS84CDuU3jSS5jpHPREAF9faG1s2PC9y7TVC2bizFhLzfoWmyMsFmIlnB8/rhqY7HMu5tlM3FM0cYYO4WEZdUZa9iKIWcDAeugWCxtNkrg2ttYdFeMOvYL2ptT84ixdwt8pl95rVQBpZ90daD8ANYgaqXGNkh4KNeLG2vikcOlR6FqHDmUX0J/w+MosB1YwsC2y3g8G0dvWNBCPdR9 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Sep 2017 20:47:04.2185 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0158 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The command is used for creating a memory encryption context. 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 | 2 + arch/x86/kvm/svm.c | 194 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 6bd49e80a16d..7453ef7cb487 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -750,6 +750,8 @@ enum kvm_irqchip_mode { struct kvm_sev_info { bool active; /* SEV enabled guest */ unsigned int asid; /* ASID used for this guest */ + unsigned int handle; /* SEV firmware handle */ + int fd; /* SEV device fd */ }; struct kvm_arch { diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 0149bfa75bb2..5e3e7d46270b 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1540,10 +1540,54 @@ static void sev_asid_free(struct kvm *kvm) } } +static void sev_decommission_handle(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct sev_data_decommission *data; + + if (!sev->handle) + return; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->handle = sev->handle; + sev_guest_decommission(data, NULL); + kfree(data); +} + +static void sev_deactivate_handle(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct sev_data_deactivate *data; + + if (!sev->handle) + return; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->handle = sev->handle; + sev_guest_deactivate(data, NULL); + + wbinvd_on_all_cpus(); + sev_guest_df_flush(NULL); + + kfree(data); +} + static void sev_vm_destroy(struct kvm *kvm) { + struct kvm_sev_info *sev = &kvm->arch.sev_info; + + sev_deactivate_handle(kvm); + sev_decommission_handle(kvm); sev_asid_free(kvm); sev_firmware_exit(); + + memset(sev, 0x00, sizeof(*sev)); } static void avic_vm_destroy(struct kvm *kvm) @@ -5625,6 +5669,152 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) return ret; } +static int sev_activate_asid(struct kvm *kvm, unsigned int handle, int *error) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct sev_data_activate *data; + int asid = sev_get_asid(kvm); + int ret; + + wbinvd_on_all_cpus(); + + ret = sev_guest_df_flush(error); + if (ret) + 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) + goto e_err; + + sev->asid = asid; +e_err: + kfree(data); + return ret; +} + +static int sev_issue_cmd(int fd, int id, void *data, int *error) +{ + struct fd f; + int ret; + + f = fdget(fd); + if (!f.file) + return -EBADF; + + ret = sev_issue_cmd_external_user(f.file, id, data, error); + + fdput(f); + return ret; +} + +static void *copy_user_blob(u64 __user uaddr, u32 len) +{ + void *data; + + if (!uaddr || !len) + return ERR_PTR(-EINVAL); + + /* verify that blob length does not exceed our limit */ + if (len > SEV_FW_BLOB_MAX_SIZE) + return ERR_PTR(-EINVAL); + + data = kmalloc(len, GFP_KERNEL); + if (IS_ERR(data)) + return ERR_PTR(-ENOMEM); + + if (copy_from_user(data, (void __user *)(uintptr_t)uaddr, len)) + goto e_free; + + return data; +e_free: + kfree(data); + return ERR_PTR(-EFAULT); +} + +static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct sev_data_launch_start *start; + struct kvm_sev_launch_start params; + void *dh_blob, *session_blob; + int *error = &argp->error; + int ret; + + if (!sev_guest(kvm)) + return -ENOTTY; + + if (copy_from_user(¶ms, (void __user *)(uintptr_t)argp->data, + sizeof(struct kvm_sev_launch_start))) + return -EFAULT; + + start = kzalloc(sizeof(*start), GFP_KERNEL); + if (!start) + return -ENOMEM; + + dh_blob = NULL; + if (params.dh_uaddr) { + dh_blob = copy_user_blob(params.dh_uaddr, params.dh_len); + if (IS_ERR(dh_blob)) { + ret = PTR_ERR(dh_blob); + goto e_free; + } + + start->dh_cert_address = __sme_set(__pa(dh_blob)); + start->dh_cert_len = params.dh_len; + } + + session_blob = NULL; + if (params.session_uaddr) { + dh_blob = copy_user_blob(params.session_uaddr, params.session_len); + if (IS_ERR(session_blob)) { + ret = PTR_ERR(session_blob); + goto e_free_dh; + } + + start->session_address = __sme_set(__pa(session_blob)); + start->session_len = params.session_len; + } + + start->handle = params.handle; + start->policy = params.policy; + + /* create memory encryption context */ + ret = sev_issue_cmd(argp->sev_fd, SEV_CMD_LAUNCH_START, start, error); + if (ret) + goto e_free_session; + + sev->handle = start->handle; + + /* Bind ASID to this guest */ + ret = sev_activate_asid(kvm, start->handle, error); + if (ret) + goto e_free_session; + + /* return handle to userspace */ + params.handle = start->handle; + if (copy_to_user((void __user *)(uintptr_t)argp->data, ¶ms, + sizeof(struct kvm_sev_launch_start))) { + sev_vm_destroy(kvm); + ret = -EFAULT; + goto e_free_session; + } + + sev->fd = argp->sev_fd; +e_free_session: + kfree(session_blob); +e_free_dh: + kfree(dh_blob); +e_free: + kfree(start); + return ret; +} + static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) { struct kvm_sev_cmd sev_cmd; @@ -5640,6 +5830,10 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) r = sev_guest_init(kvm, &sev_cmd); break; } + case KVM_SEV_LAUNCH_START: { + r = sev_launch_start(kvm, &sev_cmd); + break; + } default: break; } -- 2.9.5