From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751747AbdISUua (ORCPT ); Tue, 19 Sep 2017 16:50:30 -0400 Received: from mail-by2nam01on0056.outbound.protection.outlook.com ([104.47.34.56]:55572 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751886AbdISUrT (ORCPT ); Tue, 19 Sep 2017 16:47:19 -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 21/29] KVM: SVM: Add support for SEV DEBUG_DECRYPT command Date: Tue, 19 Sep 2017 15:46:19 -0500 Message-Id: <20170919204627.3875-22-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: 37ac42ad-aef4-4b36-8c9d-08d4ff9f99d0 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:l2mTYiAytmnlWZ7YKhb78m4g9IkbZe6Jd4FuhgQoCUzZCxS+EPph3Je04GuSp4hWA3/+mBQA0Wsc49AafXliIuoRj1KT67DAbnXbBY4sPZP/NKi3MKr8NPzvong1aNEctFCDi4wV3OIMXcsYnH2cMA+YwSe/J9g/FJgCOsLmKaX0Qm0xj+Bcd6Lbwv4Km0XDUcSCD4lGU8wJWvOeBM8N6NfbvbVGQ4C+y5Dw+TBU0P/JO1rxXCFuKJocZ1p6aobP;25:O1Pk9JNDa7217NoUdfEAhZrRcY5dp/g/ZRQAl/zHXpOT0axgAqJKS/w5B0t/qWIACkoahZuxOYDpv4HP+PIQb66qcfs5SoHO83U8hlzfDHsQfm8LNvNNfBDmGc21hmXh7KPzA+jjawfRFug8tX1RLrj9ktQGVJ6qrNuDiG6IGeEdgnbq+hv7Lm69Gms/5M5DaI36HCeLrqhVrg7aN60iX0Wvk0oZm3AQQUhUI0RFx+nNtuvTJ0/GPQ3ItR3AO2CGDj50MGGmscbNf4MxeNschBXaOqs8UoCUiID4sO7KxshB0xkAEWi1xKpEO+zSa2uKHdywK2pJdzVabU+BVmfXfg==;31:GkXDx5qc/FL7jZAjeODMz/b+k0H9nnVQmKeItdujHEYI9sT27i5VUy93Hsa05T/KRhAQuCxQlhDH/KpX5vFi0NSZddElfMFBW56AInCGcSqlQuYF2FwF6YARAXiy64dNii/eVZfBCu0vZgTUO1IIqTWXNIUREjye1vR6YJCz+8KpPsjWMLmKqxEAW2MJeIdGGS4kFNdY2t/cLEuEX6eYxEnl0WeJvwScaxhCUBbLYHY= X-MS-TrafficTypeDiagnostic: SN1PR12MB0158: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:HqSz5hI/8ztv/d5qFg7ixma2MSF6yv+wLoSOY4t2zRZK/r9MXK4ebp0eAGhgPiKps/OPwSVbndMtSUpxJpereiqXUp3m2+BNvAqyJiybV4puozicsZMx5eHkxdCUsYJEeUv+tnYNmhA2w9AqT1AS47i/6jvXj5qFOKoKfjQApzjWufOr1u2oDevz3vocnd9vwVeUkZ/M2iH5XasSt6rhGV8eAijtv1Vpq8IUpXnYJSwJjjTR5K3vDDtT4deflG84cL9KXFrnUC92vxsbWkR8f2ih6c1QWJ6vafYwe4fHrEmXVNuq65OYRuGFKWXSFqOXsL4wSOSKhueAEW62BtFdO9i1yHHHQQ33zu80SQJENMjy+WvtQJEeYuFoJcU+dvqEZ71YVq525sNHkxmgukns9mJ5TlwWYcDV3JwbNm2CD+QIn8jHgBRL1jH8doE+W3DcRUgUVcvaSJoxdj3Axpu/7090FoQ4GxX6+5XW03AycJ4aFlaAmZEPOEmhhibuKJ0b;4:L5YZWcH0kuXQDF5w+BU9iranDwfWu01H8Bfeactd97vr4Y7oPXrgO3aarjnN0rsGz0CtEPQApgE8quw/5ssGAolLeyFQId8Q77dVzAWrmi9Benjna7IKRu3vRvg6sFnEe0gmQgIDDve+WsETsX5cKA1Bkzb4I/IS5VSol9IscD6YAOgUT1cRKPzxPQ3Uy4fA7D/yVO8S/VpA4IzpMbC6uuAY3TXPVjY+2GTJHFSt8agThn7s46gHhWuCsgqE2Lw5yVykjai1TU8xUfQQGsDd4CECiH4tXlEOGe4cX5XZudtL1kt2yuRQZlGJ6dNrunl6a0knVWcUvUz6HRn2F6fMbA== 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)(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?MTtTTjFQUjEyTUIwMTU4OzIzOnQ4VjhBNnQ3eXJXVDZpRjhnRXJCKytQRkRh?= =?utf-8?B?RFVvMFRyZXY0dmJ5cXlyd09HTjYzMVN4U043NTdTNDI1cndiS2UxUVgvandM?= =?utf-8?B?Unc3QWljODFFZkNEN2Z2UDFqR3FBejBPaGR3aUNSMjY5dGFmR1haM3UzTVBm?= =?utf-8?B?eUs2UmdjSk56K244OVoxNDBOUHJCdWRDd2ZacG93U1V5VjJtTjRWTmZlWG9k?= =?utf-8?B?aGxGWnQ2TE9JRmh1aER3bExibEt0WVd1YWRIRUZlVTVIcVFmV1ZtYkNwd3Vo?= =?utf-8?B?TWQvRktiOXZGL2dKbVRLNDhvcklJTTkwUERvQzBOaXdKZzZjdGpZbmo4cjNo?= =?utf-8?B?TlJ0VHR5SmxVUkw5VzRzOW1qNTNDVEJIY25JdFo5NXZRa2dHZGlKbDB2TWR3?= =?utf-8?B?TVZKd0pBbWplNVVTdFJuWDZMMU0zbDg4NndQZXZvcmNUdDVwVEF1elJRUW9Y?= =?utf-8?B?K05xYVFPYVhFK1FPYkZHUEZqZXROcVhtVDVMV0t1MmZvVDhrbkRwUG43R1lh?= =?utf-8?B?ZFlKSnhVYXRWMWkreXlkbXozbXdFQTFBMUpZMHl2VGZNTzN2NTMwcEk0TWhv?= =?utf-8?B?SEVZdWJncWtRWjdsajN1cU04ZXZmVkZVNDJpSmVTblA0TVlibU5sa1Z1ZGY2?= =?utf-8?B?UCttbjZUbHNYS29oY2FpVk5sK1JTSkNOWHh1ZDZ5WERTdGFaUDJxNTFzZWlV?= =?utf-8?B?cjc0QkdSdWppVTk2QXk4bU5BeEpVaTVmeHFIZi96RUJpQXpTcWc5R1VJK1Rs?= =?utf-8?B?TEtKRGJHWXpSTGIrT1FncEEyQlRmaG5oVW5KQ0JHT2pwK0svWTR6dXJuUzdP?= =?utf-8?B?RmEvUVRSYlNJdHpBNjNTK2tJaWI2U281eEdSdjZBdnNjMTR3ekdMRFpXZnRK?= =?utf-8?B?eElWd0dFd09pUVZ3eFF6eEdOY3h6NG9IUWtKeGFkRDZlNVVkSjlnSjJFSWVY?= =?utf-8?B?dEJNWDRBbVdIbjNVa2xwbTdVRjQ2KzdUR0RjUDlrenExL29mSVJkc0ZVcGdK?= =?utf-8?B?cldiY3pCL0dWN1hBak5GUkxlWTBCSmZkcElyOXFkYWxDd1B1aE5GMTlRNG92?= =?utf-8?B?QjZIU3RrMHYyQVFKUkNZeFBLVHZuRVpHK3FIM0xiU1FrNXEyMEYvaktBTHBN?= =?utf-8?B?MVFxdzl2QVc1MHVXdTIxU2hpblN5WG55eElSblpFandvRUY4RXc1am5LdUFH?= =?utf-8?B?aWx2Z2UyclpzOU9idGFsNzZFVTI0UjBYeThxNmwzWWc2NTh5S0tDRThRaDEr?= =?utf-8?B?QkFMbmN0SDhTb2dXZGs4Q1htdlgzR1dMd203NmhzK2dITXRFTC9BVDJ0NEsr?= =?utf-8?B?eHhjeE5Pb3J4bzVMK1IzOGRCMzZVMTBha1VyV09tMHBETlhVWWFBelBaZ0RJ?= =?utf-8?B?Vmp2b0N0bWJnYUk1MHh2bmZwZTFPc3lhNXl0NUFFM0dRUWtpenY2bExhVGVj?= =?utf-8?Q?iCWO8hYV8z2qob6Nr3I4zdjnrxe?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;6:WQcm+NuTmKiMl69Ailk+9FyxG3lJE5Rr4FHmLfeBZL44FOqE/7bDlBsS0Xy2Ac5ALcJln9/Nofd+VS5FsPHL2WXsKTNpp9EYzbtvTZG2phJoUZcOEtjthSYJ/D9qVbWldTxcDu7UrRnGcPpolXU0SGoHHKzL53UFPwrbN6PgpXYeQFPfkalHBAmmOnJr33xa2sJJX62f24EL72vF310p4eNjYES+81rn3Ucyf2ukPYLQXiD/pVqhYJY97Vpjhdn7BmJUoTYXFEgEesNSJXEfhbuA1kt4Uz7tXJ+xqKX0f+X+LiQqunykepgnXoOYLSg7v/gEDUCK92s/geoZi4n9VA==;5:FrS0mDwugxZj3AUP06XBSGaW/EwD1cTjzzcJ+C+2XzU2oNZvHCVj1bRueNBr/se1H1aq18UFk4U3e2o7NSQWRSqI7Toyit6gnBUGvUZB9Lv3h+gMxrgnWoDy5yB7yaQa6ajaatVYc2ZXSrnRRW7ihA==;24:Gc0A7dulOv7CalSymAY8dpcF1M4At0fcnreB8e7MqT9ZmQ4pawoVb79XkWn9IL7UazRafhDHDszqIYsXTWglpSHnRiSHPVmouIQ/zUOSweY=;7:4U0pg6vyDsZsuPQtll2nlWIjpTPicIRtbu5JPU8YptMJPXOW+7mZ3xhbXuQ0HUqpIKcXkYr51vXnlRXw6mLbbURBBUMwqG38/uMdz0UDO1croo4JvMigsORVuUL7hGNed/jwR4PS54RtRHt6ZWNjC6B8sL0uM4325Nzcvl0NqSSxnDbuU4xRhZmOURkgPqR2FBGr1BLYLt1GU/2T/LgvE1NN8WMDnlbkQ4tD1TJoR5M= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:Z2cCIJ6/KIa++UmFlwS9dDDj/wwonQXTPCMP0n3O1jTkeEGc+0AZ2ShSpna7bo741NfvaX6D5TasdS6Pc93hMkstt/kDyOtUq8UIiD50tybrl6uJ3m/+YGRpGcAXKMyhS9/rsnufqC6QjBC7pa4maAGRhxjA+S4ZGPke6UDIR68cwJUTYFARI84gkYhGIZ2x87yTBPv7kzlgv4ZuqLgoxAefojC+mDMxLXgCWDz72XNJiV1JBw9m/oDhC3YV3FAR X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Sep 2017 20:47:10.2642 (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 decrypting a guest memory region for debug purposes. 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/kvm/svm.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 179 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 7a6e82c48142..4d51ccb462db 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1622,7 +1622,6 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, *n = npages; sev->locked = locked; - return pages; err: if (pinned > 0) @@ -6106,6 +6105,181 @@ static int sev_guest_status(struct kvm *kvm, struct kvm_sev_cmd *argp) return ret; } +static int __sev_issue_dbg_cmd(struct kvm *kvm, unsigned long src, + unsigned long dst, int size, + int *error, bool enc) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + struct sev_data_dbg *data; + int ret; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->handle = sev->handle; + data->dst_addr = dst; + data->src_addr = src; + data->len = size; + + ret = sev_issue_cmd(kvm, + enc ? SEV_CMD_DBG_ENCRYPT : SEV_CMD_DBG_DECRYPT, + data, error); + kfree(data); + return ret; +} + +/* + * Decrypt source memory into userspace or kernel buffer. If destination buffer + * or len is not aligned to 16-byte boundary then it uses intermediate buffer. + */ +static int __sev_dbg_decrypt(struct kvm *kvm, unsigned long paddr, + unsigned long __user dst_uaddr, + unsigned long dst_kaddr, unsigned long dst_paddr, + int size, int *error) +{ + int ret, offset = 0, len = size; + struct page *tpage = NULL; + + /* + * Debug command works with 16-byte aligned inputs, check if all inputs + * (src, dst and len) are 16-byte aligned. If one of the input is not + * aligned then we decrypt more than requested into a temporary buffer + * and copy the porition of data into destination buffer. + */ + if (!IS_ALIGNED(paddr, 16) || + !IS_ALIGNED(dst_paddr, 16) || + !IS_ALIGNED(size, 16)) { + tpage = (void *)alloc_page(GFP_KERNEL); + if (!tpage) + return -ENOMEM; + + dst_paddr = __sme_page_pa(tpage); + + /* + * if source buffer is not aligned then offset will be used + * when copying the data from the temporary buffer into + * destination buffer. + */ + offset = paddr & 15; + + /* its safe to read more than requested size. */ + len = round_up(size + offset, 16); + + paddr = round_down(paddr, 16); + + /* + * Cache access from the PSP are coherent with x86 but not other + * way around. Hence we flush the destination caches to ensure + * that x86 is able to see the PSP updates. + */ + clflush_cache_range(page_address(tpage), PAGE_SIZE); + } + + ret = __sev_issue_dbg_cmd(kvm, paddr, dst_paddr, len, error, false); + + /* + * If temporary buffer is used then copy the data from temporary buffer + * into destination buffer. + */ + if (!ret && tpage) { + + /* + * If destination buffer is a userspace buffer then use + * copy_to_user otherwise memcpy. + */ + if (dst_uaddr) { + if (copy_to_user((void __user *)(uintptr_t)dst_uaddr, + page_address(tpage) + offset, size)) + ret = -EFAULT; + } else { + memcpy((void *)dst_kaddr, page_address(tpage) + offset, size); + } + } + + if (tpage) + __free_page(tpage); + + return ret; +} + +static int sev_dbg_crypt(struct kvm *kvm, struct kvm_sev_cmd *argp, bool dec) +{ + unsigned long vaddr, vaddr_end, next_vaddr; + unsigned long dst_vaddr, dst_vaddr_end; + struct page **src_p, **dst_p; + struct kvm_sev_dbg debug; + unsigned long n; + int ret, size; + + if (!sev_guest(kvm)) + return -ENOTTY; + + if (copy_from_user(&debug, (void __user *)(uintptr_t)argp->data, + sizeof(struct kvm_sev_dbg))) + return -EFAULT; + + vaddr = debug.src_uaddr; + size = debug.len; + vaddr_end = vaddr + size; + dst_vaddr = debug.dst_uaddr; + dst_vaddr_end = dst_vaddr + size; + + for (; vaddr < vaddr_end; vaddr = next_vaddr) { + int len, s_off, d_off; + + /* lock userspace source and destination page */ + src_p = sev_pin_memory(kvm, vaddr & PAGE_MASK, PAGE_SIZE, &n, 0); + if (!src_p) + return -EFAULT; + + dst_p = sev_pin_memory(kvm, dst_vaddr & PAGE_MASK, PAGE_SIZE, &n, 1); + if (!dst_p) { + sev_unpin_memory(kvm, src_p, n); + return -EFAULT; + } + + /* + * Cache access between te PSP and x86 are not coherent, hence we + * flush the caches to buffers shared with PSP to ensure that we + * will be able to see the PSP updates. + */ + sev_clflush_pages(src_p, 1); + sev_clflush_pages(dst_p, 1); + + /* + * since user buffer may not be page aligned, calculate the + * offset within the page. + */ + s_off = vaddr & ~PAGE_MASK; + d_off = dst_vaddr & ~PAGE_MASK; + len = min_t(size_t, (PAGE_SIZE - s_off), size); + + ret = __sev_dbg_decrypt(kvm, + __sme_page_pa(src_p[0]) + s_off, + dst_vaddr, 0, + __sme_page_pa(dst_p[0]) + d_off, + len, &argp->error); + + sev_unpin_memory(kvm, src_p, 1); + sev_unpin_memory(kvm, dst_p, 1); + + if (ret) + goto err; + + next_vaddr = vaddr + len; + dst_vaddr = dst_vaddr + len; + size -= len; + } +err: + return ret; +} + +static int sev_dbg_decrypt(struct kvm *kvm, struct kvm_sev_cmd *argp) +{ + return sev_dbg_crypt(kvm, argp, true); +} + static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) { struct kvm_sev_cmd sev_cmd; @@ -6141,6 +6315,10 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) r = sev_guest_status(kvm, &sev_cmd); break; } + case KVM_SEV_DBG_DECRYPT: { + r = sev_dbg_decrypt(kvm, &sev_cmd); + break; + } default: break; } -- 2.9.5