linux/arch/x86/boot/compressed/mem_encrypt.S
<<
>>
Prefs
   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        push    %edi
  29
  30        /*
  31         * RIP-relative addressing is needed to access the encryption bit
  32         * variable. Since we are running in 32-bit mode we need this call/pop
  33         * sequence to get the proper relative addressing.
  34         */
  35        call    1f
  361:      popl    %edi
  37        subl    $1b, %edi
  38
  39        movl    enc_bit(%edi), %eax
  40        cmpl    $0, %eax
  41        jge     .Lsev_exit
  42
  43        /* Check if running under a hypervisor */
  44        movl    $1, %eax
  45        cpuid
  46        bt      $31, %ecx               /* Check the hypervisor bit */
  47        jnc     .Lno_sev
  48
  49        movl    $0x80000000, %eax       /* CPUID to check the highest leaf */
  50        cpuid
  51        cmpl    $0x8000001f, %eax       /* See if 0x8000001f is available */
  52        jb      .Lno_sev
  53
  54        /*
  55         * Check for the SEV feature:
  56         *   CPUID Fn8000_001F[EAX] - Bit 1
  57         *   CPUID Fn8000_001F[EBX] - Bits 5:0
  58         *     Pagetable bit position used to indicate encryption
  59         */
  60        movl    $0x8000001f, %eax
  61        cpuid
  62        bt      $1, %eax                /* Check if SEV is available */
  63        jnc     .Lno_sev
  64
  65        movl    $MSR_AMD64_SEV, %ecx    /* Read the SEV MSR */
  66        rdmsr
  67        bt      $MSR_AMD64_SEV_ENABLED_BIT, %eax        /* Check if SEV is active */
  68        jnc     .Lno_sev
  69
  70        movl    %ebx, %eax
  71        andl    $0x3f, %eax             /* Return the encryption bit location */
  72        movl    %eax, enc_bit(%edi)
  73        jmp     .Lsev_exit
  74
  75.Lno_sev:
  76        xor     %eax, %eax
  77        movl    %eax, enc_bit(%edi)
  78
  79.Lsev_exit:
  80        pop     %edi
  81        pop     %edx
  82        pop     %ecx
  83        pop     %ebx
  84
  85#endif  /* CONFIG_AMD_MEM_ENCRYPT */
  86
  87        ret
  88ENDPROC(get_sev_encryption_bit)
  89
  90        .code64
  91ENTRY(set_sev_encryption_mask)
  92#ifdef CONFIG_AMD_MEM_ENCRYPT
  93        push    %rbp
  94        push    %rdx
  95
  96        movq    %rsp, %rbp              /* Save current stack pointer */
  97
  98        call    get_sev_encryption_bit  /* Get the encryption bit position */
  99        testl   %eax, %eax
 100        jz      .Lno_sev_mask
 101
 102        bts     %rax, sme_me_mask(%rip) /* Create the encryption mask */
 103
 104.Lno_sev_mask:
 105        movq    %rbp, %rsp              /* Restore original stack pointer */
 106
 107        pop     %rdx
 108        pop     %rbp
 109#endif
 110
 111        xor     %rax, %rax
 112        ret
 113ENDPROC(set_sev_encryption_mask)
 114
 115        .data
 116enc_bit:
 117        .int    0xffffffff
 118
 119#ifdef CONFIG_AMD_MEM_ENCRYPT
 120        .balign 8
 121GLOBAL(sme_me_mask)
 122        .quad   0
 123#endif
 124