From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752742AbdJDNVe (ORCPT ); Wed, 4 Oct 2017 09:21:34 -0400 Received: from mail-cys01nam02on0075.outbound.protection.outlook.com ([104.47.37.75]:59363 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752368AbdJDNPU (ORCPT ); Wed, 4 Oct 2017 09:15:20 -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 17/31] KVM: SVM: Add KVM_SEV_INIT command Date: Wed, 4 Oct 2017 08:13:58 -0500 Message-Id: <20171004131412.13038-18-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: e2b6b4d6-fcbb-48c4-b79e-08d50b29f0fc 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:FM0irH0JJoZUwOe1URPEk9ixMonNTESZIqHAKJP8wUhDCYFdr6MogXxO6odJ21hCICWY/xyKbPrbNkewkrhJ9/tL9qBvF5+6GVFDXVplUJCiDp7rsuDRoJJkrE442rr8twe8EZPU6UPnft4g0XYHvmHoaZgIOXUkvJmJj3UBO2WWW2e07mRMRMQWTNuggOKHr9im3LGMch2VdQbm1HCx7X/s56BCAhJi3/ljlKIlfDreK8qcVzs42bB7AhIVRXfC;25:0yIZoIPbVLTfT7ERRFOJ/DXdmjeWoRojM8KCPy30ch/mZTJzE2+BtsJivEDyusfKRh4OV1WQBESstvXWzbfDtaBxyCdrbyVKEix6v5WJgexgA77uaBb7GOW1s8ZZUABss110e8aSpQUN7OR5rKg9/4bkhQjbsHdBw4DGpGwZUZo79AUXXyK4pBzHpmagx8MhBmta2LcFUwOanpOUsKMZntLYTR7owjuYmnGDH/zMkunPR1JoX0o2WUf2HVDB2Ex9QhY7554FxDts+o/qExb0jcAXS6458yXWfnwvweh1Sphc+ukjF/+4NbH3XQBSXcEq2QxVx6RmpT05pzt4c5VgUQ==;31:WyOYe7HTlZj0aujNkbf72TjZ2kE6hCB2w70WEJBefE2DrTBC1JAPvyiNuBRYDZMESRsLx5WuvEoqaJFKn6azZXZLhTEhnaX0qwu6yLRLerbBWpmncpt/da9eanswqZVT+VM7AJtZXTIm78lfNr5hNfdEjMX4NPJKOQF4Vw1BndpV+QNU7HsLc/nTKHy7/jwNYpmUuqYodb9dAof4EsSYQI0EQHVpk8NdoTa9dHuMMYQ= X-MS-TrafficTypeDiagnostic: SN1PR12MB0160: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;20:88z/MeHf2d4vs3S0K5ijk4PIZo5S1CISj+ake3kdOp1Jy19Ai9NuQ51xoL/4l2KA6B/2e/A9U4wvDroFZaCHSzHh/6geGMsn7odiYlwk6gfpLih+ulhSXFniDMo3qdyyURdmocDAz41zMPRNWbOlV7KBzZ/MmOOV7vklm1O7EOI2k+HIi3LjnkxBeBKBpUECJ5BfqbxaPzcAsrV5xiiJ6dXUe6ENlqIaLoluOrubM4LkDIGaA41FhbKGomHPDraNQoI2bUVHuYc3bqmPCPoBqQW+RJAH4bvwSHsVj97yZ4nsPeh7vcD2jFD0EiarAK1zU/9b1mv/EbNpbudy+h24WXGW9znid+TybH1ydqBXAK7BTlmPcLpoVBn/iWI9rf9AOVIMHQBE+9WTmYYZswCwS4NYf9KtyKtbp829Q/4DdDBF8CdkLRwthbWY+PT8Nto/foB0IC3W/btVwDxowAmH4UPWq7E9mxbTJoRk7Zur+fd33BIUB1Zq941SuYQJPKF6;4:qMn5HzvZokdUnmv0nLmAIsSdgMYvTIbwtIw07y/W/AjM1Cw4lIbn2PtvasXdJb/zDM/Pkqa17ePkYZkR6bFC5OCJzVpqDLUfTJoNGLobCk7aVUDILl/hEyDo4qSNbs5htc77Xi4882nPvTon+bSzMujAycDO7lHUyevQxo4aKSfILEaFIxPFORE+pK4FcI0iiFI2bniGBK8C0pkclpqiG+pE2lOLj4NufTb0P+nchhCFAvGT8LNxpFg7/ofy1AdDwszyebMup4c0U4HdZQjH7mLOI5wCybgLazoEa2RNI6m79GO27LyJ/Km7x71NrNftHyvLW9pkpdRIO4NNXzr72w== 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)(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);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?MTtTTjFQUjEyTUIwMTYwOzIzOjEvdmVCeGVUNnBnRHczaXBHRmF4Mm1YM2Yz?= =?utf-8?B?S1p6TzZSOUd6Q2JVcHJBcm1GV2xFRTVkcUxSblZoaGs5eWNKZmwweXJVaUdE?= =?utf-8?B?OEFTT2RFR0ZjZkpPVkFaNlE3M2NLMXI2WGtNK3hzTjUvUVZHbVdwc09SOCt6?= =?utf-8?B?ajhvTUV4T3lla3N3NEpPUU5qcEphUUorVTZ5Q0hyOEdFa3o2aXBNbDk3VUJR?= =?utf-8?B?U2hSZU53RUtvZzgvT3FGdTlSeWduQitROFgzUWFMelY5aXBJRWowNkYzd25N?= =?utf-8?B?L0JZS1JKc0F3ODJVMnBLTUNCZUJtMmIxVG1kUDRRNlZyVENCN2o1VUozWGd5?= =?utf-8?B?QlNsd0E4TC9uS3JKaG11Q25mN0IzOEVLK0NjQ3c1TjRXcEQ0K3R2U0FCQUR5?= =?utf-8?B?d2pMSHlnT0I2eXI3Vk5IQUtrREJVaXVhMjBlSjJoWEo0elc5SWVYR3pKR2pC?= =?utf-8?B?U3NzaTZXR2dENE5BUW9JczA2TzhsMjhZaUk4ZE51Rmp3T2EwMWx6eWlSa1ZV?= =?utf-8?B?aXZpZk1uNmdBSnZKQzZYMzJ4eVc3WHlBWE9BQzFWMzY2WS85VDBPdkU0Mzgz?= =?utf-8?B?WTVSRFpwOFpWSlRtaWtWdG5IMUVJaXgxN2lkS3NEWE5WQk01dTB2bnczeUt0?= =?utf-8?B?aDZDbit0V2pVd2Frd0prbTlua0E2L3dIZm90aW5zV3Y5Vi9Ucm1EdHpMUC9F?= =?utf-8?B?QlpSeVBIK1hsd0E0VlVxM2t6cmFaWmRHcHZZbEtyN3gvMTRGTmVUOEpQYmN1?= =?utf-8?B?NG5zQVFIR3djOWZEN0s1ZFAxQXRGQUFGcytIZmVCaGxrSEc0R3NmK05kTnI4?= =?utf-8?B?NGcwclpncGJDc1RYSVY4VVhpZTlLbENYalZNUUxvZERybWgzSkZvSVZNemhH?= =?utf-8?B?OTZkcm5ZR2RqY2tKb2pVYk8rTzBNUEFnaGtQYVQzTkZZeWo0MXdOQnJyRHNQ?= =?utf-8?B?dHFGMnh6YmZSRWdhR01MSkF1cnRORDlFeCt4N3E5S3NMNWNQL2JKVllxdndF?= =?utf-8?B?MU55ZHJPWG5MampuL3JRckR6ZHE4S3RRZzlSYXRteHh2NElKR3RBUnhuUXpO?= =?utf-8?B?ZkVCeXh1REdRcVh3MGZWWkJYYW5ZQnZlVHdjU25FR1k1bjNDRHN3S1FleGY4?= =?utf-8?B?QWtKdHlYVXJwUXlHN2dWQUk2WEx6aHpVM1ljN2VmMzl6cHl5aCtYOEtvdkZG?= =?utf-8?B?dHFrb0ZLbHVIVldweksxektjaXlDRDIyNkZDNSt3SWJMaVhobnlnTS9teTl3?= =?utf-8?B?dHBPZForNUl0SjRMdlJZZG9KbnlZbXVXemZETyt4V0tHakNuZ216WnFoK0lF?= =?utf-8?B?S2lVK0VNMG9ySzI2eElTWUJPVlQ4cGF0UnZRSVZNSktJVUh2UlJzNFdMSHVi?= =?utf-8?B?VFlaT2diSm5XdnZXL281N0NjcnFZbjVBYzVEbUlnUUdHVkZ0MG90UFdOd2Nn?= =?utf-8?Q?NT9ejZS0AljxjN7XlMyJbBT3ihM?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;6:Iyujvm+3UjpS0QNd2fO6bE4zpqvzen8R16ObLdDmPk0wwpHcSrw35PsaZvJHZJvi9dlgsjntx79WW3qZGypQsi1uhFK3IM1xqnyLe14/xxVFKUS0bYT612Tznt0EoEFukb5k1upWoW8UfcyCDSH7BgdAi4ItX3EHZ5u8Qv4jWM3kOUiRWpv4L3w7X1O7wngU3TLyW2rzOlC2FQWwCBd4v7/0CXdqL7aeMjBBLed7VWgGQBL6/vjw9L3OiQ5Ve5aJDaOu91KQn/3JUX4XKo5SzuhsrEo+YAP2oAbzPIBs4hgIuqNq8kIMpXFTPs58qpJm737kTMwNdIjtjgSS79v7lg==;5:Y0+Y1UC7SYurfLlLFoJV+oq2yy6Z1pW9T9r1T3lTyC6iuwmo4miQq7LLnCnCEi8JaKJEOk43+0eh8cpWiyok2u6VIxjqdHiH3uvAPqaxTvmhUtVChSk5i72fxYWiEcPFBjGCf0serO7DFr/d5uTi9w==;24:XQfoTdHBMnNH5utvqwvaMyrnaMY/gSX5d9WFq7ckZSuJf/PnVu4Ju3vXow9a0u0ElthbITGmJj8hovRtG7FRm3rf3N63xSQ7MsUHhyNqdnE=;7:5Waulr2ABmWe2b8OD9DUbNCN/lnegAx/lZdSkLf189jtUWoJh0dW2Fjg5MB6XKLuCCMzwANlLkS51vTttMyHFXUssRSbWSG52AInHBuWnx/IMbCa2mCee/e8b6/b2PkYUnTzcITtHEKmOqopR9tDfh0c5nxEXesaMnhMX94ydx1vOoiROz3SKpQxdiBMqIaJrWRXeafP7ll5mLgfSV1YFcf44o4TSN+WdGr6gNkZLhs= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0160;20:0jhNMzpjUVA05Ek4D8m2LCxHESwpiw6GTo0CFygr2YHLBdIb8KD0AaNc8kTHZ6i5XDxQlqtEbRWjOPLDUAM9zm+AgVOiE/B2mc4qcjsQNktQ5/75hYVn8eFDM7JNUVVu/zE9HSRbFpv85JI67y8DVpl5sesoi0S5ok/WPOXgvHNaJqYUnm6Rx4mFVrLE+xuI9maXj0Cu5qpzuHqOzyyq5lIUg9bUcz+J+nDu9ZWA61a9u+1EwquNLRa4jhKWi/Sg X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Oct 2017 13:15:09.1202 (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 initializes the SEV platform context and allocates a new ASID for this guest from the SEV ASID pool. The firmware must be initialized before we issue any guest launch commands to create a new 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 | 7 ++ arch/x86/kvm/svm.c | 189 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 20fba8bfa727..6bd49e80a16d 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -747,6 +747,11 @@ enum kvm_irqchip_mode { KVM_IRQCHIP_SPLIT, /* created with KVM_CAP_SPLIT_IRQCHIP */ }; +struct kvm_sev_info { + bool active; /* SEV enabled guest */ + unsigned int asid; /* ASID used for this guest */ +}; + struct kvm_arch { unsigned int n_used_mmu_pages; unsigned int n_requested_mmu_pages; @@ -834,6 +839,8 @@ struct kvm_arch { bool x2apic_format; bool x2apic_broadcast_quirk_disabled; + + struct kvm_sev_info sev_info; }; struct kvm_vm_stat { diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 3244b8f88010..7f3179555a57 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -324,6 +326,19 @@ enum { #define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL static unsigned int max_sev_asid; +static unsigned long *sev_asid_bitmap; + +static inline bool svm_sev_enabled(void) +{ + return max_sev_asid; +} + +static inline bool sev_guest(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + + return sev->active; +} static inline void mark_all_dirty(struct vmcb *vmcb) { @@ -1063,6 +1078,11 @@ static int avic_ga_log_notifier(u32 ga_tag) static __init void sev_hardware_setup(void) { max_sev_asid = cpuid_ecx(0x8000001F); + + /* Initialize SEV ASID bitmap */ + if (max_sev_asid) + sev_asid_bitmap = kcalloc(BITS_TO_LONGS(max_sev_asid), + sizeof(unsigned long), GFP_KERNEL); } static __init int svm_hardware_setup(void) @@ -1167,10 +1187,45 @@ static __init int svm_hardware_setup(void) return r; } +static int sev_platform_get_state(int *state, int *error) +{ + int ret; + struct sev_data_status *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = sev_platform_status(data, error); + if (!ret) + *state = data->state; + + pr_info_once("SEV firmware major %d minor %d build %d\n", + data->api_major, data->api_minor, data->build); + + kfree(data); + return ret; +} + +static __exit void sev_hardware_unsetup(void) +{ + int state; + + sev_platform_get_state(&state, NULL); + + if (state != SEV_STATE_UNINIT) + sev_platform_shutdown(NULL); + + kfree(sev_asid_bitmap); +} + static __exit void svm_hardware_unsetup(void) { int cpu; + if (svm_sev_enabled()) + sev_hardware_unsetup(); + for_each_possible_cpu(cpu) svm_cpu_uninit(cpu); @@ -1361,6 +1416,9 @@ static void init_vmcb(struct vcpu_svm *svm) svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK; } + if (sev_guest(svm->vcpu.kvm)) + svm->vmcb->control.nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE; + mark_all_dirty(svm->vmcb); enable_gif(svm); @@ -1443,6 +1501,38 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu) return 0; } +static void sev_firmware_exit(void) +{ + int state; + + sev_platform_get_state(&state, NULL); + + if (state == SEV_STATE_INIT) + sev_platform_shutdown(NULL); +} + +static void sev_asid_free(struct kvm *kvm) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + int pos, asid; + + if (!svm_sev_enabled()) + return; + + asid = sev->asid; + pos = asid - 1; + clear_bit(pos, sev_asid_bitmap); +} + +static void sev_vm_destroy(struct kvm *kvm) +{ + if (!sev_guest(kvm)) + return; + + sev_firmware_exit(); + sev_asid_free(kvm); +} + static void avic_vm_destroy(struct kvm *kvm) { unsigned long flags; @@ -1461,6 +1551,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; @@ -5427,6 +5523,95 @@ static void svm_setup_mce(struct kvm_vcpu *vcpu) vcpu->arch.mcg_cap &= 0x1ff; } +static int sev_asid_new(void) +{ + int pos; + + if (!svm_sev_enabled()) + 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 int sev_firmware_init(struct kvm *kvm, int *error) +{ + int ret, state = 0; + + ret = sev_platform_get_state(&state, error); + if (ret) + return ret; + + /* If SEV firmware is in uninitialized state, lets initialize it. */ + if (state == SEV_STATE_UNINIT) { + struct sev_data_init *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = sev_platform_init(data, error); + kfree(data); + } + + return ret; +} + +static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) +{ + struct kvm_sev_info *sev = &kvm->arch.sev_info; + int asid, ret; + + ret = sev_firmware_init(kvm, &argp->error); + if (ret) + return ret; + + ret = -EBUSY; + asid = sev_asid_new(); + if (asid < 0) + goto e_shutdown; + + sev->active = true; + sev->asid = asid; + return 0; + +e_shutdown: + sev_firmware_exit(); + return ret; +} + +static int svm_mem_enc_op(struct kvm *kvm, void __user *argp) +{ + struct kvm_sev_cmd sev_cmd; + int r = -ENOTTY; + + if (!svm_sev_enabled()) + return -ENOTTY; + + 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_INIT: { + r = sev_guest_init(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, @@ -5443,7 +5628,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, @@ -5537,6 +5722,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = { .deliver_posted_interrupt = svm_deliver_avic_intr, .update_pi_irte = svm_update_pi_irte, .setup_mce = svm_setup_mce, + + .mem_enc_op = svm_mem_enc_op, }; static int __init svm_init(void) -- 2.9.5