1/* 2 * AMD Memory Encryption Support 3 * 4 * Copyright (C) 2017 Advanced Micro Devices, Inc. 5 * 6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/linkage.h> 14 15#include <asm/processor-flags.h> 16#include <asm/msr.h> 17#include <asm/asm-offsets.h> 18 19 .text 20 .code32 21ENTRY(get_sev_encryption_bit) 22 xor %eax, %eax 23 24#ifdef CONFIG_AMD_MEM_ENCRYPT 25 push %ebx 26 push %ecx 27 push %edx 28 push %edi 29 30 /* 31 * RIP-relative addressing is needed to access the encryption bit 32 * variable. Since we are running in 32-bit mode we need this call/pop 33 * sequence to get the proper relative addressing. 34 */ 35 call 1f 361: popl %edi 37 subl $1b, %edi 38 39 movl enc_bit(%edi), %eax 40 cmpl $0, %eax 41 jge .Lsev_exit 42 43 /* Check if running under a hypervisor */ 44 movl $1, %eax 45 cpuid 46 bt $31, %ecx /* Check the hypervisor bit */ 47 jnc .Lno_sev 48 49 movl $0x80000000, %eax /* CPUID to check the highest leaf */ 50 cpuid 51 cmpl $0x8000001f, %eax /* See if 0x8000001f is available */ 52 jb .Lno_sev 53 54 /* 55 * Check for the SEV feature: 56 * CPUID Fn8000_001F[EAX] - Bit 1 57 * CPUID Fn8000_001F[EBX] - Bits 5:0 58 * Pagetable bit position used to indicate encryption 59 */ 60 movl $0x8000001f, %eax 61 cpuid 62 bt $1, %eax /* Check if SEV is available */ 63 jnc .Lno_sev 64 65 movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */ 66 rdmsr 67 bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */ 68 jnc .Lno_sev 69 70 movl %ebx, %eax 71 andl $0x3f, %eax /* Return the encryption bit location */ 72 movl %eax, enc_bit(%edi) 73 jmp .Lsev_exit 74 75.Lno_sev: 76 xor %eax, %eax 77 movl %eax, enc_bit(%edi) 78 79.Lsev_exit: 80 pop %edi 81 pop %edx 82 pop %ecx 83 pop %ebx 84 85#endif /* CONFIG_AMD_MEM_ENCRYPT */ 86 87 ret 88ENDPROC(get_sev_encryption_bit) 89 90 .code64 91ENTRY(set_sev_encryption_mask) 92#ifdef CONFIG_AMD_MEM_ENCRYPT 93 push %rbp 94 push %rdx 95 96 movq %rsp, %rbp /* Save current stack pointer */ 97 98 call get_sev_encryption_bit /* Get the encryption bit position */ 99 testl %eax, %eax 100 jz .Lno_sev_mask 101 102 bts %rax, sme_me_mask(%rip) /* Create the encryption mask */ 103 104.Lno_sev_mask: 105 movq %rbp, %rsp /* Restore original stack pointer */ 106 107 pop %rdx 108 pop %rbp 109#endif 110 111 xor %rax, %rax 112 ret 113ENDPROC(set_sev_encryption_mask) 114 115 .data 116enc_bit: 117 .int 0xffffffff 118 119#ifdef CONFIG_AMD_MEM_ENCRYPT 120 .balign 8 121GLOBAL(sme_me_mask) 122 .quad 0 123#endif 124