18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AMD Memory Encryption Support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Advanced Micro Devices, Inc. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/linkage.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/processor-flags.h> 138c2ecf20Sopenharmony_ci#include <asm/msr.h> 148c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci .text 178c2ecf20Sopenharmony_ci .code32 188c2ecf20Sopenharmony_ciSYM_FUNC_START(get_sev_encryption_bit) 198c2ecf20Sopenharmony_ci xor %eax, %eax 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT 228c2ecf20Sopenharmony_ci push %ebx 238c2ecf20Sopenharmony_ci push %ecx 248c2ecf20Sopenharmony_ci push %edx 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci movl $0x80000000, %eax /* CPUID to check the highest leaf */ 278c2ecf20Sopenharmony_ci cpuid 288c2ecf20Sopenharmony_ci cmpl $0x8000001f, %eax /* See if 0x8000001f is available */ 298c2ecf20Sopenharmony_ci jb .Lno_sev 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci /* 328c2ecf20Sopenharmony_ci * Check for the SEV feature: 338c2ecf20Sopenharmony_ci * CPUID Fn8000_001F[EAX] - Bit 1 348c2ecf20Sopenharmony_ci * CPUID Fn8000_001F[EBX] - Bits 5:0 358c2ecf20Sopenharmony_ci * Pagetable bit position used to indicate encryption 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci movl $0x8000001f, %eax 388c2ecf20Sopenharmony_ci cpuid 398c2ecf20Sopenharmony_ci bt $1, %eax /* Check if SEV is available */ 408c2ecf20Sopenharmony_ci jnc .Lno_sev 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */ 438c2ecf20Sopenharmony_ci rdmsr 448c2ecf20Sopenharmony_ci bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */ 458c2ecf20Sopenharmony_ci jnc .Lno_sev 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci movl %ebx, %eax 488c2ecf20Sopenharmony_ci andl $0x3f, %eax /* Return the encryption bit location */ 498c2ecf20Sopenharmony_ci jmp .Lsev_exit 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci.Lno_sev: 528c2ecf20Sopenharmony_ci xor %eax, %eax 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci.Lsev_exit: 558c2ecf20Sopenharmony_ci pop %edx 568c2ecf20Sopenharmony_ci pop %ecx 578c2ecf20Sopenharmony_ci pop %ebx 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#endif /* CONFIG_AMD_MEM_ENCRYPT */ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci RET 628c2ecf20Sopenharmony_ciSYM_FUNC_END(get_sev_encryption_bit) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci .code64 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#include "../../kernel/sev_verify_cbit.S" 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciSYM_FUNC_START(set_sev_encryption_mask) 698c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT 708c2ecf20Sopenharmony_ci push %rbp 718c2ecf20Sopenharmony_ci push %rdx 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci movq %rsp, %rbp /* Save current stack pointer */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci call get_sev_encryption_bit /* Get the encryption bit position */ 768c2ecf20Sopenharmony_ci testl %eax, %eax 778c2ecf20Sopenharmony_ci jz .Lno_sev_mask 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci bts %rax, sme_me_mask(%rip) /* Create the encryption mask */ 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* 828c2ecf20Sopenharmony_ci * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in 838c2ecf20Sopenharmony_ci * get_sev_encryption_bit() because this function is 32-bit code and 848c2ecf20Sopenharmony_ci * shared between 64-bit and 32-bit boot path. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */ 878c2ecf20Sopenharmony_ci rdmsr 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Store MSR value in sev_status */ 908c2ecf20Sopenharmony_ci shlq $32, %rdx 918c2ecf20Sopenharmony_ci orq %rdx, %rax 928c2ecf20Sopenharmony_ci movq %rax, sev_status(%rip) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci.Lno_sev_mask: 958c2ecf20Sopenharmony_ci movq %rbp, %rsp /* Restore original stack pointer */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci pop %rdx 988c2ecf20Sopenharmony_ci pop %rbp 998c2ecf20Sopenharmony_ci#endif 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci xor %rax, %rax 1028c2ecf20Sopenharmony_ci RET 1038c2ecf20Sopenharmony_ciSYM_FUNC_END(set_sev_encryption_mask) 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci .data 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT 1088c2ecf20Sopenharmony_ci .balign 8 1098c2ecf20Sopenharmony_ciSYM_DATA(sme_me_mask, .quad 0) 1108c2ecf20Sopenharmony_ciSYM_DATA(sev_status, .quad 0) 1118c2ecf20Sopenharmony_ciSYM_DATA(sev_check_data, .quad 0) 1128c2ecf20Sopenharmony_ci#endif 113