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
18SYM_FUNC_START(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	movl	$0x80000000, %eax	/* CPUID to check the highest leaf */
27	cpuid
28	cmpl	$0x8000001f, %eax	/* See if 0x8000001f is available */
29	jb	.Lno_sev
30
31	/*
32	 * Check for the SEV feature:
33	 *   CPUID Fn8000_001F[EAX] - Bit 1
34	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
35	 *     Pagetable bit position used to indicate encryption
36	 */
37	movl	$0x8000001f, %eax
38	cpuid
39	bt	$1, %eax		/* Check if SEV is available */
40	jnc	.Lno_sev
41
42	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
43	rdmsr
44	bt	$MSR_AMD64_SEV_ENABLED_BIT, %eax	/* Check if SEV is active */
45	jnc	.Lno_sev
46
47	movl	%ebx, %eax
48	andl	$0x3f, %eax		/* Return the encryption bit location */
49	jmp	.Lsev_exit
50
51.Lno_sev:
52	xor	%eax, %eax
53
54.Lsev_exit:
55	pop	%edx
56	pop	%ecx
57	pop	%ebx
58
59#endif	/* CONFIG_AMD_MEM_ENCRYPT */
60
61	RET
62SYM_FUNC_END(get_sev_encryption_bit)
63
64	.code64
65
66#include "../../kernel/sev_verify_cbit.S"
67
68SYM_FUNC_START(set_sev_encryption_mask)
69#ifdef CONFIG_AMD_MEM_ENCRYPT
70	push	%rbp
71	push	%rdx
72
73	movq	%rsp, %rbp		/* Save current stack pointer */
74
75	call	get_sev_encryption_bit	/* Get the encryption bit position */
76	testl	%eax, %eax
77	jz	.Lno_sev_mask
78
79	bts	%rax, sme_me_mask(%rip)	/* Create the encryption mask */
80
81	/*
82	 * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
83	 * get_sev_encryption_bit() because this function is 32-bit code and
84	 * shared between 64-bit and 32-bit boot path.
85	 */
86	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
87	rdmsr
88
89	/* Store MSR value in sev_status */
90	shlq	$32, %rdx
91	orq	%rdx, %rax
92	movq	%rax, sev_status(%rip)
93
94.Lno_sev_mask:
95	movq	%rbp, %rsp		/* Restore original stack pointer */
96
97	pop	%rdx
98	pop	%rbp
99#endif
100
101	xor	%rax, %rax
102	RET
103SYM_FUNC_END(set_sev_encryption_mask)
104
105	.data
106
107#ifdef CONFIG_AMD_MEM_ENCRYPT
108	.balign	8
109SYM_DATA(sme_me_mask,		.quad 0)
110SYM_DATA(sev_status,		.quad 0)
111SYM_DATA(sev_check_data,	.quad 0)
112#endif
113