Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / x86 / boot / compressed / mem_encrypt.S
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
21 ENTRY(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
36 1:      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
88 ENDPROC(get_sev_encryption_bit)
89
90         .code64
91 ENTRY(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
113 ENDPROC(set_sev_encryption_mask)
114
115         .data
116 enc_bit:
117         .int    0xffffffff
118
119 #ifdef CONFIG_AMD_MEM_ENCRYPT
120         .balign 8
121 GLOBAL(sme_me_mask)
122         .quad   0
123 #endif