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
29	/* Check if running under a hypervisor */
30	movl	$1, %eax
31	cpuid
32	bt	$31, %ecx		/* Check the hypervisor bit */
33	jnc	.Lno_sev
34
35	movl	$0x80000000, %eax	/* CPUID to check the highest leaf */
36	cpuid
37	cmpl	$0x8000001f, %eax	/* See if 0x8000001f is available */
38	jb	.Lno_sev
39
40	/*
41	 * Check for the SEV feature:
42	 *   CPUID Fn8000_001F[EAX] - Bit 1
43	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
44	 *     Pagetable bit position used to indicate encryption
45	 */
46	movl	$0x8000001f, %eax
47	cpuid
48	bt	$1, %eax		/* Check if SEV is available */
49	jnc	.Lno_sev
50
51	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
52	rdmsr
53	bt	$MSR_AMD64_SEV_ENABLED_BIT, %eax	/* Check if SEV is active */
54	jnc	.Lno_sev
55
56	movl	%ebx, %eax
57	andl	$0x3f, %eax		/* Return the encryption bit location */
58	jmp	.Lsev_exit
59
60.Lno_sev:
61	xor	%eax, %eax
62
63.Lsev_exit:
64	pop	%edx
65	pop	%ecx
66	pop	%ebx
67
68#endif	/* CONFIG_AMD_MEM_ENCRYPT */
69
70	ret
71ENDPROC(get_sev_encryption_bit)
72
73	.code64
74ENTRY(set_sev_encryption_mask)
75#ifdef CONFIG_AMD_MEM_ENCRYPT
76	push	%rbp
77	push	%rdx
78
79	movq	%rsp, %rbp		/* Save current stack pointer */
80
81	call	get_sev_encryption_bit	/* Get the encryption bit position */
82	testl	%eax, %eax
83	jz	.Lno_sev_mask
84
85	bts	%rax, sme_me_mask(%rip)	/* Create the encryption mask */
86
87.Lno_sev_mask:
88	movq	%rbp, %rsp		/* Restore original stack pointer */
89
90	pop	%rdx
91	pop	%rbp
92#endif
93
94	xor	%rax, %rax
95	ret
96ENDPROC(set_sev_encryption_mask)
97
98	.data
99
100#ifdef CONFIG_AMD_MEM_ENCRYPT
101	.balign	8
102GLOBAL(sme_me_mask)
103	.quad	0
104#endif
105