1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * AMD Memory Encryption Support
4 *
5 * Copyright (C) 2017 Advanced Micro Devices, Inc.
6 *
7 * Author: Tom Lendacky <thomas.lendacky@amd.com>
8 */
9
10#include <linux/linkage.h>
11
12#include <asm/processor-flags.h>
13#include <asm/msr.h>
14#include <asm/asm-offsets.h>
15
16	.text
17	.code32
18ENTRY(get_sev_encryption_bit)
19	xor	%eax, %eax
20
21#ifdef CONFIG_AMD_MEM_ENCRYPT
22	push	%ebx
23	push	%ecx
24	push	%edx
25
26	/* Check if running under a hypervisor */
27	movl	$1, %eax
28	cpuid
29	bt	$31, %ecx		/* Check the hypervisor bit */
30	jnc	.Lno_sev
31
32	movl	$0x80000000, %eax	/* CPUID to check the highest leaf */
33	cpuid
34	cmpl	$0x8000001f, %eax	/* See if 0x8000001f is available */
35	jb	.Lno_sev
36
37	/*
38	 * Check for the SEV feature:
39	 *   CPUID Fn8000_001F[EAX] - Bit 1
40	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
41	 *     Pagetable bit position used to indicate encryption
42	 */
43	movl	$0x8000001f, %eax
44	cpuid
45	bt	$1, %eax		/* Check if SEV is available */
46	jnc	.Lno_sev
47
48	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
49	rdmsr
50	bt	$MSR_AMD64_SEV_ENABLED_BIT, %eax	/* Check if SEV is active */
51	jnc	.Lno_sev
52
53	movl	%ebx, %eax
54	andl	$0x3f, %eax		/* Return the encryption bit location */
55	jmp	.Lsev_exit
56
57.Lno_sev:
58	xor	%eax, %eax
59
60.Lsev_exit:
61	pop	%edx
62	pop	%ecx
63	pop	%ebx
64
65#endif	/* CONFIG_AMD_MEM_ENCRYPT */
66
67	ret
68ENDPROC(get_sev_encryption_bit)
69
70	.code64
71ENTRY(set_sev_encryption_mask)
72#ifdef CONFIG_AMD_MEM_ENCRYPT
73	push	%rbp
74	push	%rdx
75
76	movq	%rsp, %rbp		/* Save current stack pointer */
77
78	call	get_sev_encryption_bit	/* Get the encryption bit position */
79	testl	%eax, %eax
80	jz	.Lno_sev_mask
81
82	bts	%rax, sme_me_mask(%rip)	/* Create the encryption mask */
83
84.Lno_sev_mask:
85	movq	%rbp, %rsp		/* Restore original stack pointer */
86
87	pop	%rdx
88	pop	%rbp
89#endif
90
91	xor	%rax, %rax
92	ret
93ENDPROC(set_sev_encryption_mask)
94
95	.data
96
97#ifdef CONFIG_AMD_MEM_ENCRYPT
98	.balign	8
99GLOBAL(sme_me_mask)
100	.quad	0
101#endif
102