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(get_sev_encryption_mask) 92 xor %rax, %rax 93 94#ifdef CONFIG_AMD_MEM_ENCRYPT 95 push %rbp 96 push %rdx 97 98 movq %rsp, %rbp /* Save current stack pointer */ 99 100 call get_sev_encryption_bit /* Get the encryption bit position */ 101 testl %eax, %eax 102 jz .Lno_sev_mask 103 104 xor %rdx, %rdx 105 bts %rax, %rdx /* Create the encryption mask */ 106 mov %rdx, %rax /* ... and return it */ 107 108.Lno_sev_mask: 109 movq %rbp, %rsp /* Restore original stack pointer */ 110 111 pop %rdx 112 pop %rbp 113#endif 114 115 ret 116ENDPROC(get_sev_encryption_mask) 117 118 .data 119enc_bit: 120 .int 0xffffffff 121