Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/arch/x86/boot/compressed/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  mem_encrypt.S   Sprache: Sparc

 
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * AMD Memory Encryption Support
 *
 * Copyright (C) 2017 Advanced Micro Devices, Inc.
 *
 * Author: Tom Lendacky <thomas.lendacky@amd.com>
 */


#include <linux/linkage.h>

#include <asm/processor-flags.h>
#include <asm/msr.h>
#include <asm/asm-offsets.h>
#include <asm/segment.h>
#include <asm/trapnr.h>

 .text
 .code32
SYM_FUNC_START(get_sev_encryption_bit)
 push %ebx

 movl $0x80000000, %eax /* CPUID to check the highest leaf */
 cpuid
 cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
 jb .Lno_sev

 /*
 * Check for the SEV feature:
 *   CPUID Fn8000_001F[EAX] - Bit 1
 *   CPUID Fn8000_001F[EBX] - Bits 5:0
 *     Pagetable bit position used to indicate encryption
 */

 movl $0x8000001f, %eax
 cpuid
 bt $1, %eax  /* Check if SEV is available */
 jnc .Lno_sev

 movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
 rdmsr
 bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */
 jnc .Lno_sev

 movl %ebx, %eax
 andl $0x3f, %eax  /* Return the encryption bit location */
 jmp .Lsev_exit

.Lno_sev:
 xor %eax, %eax

.Lsev_exit:
 pop %ebx
 RET
SYM_FUNC_END(get_sev_encryption_bit)

/**
 * sev_es_req_cpuid - Request a CPUID value from the Hypervisor using
 *       the GHCB MSR protocol
 *
 * @%eax: Register to request (0=EAX, 1=EBX, 2=ECX, 3=EDX)
 * @%edx: CPUID Function
 *
 * Returns 0 in %eax on success, non-zero on failure
 * %edx returns CPUID value on success
 */

SYM_CODE_START_LOCAL(sev_es_req_cpuid)
 shll $30, %eax
 orl     $0x00000004, %eax
 movl    $MSR_AMD64_SEV_ES_GHCB, %ecx
 wrmsr
 rep; vmmcall  # VMGEXIT
 rdmsr

 /* Check response */
 movl %eax, %ecx
 andl $0x3ffff000, %ecx # Bits [12-29] MBZ
 jnz 2f

 /* Check return code */
 andl    $0xfff, %eax
 cmpl    $5, %eax
 jne 2f

 /* All good - return success */
 xorl %eax, %eax
1:
 RET
2:
 movl $-1, %eax
 jmp 1b
SYM_CODE_END(sev_es_req_cpuid)

SYM_CODE_START_LOCAL(startup32_vc_handler)
 pushl %eax
 pushl %ebx
 pushl %ecx
 pushl %edx

 /* Keep CPUID function in %ebx */
 movl %eax, %ebx

 /* Check if error-code == SVM_EXIT_CPUID */
 cmpl $0x72, 16(%esp)
 jne .Lfail

 movl $0, %eax  # Request CPUID[fn].EAX
 movl %ebx, %edx  # CPUID fn
 call sev_es_req_cpuid # Call helper
 testl %eax, %eax  # Check return code
 jnz .Lfail
 movl %edx, 12(%esp)  # Store result

 movl $1, %eax  # Request CPUID[fn].EBX
 movl %ebx, %edx  # CPUID fn
 call sev_es_req_cpuid # Call helper
 testl %eax, %eax  # Check return code
 jnz .Lfail
 movl %edx, 8(%esp)  # Store result

 movl $2, %eax  # Request CPUID[fn].ECX
 movl %ebx, %edx  # CPUID fn
 call sev_es_req_cpuid # Call helper
 testl %eax, %eax  # Check return code
 jnz .Lfail
 movl %edx, 4(%esp)  # Store result

 movl $3, %eax  # Request CPUID[fn].EDX
 movl %ebx, %edx  # CPUID fn
 call sev_es_req_cpuid # Call helper
 testl %eax, %eax  # Check return code
 jnz .Lfail
 movl %edx, 0(%esp)  # Store result

 /*
 * Sanity check CPUID results from the Hypervisor. See comment in
 * do_vc_no_ghcb() for more details on why this is necessary.
 */


 /* Fail if SEV leaf not available in CPUID[0x80000000].EAX */
 cmpl    $0x80000000, %ebx
 jne     .Lcheck_sev
 cmpl    $0x8000001f, 12(%esp)
 jb      .Lfail
 jmp     .Ldone

.Lcheck_sev:
 /* Fail if SEV bit not set in CPUID[0x8000001f].EAX[1] */
 cmpl    $0x8000001f, %ebx
 jne     .Ldone
 btl     $1, 12(%esp)
 jnc     .Lfail

.Ldone:
 popl %edx
 popl %ecx
 popl %ebx
 popl %eax

 /* Remove error code */
 addl $4, %esp

 /* Jump over CPUID instruction */
 addl $2, (%esp)

 iret
.Lfail:
 /* Send terminate request to Hypervisor */
 movl    $0x100, %eax
 xorl    %edx, %edx
 movl    $MSR_AMD64_SEV_ES_GHCB, %ecx
 wrmsr
 rep; vmmcall

 /* If request fails, go to hlt loop */
 hlt
 jmp .Lfail
SYM_CODE_END(startup32_vc_handler)

/*
 * Write an IDT entry into boot32_idt
 *
 * Parameters:
 *
 * %eax: Handler address
 * %edx: Vector number
 * %ecx: IDT address
 */

SYM_FUNC_START_LOCAL(startup32_set_idt_entry)
 /* IDT entry address to %ecx */
 leal (%ecx, %edx, 8), %ecx

 /* Build IDT entry, lower 4 bytes */
 movl    %eax, %edx
 andl    $0x0000ffff, %edx  # Target code segment offset [15:0]
 orl $(__KERNEL32_CS << 16), %edx # Target code segment selector

 /* Store lower 4 bytes to IDT */
 movl    %edx, (%ecx)

 /* Build IDT entry, upper 4 bytes */
 movl    %eax, %edx
 andl    $0xffff0000, %edx # Target code segment offset [31:16]
 orl     $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate

 /* Store upper 4 bytes to IDT */
 movl    %edx, 4(%ecx)

 RET
SYM_FUNC_END(startup32_set_idt_entry)

SYM_FUNC_START(startup32_load_idt)
 push %ebp
 push %ebx

 call 1f
1: pop %ebp

 leal    (boot32_idt - 1b)(%ebp), %ebx

 /* #VC handler */
 leal    (startup32_vc_handler - 1b)(%ebp), %eax
 movl    $X86_TRAP_VC, %edx
 movl %ebx, %ecx
 call    startup32_set_idt_entry

 /* Load IDT */
 leal (boot32_idt_desc - 1b)(%ebp), %ecx
 movl %ebx, 2(%ecx)
 lidt    (%ecx)

 pop %ebx
 pop %ebp
 RET
SYM_FUNC_END(startup32_load_idt)

/*
 * Check for the correct C-bit position when the startup_32 boot-path is used.
 *
 * The check makes use of the fact that all memory is encrypted when paging is
 * disabled. The function creates 64 bits of random data using the RDRAND
 * instruction. RDRAND is mandatory for SEV guests, so always available. If the
 * hypervisor violates that the kernel will crash right here.
 *
 * The 64 bits of random data are stored to a memory location and at the same
 * time kept in the %eax and %ebx registers. Since encryption is always active
 * when paging is off the random data will be stored encrypted in main memory.
 *
 * Then paging is enabled. When the C-bit position is correct all memory is
 * still mapped encrypted and comparing the register values with memory will
 * succeed. An incorrect C-bit position will map all memory unencrypted, so that
 * the compare will use the encrypted random data and fail.
 */

SYM_FUNC_START(startup32_check_sev_cbit)
 pushl %ebx
 pushl %ebp

 call 0f
0: popl %ebp

 /* Check for non-zero sev_status */
 movl (sev_status - 0b)(%ebp), %eax
 testl %eax, %eax
 jz 4f

 /*
 * Get two 32-bit random values - Don't bail out if RDRAND fails
 * because it is better to prevent forward progress if no random value
 * can be gathered.
 */

1: rdrand %eax
 jnc 1b
2: rdrand %ebx
 jnc 2b

 /* Store to memory and keep it in the registers */
 leal (sev_check_data - 0b)(%ebp), %ebp
 movl %eax, 0(%ebp)
 movl %ebx, 4(%ebp)

 /* Enable paging to see if encryption is active */
 movl %cr0, %edx    /* Backup %cr0 in %edx */
 movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */
 movl %ecx, %cr0

 cmpl %eax, 0(%ebp)
 jne 3f
 cmpl %ebx, 4(%ebp)
 jne 3f

 movl %edx, %cr0 /* Restore previous %cr0 */

 jmp 4f

3: /* Check failed - hlt the machine */
 hlt
 jmp 3b

4:
 popl %ebp
 popl %ebx
 RET
SYM_FUNC_END(startup32_check_sev_cbit)

 .code64

#include "../../kernel/sev_verify_cbit.S"

 .data

 .balign 8
SYM_DATA(sme_me_mask,  .quad 0)
SYM_DATA(sev_status,  .quad 0)
SYM_DATA(sev_check_data, .quad 0)

SYM_DATA_START_LOCAL(boot32_idt)
 .rept 32
 .quad 0
 .endr
SYM_DATA_END(boot32_idt)

SYM_DATA_START_LOCAL(boot32_idt_desc)
 .word . - boot32_idt - 1
 .long 0
SYM_DATA_END(boot32_idt_desc)

Messung V0.5
C=92 H=100 G=95

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.