From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751889AbdISU63 (ORCPT ); Tue, 19 Sep 2017 16:58:29 -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 S1751653AbdISUqv (ORCPT ); Tue, 19 Sep 2017 16:46:51 -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?= , Jonathan Corbet , Borislav Petkov , Tom Lendacky , x86@kernel.org Subject: [Part2 PATCH v4 01/29] Documentation/virtual/kvm: Add AMD Secure Encrypted Virtualization (SEV) Date: Tue, 19 Sep 2017 15:45:59 -0500 Message-Id: <20170919204627.3875-2-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: ca90bc6d-1f8b-4979-937a-08d4ff9f8bd6 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:Lk5Nm9Nu22ZxLY1bo0nKh88hXWhQxYKEVf3z0d+5FvejLiUZj2RddXcBfp8OveBHXujqXDTLVhTpWDbBJdg0MVtEHABDlE1+fFYfLlf+JDVBeiKcddEL9nGyiKn+ZxP56jLd1O9Yh/xgJSMftA6tmXcKEJWnUgXO3nfor4wxg9SLl4iQ+2FUjSN9vjRnUZKx5JEPr6mbOSXV4J0Hgnuvtvu9sOP81/gXi0njn/ujR9MzAqnxgYQaY3+xdD/JpMW6;25:BT1LKY6Zm2jb3gRl038NwL4+3UnMAtC6Zc9iWs45OUUmABOP+8rbP3m91MC5CLB81hJV3VflIVmU0AKs/uqCA3P/KQydz7XbExU2O75/DU+wnTt8M7mAYcniverzo/ol/TD1MW3PpATXJS0oZntgGyB2gMbBAgrSwbwV+CY4jeCTVbV0hvHjQJkZdKm1MxDy/nN8Q1PHAFcDUydW+BnKHn+Y9OOWb/mQiz9OGIh0ycZLFgfRwsT9kaLg6ZH94dLxAGlTVfenVmaTsH+GkXiE1u9Ysjbf1jV1ksw6r9zArIrISNy5UtpsZi7SVx0M9OV+7WPQw5GqR0ujS/oMhx+EMA==;31:47NZV21ccs62bWrOSNDvW2RRlHHjcJ6FJdgd2rBYQTMiMFq9YbF5G8Ns5FoluSyXtxLILm9bJaq7Xr/owahSlf20l+0ZP87kVoMXUNfj/FAI7GISKCbss428/cw3YbNxVE3iyxc2fZTQtXXZkwpf9CtGPsmjc1XRCG20F9c49mQVyKC9VsMCNcdJHr7VxOCU+4ieJJ0v2OfBeEw24pllKSCU/iXQoc2gziXeQCle008= X-MS-TrafficTypeDiagnostic: SN1PR12MB0158: X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:G3QuXQ0lY7U3Z2+xHTiUI4nwL+wtbFujWd3wRc2IwhP8A4lf+YRFRm/BmSiruVR458wUUnbLYWzNnC+0USH5qM20vldaRnE0Pu1lpEw/Depl4fIr6M72X01wGfuv8kMYM/f0wRm9FXzy/UAUVGRER3rDjTpVtHUXgzfMtpQaJpR6PgIxSrmp8b47Bgark+fe3VA7Vn9tbdSVrx4R34j5fR5SauZhWc5XPVPND/mtaiT5i3PZrKgX0hBeoiiLd/ZrMXpQbANdJQr/LkTqNbqwbono46RAH7bvZBk9vy1MAjbpNLcdam5mTcCBXmnpc//vLxwws+a1TBXqCSnrRimLzafIaK/xY3kW/mM2GbeA0dXnNJz5jI0BWwuAKCEREW7F3Wx6ukNdtFHxXGzaabTTlk9l894D2M5bX1S0qpeGsJe50QycK1gVYPm8dVRNJSNq5dFpIRdEuTWD7uSMRcvz1+//8PmUWBQb643yfOb/9C5Cc8YyjDJXk1r7AM0onpBN;4:alHlvhIXflkmvjTLkQjRrgtLAhgCagh0gPYncFuUGK6TnBm2S6RMHrNTvCnmZa+HebRFcgCQM3nKPgwMFMAYen/nKWVXhQ5cZ80dbWH5z4ureMupFM1P/KmkJQeQtem1v0Dv6jxEHjB1AqB1U9L0s+tcHSqkVV5l3WSCg89guuJCC7vtXVCo0ApoC7zuu+GLk3xQH9NqZUUrGulYr3YSOVcMnwps/A+6lUI8f3Fb+GuyavmTN+DAepQrMUGpZon5sE5fPNXEIAUAJ51+Ffn+CKoOXwi5Ps4FwE6SEj8nfzzam83kBny7dWFPbmHhDxiy6oPWy0PfG92/cUn/umA6x1oXmsz1oHy9r0mtw4hTZ9Q47xJc+6pos23nZo6AKP7oSiffU7v9RfpccR1WybAMUQ== X-Exchange-Antispam-Report-Test: UriScan:(20558992708506)(9452136761055)(767451399110)(17755550239193); 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)(6306002)(189998001)(53416004)(25786009)(101416001)(2870700001)(50986999)(76176999)(53936002)(2906002)(68736007)(36756003)(106356001)(1076002)(4326008)(5660300001)(105586002)(33646002)(23676002)(54906003)(19627235001);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?MTtTTjFQUjEyTUIwMTU4OzIzOmZuYnF4Q21BZUdieHpzZ2l4TWxQZFQwbEtn?= =?utf-8?B?c1l3dGFNYmtCRy9kZHZielNqUktIcWU0cFE0cmNyK1dqNmtadE96L1IwcVZ4?= =?utf-8?B?Z2VIS0htTms0SDNSczRibUdnUzN5TUZaMDYyNFU4WUU0ZFhRM0JUQ0pkVzIz?= =?utf-8?B?TUxPZ0w4R2owUGxJZzZacTB3ME9PZkpYVTkrR2N6aE5sMnU0c0xhUkM2bU1H?= =?utf-8?B?UmdCMmljalM0WXg5WDJweGhDMnlhTEZnMkt4VW9NM2tuVEExNWxzNFBzd3FN?= =?utf-8?B?QXFuSDhoMlVWa1dKLzJLRXNmc2IvbFNjbW1iNTZadEVkSkE1MmRkNVpoOXBS?= =?utf-8?B?MWs3eXRndXUxTEJIQXk1Q2Q3emUreWJhUG1lZWs1ZnFac09aTjRMbEVqdGxI?= =?utf-8?B?MHBvZTJ0ejNxUU1qMnViQW5wL3JiSTFweWg3TWE4YXQ1N0IyTkhVSklDZEFF?= =?utf-8?B?eHJzUFJlL1k3RWpib3lJQWJRM2xxTlppZlhpdXpxVHY0d3VRbUNhZm5wRTdO?= =?utf-8?B?VGhCbXZSNDBRUHc3c1NQczBSVVA0dEtHTVJVUU8zU01mc1VqZWNaTkNUMEp1?= =?utf-8?B?eE5aS1cwUE9nbk1CNngwTy9JdTlTMnRtdTJaU01aWEliekU1NVlqcjgrTHZG?= =?utf-8?B?bFFpWGRVQmgyODNFV3JCY0NsSmNodURXbjB5c2Z0Q091NzlxcUlVKzZEMDVZ?= =?utf-8?B?NTRsbThNbU1zb2NPb3VlK2FWR3l0azlEZUxabjNFcWg4RW5KRUNBcUV3K1ZJ?= =?utf-8?B?dzk2MFFnQVlMK1grT284V1dKdHFYejBNNFMrSnQxSDZCU2YrMzcwOEtIa2xS?= =?utf-8?B?NlFEbGtxVFJJNEowSS9FaWpBVEJVRDVQdjl3U0NHVlpsWklaN2lEL095bmpW?= =?utf-8?B?d21hYnpBeHZCR0h4dXc5UFhPMnF0SE5xUmIxREluMDlZMEtVRkx5a0N6bXJ3?= =?utf-8?B?MXZhSEl5ayt4bTJpaC9CNlZNanF1OU8zU0gyZ3Jmei9tRU05VkR2bWw2MWVQ?= =?utf-8?B?RDJsay9uY0d4NmRKOFcwZHdqZEtYVGhTeFo2OURxNW04QTJ1ZlRJY1BPKzNH?= =?utf-8?B?NExqRkVlekQ5Rk5OMkxyNXVnSUNyQ0RqREw1SDFVUlpTdGx6VDlLemdZRndw?= =?utf-8?B?OTJBWnBMcGREbk1Vc0dCOXBEM1BLVFJhN2RBUDNZVGpVd0U5WDdpelJPMzQz?= =?utf-8?B?WjJOaGQxT01JelJ2cXloVFBqaldkYktjK3poY3p0RjZzYmFicDlTa1owZ1hh?= =?utf-8?B?Zi9tdVBSdURUc1NhalY2M0NvL0ViQnVUUnBadmlmUSs3WWg1SitCUlZvU2lT?= =?utf-8?B?eDkzQUNvZWpvZ1kwclRSS0N2cG5KYlJoNkVkMUxiUlhERS82bFhpNzQrcnk2?= =?utf-8?B?a1kweVlmVjRqME5sa3lVVmVSakxsV3NFcFFEVGJHeGtiQTZzaDdpcWwzUWhR?= =?utf-8?B?bnVEK2xlV252OXBZdVFKMEFiblpZWUJrOUNkeHE4WExYWS9jMGFFUU1sa1Q4?= =?utf-8?Q?mOfy+ZYElR+4u4iWTIYu3qUixvOQczdlyqZCin6ISWzC2F?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;6:Mc/MW0PxprMYqxPIPrBShKXngagCroBQH9iQa3sUSnGIoJxG6kdQ4cuo3B7tfNCIC6Mn0qPDC2i5M+lI7VZBgoCSFQ7I73yseASxjpy8+SfG+dLccefx/0ItwP/4ApmNXnjON86eLt98qzCP69nsPN1pOrS/3T5LQPVqg+jn1J85q1BVbb9BDJHfGgMD+bs0wOlq2wqRAfVrSVkVW+8xHgzXjwn6HjujP4UaJCIk0h1kyh7XWi69t2Ju1weq7Vd5BWit2J+hAfINbgp0dHNx3+RX8XAguaV3wvzNIvmkXye0KsQGA6VFA3NgxaYOLLkvxxbDOLepf1SAIIJIMsW/sQ==;5:WwnUq3ypABL+ejDDylGMurjMGc2+ZJ7QrMhZkC0VQQT6gHy712NMiA5RZjLMerr93awziuzSxuzx3JCviVGvlnaNGwhoOdRCwGuUxEbekTbxRxpDWlL7t+P8cIEUXKhAf16qHRtvfHn4xjog+K2OuA==;24:35zqcilT6SABMcmVfbHVl4jVYCBKfm2DR23zyAX/Y1nuMHejcAg32nOJD4Fxr/olpXw0iFFhGhpVS3wwNkJs84CgbCB2gAFSVkPKlvzBx+E=;7:vfONkq11M0hmSFvba3rtEeB8YDQjeUjng7L6//Ts/+f9c7Yf9raLuJTIdN3me6Qrm2Kg1Mjp9LR95ZNgDqnhdZ3p6FxRheo4DA5eSWNji4utdgQasBMlhdkuzlNzBBOZCZjNNLzGmqWMO5qayHkOiiH8TWROUrIJCVQadsiAirEX4VDOqF92efMVd6rqQCsQUOdIaCpyn5HCaFhUTOXDccXaxw9G1bEMyvdRFACQb3o= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0158;20:KskwSzahEbXeP+p1gQRA9rvAoyRyyPTLL9XYLiscy3BX0E1irsB/ZAf8ua3OtUS1t19PQkFxGBGVrLs8Eya9P/RuOxtZ+WOkxREI8exZFkLl0Tff3+wImiQkM8rmwhl/uuCBqkyGVn/eV8UevfRYVO4HP6XtSCQL1XbIoFfopmX8Gc34t7VMc0Cevd9NwziBc8ftvcn5nJwSw2dePTefELn7J5zxw0SOyonQZz5+Q4frFyg+iUo5D00ZNaBssjLR X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Sep 2017 20:46:46.8156 (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 Create a Documentation entry to describe the AMD Secure Encrypted Virtualization (SEV) feature. Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Paolo Bonzini Cc: "Radim Krčmář" Cc: Jonathan Corbet Cc: Borislav Petkov Cc: Tom Lendacky Cc: kvm@vger.kernel.org Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Brijesh Singh --- Documentation/virtual/kvm/00-INDEX | 3 + .../virtual/kvm/amd-memory-encryption.txt | 210 +++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 Documentation/virtual/kvm/amd-memory-encryption.txt diff --git a/Documentation/virtual/kvm/00-INDEX b/Documentation/virtual/kvm/00-INDEX index 69fe1a8b7ad1..3da73aabff5a 100644 --- a/Documentation/virtual/kvm/00-INDEX +++ b/Documentation/virtual/kvm/00-INDEX @@ -26,3 +26,6 @@ s390-diag.txt - Diagnose hypercall description (for IBM S/390) timekeeping.txt - timekeeping virtualization for x86-based architectures. +amd-memory-encryption.txt + - notes on AMD Secure Encrypted Virtualization feature and SEV firmware + command description diff --git a/Documentation/virtual/kvm/amd-memory-encryption.txt b/Documentation/virtual/kvm/amd-memory-encryption.txt new file mode 100644 index 000000000000..5586d51a8983 --- /dev/null +++ b/Documentation/virtual/kvm/amd-memory-encryption.txt @@ -0,0 +1,210 @@ +Secure Encrypted Virtualization (SEV) is a feature found on AMD processors. + +SEV is an extension to the AMD-V architecture which supports running virtual +machines (VMs) under the control of a hypervisor. When enabled, the memory +contents of VM will be transparently encrypted with a key unique to the VM. + +Hypervisor can determine the SEV support through the CPUID instruction. The CPUID +function 0x8000001f reports information related to SEV: + + 0x8000001f[eax]: + Bit[1] indicates support for SEV + + [ecx]: + Bits[31:0] Number of encrypted guest supported simultaneously + +If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR +0xc001_0015 (MSR_K7_HWCR_SMMLOCK) can be used to determine if it can be enabled: + + 0xc001_0010: + Bit[23] 0 = memory encryption can be enabled + 0 = memory encryption can not be enabled + + 0xc001_0015: + Bit[0] 0 = memory encryption can not be enabled + 1 = memory encryption can be enabled + +When SEV support is available, it can be enabled in specific VM during the VMRUN +instruction by setting SEV bit in VMCB offset 090h: + + VMCB[0x90]: + Bit[1] 1 = Enable SEV + +SEV hardware uses ASIDs to associate a memory encryption key with a VM. Hence +the ASID for the SEV enabled guests must be from 1 to a maximum value defined +in the CPUID function 0x8000001f[ecx] field. + +SEV Key Management +------------------ +The Key management for the SEV guest is handled by a separate processor known as +the AMD Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a +secure key management interface to perform common hypervisor activities such as +encrypting bootstrap code, snapshot, migrating and debugging the guest. For +more information, see SEV Key Management spec at + +http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf + +KVM implements the following commands to support SEV guests launch, migrate +and save/restore. + +1. KVM_SEV_LAUNCH_START + +Parameters: struct kvm_sev_launch_start (in/out) +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_START command is used for creation the encryption context. +To create the encryption context, user must provide a guest policy, the owner's +public Diffie-Hellman (PDH) key and session information. + +struct kvm_sev_launch_start { + /* if zero then FW creates a new handle */ + __u32 handle; + + /* guest policy */ + __u32 policy; + + /* userspace address pointing to the guest owner's PDH key */ + __u64 dh_uaddr; + __u32 dh_len; + + /* userspace address which points to the guest session information */ + __u64 session_addr; + __u32 session_len; +}; + +On success, the 'handle' field contain a new handle and on error, a negative value. + +For more details, see SEV spec Section 6.2. + +2. KVM_SEV_LAUNCH_UPDATE_DATA + +Parameters (in): struct kvm_sev_launch_update +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting the guest memory regions +with the encryption context created using KVM_SEV_LAUNCH_START. + +struct kvm_sev_launch_update { + /* userspace address need to be encrypted (must be 16-byte aligned) */ + __u64 uaddr; + + /* length of the data to be encrypted (must be 16-byte aligned) */ + __u32 len; +}; + +For more details, see SEV spec Section 6.3. + +3. KVM_SEV_LAUNCH_MEASURE + +Parameters (in): struct kvm_sev_launch_measure +Returns: 0 on success, -negative on error + +The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the +memory regions encrypted using KVM_SEV_LAUNCH_UPDATE_DATA. + +struct kvm_sev_launch_measure { + /* where to copy the measurement */ + __u64 uaddr; + + /* length of measurement blob */ + __u32 len; +}; + +For more details on how the measurement can be used for attesation, see SEV +spec Section 6.4. + +4. KVM_SEV_LAUNCH_FINISH + +Returns: 0 on success, -negative on error + +KVM_SEV_LAUNCH_FINISH command finalize the SEV guest launch process. + +5. KVM_SEV_GUEST_STATUS + +Parameters (out): struct kvm_sev_guest_status +Returns: 0 on success, -negative on error + +The KVM_SEV_GUEST_STATUS command is used to retrieve status information about an +SEV-enabled guest.. + +struct kvm_sev_guest_status { + /* guest handle */ + __u32 handle; + + /* guest policy */ + __u32 policy; + + /* guest state (see below) */ + __u8 state; +}; + +SEV guest state: + +enum { + SEV_STATE_INVALID = 0; + SEV_STATE_LAUNCHING, /* guest is currently being launched */ + SEV_STATE_SECRET, /* guest is being launched and ready to accept the ciphertext data */ + SEV_STATE_RUNNING, /* guest is fully launched and running */ + SEV_STATE_RECEIVING, /* guest is being migrated in from another SEV machine */ + SEV_STATE_SENDING /* guest is getting migrated out another SEV machine */ +}; + +6. KVM_SEV_DBG_DECRYPT + +Parameters (in): struct kvm_sev_dbg +Returns: 0 on success, -negative on error + +The KVM_SEV_DEBUG_DECRYPT command is used for decrypting a memory region for the +debug purposes. + +struct kvm_sev_dbg { + /* userspace address of data to decrypt */ + __u64 src_uaddr; + /* userspace address of destination */ + __u64 dst_uaddr; + + /* length of memory region to decrypt */ + __u32 len; +}; + +The command returns an error if guest policy does not allow debugging. + +7. KVM_SEV_DBG_ENCRYPT + +Parameters (in): struct kvm_sev_dbg +Returns: 0 on success, -negative on error + +The KVM_SEV_DEBUG_ENCRYPT command is used for encrypting a plaintext using the +VM encryption key. + +struct kvm_sev_dbg { + /* userspace address of data to encrypt */ + __u64 src_uaddr; + /* userspace address of destination */ + __u64 dst_uaddr; + + /* length of memory region to encrypt */ + __u32 len; +}; + +8. KVM_SEV_LAUNCH_SECRET + +Parameters (in): struct kvm_sev_launch_secret +Returns: 0 on success, -negative on error + +Te KVM_SEV_LAUNCH_SECRET command can be used by hypevisor to inject a secret +into the guest. + +struct kvm_sev_launch_secret { + /* userspace address containing the packet header */ + __u64 hdr_uaddr; + __u32 hdr_len; + + /* the guest memory region where the secret should be injected */ + __u64 guest_uaddr; + __u32 guest_len; + + /* the hypervisor memory region which contains the secret */ + __u64 trans_uaddr; + __u32 trans_len; +}; -- 2.9.5