18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * AMD Memory Encryption Support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Advanced Micro Devices, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/linkage.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm/processor-flags.h>
138c2ecf20Sopenharmony_ci#include <asm/msr.h>
148c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	.text
178c2ecf20Sopenharmony_ci	.code32
188c2ecf20Sopenharmony_ciSYM_FUNC_START(get_sev_encryption_bit)
198c2ecf20Sopenharmony_ci	xor	%eax, %eax
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT
228c2ecf20Sopenharmony_ci	push	%ebx
238c2ecf20Sopenharmony_ci	push	%ecx
248c2ecf20Sopenharmony_ci	push	%edx
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	movl	$0x80000000, %eax	/* CPUID to check the highest leaf */
278c2ecf20Sopenharmony_ci	cpuid
288c2ecf20Sopenharmony_ci	cmpl	$0x8000001f, %eax	/* See if 0x8000001f is available */
298c2ecf20Sopenharmony_ci	jb	.Lno_sev
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	/*
328c2ecf20Sopenharmony_ci	 * Check for the SEV feature:
338c2ecf20Sopenharmony_ci	 *   CPUID Fn8000_001F[EAX] - Bit 1
348c2ecf20Sopenharmony_ci	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
358c2ecf20Sopenharmony_ci	 *     Pagetable bit position used to indicate encryption
368c2ecf20Sopenharmony_ci	 */
378c2ecf20Sopenharmony_ci	movl	$0x8000001f, %eax
388c2ecf20Sopenharmony_ci	cpuid
398c2ecf20Sopenharmony_ci	bt	$1, %eax		/* Check if SEV is available */
408c2ecf20Sopenharmony_ci	jnc	.Lno_sev
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
438c2ecf20Sopenharmony_ci	rdmsr
448c2ecf20Sopenharmony_ci	bt	$MSR_AMD64_SEV_ENABLED_BIT, %eax	/* Check if SEV is active */
458c2ecf20Sopenharmony_ci	jnc	.Lno_sev
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	movl	%ebx, %eax
488c2ecf20Sopenharmony_ci	andl	$0x3f, %eax		/* Return the encryption bit location */
498c2ecf20Sopenharmony_ci	jmp	.Lsev_exit
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci.Lno_sev:
528c2ecf20Sopenharmony_ci	xor	%eax, %eax
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci.Lsev_exit:
558c2ecf20Sopenharmony_ci	pop	%edx
568c2ecf20Sopenharmony_ci	pop	%ecx
578c2ecf20Sopenharmony_ci	pop	%ebx
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#endif	/* CONFIG_AMD_MEM_ENCRYPT */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	RET
628c2ecf20Sopenharmony_ciSYM_FUNC_END(get_sev_encryption_bit)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	.code64
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#include "../../kernel/sev_verify_cbit.S"
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciSYM_FUNC_START(set_sev_encryption_mask)
698c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT
708c2ecf20Sopenharmony_ci	push	%rbp
718c2ecf20Sopenharmony_ci	push	%rdx
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	movq	%rsp, %rbp		/* Save current stack pointer */
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	call	get_sev_encryption_bit	/* Get the encryption bit position */
768c2ecf20Sopenharmony_ci	testl	%eax, %eax
778c2ecf20Sopenharmony_ci	jz	.Lno_sev_mask
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	bts	%rax, sme_me_mask(%rip)	/* Create the encryption mask */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/*
828c2ecf20Sopenharmony_ci	 * Read MSR_AMD64_SEV again and store it to sev_status. Can't do this in
838c2ecf20Sopenharmony_ci	 * get_sev_encryption_bit() because this function is 32-bit code and
848c2ecf20Sopenharmony_ci	 * shared between 64-bit and 32-bit boot path.
858c2ecf20Sopenharmony_ci	 */
868c2ecf20Sopenharmony_ci	movl	$MSR_AMD64_SEV, %ecx	/* Read the SEV MSR */
878c2ecf20Sopenharmony_ci	rdmsr
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/* Store MSR value in sev_status */
908c2ecf20Sopenharmony_ci	shlq	$32, %rdx
918c2ecf20Sopenharmony_ci	orq	%rdx, %rax
928c2ecf20Sopenharmony_ci	movq	%rax, sev_status(%rip)
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci.Lno_sev_mask:
958c2ecf20Sopenharmony_ci	movq	%rbp, %rsp		/* Restore original stack pointer */
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	pop	%rdx
988c2ecf20Sopenharmony_ci	pop	%rbp
998c2ecf20Sopenharmony_ci#endif
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	xor	%rax, %rax
1028c2ecf20Sopenharmony_ci	RET
1038c2ecf20Sopenharmony_ciSYM_FUNC_END(set_sev_encryption_mask)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	.data
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT
1088c2ecf20Sopenharmony_ci	.balign	8
1098c2ecf20Sopenharmony_ciSYM_DATA(sme_me_mask,		.quad 0)
1108c2ecf20Sopenharmony_ciSYM_DATA(sev_status,		.quad 0)
1118c2ecf20Sopenharmony_ciSYM_DATA(sev_check_data,	.quad 0)
1128c2ecf20Sopenharmony_ci#endif
113