mem_encrypt.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * AMD Memory Encryption Support
  3. *
  4. * Copyright (C) 2016 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. #include <linux/linkage.h>
  13. #include <linux/init.h>
  14. #include <linux/mm.h>
  15. #include <asm/tlbflush.h>
  16. #include <asm/fixmap.h>
  17. /*
  18. * Since SME related variables are set early in the boot process they must
  19. * reside in the .data section so as not to be zeroed out when the .bss
  20. * section is later cleared.
  21. */
  22. unsigned long sme_me_mask __section(.data) = 0;
  23. EXPORT_SYMBOL_GPL(sme_me_mask);
  24. /* Buffer used for early in-place encryption by BSP, no locking needed */
  25. static char sme_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
  26. /*
  27. * This routine does not change the underlying encryption setting of the
  28. * page(s) that map this memory. It assumes that eventually the memory is
  29. * meant to be accessed as either encrypted or decrypted but the contents
  30. * are currently not in the desired state.
  31. *
  32. * This routine follows the steps outlined in the AMD64 Architecture
  33. * Programmer's Manual Volume 2, Section 7.10.8 Encrypt-in-Place.
  34. */
  35. static void __init __sme_early_enc_dec(resource_size_t paddr,
  36. unsigned long size, bool enc)
  37. {
  38. void *src, *dst;
  39. size_t len;
  40. if (!sme_me_mask)
  41. return;
  42. local_flush_tlb();
  43. wbinvd();
  44. /*
  45. * There are limited number of early mapping slots, so map (at most)
  46. * one page at time.
  47. */
  48. while (size) {
  49. len = min_t(size_t, sizeof(sme_early_buffer), size);
  50. /*
  51. * Create mappings for the current and desired format of
  52. * the memory. Use a write-protected mapping for the source.
  53. */
  54. src = enc ? early_memremap_decrypted_wp(paddr, len) :
  55. early_memremap_encrypted_wp(paddr, len);
  56. dst = enc ? early_memremap_encrypted(paddr, len) :
  57. early_memremap_decrypted(paddr, len);
  58. /*
  59. * If a mapping can't be obtained to perform the operation,
  60. * then eventual access of that area in the desired mode
  61. * will cause a crash.
  62. */
  63. BUG_ON(!src || !dst);
  64. /*
  65. * Use a temporary buffer, of cache-line multiple size, to
  66. * avoid data corruption as documented in the APM.
  67. */
  68. memcpy(sme_early_buffer, src, len);
  69. memcpy(dst, sme_early_buffer, len);
  70. early_memunmap(dst, len);
  71. early_memunmap(src, len);
  72. paddr += len;
  73. size -= len;
  74. }
  75. }
  76. void __init sme_early_encrypt(resource_size_t paddr, unsigned long size)
  77. {
  78. __sme_early_enc_dec(paddr, size, true);
  79. }
  80. void __init sme_early_decrypt(resource_size_t paddr, unsigned long size)
  81. {
  82. __sme_early_enc_dec(paddr, size, false);
  83. }
  84. void __init sme_early_init(void)
  85. {
  86. unsigned int i;
  87. if (!sme_me_mask)
  88. return;
  89. early_pmd_flags = __sme_set(early_pmd_flags);
  90. __supported_pte_mask = __sme_set(__supported_pte_mask);
  91. /* Update the protection map with memory encryption mask */
  92. for (i = 0; i < ARRAY_SIZE(protection_map); i++)
  93. protection_map[i] = pgprot_encrypted(protection_map[i]);
  94. }
  95. void __init sme_encrypt_kernel(void)
  96. {
  97. }
  98. void __init sme_enable(void)
  99. {
  100. }