cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mem_encrypt.S (4039B)


      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/**
     65 * sev_es_req_cpuid - Request a CPUID value from the Hypervisor using
     66 *		      the GHCB MSR protocol
     67 *
     68 * @%eax:	Register to request (0=EAX, 1=EBX, 2=ECX, 3=EDX)
     69 * @%edx:	CPUID Function
     70 *
     71 * Returns 0 in %eax on success, non-zero on failure
     72 * %edx returns CPUID value on success
     73 */
     74SYM_CODE_START_LOCAL(sev_es_req_cpuid)
     75	shll	$30, %eax
     76	orl     $0x00000004, %eax
     77	movl    $MSR_AMD64_SEV_ES_GHCB, %ecx
     78	wrmsr
     79	rep; vmmcall		# VMGEXIT
     80	rdmsr
     81
     82	/* Check response */
     83	movl	%eax, %ecx
     84	andl	$0x3ffff000, %ecx	# Bits [12-29] MBZ
     85	jnz	2f
     86
     87	/* Check return code */
     88	andl    $0xfff, %eax
     89	cmpl    $5, %eax
     90	jne	2f
     91
     92	/* All good - return success */
     93	xorl	%eax, %eax
     941:
     95	RET
     962:
     97	movl	$-1, %eax
     98	jmp	1b
     99SYM_CODE_END(sev_es_req_cpuid)
    100
    101SYM_CODE_START(startup32_vc_handler)
    102	pushl	%eax
    103	pushl	%ebx
    104	pushl	%ecx
    105	pushl	%edx
    106
    107	/* Keep CPUID function in %ebx */
    108	movl	%eax, %ebx
    109
    110	/* Check if error-code == SVM_EXIT_CPUID */
    111	cmpl	$0x72, 16(%esp)
    112	jne	.Lfail
    113
    114	movl	$0, %eax		# Request CPUID[fn].EAX
    115	movl	%ebx, %edx		# CPUID fn
    116	call	sev_es_req_cpuid	# Call helper
    117	testl	%eax, %eax		# Check return code
    118	jnz	.Lfail
    119	movl	%edx, 12(%esp)		# Store result
    120
    121	movl	$1, %eax		# Request CPUID[fn].EBX
    122	movl	%ebx, %edx		# CPUID fn
    123	call	sev_es_req_cpuid	# Call helper
    124	testl	%eax, %eax		# Check return code
    125	jnz	.Lfail
    126	movl	%edx, 8(%esp)		# Store result
    127
    128	movl	$2, %eax		# Request CPUID[fn].ECX
    129	movl	%ebx, %edx		# CPUID fn
    130	call	sev_es_req_cpuid	# Call helper
    131	testl	%eax, %eax		# Check return code
    132	jnz	.Lfail
    133	movl	%edx, 4(%esp)		# Store result
    134
    135	movl	$3, %eax		# Request CPUID[fn].EDX
    136	movl	%ebx, %edx		# CPUID fn
    137	call	sev_es_req_cpuid	# Call helper
    138	testl	%eax, %eax		# Check return code
    139	jnz	.Lfail
    140	movl	%edx, 0(%esp)		# Store result
    141
    142	/*
    143	 * Sanity check CPUID results from the Hypervisor. See comment in
    144	 * do_vc_no_ghcb() for more details on why this is necessary.
    145	 */
    146
    147	/* Fail if SEV leaf not available in CPUID[0x80000000].EAX */
    148	cmpl    $0x80000000, %ebx
    149	jne     .Lcheck_sev
    150	cmpl    $0x8000001f, 12(%esp)
    151	jb      .Lfail
    152	jmp     .Ldone
    153
    154.Lcheck_sev:
    155	/* Fail if SEV bit not set in CPUID[0x8000001f].EAX[1] */
    156	cmpl    $0x8000001f, %ebx
    157	jne     .Ldone
    158	btl     $1, 12(%esp)
    159	jnc     .Lfail
    160
    161.Ldone:
    162	popl	%edx
    163	popl	%ecx
    164	popl	%ebx
    165	popl	%eax
    166
    167	/* Remove error code */
    168	addl	$4, %esp
    169
    170	/* Jump over CPUID instruction */
    171	addl	$2, (%esp)
    172
    173	iret
    174.Lfail:
    175	/* Send terminate request to Hypervisor */
    176	movl    $0x100, %eax
    177	xorl    %edx, %edx
    178	movl    $MSR_AMD64_SEV_ES_GHCB, %ecx
    179	wrmsr
    180	rep; vmmcall
    181
    182	/* If request fails, go to hlt loop */
    183	hlt
    184	jmp .Lfail
    185SYM_CODE_END(startup32_vc_handler)
    186
    187	.code64
    188
    189#include "../../kernel/sev_verify_cbit.S"
    190
    191	.data
    192
    193#ifdef CONFIG_AMD_MEM_ENCRYPT
    194	.balign	8
    195SYM_DATA(sme_me_mask,		.quad 0)
    196SYM_DATA(sev_status,		.quad 0)
    197SYM_DATA(sev_check_data,	.quad 0)
    198#endif