All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/20] x86: Secure Memory Encryption (AMD)
@ 2016-08-22 22:35 ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This RFC patch series provides support for AMD's new Secure Memory
Encryption (SME) feature.

SME can be used to mark individual pages of memory as encrypted through the
page tables. A page of memory that is marked encrypted will be automatically
decrypted when read from DRAM and will be automatically encrypted when
written to DRAM. Details on SME can found in the links below.

The SME feature is identified through a CPUID function and enabled through
the SYSCFG MSR. Once enabled, page table entries will determine how the
memory is accessed. If a page table entry has the memory encryption mask set,
then that memory will be accessed as encrypted memory. The memory encryption
mask (as well as other related information) is determined from settings
returned through the same CPUID function that identifies the presence of the
feature.

The approach that this patch series takes is to encrypt everything possible
starting early in the boot where the kernel is encrypted. Using the page
table macros the encryption mask can be incorporated into all page table
entries and page allocations. By updating the protection map, userspace
allocations are also marked encrypted. Certain data must be accounted for
as having been placed in memory before SME was enabled (EFI, initrd, etc.)
and accessed accordingly.

This patch series is a pre-cursor to another AMD processor feature called
Secure Encrypted Virtualization (SEV). The support for SEV will build upon
the SME support and will be submitted later. Details on SEV can be found
in the links below.

The following links provide additional detail:

AMD Memory Encryption whitepaper:
   http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
   http://support.amd.com/TechDocs/24593.pdf
   SME is section 7.10
   SEV is section 15.34

This patch series is based off of the master branch of tip.
  Commit 9fc6ddd95cbb ("Merge branch 'x86/platform'")

---

Sorry for the delay in getting v2 out.

Still to do: kexec support

Changes since v1:
- Added Documentation.
- Removed AMD vendor check for setting the PAT write protect mode
- Updated naming of trampoline flag for SME as well as moving of the
  SME check to before paging is enabled.
- Change to early_memremap to identify the data being mapped as either
  boot data or kernel data.  The idea being that boot data will have
  been placed in memory as un-encrypted data and would need to be accessed
  as such.
- Updated debugfs support for the bootparams to access the data properly.
- Do not set the SYSCFG[MEME] bit, only check it.  The setting of the
  MemEncryptionModeEn bit results in a reduction of physical address size
  of the processor.  It is possible that BIOS could have configured resources
  resources into a range that will now not be addressable.  To prevent this,
  rely on BIOS to set the SYSCFG[MEME] bit and only then enable memory
  encryption support in the kernel.

Tom Lendacky (20):
      x86: Documentation for AMD Secure Memory Encryption (SME)
      x86: Set the write-protect cache mode for full PAT support
      x86: Secure Memory Encryption (SME) build enablement
      x86: Secure Memory Encryption (SME) support
      x86: Add the Secure Memory Encryption cpu feature
      x86: Handle reduction in physical address size with SME
      x86: Provide general kernel support for memory encryption
      x86: Extend the early_memmap support with additional attrs
      x86: Add support for early encryption/decryption of memory
      x86: Insure that memory areas are encrypted when possible
      mm: Access BOOT related data in the clear
      x86: Add support for changing memory encryption attribute
      x86: Decrypt trampoline area if memory encryption is active
      x86: DMA support for memory encryption
      iommu/amd: AMD IOMMU support for memory encryption
      x86: Check for memory encryption on the APs
      x86: Do not specify encrypted memory for VGA mapping
      x86/kvm: Enable Secure Memory Encryption of nested page tables
      x86: Access the setup data through debugfs un-encrypted
      x86: Add support to make use of Secure Memory Encryption


 Documentation/kernel-parameters.txt         |    3 
 Documentation/x86/amd-memory-encryption.txt |   35 +++
 arch/arm64/kernel/acpi.c                    |    2 
 arch/ia64/include/asm/early_ioremap.h       |    2 
 arch/x86/Kconfig                            |    9 +
 arch/x86/boot/compressed/pagetable.c        |    7 +
 arch/x86/include/asm/cacheflush.h           |    3 
 arch/x86/include/asm/cpufeature.h           |    7 -
 arch/x86/include/asm/cpufeatures.h          |    5 
 arch/x86/include/asm/disabled-features.h    |    3 
 arch/x86/include/asm/dma-mapping.h          |    5 
 arch/x86/include/asm/fixmap.h               |   16 +
 arch/x86/include/asm/kvm_host.h             |    3 
 arch/x86/include/asm/mem_encrypt.h          |   91 +++++++
 arch/x86/include/asm/msr-index.h            |    2 
 arch/x86/include/asm/pgtable.h              |   26 +-
 arch/x86/include/asm/pgtable_types.h        |   49 +++-
 arch/x86/include/asm/processor.h            |    3 
 arch/x86/include/asm/realmode.h             |   12 +
 arch/x86/include/asm/required-features.h    |    3 
 arch/x86/include/asm/vga.h                  |   13 +
 arch/x86/kernel/Makefile                    |    2 
 arch/x86/kernel/asm-offsets.c               |    2 
 arch/x86/kernel/cpu/common.c                |    2 
 arch/x86/kernel/cpu/scattered.c             |    1 
 arch/x86/kernel/devicetree.c                |    6 
 arch/x86/kernel/e820.c                      |    2 
 arch/x86/kernel/espfix_64.c                 |    2 
 arch/x86/kernel/head64.c                    |  103 ++++++++
 arch/x86/kernel/head_64.S                   |   42 +++
 arch/x86/kernel/kdebugfs.c                  |   30 +-
 arch/x86/kernel/machine_kexec_64.c          |    2 
 arch/x86/kernel/mem_encrypt.S               |  339 +++++++++++++++++++++++++++
 arch/x86/kernel/pci-dma.c                   |   11 +
 arch/x86/kernel/pci-nommu.c                 |    2 
 arch/x86/kernel/pci-swiotlb.c               |    8 -
 arch/x86/kernel/setup.c                     |   17 +
 arch/x86/kernel/x8664_ksyms_64.c            |    6 
 arch/x86/kvm/mmu.c                          |    8 -
 arch/x86/kvm/vmx.c                          |    3 
 arch/x86/kvm/x86.c                          |    3 
 arch/x86/mm/Makefile                        |    1 
 arch/x86/mm/fault.c                         |    5 
 arch/x86/mm/ioremap.c                       |   50 ++++
 arch/x86/mm/kasan_init_64.c                 |    4 
 arch/x86/mm/mem_encrypt.c                   |  203 ++++++++++++++++
 arch/x86/mm/pageattr.c                      |   78 ++++++
 arch/x86/mm/pat.c                           |    4 
 arch/x86/platform/efi/efi.c                 |   15 +
 arch/x86/platform/efi/efi_64.c              |   13 +
 arch/x86/platform/efi/quirks.c              |    4 
 arch/x86/realmode/init.c                    |   13 +
 arch/x86/realmode/rm/trampoline_64.S        |   19 ++
 arch/x86/xen/mmu.c                          |    9 -
 arch/x86/xen/setup.c                        |    6 
 drivers/acpi/tables.c                       |    2 
 drivers/firmware/efi/arm-init.c             |   13 +
 drivers/firmware/efi/efi.c                  |    7 -
 drivers/firmware/efi/esrt.c                 |    4 
 drivers/firmware/efi/fake_mem.c             |    3 
 drivers/firmware/efi/memattr.c              |    2 
 drivers/iommu/amd_iommu.c                   |   10 +
 include/asm-generic/early_ioremap.h         |   17 +
 include/linux/swiotlb.h                     |    1 
 init/main.c                                 |   13 +
 lib/swiotlb.c                               |   64 ++++-
 mm/early_ioremap.c                          |   51 +++-
 67 files changed, 1351 insertions(+), 150 deletions(-)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S
 create mode 100644 arch/x86/mm/mem_encrypt.c

-- 
Tom Lendacky

^ permalink raw reply	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 00/20] x86: Secure Memory Encryption (AMD)
@ 2016-08-22 22:35 ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This RFC patch series provides support for AMD's new Secure Memory
Encryption (SME) feature.

SME can be used to mark individual pages of memory as encrypted through the
page tables. A page of memory that is marked encrypted will be automatically
decrypted when read from DRAM and will be automatically encrypted when
written to DRAM. Details on SME can found in the links below.

The SME feature is identified through a CPUID function and enabled through
the SYSCFG MSR. Once enabled, page table entries will determine how the
memory is accessed. If a page table entry has the memory encryption mask set,
then that memory will be accessed as encrypted memory. The memory encryption
mask (as well as other related information) is determined from settings
returned through the same CPUID function that identifies the presence of the
feature.

The approach that this patch series takes is to encrypt everything possible
starting early in the boot where the kernel is encrypted. Using the page
table macros the encryption mask can be incorporated into all page table
entries and page allocations. By updating the protection map, userspace
allocations are also marked encrypted. Certain data must be accounted for
as having been placed in memory before SME was enabled (EFI, initrd, etc.)
and accessed accordingly.

This patch series is a pre-cursor to another AMD processor feature called
Secure Encrypted Virtualization (SEV). The support for SEV will build upon
the SME support and will be submitted later. Details on SEV can be found
in the links below.

The following links provide additional detail:

AMD Memory Encryption whitepaper:
   http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
   http://support.amd.com/TechDocs/24593.pdf
   SME is section 7.10
   SEV is section 15.34

This patch series is based off of the master branch of tip.
  Commit 9fc6ddd95cbb ("Merge branch 'x86/platform'")

---

Sorry for the delay in getting v2 out.

Still to do: kexec support

Changes since v1:
- Added Documentation.
- Removed AMD vendor check for setting the PAT write protect mode
- Updated naming of trampoline flag for SME as well as moving of the
  SME check to before paging is enabled.
- Change to early_memremap to identify the data being mapped as either
  boot data or kernel data.  The idea being that boot data will have
  been placed in memory as un-encrypted data and would need to be accessed
  as such.
- Updated debugfs support for the bootparams to access the data properly.
- Do not set the SYSCFG[MEME] bit, only check it.  The setting of the
  MemEncryptionModeEn bit results in a reduction of physical address size
  of the processor.  It is possible that BIOS could have configured resources
  resources into a range that will now not be addressable.  To prevent this,
  rely on BIOS to set the SYSCFG[MEME] bit and only then enable memory
  encryption support in the kernel.

Tom Lendacky (20):
      x86: Documentation for AMD Secure Memory Encryption (SME)
      x86: Set the write-protect cache mode for full PAT support
      x86: Secure Memory Encryption (SME) build enablement
      x86: Secure Memory Encryption (SME) support
      x86: Add the Secure Memory Encryption cpu feature
      x86: Handle reduction in physical address size with SME
      x86: Provide general kernel support for memory encryption
      x86: Extend the early_memmap support with additional attrs
      x86: Add support for early encryption/decryption of memory
      x86: Insure that memory areas are encrypted when possible
      mm: Access BOOT related data in the clear
      x86: Add support for changing memory encryption attribute
      x86: Decrypt trampoline area if memory encryption is active
      x86: DMA support for memory encryption
      iommu/amd: AMD IOMMU support for memory encryption
      x86: Check for memory encryption on the APs
      x86: Do not specify encrypted memory for VGA mapping
      x86/kvm: Enable Secure Memory Encryption of nested page tables
      x86: Access the setup data through debugfs un-encrypted
      x86: Add support to make use of Secure Memory Encryption


 Documentation/kernel-parameters.txt         |    3 
 Documentation/x86/amd-memory-encryption.txt |   35 +++
 arch/arm64/kernel/acpi.c                    |    2 
 arch/ia64/include/asm/early_ioremap.h       |    2 
 arch/x86/Kconfig                            |    9 +
 arch/x86/boot/compressed/pagetable.c        |    7 +
 arch/x86/include/asm/cacheflush.h           |    3 
 arch/x86/include/asm/cpufeature.h           |    7 -
 arch/x86/include/asm/cpufeatures.h          |    5 
 arch/x86/include/asm/disabled-features.h    |    3 
 arch/x86/include/asm/dma-mapping.h          |    5 
 arch/x86/include/asm/fixmap.h               |   16 +
 arch/x86/include/asm/kvm_host.h             |    3 
 arch/x86/include/asm/mem_encrypt.h          |   91 +++++++
 arch/x86/include/asm/msr-index.h            |    2 
 arch/x86/include/asm/pgtable.h              |   26 +-
 arch/x86/include/asm/pgtable_types.h        |   49 +++-
 arch/x86/include/asm/processor.h            |    3 
 arch/x86/include/asm/realmode.h             |   12 +
 arch/x86/include/asm/required-features.h    |    3 
 arch/x86/include/asm/vga.h                  |   13 +
 arch/x86/kernel/Makefile                    |    2 
 arch/x86/kernel/asm-offsets.c               |    2 
 arch/x86/kernel/cpu/common.c                |    2 
 arch/x86/kernel/cpu/scattered.c             |    1 
 arch/x86/kernel/devicetree.c                |    6 
 arch/x86/kernel/e820.c                      |    2 
 arch/x86/kernel/espfix_64.c                 |    2 
 arch/x86/kernel/head64.c                    |  103 ++++++++
 arch/x86/kernel/head_64.S                   |   42 +++
 arch/x86/kernel/kdebugfs.c                  |   30 +-
 arch/x86/kernel/machine_kexec_64.c          |    2 
 arch/x86/kernel/mem_encrypt.S               |  339 +++++++++++++++++++++++++++
 arch/x86/kernel/pci-dma.c                   |   11 +
 arch/x86/kernel/pci-nommu.c                 |    2 
 arch/x86/kernel/pci-swiotlb.c               |    8 -
 arch/x86/kernel/setup.c                     |   17 +
 arch/x86/kernel/x8664_ksyms_64.c            |    6 
 arch/x86/kvm/mmu.c                          |    8 -
 arch/x86/kvm/vmx.c                          |    3 
 arch/x86/kvm/x86.c                          |    3 
 arch/x86/mm/Makefile                        |    1 
 arch/x86/mm/fault.c                         |    5 
 arch/x86/mm/ioremap.c                       |   50 ++++
 arch/x86/mm/kasan_init_64.c                 |    4 
 arch/x86/mm/mem_encrypt.c                   |  203 ++++++++++++++++
 arch/x86/mm/pageattr.c                      |   78 ++++++
 arch/x86/mm/pat.c                           |    4 
 arch/x86/platform/efi/efi.c                 |   15 +
 arch/x86/platform/efi/efi_64.c              |   13 +
 arch/x86/platform/efi/quirks.c              |    4 
 arch/x86/realmode/init.c                    |   13 +
 arch/x86/realmode/rm/trampoline_64.S        |   19 ++
 arch/x86/xen/mmu.c                          |    9 -
 arch/x86/xen/setup.c                        |    6 
 drivers/acpi/tables.c                       |    2 
 drivers/firmware/efi/arm-init.c             |   13 +
 drivers/firmware/efi/efi.c                  |    7 -
 drivers/firmware/efi/esrt.c                 |    4 
 drivers/firmware/efi/fake_mem.c             |    3 
 drivers/firmware/efi/memattr.c              |    2 
 drivers/iommu/amd_iommu.c                   |   10 +
 include/asm-generic/early_ioremap.h         |   17 +
 include/linux/swiotlb.h                     |    1 
 init/main.c                                 |   13 +
 lib/swiotlb.c                               |   64 ++++-
 mm/early_ioremap.c                          |   51 +++-
 67 files changed, 1351 insertions(+), 150 deletions(-)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S
 create mode 100644 arch/x86/mm/mem_encrypt.c

-- 
Tom Lendacky

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 00/20] x86: Secure Memory Encryption (AMD)
@ 2016-08-22 22:35 ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This RFC patch series provides support for AMD's new Secure Memory
Encryption (SME) feature.

SME can be used to mark individual pages of memory as encrypted through the
page tables. A page of memory that is marked encrypted will be automatically
decrypted when read from DRAM and will be automatically encrypted when
written to DRAM. Details on SME can found in the links below.

The SME feature is identified through a CPUID function and enabled through
the SYSCFG MSR. Once enabled, page table entries will determine how the
memory is accessed. If a page table entry has the memory encryption mask set,
then that memory will be accessed as encrypted memory. The memory encryption
mask (as well as other related information) is determined from settings
returned through the same CPUID function that identifies the presence of the
feature.

The approach that this patch series takes is to encrypt everything possible
starting early in the boot where the kernel is encrypted. Using the page
table macros the encryption mask can be incorporated into all page table
entries and page allocations. By updating the protection map, userspace
allocations are also marked encrypted. Certain data must be accounted for
as having been placed in memory before SME was enabled (EFI, initrd, etc.)
and accessed accordingly.

This patch series is a pre-cursor to another AMD processor feature called
Secure Encrypted Virtualization (SEV). The support for SEV will build upon
the SME support and will be submitted later. Details on SEV can be found
in the links below.

The following links provide additional detail:

AMD Memory Encryption whitepaper:
   http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
   http://support.amd.com/TechDocs/24593.pdf
   SME is section 7.10
   SEV is section 15.34

This patch series is based off of the master branch of tip.
  Commit 9fc6ddd95cbb ("Merge branch 'x86/platform'")

---

Sorry for the delay in getting v2 out.

Still to do: kexec support

Changes since v1:
- Added Documentation.
- Removed AMD vendor check for setting the PAT write protect mode
- Updated naming of trampoline flag for SME as well as moving of the
  SME check to before paging is enabled.
- Change to early_memremap to identify the data being mapped as either
  boot data or kernel data.  The idea being that boot data will have
  been placed in memory as un-encrypted data and would need to be accessed
  as such.
- Updated debugfs support for the bootparams to access the data properly.
- Do not set the SYSCFG[MEME] bit, only check it.  The setting of the
  MemEncryptionModeEn bit results in a reduction of physical address size
  of the processor.  It is possible that BIOS could have configured resources
  resources into a range that will now not be addressable.  To prevent this,
  rely on BIOS to set the SYSCFG[MEME] bit and only then enable memory
  encryption support in the kernel.

Tom Lendacky (20):
      x86: Documentation for AMD Secure Memory Encryption (SME)
      x86: Set the write-protect cache mode for full PAT support
      x86: Secure Memory Encryption (SME) build enablement
      x86: Secure Memory Encryption (SME) support
      x86: Add the Secure Memory Encryption cpu feature
      x86: Handle reduction in physical address size with SME
      x86: Provide general kernel support for memory encryption
      x86: Extend the early_memmap support with additional attrs
      x86: Add support for early encryption/decryption of memory
      x86: Insure that memory areas are encrypted when possible
      mm: Access BOOT related data in the clear
      x86: Add support for changing memory encryption attribute
      x86: Decrypt trampoline area if memory encryption is active
      x86: DMA support for memory encryption
      iommu/amd: AMD IOMMU support for memory encryption
      x86: Check for memory encryption on the APs
      x86: Do not specify encrypted memory for VGA mapping
      x86/kvm: Enable Secure Memory Encryption of nested page tables
      x86: Access the setup data through debugfs un-encrypted
      x86: Add support to make use of Secure Memory Encryption


 Documentation/kernel-parameters.txt         |    3 
 Documentation/x86/amd-memory-encryption.txt |   35 +++
 arch/arm64/kernel/acpi.c                    |    2 
 arch/ia64/include/asm/early_ioremap.h       |    2 
 arch/x86/Kconfig                            |    9 +
 arch/x86/boot/compressed/pagetable.c        |    7 +
 arch/x86/include/asm/cacheflush.h           |    3 
 arch/x86/include/asm/cpufeature.h           |    7 -
 arch/x86/include/asm/cpufeatures.h          |    5 
 arch/x86/include/asm/disabled-features.h    |    3 
 arch/x86/include/asm/dma-mapping.h          |    5 
 arch/x86/include/asm/fixmap.h               |   16 +
 arch/x86/include/asm/kvm_host.h             |    3 
 arch/x86/include/asm/mem_encrypt.h          |   91 +++++++
 arch/x86/include/asm/msr-index.h            |    2 
 arch/x86/include/asm/pgtable.h              |   26 +-
 arch/x86/include/asm/pgtable_types.h        |   49 +++-
 arch/x86/include/asm/processor.h            |    3 
 arch/x86/include/asm/realmode.h             |   12 +
 arch/x86/include/asm/required-features.h    |    3 
 arch/x86/include/asm/vga.h                  |   13 +
 arch/x86/kernel/Makefile                    |    2 
 arch/x86/kernel/asm-offsets.c               |    2 
 arch/x86/kernel/cpu/common.c                |    2 
 arch/x86/kernel/cpu/scattered.c             |    1 
 arch/x86/kernel/devicetree.c                |    6 
 arch/x86/kernel/e820.c                      |    2 
 arch/x86/kernel/espfix_64.c                 |    2 
 arch/x86/kernel/head64.c                    |  103 ++++++++
 arch/x86/kernel/head_64.S                   |   42 +++
 arch/x86/kernel/kdebugfs.c                  |   30 +-
 arch/x86/kernel/machine_kexec_64.c          |    2 
 arch/x86/kernel/mem_encrypt.S               |  339 +++++++++++++++++++++++++++
 arch/x86/kernel/pci-dma.c                   |   11 +
 arch/x86/kernel/pci-nommu.c                 |    2 
 arch/x86/kernel/pci-swiotlb.c               |    8 -
 arch/x86/kernel/setup.c                     |   17 +
 arch/x86/kernel/x8664_ksyms_64.c            |    6 
 arch/x86/kvm/mmu.c                          |    8 -
 arch/x86/kvm/vmx.c                          |    3 
 arch/x86/kvm/x86.c                          |    3 
 arch/x86/mm/Makefile                        |    1 
 arch/x86/mm/fault.c                         |    5 
 arch/x86/mm/ioremap.c                       |   50 ++++
 arch/x86/mm/kasan_init_64.c                 |    4 
 arch/x86/mm/mem_encrypt.c                   |  203 ++++++++++++++++
 arch/x86/mm/pageattr.c                      |   78 ++++++
 arch/x86/mm/pat.c                           |    4 
 arch/x86/platform/efi/efi.c                 |   15 +
 arch/x86/platform/efi/efi_64.c              |   13 +
 arch/x86/platform/efi/quirks.c              |    4 
 arch/x86/realmode/init.c                    |   13 +
 arch/x86/realmode/rm/trampoline_64.S        |   19 ++
 arch/x86/xen/mmu.c                          |    9 -
 arch/x86/xen/setup.c                        |    6 
 drivers/acpi/tables.c                       |    2 
 drivers/firmware/efi/arm-init.c             |   13 +
 drivers/firmware/efi/efi.c                  |    7 -
 drivers/firmware/efi/esrt.c                 |    4 
 drivers/firmware/efi/fake_mem.c             |    3 
 drivers/firmware/efi/memattr.c              |    2 
 drivers/iommu/amd_iommu.c                   |   10 +
 include/asm-generic/early_ioremap.h         |   17 +
 include/linux/swiotlb.h                     |    1 
 init/main.c                                 |   13 +
 lib/swiotlb.c                               |   64 ++++-
 mm/early_ioremap.c                          |   51 +++-
 67 files changed, 1351 insertions(+), 150 deletions(-)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S
 create mode 100644 arch/x86/mm/mem_encrypt.c

-- 
Tom Lendacky

^ permalink raw reply	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 00/20] x86: Secure Memory Encryption (AMD)
@ 2016-08-22 22:35 ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This RFC patch series provides support for AMD's new Secure Memory
Encryption (SME) feature.

SME can be used to mark individual pages of memory as encrypted through the
page tables. A page of memory that is marked encrypted will be automatically
decrypted when read from DRAM and will be automatically encrypted when
written to DRAM. Details on SME can found in the links below.

The SME feature is identified through a CPUID function and enabled through
the SYSCFG MSR. Once enabled, page table entries will determine how the
memory is accessed. If a page table entry has the memory encryption mask set,
then that memory will be accessed as encrypted memory. The memory encryption
mask (as well as other related information) is determined from settings
returned through the same CPUID function that identifies the presence of the
feature.

The approach that this patch series takes is to encrypt everything possible
starting early in the boot where the kernel is encrypted. Using the page
table macros the encryption mask can be incorporated into all page table
entries and page allocations. By updating the protection map, userspace
allocations are also marked encrypted. Certain data must be accounted for
as having been placed in memory before SME was enabled (EFI, initrd, etc.)
and accessed accordingly.

This patch series is a pre-cursor to another AMD processor feature called
Secure Encrypted Virtualization (SEV). The support for SEV will build upon
the SME support and will be submitted later. Details on SEV can be found
in the links below.

The following links provide additional detail:

AMD Memory Encryption whitepaper:
   http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
   http://support.amd.com/TechDocs/24593.pdf
   SME is section 7.10
   SEV is section 15.34

This patch series is based off of the master branch of tip.
  Commit 9fc6ddd95cbb ("Merge branch 'x86/platform'")

---

Sorry for the delay in getting v2 out.

Still to do: kexec support

Changes since v1:
- Added Documentation.
- Removed AMD vendor check for setting the PAT write protect mode
- Updated naming of trampoline flag for SME as well as moving of the
  SME check to before paging is enabled.
- Change to early_memremap to identify the data being mapped as either
  boot data or kernel data.  The idea being that boot data will have
  been placed in memory as un-encrypted data and would need to be accessed
  as such.
- Updated debugfs support for the bootparams to access the data properly.
- Do not set the SYSCFG[MEME] bit, only check it.  The setting of the
  MemEncryptionModeEn bit results in a reduction of physical address size
  of the processor.  It is possible that BIOS could have configured resources
  resources into a range that will now not be addressable.  To prevent this,
  rely on BIOS to set the SYSCFG[MEME] bit and only then enable memory
  encryption support in the kernel.

Tom Lendacky (20):
      x86: Documentation for AMD Secure Memory Encryption (SME)
      x86: Set the write-protect cache mode for full PAT support
      x86: Secure Memory Encryption (SME) build enablement
      x86: Secure Memory Encryption (SME) support
      x86: Add the Secure Memory Encryption cpu feature
      x86: Handle reduction in physical address size with SME
      x86: Provide general kernel support for memory encryption
      x86: Extend the early_memmap support with additional attrs
      x86: Add support for early encryption/decryption of memory
      x86: Insure that memory areas are encrypted when possible
      mm: Access BOOT related data in the clear
      x86: Add support for changing memory encryption attribute
      x86: Decrypt trampoline area if memory encryption is active
      x86: DMA support for memory encryption
      iommu/amd: AMD IOMMU support for memory encryption
      x86: Check for memory encryption on the APs
      x86: Do not specify encrypted memory for VGA mapping
      x86/kvm: Enable Secure Memory Encryption of nested page tables
      x86: Access the setup data through debugfs un-encrypted
      x86: Add support to make use of Secure Memory Encryption


 Documentation/kernel-parameters.txt         |    3 
 Documentation/x86/amd-memory-encryption.txt |   35 +++
 arch/arm64/kernel/acpi.c                    |    2 
 arch/ia64/include/asm/early_ioremap.h       |    2 
 arch/x86/Kconfig                            |    9 +
 arch/x86/boot/compressed/pagetable.c        |    7 +
 arch/x86/include/asm/cacheflush.h           |    3 
 arch/x86/include/asm/cpufeature.h           |    7 -
 arch/x86/include/asm/cpufeatures.h          |    5 
 arch/x86/include/asm/disabled-features.h    |    3 
 arch/x86/include/asm/dma-mapping.h          |    5 
 arch/x86/include/asm/fixmap.h               |   16 +
 arch/x86/include/asm/kvm_host.h             |    3 
 arch/x86/include/asm/mem_encrypt.h          |   91 +++++++
 arch/x86/include/asm/msr-index.h            |    2 
 arch/x86/include/asm/pgtable.h              |   26 +-
 arch/x86/include/asm/pgtable_types.h        |   49 +++-
 arch/x86/include/asm/processor.h            |    3 
 arch/x86/include/asm/realmode.h             |   12 +
 arch/x86/include/asm/required-features.h    |    3 
 arch/x86/include/asm/vga.h                  |   13 +
 arch/x86/kernel/Makefile                    |    2 
 arch/x86/kernel/asm-offsets.c               |    2 
 arch/x86/kernel/cpu/common.c                |    2 
 arch/x86/kernel/cpu/scattered.c             |    1 
 arch/x86/kernel/devicetree.c                |    6 
 arch/x86/kernel/e820.c                      |    2 
 arch/x86/kernel/espfix_64.c                 |    2 
 arch/x86/kernel/head64.c                    |  103 ++++++++
 arch/x86/kernel/head_64.S                   |   42 +++
 arch/x86/kernel/kdebugfs.c                  |   30 +-
 arch/x86/kernel/machine_kexec_64.c          |    2 
 arch/x86/kernel/mem_encrypt.S               |  339 +++++++++++++++++++++++++++
 arch/x86/kernel/pci-dma.c                   |   11 +
 arch/x86/kernel/pci-nommu.c                 |    2 
 arch/x86/kernel/pci-swiotlb.c               |    8 -
 arch/x86/kernel/setup.c                     |   17 +
 arch/x86/kernel/x8664_ksyms_64.c            |    6 
 arch/x86/kvm/mmu.c                          |    8 -
 arch/x86/kvm/vmx.c                          |    3 
 arch/x86/kvm/x86.c                          |    3 
 arch/x86/mm/Makefile                        |    1 
 arch/x86/mm/fault.c                         |    5 
 arch/x86/mm/ioremap.c                       |   50 ++++
 arch/x86/mm/kasan_init_64.c                 |    4 
 arch/x86/mm/mem_encrypt.c                   |  203 ++++++++++++++++
 arch/x86/mm/pageattr.c                      |   78 ++++++
 arch/x86/mm/pat.c                           |    4 
 arch/x86/platform/efi/efi.c                 |   15 +
 arch/x86/platform/efi/efi_64.c              |   13 +
 arch/x86/platform/efi/quirks.c              |    4 
 arch/x86/realmode/init.c                    |   13 +
 arch/x86/realmode/rm/trampoline_64.S        |   19 ++
 arch/x86/xen/mmu.c                          |    9 -
 arch/x86/xen/setup.c                        |    6 
 drivers/acpi/tables.c                       |    2 
 drivers/firmware/efi/arm-init.c             |   13 +
 drivers/firmware/efi/efi.c                  |    7 -
 drivers/firmware/efi/esrt.c                 |    4 
 drivers/firmware/efi/fake_mem.c             |    3 
 drivers/firmware/efi/memattr.c              |    2 
 drivers/iommu/amd_iommu.c                   |   10 +
 include/asm-generic/early_ioremap.h         |   17 +
 include/linux/swiotlb.h                     |    1 
 init/main.c                                 |   13 +
 lib/swiotlb.c                               |   64 ++++-
 mm/early_ioremap.c                          |   51 +++-
 67 files changed, 1351 insertions(+), 150 deletions(-)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S
 create mode 100644 arch/x86/mm/mem_encrypt.c

-- 
Tom Lendacky

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:35   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds a Documenation entry to decribe the AMD Secure Memory
Encryption (SME) feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt

diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
new file mode 100644
index 0000000..f19c555
--- /dev/null
+++ b/Documentation/x86/amd-memory-encryption.txt
@@ -0,0 +1,35 @@
+Secure Memory Encryption (SME) is a feature found on AMD processors.
+
+SME provides the ability to mark individual pages of memory as encrypted using
+the standard x86 page tables.  A page that is marked encrpyted will be
+automatically decrypted when read from DRAM and encrypted when written to
+DRAM.  SME can therefore be used to protect the contents of DRAM from physical
+attacks on the system.
+
+Support for SME can be determined through the CPUID instruction. The CPUID
+function 0x8000001f reports information related to SME:
+
+	0x8000001f[eax]:
+		Bit[0] indicates support for SME
+	0x8000001f[ebx]:
+		Bit[5:0]  pagetable bit number used to enable memory encryption
+		Bit[11:6] reduction in physical address space, in bits, when
+			  memory encryption is enabled (this only affects system
+			  physical addresses, not guest physical addresses)
+
+If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
+determine if SME is enabled and/or to enable memory encryption:
+
+	0xc0010010:
+		Bit[23]   0 = memory encryption features are disabled
+			  1 = memory encryption features are enabled
+
+Linux relies on BIOS to set this bit if BIOS has determined that the reduction
+in the physical address space as a result of enabling memory encryption (see
+CPUID information above) will not conflict with the address space resource
+requirements for the system.  If this bit is not set upon Linux startup then
+Linux itself will not set it and memory encryption will not be possible.
+
+SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
+option. Additionally, the mem_encrypt=on command line parameter is required
+to activate memory encryption.

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds a Documenation entry to decribe the AMD Secure Memory
Encryption (SME) feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt

diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
new file mode 100644
index 0000000..f19c555
--- /dev/null
+++ b/Documentation/x86/amd-memory-encryption.txt
@@ -0,0 +1,35 @@
+Secure Memory Encryption (SME) is a feature found on AMD processors.
+
+SME provides the ability to mark individual pages of memory as encrypted using
+the standard x86 page tables.  A page that is marked encrpyted will be
+automatically decrypted when read from DRAM and encrypted when written to
+DRAM.  SME can therefore be used to protect the contents of DRAM from physical
+attacks on the system.
+
+Support for SME can be determined through the CPUID instruction. The CPUID
+function 0x8000001f reports information related to SME:
+
+	0x8000001f[eax]:
+		Bit[0] indicates support for SME
+	0x8000001f[ebx]:
+		Bit[5:0]  pagetable bit number used to enable memory encryption
+		Bit[11:6] reduction in physical address space, in bits, when
+			  memory encryption is enabled (this only affects system
+			  physical addresses, not guest physical addresses)
+
+If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
+determine if SME is enabled and/or to enable memory encryption:
+
+	0xc0010010:
+		Bit[23]   0 = memory encryption features are disabled
+			  1 = memory encryption features are enabled
+
+Linux relies on BIOS to set this bit if BIOS has determined that the reduction
+in the physical address space as a result of enabling memory encryption (see
+CPUID information above) will not conflict with the address space resource
+requirements for the system.  If this bit is not set upon Linux startup then
+Linux itself will not set it and memory encryption will not be possible.
+
+SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
+option. Additionally, the mem_encrypt=on command line parameter is required
+to activate memory encryption.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds a Documenation entry to decribe the AMD Secure Memory
Encryption (SME) feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt

diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
new file mode 100644
index 0000000..f19c555
--- /dev/null
+++ b/Documentation/x86/amd-memory-encryption.txt
@@ -0,0 +1,35 @@
+Secure Memory Encryption (SME) is a feature found on AMD processors.
+
+SME provides the ability to mark individual pages of memory as encrypted using
+the standard x86 page tables.  A page that is marked encrpyted will be
+automatically decrypted when read from DRAM and encrypted when written to
+DRAM.  SME can therefore be used to protect the contents of DRAM from physical
+attacks on the system.
+
+Support for SME can be determined through the CPUID instruction. The CPUID
+function 0x8000001f reports information related to SME:
+
+	0x8000001f[eax]:
+		Bit[0] indicates support for SME
+	0x8000001f[ebx]:
+		Bit[5:0]  pagetable bit number used to enable memory encryption
+		Bit[11:6] reduction in physical address space, in bits, when
+			  memory encryption is enabled (this only affects system
+			  physical addresses, not guest physical addresses)
+
+If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
+determine if SME is enabled and/or to enable memory encryption:
+
+	0xc0010010:
+		Bit[23]   0 = memory encryption features are disabled
+			  1 = memory encryption features are enabled
+
+Linux relies on BIOS to set this bit if BIOS has determined that the reduction
+in the physical address space as a result of enabling memory encryption (see
+CPUID information above) will not conflict with the address space resource
+requirements for the system.  If this bit is not set upon Linux startup then
+Linux itself will not set it and memory encryption will not be possible.
+
+SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
+option. Additionally, the mem_encrypt=on command line parameter is required
+to activate memory encryption.


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds a Documenation entry to decribe the AMD Secure Memory
Encryption (SME) feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/x86/amd-memory-encryption.txt

diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
new file mode 100644
index 0000000..f19c555
--- /dev/null
+++ b/Documentation/x86/amd-memory-encryption.txt
@@ -0,0 +1,35 @@
+Secure Memory Encryption (SME) is a feature found on AMD processors.
+
+SME provides the ability to mark individual pages of memory as encrypted using
+the standard x86 page tables.  A page that is marked encrpyted will be
+automatically decrypted when read from DRAM and encrypted when written to
+DRAM.  SME can therefore be used to protect the contents of DRAM from physical
+attacks on the system.
+
+Support for SME can be determined through the CPUID instruction. The CPUID
+function 0x8000001f reports information related to SME:
+
+	0x8000001f[eax]:
+		Bit[0] indicates support for SME
+	0x8000001f[ebx]:
+		Bit[5:0]  pagetable bit number used to enable memory encryption
+		Bit[11:6] reduction in physical address space, in bits, when
+			  memory encryption is enabled (this only affects system
+			  physical addresses, not guest physical addresses)
+
+If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
+determine if SME is enabled and/or to enable memory encryption:
+
+	0xc0010010:
+		Bit[23]   0 = memory encryption features are disabled
+			  1 = memory encryption features are enabled
+
+Linux relies on BIOS to set this bit if BIOS has determined that the reduction
+in the physical address space as a result of enabling memory encryption (see
+CPUID information above) will not conflict with the address space resource
+requirements for the system.  If this bit is not set upon Linux startup then
+Linux itself will not set it and memory encryption will not be possible.
+
+SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
+option. Additionally, the mem_encrypt=on command line parameter is required
+to activate memory encryption.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:35   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

For processors that support PAT, set the write-protect cache mode
(_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/pat.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ecb1b69..8f0c44f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -355,7 +355,7 @@ void pat_init(void)
 		 *      010    2    UC-: _PAGE_CACHE_MODE_UC_MINUS
 		 *      011    3    UC : _PAGE_CACHE_MODE_UC
 		 *      100    4    WB : Reserved
-		 *      101    5    WC : Reserved
+		 *      101    5    WP : _PAGE_CACHE_MODE_WP
 		 *      110    6    UC-: Reserved
 		 *      111    7    WT : _PAGE_CACHE_MODE_WT
 		 *
@@ -363,7 +363,7 @@ void pat_init(void)
 		 * corresponding types in the presence of PAT errata.
 		 */
 		pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
-		      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, WT);
+		      PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
 	}
 
 	if (!boot_cpu_done) {

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

For processors that support PAT, set the write-protect cache mode
(_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/pat.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ecb1b69..8f0c44f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -355,7 +355,7 @@ void pat_init(void)
 		 *      010    2    UC-: _PAGE_CACHE_MODE_UC_MINUS
 		 *      011    3    UC : _PAGE_CACHE_MODE_UC
 		 *      100    4    WB : Reserved
-		 *      101    5    WC : Reserved
+		 *      101    5    WP : _PAGE_CACHE_MODE_WP
 		 *      110    6    UC-: Reserved
 		 *      111    7    WT : _PAGE_CACHE_MODE_WT
 		 *
@@ -363,7 +363,7 @@ void pat_init(void)
 		 * corresponding types in the presence of PAT errata.
 		 */
 		pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
-		      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, WT);
+		      PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
 	}
 
 	if (!boot_cpu_done) {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

For processors that support PAT, set the write-protect cache mode
(_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/pat.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ecb1b69..8f0c44f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -355,7 +355,7 @@ void pat_init(void)
 		 *      010    2    UC-: _PAGE_CACHE_MODE_UC_MINUS
 		 *      011    3    UC : _PAGE_CACHE_MODE_UC
 		 *      100    4    WB : Reserved
-		 *      101    5    WC : Reserved
+		 *      101    5    WP : _PAGE_CACHE_MODE_WP
 		 *      110    6    UC-: Reserved
 		 *      111    7    WT : _PAGE_CACHE_MODE_WT
 		 *
@@ -363,7 +363,7 @@ void pat_init(void)
 		 * corresponding types in the presence of PAT errata.
 		 */
 		pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
-		      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, WT);
+		      PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
 	}
 
 	if (!boot_cpu_done) {


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

For processors that support PAT, set the write-protect cache mode
(_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/mm/pat.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ecb1b69..8f0c44f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -355,7 +355,7 @@ void pat_init(void)
 		 *      010    2    UC-: _PAGE_CACHE_MODE_UC_MINUS
 		 *      011    3    UC : _PAGE_CACHE_MODE_UC
 		 *      100    4    WB : Reserved
-		 *      101    5    WC : Reserved
+		 *      101    5    WP : _PAGE_CACHE_MODE_WP
 		 *      110    6    UC-: Reserved
 		 *      111    7    WT : _PAGE_CACHE_MODE_WT
 		 *
@@ -363,7 +363,7 @@ void pat_init(void)
 		 * corresponding types in the presence of PAT errata.
 		 */
 		pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
-		      PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, WT);
+		      PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
 	}
 
 	if (!boot_cpu_done) {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:35   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide the Kconfig support to build the SME support in the kernel.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..131f329 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
 	  supports them), so don't confuse the user by printing
 	  that we have them enabled.
 
+config AMD_MEM_ENCRYPT
+	bool "Secure Memory Encryption support for AMD"
+	depends on X86_64 && CPU_SUP_AMD
+	---help---
+	  Say yes to enable the encryption of system memory. This requires
+	  an AMD processor that supports Secure Memory Encryption (SME).
+	  The encryption of system memory is disabled by default but can be
+	  enabled with the mem_encrypt=on command line option.
+
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide the Kconfig support to build the SME support in the kernel.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..131f329 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
 	  supports them), so don't confuse the user by printing
 	  that we have them enabled.
 
+config AMD_MEM_ENCRYPT
+	bool "Secure Memory Encryption support for AMD"
+	depends on X86_64 && CPU_SUP_AMD
+	---help---
+	  Say yes to enable the encryption of system memory. This requires
+	  an AMD processor that supports Secure Memory Encryption (SME).
+	  The encryption of system memory is disabled by default but can be
+	  enabled with the mem_encrypt=on command line option.
+
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide the Kconfig support to build the SME support in the kernel.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..131f329 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
 	  supports them), so don't confuse the user by printing
 	  that we have them enabled.
 
+config AMD_MEM_ENCRYPT
+	bool "Secure Memory Encryption support for AMD"
+	depends on X86_64 && CPU_SUP_AMD
+	---help---
+	  Say yes to enable the encryption of system memory. This requires
+	  an AMD processor that supports Secure Memory Encryption (SME).
+	  The encryption of system memory is disabled by default but can be
+	  enabled with the mem_encrypt=on command line option.
+
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-08-22 22:35   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:35 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide the Kconfig support to build the SME support in the kernel.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/Kconfig |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c580d8c..131f329 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
 	  supports them), so don't confuse the user by printing
 	  that we have them enabled.
 
+config AMD_MEM_ENCRYPT
+	bool "Secure Memory Encryption support for AMD"
+	depends on X86_64 && CPU_SUP_AMD
+	---help---
+	  Say yes to enable the encryption of system memory. This requires
+	  an AMD processor that supports Secure Memory Encryption (SME).
+	  The encryption of system memory is disabled by default but can be
+	  enabled with the mem_encrypt=on command line option.
+
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:36   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide support for Secure Memory Encryption (SME). This initial support
defines the memory encryption mask as a variable for quick access and an
accessor for retrieving the number of physical addressing bits lost if
SME is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   37 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/Makefile           |    2 ++
 arch/x86/kernel/mem_encrypt.S      |   29 ++++++++++++++++++++++++++++
 arch/x86/kernel/x8664_ksyms_64.c   |    6 ++++++
 4 files changed, 74 insertions(+)
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
new file mode 100644
index 0000000..747fc52
--- /dev/null
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -0,0 +1,37 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __X86_MEM_ENCRYPT_H__
+#define __X86_MEM_ENCRYPT_H__
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern unsigned long sme_me_mask;
+
+u8 sme_get_me_loss(void);
+
+#else	/* !CONFIG_AMD_MEM_ENCRYPT */
+
+#define sme_me_mask		0UL
+
+static inline u8 sme_get_me_loss(void)
+{
+	return 0;
+}
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __X86_MEM_ENCRYPT_H__ */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0503f5b..bda997f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 
+obj-y					+= mem_encrypt.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
new file mode 100644
index 0000000..ef7f325
--- /dev/null
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -0,0 +1,29 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+	.code64
+ENTRY(sme_get_me_loss)
+	xor	%rax, %rax
+	mov	sme_me_loss(%rip), %al
+	ret
+ENDPROC(sme_get_me_loss)
+
+	.data
+	.align 16
+ENTRY(sme_me_mask)
+	.quad	0x0000000000000000
+sme_me_loss:
+	.byte	0x00
+	.align	8
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 95e49f6..651c4c8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -12,6 +12,7 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ftrace.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 /* mcount and __fentry__ are defined in assembly */
@@ -83,3 +84,8 @@ EXPORT_SYMBOL(native_load_gs_index);
 EXPORT_SYMBOL(___preempt_schedule);
 EXPORT_SYMBOL(___preempt_schedule_notrace);
 #endif
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+EXPORT_SYMBOL_GPL(sme_me_mask);
+EXPORT_SYMBOL_GPL(sme_get_me_loss);
+#endif

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide support for Secure Memory Encryption (SME). This initial support
defines the memory encryption mask as a variable for quick access and an
accessor for retrieving the number of physical addressing bits lost if
SME is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   37 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/Makefile           |    2 ++
 arch/x86/kernel/mem_encrypt.S      |   29 ++++++++++++++++++++++++++++
 arch/x86/kernel/x8664_ksyms_64.c   |    6 ++++++
 4 files changed, 74 insertions(+)
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
new file mode 100644
index 0000000..747fc52
--- /dev/null
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -0,0 +1,37 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __X86_MEM_ENCRYPT_H__
+#define __X86_MEM_ENCRYPT_H__
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern unsigned long sme_me_mask;
+
+u8 sme_get_me_loss(void);
+
+#else	/* !CONFIG_AMD_MEM_ENCRYPT */
+
+#define sme_me_mask		0UL
+
+static inline u8 sme_get_me_loss(void)
+{
+	return 0;
+}
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __X86_MEM_ENCRYPT_H__ */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0503f5b..bda997f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 
+obj-y					+= mem_encrypt.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
new file mode 100644
index 0000000..ef7f325
--- /dev/null
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -0,0 +1,29 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+	.code64
+ENTRY(sme_get_me_loss)
+	xor	%rax, %rax
+	mov	sme_me_loss(%rip), %al
+	ret
+ENDPROC(sme_get_me_loss)
+
+	.data
+	.align 16
+ENTRY(sme_me_mask)
+	.quad	0x0000000000000000
+sme_me_loss:
+	.byte	0x00
+	.align	8
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 95e49f6..651c4c8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -12,6 +12,7 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ftrace.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 /* mcount and __fentry__ are defined in assembly */
@@ -83,3 +84,8 @@ EXPORT_SYMBOL(native_load_gs_index);
 EXPORT_SYMBOL(___preempt_schedule);
 EXPORT_SYMBOL(___preempt_schedule_notrace);
 #endif
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+EXPORT_SYMBOL_GPL(sme_me_mask);
+EXPORT_SYMBOL_GPL(sme_get_me_loss);
+#endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide support for Secure Memory Encryption (SME). This initial support
defines the memory encryption mask as a variable for quick access and an
accessor for retrieving the number of physical addressing bits lost if
SME is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   37 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/Makefile           |    2 ++
 arch/x86/kernel/mem_encrypt.S      |   29 ++++++++++++++++++++++++++++
 arch/x86/kernel/x8664_ksyms_64.c   |    6 ++++++
 4 files changed, 74 insertions(+)
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
new file mode 100644
index 0000000..747fc52
--- /dev/null
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -0,0 +1,37 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __X86_MEM_ENCRYPT_H__
+#define __X86_MEM_ENCRYPT_H__
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern unsigned long sme_me_mask;
+
+u8 sme_get_me_loss(void);
+
+#else	/* !CONFIG_AMD_MEM_ENCRYPT */
+
+#define sme_me_mask		0UL
+
+static inline u8 sme_get_me_loss(void)
+{
+	return 0;
+}
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __X86_MEM_ENCRYPT_H__ */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0503f5b..bda997f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 
+obj-y					+= mem_encrypt.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
new file mode 100644
index 0000000..ef7f325
--- /dev/null
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -0,0 +1,29 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+	.code64
+ENTRY(sme_get_me_loss)
+	xor	%rax, %rax
+	mov	sme_me_loss(%rip), %al
+	ret
+ENDPROC(sme_get_me_loss)
+
+	.data
+	.align 16
+ENTRY(sme_me_mask)
+	.quad	0x0000000000000000
+sme_me_loss:
+	.byte	0x00
+	.align	8
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 95e49f6..651c4c8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -12,6 +12,7 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ftrace.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 /* mcount and __fentry__ are defined in assembly */
@@ -83,3 +84,8 @@ EXPORT_SYMBOL(native_load_gs_index);
 EXPORT_SYMBOL(___preempt_schedule);
 EXPORT_SYMBOL(___preempt_schedule_notrace);
 #endif
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+EXPORT_SYMBOL_GPL(sme_me_mask);
+EXPORT_SYMBOL_GPL(sme_get_me_loss);
+#endif


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Provide support for Secure Memory Encryption (SME). This initial support
defines the memory encryption mask as a variable for quick access and an
accessor for retrieving the number of physical addressing bits lost if
SME is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   37 ++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/Makefile           |    2 ++
 arch/x86/kernel/mem_encrypt.S      |   29 ++++++++++++++++++++++++++++
 arch/x86/kernel/x8664_ksyms_64.c   |    6 ++++++
 4 files changed, 74 insertions(+)
 create mode 100644 arch/x86/include/asm/mem_encrypt.h
 create mode 100644 arch/x86/kernel/mem_encrypt.S

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
new file mode 100644
index 0000000..747fc52
--- /dev/null
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -0,0 +1,37 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __X86_MEM_ENCRYPT_H__
+#define __X86_MEM_ENCRYPT_H__
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+
+extern unsigned long sme_me_mask;
+
+u8 sme_get_me_loss(void);
+
+#else	/* !CONFIG_AMD_MEM_ENCRYPT */
+
+#define sme_me_mask		0UL
+
+static inline u8 sme_get_me_loss(void)
+{
+	return 0;
+}
+
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __X86_MEM_ENCRYPT_H__ */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0503f5b..bda997f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -125,6 +125,8 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
 
+obj-y					+= mem_encrypt.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
new file mode 100644
index 0000000..ef7f325
--- /dev/null
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -0,0 +1,29 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+	.code64
+ENTRY(sme_get_me_loss)
+	xor	%rax, %rax
+	mov	sme_me_loss(%rip), %al
+	ret
+ENDPROC(sme_get_me_loss)
+
+	.data
+	.align 16
+ENTRY(sme_me_mask)
+	.quad	0x0000000000000000
+sme_me_loss:
+	.byte	0x00
+	.align	8
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 95e49f6..651c4c8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -12,6 +12,7 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ftrace.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 /* mcount and __fentry__ are defined in assembly */
@@ -83,3 +84,8 @@ EXPORT_SYMBOL(native_load_gs_index);
 EXPORT_SYMBOL(___preempt_schedule);
 EXPORT_SYMBOL(___preempt_schedule_notrace);
 #endif
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+EXPORT_SYMBOL_GPL(sme_me_mask);
+EXPORT_SYMBOL_GPL(sme_get_me_loss);
+#endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the cpu features to include identifying and reporting on the
Secure Memory Encryption feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cpufeature.h        |    7 +++++--
 arch/x86/include/asm/cpufeatures.h       |    5 ++++-
 arch/x86/include/asm/disabled-features.h |    3 ++-
 arch/x86/include/asm/required-features.h |    3 ++-
 arch/x86/kernel/cpu/scattered.c          |    1 +
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69f..de5bdb1 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -28,6 +28,7 @@ enum cpuid_leafs
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
+	CPUID_8000_001F_EAX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..8babbd8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	18	/* N 32-bit words worth of info */
+#define NCAPINTS	19	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -286,6 +286,9 @@
 #define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
 
+/* AMD SME Feature Identification, CPUID level 0x8000001f (eax), word 18 */
+#define X86_FEATURE_SME		(18*32+ 0) /* Secure Memory Encryption */
+
 /*
  * BUG word(s)
  */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad..8b45e08 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -57,6 +57,7 @@
 #define DISABLED_MASK15	0
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
 #define DISABLED_MASK17	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define DISABLED_MASK18	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c..6847d85 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -100,6 +100,7 @@
 #define REQUIRED_MASK15	0
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define REQUIRED_MASK18	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8cb57df..d86d9a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Update the cpu features to include identifying and reporting on the
Secure Memory Encryption feature.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/cpufeature.h        |    7 +++++--
 arch/x86/include/asm/cpufeatures.h       |    5 ++++-
 arch/x86/include/asm/disabled-features.h |    3 ++-
 arch/x86/include/asm/required-features.h |    3 ++-
 arch/x86/kernel/cpu/scattered.c          |    1 +
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69f..de5bdb1 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -28,6 +28,7 @@ enum cpuid_leafs
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
+	CPUID_8000_001F_EAX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..8babbd8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	18	/* N 32-bit words worth of info */
+#define NCAPINTS	19	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -286,6 +286,9 @@
 #define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
 
+/* AMD SME Feature Identification, CPUID level 0x8000001f (eax), word 18 */
+#define X86_FEATURE_SME		(18*32+ 0) /* Secure Memory Encryption */
+
 /*
  * BUG word(s)
  */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad..8b45e08 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -57,6 +57,7 @@
 #define DISABLED_MASK15	0
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
 #define DISABLED_MASK17	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define DISABLED_MASK18	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c..6847d85 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -100,6 +100,7 @@
 #define REQUIRED_MASK15	0
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define REQUIRED_MASK18	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8cb57df..d86d9a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the cpu features to include identifying and reporting on the
Secure Memory Encryption feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cpufeature.h        |    7 +++++--
 arch/x86/include/asm/cpufeatures.h       |    5 ++++-
 arch/x86/include/asm/disabled-features.h |    3 ++-
 arch/x86/include/asm/required-features.h |    3 ++-
 arch/x86/kernel/cpu/scattered.c          |    1 +
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69f..de5bdb1 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -28,6 +28,7 @@ enum cpuid_leafs
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
+	CPUID_8000_001F_EAX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..8babbd8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	18	/* N 32-bit words worth of info */
+#define NCAPINTS	19	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -286,6 +286,9 @@
 #define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
 
+/* AMD SME Feature Identification, CPUID level 0x8000001f (eax), word 18 */
+#define X86_FEATURE_SME		(18*32+ 0) /* Secure Memory Encryption */
+
 /*
  * BUG word(s)
  */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad..8b45e08 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -57,6 +57,7 @@
 #define DISABLED_MASK15	0
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
 #define DISABLED_MASK17	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define DISABLED_MASK18	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c..6847d85 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -100,6 +100,7 @@
 #define REQUIRED_MASK15	0
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define REQUIRED_MASK18	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8cb57df..d86d9a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Update the cpu features to include identifying and reporting on the
Secure Memory Encryption feature.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/cpufeature.h        |    7 +++++--
 arch/x86/include/asm/cpufeatures.h       |    5 ++++-
 arch/x86/include/asm/disabled-features.h |    3 ++-
 arch/x86/include/asm/required-features.h |    3 ++-
 arch/x86/kernel/cpu/scattered.c          |    1 +
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69f..de5bdb1 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -28,6 +28,7 @@ enum cpuid_leafs
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
+	CPUID_8000_001F_EAX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..8babbd8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	18	/* N 32-bit words worth of info */
+#define NCAPINTS	19	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -286,6 +286,9 @@
 #define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
 
+/* AMD SME Feature Identification, CPUID level 0x8000001f (eax), word 18 */
+#define X86_FEATURE_SME		(18*32+ 0) /* Secure Memory Encryption */
+
 /*
  * BUG word(s)
  */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad..8b45e08 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -57,6 +57,7 @@
 #define DISABLED_MASK15	0
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
 #define DISABLED_MASK17	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define DISABLED_MASK18	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c..6847d85 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -100,6 +100,7 @@
 #define REQUIRED_MASK15	0
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define REQUIRED_MASK18	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8cb57df..d86d9a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the cpu features to include identifying and reporting on the
Secure Memory Encryption feature.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cpufeature.h        |    7 +++++--
 arch/x86/include/asm/cpufeatures.h       |    5 ++++-
 arch/x86/include/asm/disabled-features.h |    3 ++-
 arch/x86/include/asm/required-features.h |    3 ++-
 arch/x86/kernel/cpu/scattered.c          |    1 +
 5 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 1d2b69f..de5bdb1 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -28,6 +28,7 @@ enum cpuid_leafs
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
+	CPUID_8000_001F_EAX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -78,8 +79,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -100,8 +102,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 15, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 18))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..8babbd8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	18	/* N 32-bit words worth of info */
+#define NCAPINTS	19	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -286,6 +286,9 @@
 #define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
 #define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
 
+/* AMD SME Feature Identification, CPUID level 0x8000001f (eax), word 18 */
+#define X86_FEATURE_SME		(18*32+ 0) /* Secure Memory Encryption */
+
 /*
  * BUG word(s)
  */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad..8b45e08 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -57,6 +57,7 @@
 #define DISABLED_MASK15	0
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
 #define DISABLED_MASK17	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define DISABLED_MASK18	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c..6847d85 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -100,6 +100,7 @@
 #define REQUIRED_MASK15	0
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
+#define REQUIRED_MASK18	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index 8cb57df..d86d9a5 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 06/20] x86: Handle reduction in physical address size with SME
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:36   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When System Memory Encryption (SME) is enabled, the physical address
space is reduced. Adjust the x86_phys_bits value to reflect this
reduction.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/cpu/common.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ce7a4c1..c0fe783 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -44,6 +44,7 @@
 #include <asm/pat.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
@@ -736,6 +737,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 
 		c->x86_virt_bits = (eax >> 8) & 0xff;
 		c->x86_phys_bits = eax & 0xff;
+		c->x86_phys_bits -= sme_get_me_loss();
 		c->x86_capability[CPUID_8000_0008_EBX] = ebx;
 	}
 #ifdef CONFIG_X86_32

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 06/20] x86: Handle reduction in physical address size with SME
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When System Memory Encryption (SME) is enabled, the physical address
space is reduced. Adjust the x86_phys_bits value to reflect this
reduction.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/cpu/common.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ce7a4c1..c0fe783 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -44,6 +44,7 @@
 #include <asm/pat.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
@@ -736,6 +737,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 
 		c->x86_virt_bits = (eax >> 8) & 0xff;
 		c->x86_phys_bits = eax & 0xff;
+		c->x86_phys_bits -= sme_get_me_loss();
 		c->x86_capability[CPUID_8000_0008_EBX] = ebx;
 	}
 #ifdef CONFIG_X86_32

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 06/20] x86: Handle reduction in physical address size with SME
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When System Memory Encryption (SME) is enabled, the physical address
space is reduced. Adjust the x86_phys_bits value to reflect this
reduction.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/cpu/common.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ce7a4c1..c0fe783 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -44,6 +44,7 @@
 #include <asm/pat.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
@@ -736,6 +737,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 
 		c->x86_virt_bits = (eax >> 8) & 0xff;
 		c->x86_phys_bits = eax & 0xff;
+		c->x86_phys_bits -= sme_get_me_loss();
 		c->x86_capability[CPUID_8000_0008_EBX] = ebx;
 	}
 #ifdef CONFIG_X86_32


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 06/20] x86: Handle reduction in physical address size with SME
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When System Memory Encryption (SME) is enabled, the physical address
space is reduced. Adjust the x86_phys_bits value to reflect this
reduction.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/cpu/common.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ce7a4c1..c0fe783 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -44,6 +44,7 @@
 #include <asm/pat.h>
 #include <asm/microcode.h>
 #include <asm/microcode_intel.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
@@ -736,6 +737,7 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 
 		c->x86_virt_bits = (eax >> 8) & 0xff;
 		c->x86_phys_bits = eax & 0xff;
+		c->x86_phys_bits -= sme_get_me_loss();
 		c->x86_capability[CPUID_8000_0008_EBX] = ebx;
 	}
 #ifdef CONFIG_X86_32

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:36   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Adding general kernel support for memory encryption includes:
- Modify and create some page table macros to include the Secure Memory
  Encryption (SME) memory encryption mask
- Update kernel boot support to call an SME routine that checks for and
  sets the SME capability (the SME routine will grow later and for now
  is just a stub routine)
- Update kernel boot support to call an SME routine that encrypts the
  kernel (the SME routine will grow later and for now is just a stub
  routine)
- Provide an SME initialization routine to update the protection map with
  the memory encryption mask so that it is used by default

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/boot/compressed/pagetable.c |    7 ++++++
 arch/x86/include/asm/fixmap.h        |    7 ++++++
 arch/x86/include/asm/mem_encrypt.h   |   18 +++++++++++++++
 arch/x86/include/asm/pgtable.h       |   26 ++++++++++++---------
 arch/x86/include/asm/pgtable_types.h |   41 ++++++++++++++++++++++-----------
 arch/x86/include/asm/processor.h     |    3 ++
 arch/x86/kernel/espfix_64.c          |    2 +-
 arch/x86/kernel/head64.c             |   10 ++++++--
 arch/x86/kernel/head_64.S            |   42 ++++++++++++++++++++++++++--------
 arch/x86/kernel/machine_kexec_64.c   |    2 +-
 arch/x86/kernel/mem_encrypt.S        |    8 ++++++
 arch/x86/mm/Makefile                 |    1 +
 arch/x86/mm/fault.c                  |    5 ++--
 arch/x86/mm/ioremap.c                |    3 ++
 arch/x86/mm/kasan_init_64.c          |    4 ++-
 arch/x86/mm/mem_encrypt.c            |   30 ++++++++++++++++++++++++
 arch/x86/mm/pageattr.c               |    3 ++
 17 files changed, 167 insertions(+), 45 deletions(-)
 create mode 100644 arch/x86/mm/mem_encrypt.c

diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c
index 56589d0..411c443 100644
--- a/arch/x86/boot/compressed/pagetable.c
+++ b/arch/x86/boot/compressed/pagetable.c
@@ -15,6 +15,13 @@
 #define __pa(x)  ((unsigned long)(x))
 #define __va(x)  ((void *)((unsigned long)(x)))
 
+/*
+ * The pgtable.h and mm/ident_map.c includes make use of the SME related
+ * information which is not used in the compressed image support. Un-define
+ * the SME support to avoid any compile and link errors.
+ */
+#undef CONFIG_AMD_MEM_ENCRYPT
+
 #include "misc.h"
 
 /* These actually do the work of building the kernel identity maps. */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 8554f96..83e91f0 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -153,6 +153,13 @@ static inline void __set_fixmap(enum fixed_addresses idx,
 }
 #endif
 
+/*
+ * Fixmap settings used with memory encryption
+ *   - FIXMAP_PAGE_NOCACHE is used for MMIO so make sure the memory
+ *     encryption mask is not part of the page attributes
+ */
+#define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 747fc52..9f3e762 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -15,12 +15,21 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/init.h>
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_init(void);
+
+#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
+#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
+
+#define __sme_va(x)		(__va((x) & ~sme_me_mask))
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask		0UL
@@ -30,6 +39,15 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_init(void)
+{
+}
+
+#define __sme_pa		__pa
+#define __sme_pa_nodebug	__pa_nodebug
+
+#define __sme_va		__va
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 437feb4..e3f2b3e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -5,6 +5,7 @@
 #include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Macro to mark a page protection value as UC-
@@ -155,17 +156,22 @@ static inline int pte_special(pte_t pte)
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
+	return (pte_val(pte) & ~sme_me_mask & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-	return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
+	return (pmd_val(pmd) & ~sme_me_mask & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pud_pfn(pud_t pud)
 {
-	return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+	return (pud_val(pud) & ~sme_me_mask & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+}
+
+static inline unsigned long pgd_pfn(pgd_t pgd)
+{
+	return (pgd_val(pgd) & ~sme_me_mask) >> PAGE_SHIFT;
 }
 
 #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
@@ -558,15 +564,14 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 {
-	return (unsigned long)__va(pmd_val(pmd) & pmd_pfn_mask(pmd));
+	return (unsigned long)__sme_va(pmd_val(pmd) & pmd_pfn_mask(pmd));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pmd_page(pmd)		\
-	pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
+#define pmd_page(pmd)	pfn_to_page(pmd_pfn(pmd))
 
 /*
  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -627,15 +632,14 @@ static inline int pud_present(pud_t pud)
 
 static inline unsigned long pud_page_vaddr(pud_t pud)
 {
-	return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
+	return (unsigned long)__sme_va(pud_val(pud) & pud_pfn_mask(pud));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pud_page(pud)		\
-	pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
+#define pud_page(pud)	pfn_to_page(pud_pfn(pud))
 
 /* Find an entry in the second-level page table.. */
 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
@@ -668,14 +672,14 @@ static inline int pgd_present(pgd_t pgd)
 
 static inline unsigned long pgd_page_vaddr(pgd_t pgd)
 {
-	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
+	return (unsigned long)__sme_va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+#define pgd_page(pgd)	pfn_to_page(pgd_pfn(pgd))
 
 /* to find an entry in a page-table-directory. */
 static inline unsigned long pud_index(unsigned long address)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index f1218f5..a01f0e1 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -3,6 +3,7 @@
 
 #include <linux/const.h>
 #include <asm/page_types.h>
+#include <asm/mem_encrypt.h>
 
 #define FIRST_USER_ADDRESS	0UL
 
@@ -121,9 +122,9 @@
 
 #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
 
-#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
 			 _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+#define __KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY)
 
 /*
@@ -191,18 +192,30 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
 
-#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
-#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
-#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
-#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
-#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
-#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
-#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
-#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
-
-#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
-#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#ifndef __ASSEMBLY__
+
+#define _PAGE_ENC	sme_me_mask
+
+/* Redefine macros to inclue the memory encryption mask */
+#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+			 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_ENC)
+#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+			 _PAGE_DIRTY | _PAGE_ENC)
+
+#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
+#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
+#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_VSYSCALL	__pgprot(__PAGE_KERNEL_VSYSCALL | _PAGE_ENC)
+#define PAGE_KERNEL_VVAR	__pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
+
+#define PAGE_KERNEL_IO		__pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE	__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+
+#endif	/* __ASSEMBLY__ */
 
 /*         xwr */
 #define __P000	PAGE_NONE
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 63def95..024d58c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -22,6 +22,7 @@ struct vm86;
 #include <asm/nops.h>
 #include <asm/special_insns.h>
 #include <asm/fpu/types.h>
+#include <asm/mem_encrypt.h>
 
 #include <linux/personality.h>
 #include <linux/cache.h>
@@ -207,7 +208,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
 
 static inline void load_cr3(pgd_t *pgdir)
 {
-	write_cr3(__pa(pgdir));
+	write_cr3(__sme_pa(pgdir));
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 04f89ca..51566d7 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -193,7 +193,7 @@ void init_espfix_ap(int cpu)
 
 	pte_p = pte_offset_kernel(&pmd, addr);
 	stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
-	pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
+	pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask));
 	for (n = 0; n < ESPFIX_PTE_CLONES; n++)
 		set_pte(&pte_p[n*PTE_STRIDE], pte);
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 54a2372..88c7bae 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -28,6 +28,7 @@
 #include <asm/bootparam_utils.h>
 #include <asm/microcode.h>
 #include <asm/kasan.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Manage page tables very early on.
@@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
 {
 	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
 	next_early_pgt = 0;
-	write_cr3(__pa_nodebug(early_level4_pgt));
+	write_cr3(__sme_pa_nodebug(early_level4_pgt));
 }
 
 /* Create a new PMD entry */
@@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
 	pmdval_t pmd, *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
-	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
+	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
 		return -1;
 
 again:
@@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 
 	clear_page(init_level4_pgt);
 
+	/* Update the early_pmd_flags with the memory encryption mask */
+	early_pmd_flags |= _PAGE_ENC;
+
+	sme_early_init();
+
 	kasan_early_init();
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c98a559..30f7715 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -95,6 +95,13 @@ startup_64:
 	jnz	bad_address
 
 	/*
+	 * Enable memory encryption (if available). Add the memory encryption
+	 * mask to %rbp to include it in the the page table fixup.
+	 */
+	call	sme_enable
+	addq	sme_me_mask(%rip), %rbp
+
+	/*
 	 * Fixup the physical addresses in the page table
 	 */
 	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
@@ -116,7 +123,8 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PGDIR_SHIFT, %rax
 
-	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
+	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
+	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
 	movq	%rdx, 0(%rbx,%rax,8)
 	movq	%rdx, 8(%rbx,%rax,8)
 
@@ -133,6 +141,7 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PMD_SHIFT, %rdi
 	addq	$(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
+	addq	sme_me_mask(%rip), %rax		/* Apply mem encryption mask */
 	leaq	(_end - 1)(%rip), %rcx
 	shrq	$PMD_SHIFT, %rcx
 	subq	%rdi, %rcx
@@ -163,9 +172,19 @@ startup_64:
 	cmp	%r8, %rdi
 	jne	1b
 
-	/* Fixup phys_base */
+	/*
+	 * Fixup phys_base, remove the memory encryption mask from %rbp
+	 * to obtain the true physical address.
+	 */
+	subq	sme_me_mask(%rip), %rbp
 	addq	%rbp, phys_base(%rip)
 
+	/*
+	 * The page tables have been updated with the memory encryption mask,
+	 * so encrypt the kernel if memory encryption is active
+	 */
+	call	sme_encrypt_kernel
+
 	movq	$(early_level4_pgt - __START_KERNEL_map), %rax
 	jmp 1f
 ENTRY(secondary_startup_64)
@@ -189,6 +208,9 @@ ENTRY(secondary_startup_64)
 	movq	$(init_level4_pgt - __START_KERNEL_map), %rax
 1:
 
+	/* Add the memory encryption mask to RAX */
+	addq	sme_me_mask(%rip), %rax
+
 	/* Enable PAE mode and PGE */
 	movl	$(X86_CR4_PAE | X86_CR4_PGE), %ecx
 	movq	%rcx, %cr4
@@ -415,7 +437,7 @@ GLOBAL(name)
 	__INITDATA
 NEXT_PAGE(early_level4_pgt)
 	.fill	511,8,0
-	.quad	level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(early_dynamic_pgts)
 	.fill	512*EARLY_DYNAMIC_PAGE_TABLES,8,0
@@ -427,15 +449,15 @@ NEXT_PAGE(init_level4_pgt)
 	.fill	512,8,0
 #else
 NEXT_PAGE(init_level4_pgt)
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_PAGE_OFFSET*8, 0
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_START_KERNEL*8, 0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad   level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level3_ident_pgt)
-	.quad	level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad	level2_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.fill	511, 8, 0
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
@@ -447,8 +469,8 @@ NEXT_PAGE(level2_ident_pgt)
 NEXT_PAGE(level3_kernel_pgt)
 	.fill	L3_START_KERNEL,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level2_kernel_pgt - __START_KERNEL_map + __KERNPG_TABLE
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level2_kernel_pgt)
 	/*
@@ -466,7 +488,7 @@ NEXT_PAGE(level2_kernel_pgt)
 
 NEXT_PAGE(level2_fixmap_pgt)
 	.fill	506,8,0
-	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
 	.fill	5,8,0
 
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 5a294e4..f976867 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -103,7 +103,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 	struct x86_mapping_info info = {
 		.alloc_pgt_page	= alloc_pgt_page,
 		.context	= image,
-		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC,
+		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC,
 	};
 	unsigned long mstart, mend;
 	pgd_t *level4p;
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index ef7f325..f2e0536 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -14,6 +14,14 @@
 
 	.text
 	.code64
+ENTRY(sme_enable)
+	ret
+ENDPROC(sme_enable)
+
+ENTRY(sme_encrypt_kernel)
+	ret
+ENDPROC(sme_encrypt_kernel)
+
 ENTRY(sme_get_me_loss)
 	xor	%rax, %rax
 	mov	sme_me_loss(%rip), %al
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 96d2b84..44d4d21 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_X86_INTEL_MPX)	+= mpx.o
 obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o
 obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o
 
+obj-$(CONFIG_AMD_MEM_ENCRYPT)	+= mem_encrypt.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index dc80230..3ea88ca 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -23,6 +23,7 @@
 #include <asm/vsyscall.h>		/* emulate_vsyscall		*/
 #include <asm/vm86.h>			/* struct vm86			*/
 #include <asm/mmu_context.h>		/* vma_pkey()			*/
+#include <asm/mem_encrypt.h>		/* __sme_va()			*/
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/exceptions.h>
@@ -523,7 +524,7 @@ static int bad_address(void *p)
 
 static void dump_pagetable(unsigned long address)
 {
-	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+	pgd_t *base = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 	pgd_t *pgd = base + pgd_index(address);
 	pud_t *pud;
 	pmd_t *pmd;
@@ -659,7 +660,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 		pgd_t *pgd;
 		pte_t *pte;
 
-		pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+		pgd = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 		pgd += pgd_index(address);
 
 		pte = lookup_address_in_pgd(pgd, address, &level);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 7aaa263..5cf0489 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -20,6 +20,7 @@
 #include <asm/tlbflush.h>
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
+#include <asm/mem_encrypt.h>
 
 #include "physaddr.h"
 
@@ -423,7 +424,7 @@ static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
 {
 	/* Don't assume we're using swapper_pg_dir at this point */
-	pgd_t *base = __va(read_cr3());
+	pgd_t *base = __sme_va(read_cr3());
 	pgd_t *pgd = &base[pgd_index(addr)];
 	pud_t *pud = pud_offset(pgd, addr);
 	pmd_t *pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 0493c17..0608dc8 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -68,7 +68,7 @@ static struct notifier_block kasan_die_notifier = {
 void __init kasan_early_init(void)
 {
 	int i;
-	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
+	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL | _PAGE_ENC;
 	pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
 	pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
 
@@ -130,7 +130,7 @@ void __init kasan_init(void)
 	 */
 	memset(kasan_zero_page, 0, PAGE_SIZE);
 	for (i = 0; i < PTRS_PER_PTE; i++) {
-		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO | _PAGE_ENC);
 		set_pte(&kasan_zero_pte[i], pte);
 	}
 	/* Flush TLBs again to be sure that write protection applied. */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
new file mode 100644
index 0000000..00eb705
--- /dev/null
+++ b/arch/x86/mm/mem_encrypt.c
@@ -0,0 +1,30 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/mem_encrypt.h>
+
+void __init sme_early_init(void)
+{
+	unsigned int i;
+
+	if (!sme_me_mask)
+		return;
+
+	__supported_pte_mask |= sme_me_mask;
+
+	/* Update the protection map with memory encryption mask */
+	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
+		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
+}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 849dc09..72c292d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1973,6 +1973,9 @@ int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
 	if (!(page_flags & _PAGE_RW))
 		cpa.mask_clr = __pgprot(_PAGE_RW);
 
+	if (!(page_flags & _PAGE_ENC))
+		cpa.mask_clr = __pgprot(pgprot_val(cpa.mask_clr) | _PAGE_ENC);
+
 	cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
 
 	retval = __change_page_attr_set_clr(&cpa, 0);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Adding general kernel support for memory encryption includes:
- Modify and create some page table macros to include the Secure Memory
  Encryption (SME) memory encryption mask
- Update kernel boot support to call an SME routine that checks for and
  sets the SME capability (the SME routine will grow later and for now
  is just a stub routine)
- Update kernel boot support to call an SME routine that encrypts the
  kernel (the SME routine will grow later and for now is just a stub
  routine)
- Provide an SME initialization routine to update the protection map with
  the memory encryption mask so that it is used by default

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/boot/compressed/pagetable.c |    7 ++++++
 arch/x86/include/asm/fixmap.h        |    7 ++++++
 arch/x86/include/asm/mem_encrypt.h   |   18 +++++++++++++++
 arch/x86/include/asm/pgtable.h       |   26 ++++++++++++---------
 arch/x86/include/asm/pgtable_types.h |   41 ++++++++++++++++++++++-----------
 arch/x86/include/asm/processor.h     |    3 ++
 arch/x86/kernel/espfix_64.c          |    2 +-
 arch/x86/kernel/head64.c             |   10 ++++++--
 arch/x86/kernel/head_64.S            |   42 ++++++++++++++++++++++++++--------
 arch/x86/kernel/machine_kexec_64.c   |    2 +-
 arch/x86/kernel/mem_encrypt.S        |    8 ++++++
 arch/x86/mm/Makefile                 |    1 +
 arch/x86/mm/fault.c                  |    5 ++--
 arch/x86/mm/ioremap.c                |    3 ++
 arch/x86/mm/kasan_init_64.c          |    4 ++-
 arch/x86/mm/mem_encrypt.c            |   30 ++++++++++++++++++++++++
 arch/x86/mm/pageattr.c               |    3 ++
 17 files changed, 167 insertions(+), 45 deletions(-)
 create mode 100644 arch/x86/mm/mem_encrypt.c

diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c
index 56589d0..411c443 100644
--- a/arch/x86/boot/compressed/pagetable.c
+++ b/arch/x86/boot/compressed/pagetable.c
@@ -15,6 +15,13 @@
 #define __pa(x)  ((unsigned long)(x))
 #define __va(x)  ((void *)((unsigned long)(x)))
 
+/*
+ * The pgtable.h and mm/ident_map.c includes make use of the SME related
+ * information which is not used in the compressed image support. Un-define
+ * the SME support to avoid any compile and link errors.
+ */
+#undef CONFIG_AMD_MEM_ENCRYPT
+
 #include "misc.h"
 
 /* These actually do the work of building the kernel identity maps. */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 8554f96..83e91f0 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -153,6 +153,13 @@ static inline void __set_fixmap(enum fixed_addresses idx,
 }
 #endif
 
+/*
+ * Fixmap settings used with memory encryption
+ *   - FIXMAP_PAGE_NOCACHE is used for MMIO so make sure the memory
+ *     encryption mask is not part of the page attributes
+ */
+#define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 747fc52..9f3e762 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -15,12 +15,21 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/init.h>
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_init(void);
+
+#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
+#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
+
+#define __sme_va(x)		(__va((x) & ~sme_me_mask))
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask		0UL
@@ -30,6 +39,15 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_init(void)
+{
+}
+
+#define __sme_pa		__pa
+#define __sme_pa_nodebug	__pa_nodebug
+
+#define __sme_va		__va
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 437feb4..e3f2b3e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -5,6 +5,7 @@
 #include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Macro to mark a page protection value as UC-
@@ -155,17 +156,22 @@ static inline int pte_special(pte_t pte)
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
+	return (pte_val(pte) & ~sme_me_mask & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-	return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
+	return (pmd_val(pmd) & ~sme_me_mask & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pud_pfn(pud_t pud)
 {
-	return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+	return (pud_val(pud) & ~sme_me_mask & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+}
+
+static inline unsigned long pgd_pfn(pgd_t pgd)
+{
+	return (pgd_val(pgd) & ~sme_me_mask) >> PAGE_SHIFT;
 }
 
 #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
@@ -558,15 +564,14 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 {
-	return (unsigned long)__va(pmd_val(pmd) & pmd_pfn_mask(pmd));
+	return (unsigned long)__sme_va(pmd_val(pmd) & pmd_pfn_mask(pmd));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pmd_page(pmd)		\
-	pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
+#define pmd_page(pmd)	pfn_to_page(pmd_pfn(pmd))
 
 /*
  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -627,15 +632,14 @@ static inline int pud_present(pud_t pud)
 
 static inline unsigned long pud_page_vaddr(pud_t pud)
 {
-	return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
+	return (unsigned long)__sme_va(pud_val(pud) & pud_pfn_mask(pud));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pud_page(pud)		\
-	pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
+#define pud_page(pud)	pfn_to_page(pud_pfn(pud))
 
 /* Find an entry in the second-level page table.. */
 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
@@ -668,14 +672,14 @@ static inline int pgd_present(pgd_t pgd)
 
 static inline unsigned long pgd_page_vaddr(pgd_t pgd)
 {
-	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
+	return (unsigned long)__sme_va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+#define pgd_page(pgd)	pfn_to_page(pgd_pfn(pgd))
 
 /* to find an entry in a page-table-directory. */
 static inline unsigned long pud_index(unsigned long address)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index f1218f5..a01f0e1 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -3,6 +3,7 @@
 
 #include <linux/const.h>
 #include <asm/page_types.h>
+#include <asm/mem_encrypt.h>
 
 #define FIRST_USER_ADDRESS	0UL
 
@@ -121,9 +122,9 @@
 
 #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
 
-#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
 			 _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+#define __KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY)
 
 /*
@@ -191,18 +192,30 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
 
-#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
-#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
-#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
-#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
-#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
-#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
-#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
-#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
-
-#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
-#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#ifndef __ASSEMBLY__
+
+#define _PAGE_ENC	sme_me_mask
+
+/* Redefine macros to inclue the memory encryption mask */
+#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+			 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_ENC)
+#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+			 _PAGE_DIRTY | _PAGE_ENC)
+
+#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
+#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
+#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_VSYSCALL	__pgprot(__PAGE_KERNEL_VSYSCALL | _PAGE_ENC)
+#define PAGE_KERNEL_VVAR	__pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
+
+#define PAGE_KERNEL_IO		__pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE	__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+
+#endif	/* __ASSEMBLY__ */
 
 /*         xwr */
 #define __P000	PAGE_NONE
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 63def95..024d58c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -22,6 +22,7 @@ struct vm86;
 #include <asm/nops.h>
 #include <asm/special_insns.h>
 #include <asm/fpu/types.h>
+#include <asm/mem_encrypt.h>
 
 #include <linux/personality.h>
 #include <linux/cache.h>
@@ -207,7 +208,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
 
 static inline void load_cr3(pgd_t *pgdir)
 {
-	write_cr3(__pa(pgdir));
+	write_cr3(__sme_pa(pgdir));
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 04f89ca..51566d7 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -193,7 +193,7 @@ void init_espfix_ap(int cpu)
 
 	pte_p = pte_offset_kernel(&pmd, addr);
 	stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
-	pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
+	pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask));
 	for (n = 0; n < ESPFIX_PTE_CLONES; n++)
 		set_pte(&pte_p[n*PTE_STRIDE], pte);
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 54a2372..88c7bae 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -28,6 +28,7 @@
 #include <asm/bootparam_utils.h>
 #include <asm/microcode.h>
 #include <asm/kasan.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Manage page tables very early on.
@@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
 {
 	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
 	next_early_pgt = 0;
-	write_cr3(__pa_nodebug(early_level4_pgt));
+	write_cr3(__sme_pa_nodebug(early_level4_pgt));
 }
 
 /* Create a new PMD entry */
@@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
 	pmdval_t pmd, *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
-	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
+	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
 		return -1;
 
 again:
@@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 
 	clear_page(init_level4_pgt);
 
+	/* Update the early_pmd_flags with the memory encryption mask */
+	early_pmd_flags |= _PAGE_ENC;
+
+	sme_early_init();
+
 	kasan_early_init();
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c98a559..30f7715 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -95,6 +95,13 @@ startup_64:
 	jnz	bad_address
 
 	/*
+	 * Enable memory encryption (if available). Add the memory encryption
+	 * mask to %rbp to include it in the the page table fixup.
+	 */
+	call	sme_enable
+	addq	sme_me_mask(%rip), %rbp
+
+	/*
 	 * Fixup the physical addresses in the page table
 	 */
 	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
@@ -116,7 +123,8 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PGDIR_SHIFT, %rax
 
-	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
+	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
+	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
 	movq	%rdx, 0(%rbx,%rax,8)
 	movq	%rdx, 8(%rbx,%rax,8)
 
@@ -133,6 +141,7 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PMD_SHIFT, %rdi
 	addq	$(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
+	addq	sme_me_mask(%rip), %rax		/* Apply mem encryption mask */
 	leaq	(_end - 1)(%rip), %rcx
 	shrq	$PMD_SHIFT, %rcx
 	subq	%rdi, %rcx
@@ -163,9 +172,19 @@ startup_64:
 	cmp	%r8, %rdi
 	jne	1b
 
-	/* Fixup phys_base */
+	/*
+	 * Fixup phys_base, remove the memory encryption mask from %rbp
+	 * to obtain the true physical address.
+	 */
+	subq	sme_me_mask(%rip), %rbp
 	addq	%rbp, phys_base(%rip)
 
+	/*
+	 * The page tables have been updated with the memory encryption mask,
+	 * so encrypt the kernel if memory encryption is active
+	 */
+	call	sme_encrypt_kernel
+
 	movq	$(early_level4_pgt - __START_KERNEL_map), %rax
 	jmp 1f
 ENTRY(secondary_startup_64)
@@ -189,6 +208,9 @@ ENTRY(secondary_startup_64)
 	movq	$(init_level4_pgt - __START_KERNEL_map), %rax
 1:
 
+	/* Add the memory encryption mask to RAX */
+	addq	sme_me_mask(%rip), %rax
+
 	/* Enable PAE mode and PGE */
 	movl	$(X86_CR4_PAE | X86_CR4_PGE), %ecx
 	movq	%rcx, %cr4
@@ -415,7 +437,7 @@ GLOBAL(name)
 	__INITDATA
 NEXT_PAGE(early_level4_pgt)
 	.fill	511,8,0
-	.quad	level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(early_dynamic_pgts)
 	.fill	512*EARLY_DYNAMIC_PAGE_TABLES,8,0
@@ -427,15 +449,15 @@ NEXT_PAGE(init_level4_pgt)
 	.fill	512,8,0
 #else
 NEXT_PAGE(init_level4_pgt)
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_PAGE_OFFSET*8, 0
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_START_KERNEL*8, 0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad   level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level3_ident_pgt)
-	.quad	level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad	level2_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.fill	511, 8, 0
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
@@ -447,8 +469,8 @@ NEXT_PAGE(level2_ident_pgt)
 NEXT_PAGE(level3_kernel_pgt)
 	.fill	L3_START_KERNEL,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level2_kernel_pgt - __START_KERNEL_map + __KERNPG_TABLE
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level2_kernel_pgt)
 	/*
@@ -466,7 +488,7 @@ NEXT_PAGE(level2_kernel_pgt)
 
 NEXT_PAGE(level2_fixmap_pgt)
 	.fill	506,8,0
-	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
 	.fill	5,8,0
 
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 5a294e4..f976867 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -103,7 +103,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 	struct x86_mapping_info info = {
 		.alloc_pgt_page	= alloc_pgt_page,
 		.context	= image,
-		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC,
+		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC,
 	};
 	unsigned long mstart, mend;
 	pgd_t *level4p;
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index ef7f325..f2e0536 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -14,6 +14,14 @@
 
 	.text
 	.code64
+ENTRY(sme_enable)
+	ret
+ENDPROC(sme_enable)
+
+ENTRY(sme_encrypt_kernel)
+	ret
+ENDPROC(sme_encrypt_kernel)
+
 ENTRY(sme_get_me_loss)
 	xor	%rax, %rax
 	mov	sme_me_loss(%rip), %al
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 96d2b84..44d4d21 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_X86_INTEL_MPX)	+= mpx.o
 obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o
 obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o
 
+obj-$(CONFIG_AMD_MEM_ENCRYPT)	+= mem_encrypt.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index dc80230..3ea88ca 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -23,6 +23,7 @@
 #include <asm/vsyscall.h>		/* emulate_vsyscall		*/
 #include <asm/vm86.h>			/* struct vm86			*/
 #include <asm/mmu_context.h>		/* vma_pkey()			*/
+#include <asm/mem_encrypt.h>		/* __sme_va()			*/
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/exceptions.h>
@@ -523,7 +524,7 @@ static int bad_address(void *p)
 
 static void dump_pagetable(unsigned long address)
 {
-	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+	pgd_t *base = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 	pgd_t *pgd = base + pgd_index(address);
 	pud_t *pud;
 	pmd_t *pmd;
@@ -659,7 +660,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 		pgd_t *pgd;
 		pte_t *pte;
 
-		pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+		pgd = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 		pgd += pgd_index(address);
 
 		pte = lookup_address_in_pgd(pgd, address, &level);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 7aaa263..5cf0489 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -20,6 +20,7 @@
 #include <asm/tlbflush.h>
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
+#include <asm/mem_encrypt.h>
 
 #include "physaddr.h"
 
@@ -423,7 +424,7 @@ static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
 {
 	/* Don't assume we're using swapper_pg_dir at this point */
-	pgd_t *base = __va(read_cr3());
+	pgd_t *base = __sme_va(read_cr3());
 	pgd_t *pgd = &base[pgd_index(addr)];
 	pud_t *pud = pud_offset(pgd, addr);
 	pmd_t *pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 0493c17..0608dc8 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -68,7 +68,7 @@ static struct notifier_block kasan_die_notifier = {
 void __init kasan_early_init(void)
 {
 	int i;
-	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
+	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL | _PAGE_ENC;
 	pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
 	pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
 
@@ -130,7 +130,7 @@ void __init kasan_init(void)
 	 */
 	memset(kasan_zero_page, 0, PAGE_SIZE);
 	for (i = 0; i < PTRS_PER_PTE; i++) {
-		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO | _PAGE_ENC);
 		set_pte(&kasan_zero_pte[i], pte);
 	}
 	/* Flush TLBs again to be sure that write protection applied. */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
new file mode 100644
index 0000000..00eb705
--- /dev/null
+++ b/arch/x86/mm/mem_encrypt.c
@@ -0,0 +1,30 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/mem_encrypt.h>
+
+void __init sme_early_init(void)
+{
+	unsigned int i;
+
+	if (!sme_me_mask)
+		return;
+
+	__supported_pte_mask |= sme_me_mask;
+
+	/* Update the protection map with memory encryption mask */
+	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
+		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
+}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 849dc09..72c292d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1973,6 +1973,9 @@ int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
 	if (!(page_flags & _PAGE_RW))
 		cpa.mask_clr = __pgprot(_PAGE_RW);
 
+	if (!(page_flags & _PAGE_ENC))
+		cpa.mask_clr = __pgprot(pgprot_val(cpa.mask_clr) | _PAGE_ENC);
+
 	cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
 
 	retval = __change_page_attr_set_clr(&cpa, 0);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Adding general kernel support for memory encryption includes:
- Modify and create some page table macros to include the Secure Memory
  Encryption (SME) memory encryption mask
- Update kernel boot support to call an SME routine that checks for and
  sets the SME capability (the SME routine will grow later and for now
  is just a stub routine)
- Update kernel boot support to call an SME routine that encrypts the
  kernel (the SME routine will grow later and for now is just a stub
  routine)
- Provide an SME initialization routine to update the protection map with
  the memory encryption mask so that it is used by default

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/boot/compressed/pagetable.c |    7 ++++++
 arch/x86/include/asm/fixmap.h        |    7 ++++++
 arch/x86/include/asm/mem_encrypt.h   |   18 +++++++++++++++
 arch/x86/include/asm/pgtable.h       |   26 ++++++++++++---------
 arch/x86/include/asm/pgtable_types.h |   41 ++++++++++++++++++++++-----------
 arch/x86/include/asm/processor.h     |    3 ++
 arch/x86/kernel/espfix_64.c          |    2 +-
 arch/x86/kernel/head64.c             |   10 ++++++--
 arch/x86/kernel/head_64.S            |   42 ++++++++++++++++++++++++++--------
 arch/x86/kernel/machine_kexec_64.c   |    2 +-
 arch/x86/kernel/mem_encrypt.S        |    8 ++++++
 arch/x86/mm/Makefile                 |    1 +
 arch/x86/mm/fault.c                  |    5 ++--
 arch/x86/mm/ioremap.c                |    3 ++
 arch/x86/mm/kasan_init_64.c          |    4 ++-
 arch/x86/mm/mem_encrypt.c            |   30 ++++++++++++++++++++++++
 arch/x86/mm/pageattr.c               |    3 ++
 17 files changed, 167 insertions(+), 45 deletions(-)
 create mode 100644 arch/x86/mm/mem_encrypt.c

diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c
index 56589d0..411c443 100644
--- a/arch/x86/boot/compressed/pagetable.c
+++ b/arch/x86/boot/compressed/pagetable.c
@@ -15,6 +15,13 @@
 #define __pa(x)  ((unsigned long)(x))
 #define __va(x)  ((void *)((unsigned long)(x)))
 
+/*
+ * The pgtable.h and mm/ident_map.c includes make use of the SME related
+ * information which is not used in the compressed image support. Un-define
+ * the SME support to avoid any compile and link errors.
+ */
+#undef CONFIG_AMD_MEM_ENCRYPT
+
 #include "misc.h"
 
 /* These actually do the work of building the kernel identity maps. */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 8554f96..83e91f0 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -153,6 +153,13 @@ static inline void __set_fixmap(enum fixed_addresses idx,
 }
 #endif
 
+/*
+ * Fixmap settings used with memory encryption
+ *   - FIXMAP_PAGE_NOCACHE is used for MMIO so make sure the memory
+ *     encryption mask is not part of the page attributes
+ */
+#define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 747fc52..9f3e762 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -15,12 +15,21 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/init.h>
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_init(void);
+
+#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
+#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
+
+#define __sme_va(x)		(__va((x) & ~sme_me_mask))
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask		0UL
@@ -30,6 +39,15 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_init(void)
+{
+}
+
+#define __sme_pa		__pa
+#define __sme_pa_nodebug	__pa_nodebug
+
+#define __sme_va		__va
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 437feb4..e3f2b3e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -5,6 +5,7 @@
 #include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Macro to mark a page protection value as UC-
@@ -155,17 +156,22 @@ static inline int pte_special(pte_t pte)
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
+	return (pte_val(pte) & ~sme_me_mask & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-	return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
+	return (pmd_val(pmd) & ~sme_me_mask & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pud_pfn(pud_t pud)
 {
-	return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+	return (pud_val(pud) & ~sme_me_mask & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+}
+
+static inline unsigned long pgd_pfn(pgd_t pgd)
+{
+	return (pgd_val(pgd) & ~sme_me_mask) >> PAGE_SHIFT;
 }
 
 #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
@@ -558,15 +564,14 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 {
-	return (unsigned long)__va(pmd_val(pmd) & pmd_pfn_mask(pmd));
+	return (unsigned long)__sme_va(pmd_val(pmd) & pmd_pfn_mask(pmd));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pmd_page(pmd)		\
-	pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
+#define pmd_page(pmd)	pfn_to_page(pmd_pfn(pmd))
 
 /*
  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -627,15 +632,14 @@ static inline int pud_present(pud_t pud)
 
 static inline unsigned long pud_page_vaddr(pud_t pud)
 {
-	return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
+	return (unsigned long)__sme_va(pud_val(pud) & pud_pfn_mask(pud));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pud_page(pud)		\
-	pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
+#define pud_page(pud)	pfn_to_page(pud_pfn(pud))
 
 /* Find an entry in the second-level page table.. */
 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
@@ -668,14 +672,14 @@ static inline int pgd_present(pgd_t pgd)
 
 static inline unsigned long pgd_page_vaddr(pgd_t pgd)
 {
-	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
+	return (unsigned long)__sme_va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+#define pgd_page(pgd)	pfn_to_page(pgd_pfn(pgd))
 
 /* to find an entry in a page-table-directory. */
 static inline unsigned long pud_index(unsigned long address)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index f1218f5..a01f0e1 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -3,6 +3,7 @@
 
 #include <linux/const.h>
 #include <asm/page_types.h>
+#include <asm/mem_encrypt.h>
 
 #define FIRST_USER_ADDRESS	0UL
 
@@ -121,9 +122,9 @@
 
 #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
 
-#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
 			 _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+#define __KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY)
 
 /*
@@ -191,18 +192,30 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
 
-#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
-#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
-#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
-#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
-#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
-#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
-#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
-#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
-
-#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
-#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#ifndef __ASSEMBLY__
+
+#define _PAGE_ENC	sme_me_mask
+
+/* Redefine macros to inclue the memory encryption mask */
+#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+			 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_ENC)
+#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+			 _PAGE_DIRTY | _PAGE_ENC)
+
+#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
+#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
+#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_VSYSCALL	__pgprot(__PAGE_KERNEL_VSYSCALL | _PAGE_ENC)
+#define PAGE_KERNEL_VVAR	__pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
+
+#define PAGE_KERNEL_IO		__pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE	__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+
+#endif	/* __ASSEMBLY__ */
 
 /*         xwr */
 #define __P000	PAGE_NONE
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 63def95..024d58c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -22,6 +22,7 @@ struct vm86;
 #include <asm/nops.h>
 #include <asm/special_insns.h>
 #include <asm/fpu/types.h>
+#include <asm/mem_encrypt.h>
 
 #include <linux/personality.h>
 #include <linux/cache.h>
@@ -207,7 +208,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
 
 static inline void load_cr3(pgd_t *pgdir)
 {
-	write_cr3(__pa(pgdir));
+	write_cr3(__sme_pa(pgdir));
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 04f89ca..51566d7 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -193,7 +193,7 @@ void init_espfix_ap(int cpu)
 
 	pte_p = pte_offset_kernel(&pmd, addr);
 	stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
-	pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
+	pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask));
 	for (n = 0; n < ESPFIX_PTE_CLONES; n++)
 		set_pte(&pte_p[n*PTE_STRIDE], pte);
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 54a2372..88c7bae 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -28,6 +28,7 @@
 #include <asm/bootparam_utils.h>
 #include <asm/microcode.h>
 #include <asm/kasan.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Manage page tables very early on.
@@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
 {
 	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
 	next_early_pgt = 0;
-	write_cr3(__pa_nodebug(early_level4_pgt));
+	write_cr3(__sme_pa_nodebug(early_level4_pgt));
 }
 
 /* Create a new PMD entry */
@@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
 	pmdval_t pmd, *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
-	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
+	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
 		return -1;
 
 again:
@@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 
 	clear_page(init_level4_pgt);
 
+	/* Update the early_pmd_flags with the memory encryption mask */
+	early_pmd_flags |= _PAGE_ENC;
+
+	sme_early_init();
+
 	kasan_early_init();
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c98a559..30f7715 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -95,6 +95,13 @@ startup_64:
 	jnz	bad_address
 
 	/*
+	 * Enable memory encryption (if available). Add the memory encryption
+	 * mask to %rbp to include it in the the page table fixup.
+	 */
+	call	sme_enable
+	addq	sme_me_mask(%rip), %rbp
+
+	/*
 	 * Fixup the physical addresses in the page table
 	 */
 	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
@@ -116,7 +123,8 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PGDIR_SHIFT, %rax
 
-	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
+	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
+	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
 	movq	%rdx, 0(%rbx,%rax,8)
 	movq	%rdx, 8(%rbx,%rax,8)
 
@@ -133,6 +141,7 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PMD_SHIFT, %rdi
 	addq	$(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
+	addq	sme_me_mask(%rip), %rax		/* Apply mem encryption mask */
 	leaq	(_end - 1)(%rip), %rcx
 	shrq	$PMD_SHIFT, %rcx
 	subq	%rdi, %rcx
@@ -163,9 +172,19 @@ startup_64:
 	cmp	%r8, %rdi
 	jne	1b
 
-	/* Fixup phys_base */
+	/*
+	 * Fixup phys_base, remove the memory encryption mask from %rbp
+	 * to obtain the true physical address.
+	 */
+	subq	sme_me_mask(%rip), %rbp
 	addq	%rbp, phys_base(%rip)
 
+	/*
+	 * The page tables have been updated with the memory encryption mask,
+	 * so encrypt the kernel if memory encryption is active
+	 */
+	call	sme_encrypt_kernel
+
 	movq	$(early_level4_pgt - __START_KERNEL_map), %rax
 	jmp 1f
 ENTRY(secondary_startup_64)
@@ -189,6 +208,9 @@ ENTRY(secondary_startup_64)
 	movq	$(init_level4_pgt - __START_KERNEL_map), %rax
 1:
 
+	/* Add the memory encryption mask to RAX */
+	addq	sme_me_mask(%rip), %rax
+
 	/* Enable PAE mode and PGE */
 	movl	$(X86_CR4_PAE | X86_CR4_PGE), %ecx
 	movq	%rcx, %cr4
@@ -415,7 +437,7 @@ GLOBAL(name)
 	__INITDATA
 NEXT_PAGE(early_level4_pgt)
 	.fill	511,8,0
-	.quad	level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(early_dynamic_pgts)
 	.fill	512*EARLY_DYNAMIC_PAGE_TABLES,8,0
@@ -427,15 +449,15 @@ NEXT_PAGE(init_level4_pgt)
 	.fill	512,8,0
 #else
 NEXT_PAGE(init_level4_pgt)
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_PAGE_OFFSET*8, 0
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_START_KERNEL*8, 0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad   level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level3_ident_pgt)
-	.quad	level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad	level2_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.fill	511, 8, 0
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
@@ -447,8 +469,8 @@ NEXT_PAGE(level2_ident_pgt)
 NEXT_PAGE(level3_kernel_pgt)
 	.fill	L3_START_KERNEL,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level2_kernel_pgt - __START_KERNEL_map + __KERNPG_TABLE
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level2_kernel_pgt)
 	/*
@@ -466,7 +488,7 @@ NEXT_PAGE(level2_kernel_pgt)
 
 NEXT_PAGE(level2_fixmap_pgt)
 	.fill	506,8,0
-	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
 	.fill	5,8,0
 
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 5a294e4..f976867 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -103,7 +103,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 	struct x86_mapping_info info = {
 		.alloc_pgt_page	= alloc_pgt_page,
 		.context	= image,
-		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC,
+		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC,
 	};
 	unsigned long mstart, mend;
 	pgd_t *level4p;
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index ef7f325..f2e0536 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -14,6 +14,14 @@
 
 	.text
 	.code64
+ENTRY(sme_enable)
+	ret
+ENDPROC(sme_enable)
+
+ENTRY(sme_encrypt_kernel)
+	ret
+ENDPROC(sme_encrypt_kernel)
+
 ENTRY(sme_get_me_loss)
 	xor	%rax, %rax
 	mov	sme_me_loss(%rip), %al
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 96d2b84..44d4d21 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_X86_INTEL_MPX)	+= mpx.o
 obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o
 obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o
 
+obj-$(CONFIG_AMD_MEM_ENCRYPT)	+= mem_encrypt.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index dc80230..3ea88ca 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -23,6 +23,7 @@
 #include <asm/vsyscall.h>		/* emulate_vsyscall		*/
 #include <asm/vm86.h>			/* struct vm86			*/
 #include <asm/mmu_context.h>		/* vma_pkey()			*/
+#include <asm/mem_encrypt.h>		/* __sme_va()			*/
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/exceptions.h>
@@ -523,7 +524,7 @@ static int bad_address(void *p)
 
 static void dump_pagetable(unsigned long address)
 {
-	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+	pgd_t *base = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 	pgd_t *pgd = base + pgd_index(address);
 	pud_t *pud;
 	pmd_t *pmd;
@@ -659,7 +660,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 		pgd_t *pgd;
 		pte_t *pte;
 
-		pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+		pgd = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 		pgd += pgd_index(address);
 
 		pte = lookup_address_in_pgd(pgd, address, &level);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 7aaa263..5cf0489 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -20,6 +20,7 @@
 #include <asm/tlbflush.h>
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
+#include <asm/mem_encrypt.h>
 
 #include "physaddr.h"
 
@@ -423,7 +424,7 @@ static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
 {
 	/* Don't assume we're using swapper_pg_dir at this point */
-	pgd_t *base = __va(read_cr3());
+	pgd_t *base = __sme_va(read_cr3());
 	pgd_t *pgd = &base[pgd_index(addr)];
 	pud_t *pud = pud_offset(pgd, addr);
 	pmd_t *pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 0493c17..0608dc8 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -68,7 +68,7 @@ static struct notifier_block kasan_die_notifier = {
 void __init kasan_early_init(void)
 {
 	int i;
-	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
+	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL | _PAGE_ENC;
 	pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
 	pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
 
@@ -130,7 +130,7 @@ void __init kasan_init(void)
 	 */
 	memset(kasan_zero_page, 0, PAGE_SIZE);
 	for (i = 0; i < PTRS_PER_PTE; i++) {
-		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO | _PAGE_ENC);
 		set_pte(&kasan_zero_pte[i], pte);
 	}
 	/* Flush TLBs again to be sure that write protection applied. */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
new file mode 100644
index 0000000..00eb705
--- /dev/null
+++ b/arch/x86/mm/mem_encrypt.c
@@ -0,0 +1,30 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/mem_encrypt.h>
+
+void __init sme_early_init(void)
+{
+	unsigned int i;
+
+	if (!sme_me_mask)
+		return;
+
+	__supported_pte_mask |= sme_me_mask;
+
+	/* Update the protection map with memory encryption mask */
+	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
+		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
+}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 849dc09..72c292d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1973,6 +1973,9 @@ int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
 	if (!(page_flags & _PAGE_RW))
 		cpa.mask_clr = __pgprot(_PAGE_RW);
 
+	if (!(page_flags & _PAGE_ENC))
+		cpa.mask_clr = __pgprot(pgprot_val(cpa.mask_clr) | _PAGE_ENC);
+
 	cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
 
 	retval = __change_page_attr_set_clr(&cpa, 0);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-08-22 22:36   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:36 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Adding general kernel support for memory encryption includes:
- Modify and create some page table macros to include the Secure Memory
  Encryption (SME) memory encryption mask
- Update kernel boot support to call an SME routine that checks for and
  sets the SME capability (the SME routine will grow later and for now
  is just a stub routine)
- Update kernel boot support to call an SME routine that encrypts the
  kernel (the SME routine will grow later and for now is just a stub
  routine)
- Provide an SME initialization routine to update the protection map with
  the memory encryption mask so that it is used by default

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/boot/compressed/pagetable.c |    7 ++++++
 arch/x86/include/asm/fixmap.h        |    7 ++++++
 arch/x86/include/asm/mem_encrypt.h   |   18 +++++++++++++++
 arch/x86/include/asm/pgtable.h       |   26 ++++++++++++---------
 arch/x86/include/asm/pgtable_types.h |   41 ++++++++++++++++++++++-----------
 arch/x86/include/asm/processor.h     |    3 ++
 arch/x86/kernel/espfix_64.c          |    2 +-
 arch/x86/kernel/head64.c             |   10 ++++++--
 arch/x86/kernel/head_64.S            |   42 ++++++++++++++++++++++++++--------
 arch/x86/kernel/machine_kexec_64.c   |    2 +-
 arch/x86/kernel/mem_encrypt.S        |    8 ++++++
 arch/x86/mm/Makefile                 |    1 +
 arch/x86/mm/fault.c                  |    5 ++--
 arch/x86/mm/ioremap.c                |    3 ++
 arch/x86/mm/kasan_init_64.c          |    4 ++-
 arch/x86/mm/mem_encrypt.c            |   30 ++++++++++++++++++++++++
 arch/x86/mm/pageattr.c               |    3 ++
 17 files changed, 167 insertions(+), 45 deletions(-)
 create mode 100644 arch/x86/mm/mem_encrypt.c

diff --git a/arch/x86/boot/compressed/pagetable.c b/arch/x86/boot/compressed/pagetable.c
index 56589d0..411c443 100644
--- a/arch/x86/boot/compressed/pagetable.c
+++ b/arch/x86/boot/compressed/pagetable.c
@@ -15,6 +15,13 @@
 #define __pa(x)  ((unsigned long)(x))
 #define __va(x)  ((void *)((unsigned long)(x)))
 
+/*
+ * The pgtable.h and mm/ident_map.c includes make use of the SME related
+ * information which is not used in the compressed image support. Un-define
+ * the SME support to avoid any compile and link errors.
+ */
+#undef CONFIG_AMD_MEM_ENCRYPT
+
 #include "misc.h"
 
 /* These actually do the work of building the kernel identity maps. */
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 8554f96..83e91f0 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -153,6 +153,13 @@ static inline void __set_fixmap(enum fixed_addresses idx,
 }
 #endif
 
+/*
+ * Fixmap settings used with memory encryption
+ *   - FIXMAP_PAGE_NOCACHE is used for MMIO so make sure the memory
+ *     encryption mask is not part of the page attributes
+ */
+#define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 747fc52..9f3e762 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -15,12 +15,21 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/init.h>
+
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 
 extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_init(void);
+
+#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
+#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
+
+#define __sme_va(x)		(__va((x) & ~sme_me_mask))
+
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask		0UL
@@ -30,6 +39,15 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_init(void)
+{
+}
+
+#define __sme_pa		__pa
+#define __sme_pa_nodebug	__pa_nodebug
+
+#define __sme_va		__va
+
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 437feb4..e3f2b3e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -5,6 +5,7 @@
 #include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Macro to mark a page protection value as UC-
@@ -155,17 +156,22 @@ static inline int pte_special(pte_t pte)
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
+	return (pte_val(pte) & ~sme_me_mask & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-	return (pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
+	return (pmd_val(pmd) & ~sme_me_mask & pmd_pfn_mask(pmd)) >> PAGE_SHIFT;
 }
 
 static inline unsigned long pud_pfn(pud_t pud)
 {
-	return (pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+	return (pud_val(pud) & ~sme_me_mask & pud_pfn_mask(pud)) >> PAGE_SHIFT;
+}
+
+static inline unsigned long pgd_pfn(pgd_t pgd)
+{
+	return (pgd_val(pgd) & ~sme_me_mask) >> PAGE_SHIFT;
 }
 
 #define pte_page(pte)	pfn_to_page(pte_pfn(pte))
@@ -558,15 +564,14 @@ static inline int pmd_none(pmd_t pmd)
 
 static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 {
-	return (unsigned long)__va(pmd_val(pmd) & pmd_pfn_mask(pmd));
+	return (unsigned long)__sme_va(pmd_val(pmd) & pmd_pfn_mask(pmd));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pmd_page(pmd)		\
-	pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
+#define pmd_page(pmd)	pfn_to_page(pmd_pfn(pmd))
 
 /*
  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
@@ -627,15 +632,14 @@ static inline int pud_present(pud_t pud)
 
 static inline unsigned long pud_page_vaddr(pud_t pud)
 {
-	return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
+	return (unsigned long)__sme_va(pud_val(pud) & pud_pfn_mask(pud));
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pud_page(pud)		\
-	pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
+#define pud_page(pud)	pfn_to_page(pud_pfn(pud))
 
 /* Find an entry in the second-level page table.. */
 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
@@ -668,14 +672,14 @@ static inline int pgd_present(pgd_t pgd)
 
 static inline unsigned long pgd_page_vaddr(pgd_t pgd)
 {
-	return (unsigned long)__va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
+	return (unsigned long)__sme_va((unsigned long)pgd_val(pgd) & PTE_PFN_MASK);
 }
 
 /*
  * Currently stuck as a macro due to indirect forward reference to
  * linux/mmzone.h's __section_mem_map_addr() definition:
  */
-#define pgd_page(pgd)		pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
+#define pgd_page(pgd)	pfn_to_page(pgd_pfn(pgd))
 
 /* to find an entry in a page-table-directory. */
 static inline unsigned long pud_index(unsigned long address)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index f1218f5..a01f0e1 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -3,6 +3,7 @@
 
 #include <linux/const.h>
 #include <asm/page_types.h>
+#include <asm/mem_encrypt.h>
 
 #define FIRST_USER_ADDRESS	0UL
 
@@ -121,9 +122,9 @@
 
 #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
 
-#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
 			 _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+#define __KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY)
 
 /*
@@ -191,18 +192,30 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
 
-#define PAGE_KERNEL			__pgprot(__PAGE_KERNEL)
-#define PAGE_KERNEL_RO			__pgprot(__PAGE_KERNEL_RO)
-#define PAGE_KERNEL_EXEC		__pgprot(__PAGE_KERNEL_EXEC)
-#define PAGE_KERNEL_RX			__pgprot(__PAGE_KERNEL_RX)
-#define PAGE_KERNEL_NOCACHE		__pgprot(__PAGE_KERNEL_NOCACHE)
-#define PAGE_KERNEL_LARGE		__pgprot(__PAGE_KERNEL_LARGE)
-#define PAGE_KERNEL_LARGE_EXEC		__pgprot(__PAGE_KERNEL_LARGE_EXEC)
-#define PAGE_KERNEL_VSYSCALL		__pgprot(__PAGE_KERNEL_VSYSCALL)
-#define PAGE_KERNEL_VVAR		__pgprot(__PAGE_KERNEL_VVAR)
-
-#define PAGE_KERNEL_IO			__pgprot(__PAGE_KERNEL_IO)
-#define PAGE_KERNEL_IO_NOCACHE		__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+#ifndef __ASSEMBLY__
+
+#define _PAGE_ENC	sme_me_mask
+
+/* Redefine macros to inclue the memory encryption mask */
+#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
+			 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_ENC)
+#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
+			 _PAGE_DIRTY | _PAGE_ENC)
+
+#define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
+#define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
+#define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_RX		__pgprot(__PAGE_KERNEL_RX | _PAGE_ENC)
+#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE | _PAGE_ENC)
+#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC)
+#define PAGE_KERNEL_VSYSCALL	__pgprot(__PAGE_KERNEL_VSYSCALL | _PAGE_ENC)
+#define PAGE_KERNEL_VVAR	__pgprot(__PAGE_KERNEL_VVAR | _PAGE_ENC)
+
+#define PAGE_KERNEL_IO		__pgprot(__PAGE_KERNEL_IO)
+#define PAGE_KERNEL_IO_NOCACHE	__pgprot(__PAGE_KERNEL_IO_NOCACHE)
+
+#endif	/* __ASSEMBLY__ */
 
 /*         xwr */
 #define __P000	PAGE_NONE
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 63def95..024d58c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -22,6 +22,7 @@ struct vm86;
 #include <asm/nops.h>
 #include <asm/special_insns.h>
 #include <asm/fpu/types.h>
+#include <asm/mem_encrypt.h>
 
 #include <linux/personality.h>
 #include <linux/cache.h>
@@ -207,7 +208,7 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
 
 static inline void load_cr3(pgd_t *pgdir)
 {
-	write_cr3(__pa(pgdir));
+	write_cr3(__sme_pa(pgdir));
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 04f89ca..51566d7 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -193,7 +193,7 @@ void init_espfix_ap(int cpu)
 
 	pte_p = pte_offset_kernel(&pmd, addr);
 	stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0));
-	pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask));
+	pte = __pte(__pa(stack_page) | ((__PAGE_KERNEL_RO | _PAGE_ENC) & ptemask));
 	for (n = 0; n < ESPFIX_PTE_CLONES; n++)
 		set_pte(&pte_p[n*PTE_STRIDE], pte);
 
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 54a2372..88c7bae 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -28,6 +28,7 @@
 #include <asm/bootparam_utils.h>
 #include <asm/microcode.h>
 #include <asm/kasan.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * Manage page tables very early on.
@@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
 {
 	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
 	next_early_pgt = 0;
-	write_cr3(__pa_nodebug(early_level4_pgt));
+	write_cr3(__sme_pa_nodebug(early_level4_pgt));
 }
 
 /* Create a new PMD entry */
@@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
 	pmdval_t pmd, *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
-	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
+	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
 		return -1;
 
 again:
@@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 
 	clear_page(init_level4_pgt);
 
+	/* Update the early_pmd_flags with the memory encryption mask */
+	early_pmd_flags |= _PAGE_ENC;
+
+	sme_early_init();
+
 	kasan_early_init();
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index c98a559..30f7715 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -95,6 +95,13 @@ startup_64:
 	jnz	bad_address
 
 	/*
+	 * Enable memory encryption (if available). Add the memory encryption
+	 * mask to %rbp to include it in the the page table fixup.
+	 */
+	call	sme_enable
+	addq	sme_me_mask(%rip), %rbp
+
+	/*
 	 * Fixup the physical addresses in the page table
 	 */
 	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
@@ -116,7 +123,8 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PGDIR_SHIFT, %rax
 
-	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
+	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
+	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
 	movq	%rdx, 0(%rbx,%rax,8)
 	movq	%rdx, 8(%rbx,%rax,8)
 
@@ -133,6 +141,7 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PMD_SHIFT, %rdi
 	addq	$(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
+	addq	sme_me_mask(%rip), %rax		/* Apply mem encryption mask */
 	leaq	(_end - 1)(%rip), %rcx
 	shrq	$PMD_SHIFT, %rcx
 	subq	%rdi, %rcx
@@ -163,9 +172,19 @@ startup_64:
 	cmp	%r8, %rdi
 	jne	1b
 
-	/* Fixup phys_base */
+	/*
+	 * Fixup phys_base, remove the memory encryption mask from %rbp
+	 * to obtain the true physical address.
+	 */
+	subq	sme_me_mask(%rip), %rbp
 	addq	%rbp, phys_base(%rip)
 
+	/*
+	 * The page tables have been updated with the memory encryption mask,
+	 * so encrypt the kernel if memory encryption is active
+	 */
+	call	sme_encrypt_kernel
+
 	movq	$(early_level4_pgt - __START_KERNEL_map), %rax
 	jmp 1f
 ENTRY(secondary_startup_64)
@@ -189,6 +208,9 @@ ENTRY(secondary_startup_64)
 	movq	$(init_level4_pgt - __START_KERNEL_map), %rax
 1:
 
+	/* Add the memory encryption mask to RAX */
+	addq	sme_me_mask(%rip), %rax
+
 	/* Enable PAE mode and PGE */
 	movl	$(X86_CR4_PAE | X86_CR4_PGE), %ecx
 	movq	%rcx, %cr4
@@ -415,7 +437,7 @@ GLOBAL(name)
 	__INITDATA
 NEXT_PAGE(early_level4_pgt)
 	.fill	511,8,0
-	.quad	level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(early_dynamic_pgts)
 	.fill	512*EARLY_DYNAMIC_PAGE_TABLES,8,0
@@ -427,15 +449,15 @@ NEXT_PAGE(init_level4_pgt)
 	.fill	512,8,0
 #else
 NEXT_PAGE(init_level4_pgt)
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_PAGE_OFFSET*8, 0
-	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad   level3_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.org    init_level4_pgt + L4_START_KERNEL*8, 0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad   level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad   level3_kernel_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level3_ident_pgt)
-	.quad	level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
+	.quad	level2_ident_pgt - __START_KERNEL_map + __KERNPG_TABLE
 	.fill	511, 8, 0
 NEXT_PAGE(level2_ident_pgt)
 	/* Since I easily can, map the first 1G.
@@ -447,8 +469,8 @@ NEXT_PAGE(level2_ident_pgt)
 NEXT_PAGE(level3_kernel_pgt)
 	.fill	L3_START_KERNEL,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-	.quad	level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
-	.quad	level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level2_kernel_pgt - __START_KERNEL_map + __KERNPG_TABLE
+	.quad	level2_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 
 NEXT_PAGE(level2_kernel_pgt)
 	/*
@@ -466,7 +488,7 @@ NEXT_PAGE(level2_kernel_pgt)
 
 NEXT_PAGE(level2_fixmap_pgt)
 	.fill	506,8,0
-	.quad	level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE
+	.quad	level1_fixmap_pgt - __START_KERNEL_map + __PAGE_TABLE
 	/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */
 	.fill	5,8,0
 
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 5a294e4..f976867 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -103,7 +103,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 	struct x86_mapping_info info = {
 		.alloc_pgt_page	= alloc_pgt_page,
 		.context	= image,
-		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC,
+		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC | _PAGE_ENC,
 	};
 	unsigned long mstart, mend;
 	pgd_t *level4p;
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index ef7f325..f2e0536 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -14,6 +14,14 @@
 
 	.text
 	.code64
+ENTRY(sme_enable)
+	ret
+ENDPROC(sme_enable)
+
+ENTRY(sme_encrypt_kernel)
+	ret
+ENDPROC(sme_encrypt_kernel)
+
 ENTRY(sme_get_me_loss)
 	xor	%rax, %rax
 	mov	sme_me_loss(%rip), %al
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 96d2b84..44d4d21 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_X86_INTEL_MPX)	+= mpx.o
 obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o
 obj-$(CONFIG_RANDOMIZE_MEMORY) += kaslr.o
 
+obj-$(CONFIG_AMD_MEM_ENCRYPT)	+= mem_encrypt.o
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index dc80230..3ea88ca 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -23,6 +23,7 @@
 #include <asm/vsyscall.h>		/* emulate_vsyscall		*/
 #include <asm/vm86.h>			/* struct vm86			*/
 #include <asm/mmu_context.h>		/* vma_pkey()			*/
+#include <asm/mem_encrypt.h>		/* __sme_va()			*/
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/exceptions.h>
@@ -523,7 +524,7 @@ static int bad_address(void *p)
 
 static void dump_pagetable(unsigned long address)
 {
-	pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+	pgd_t *base = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 	pgd_t *pgd = base + pgd_index(address);
 	pud_t *pud;
 	pmd_t *pmd;
@@ -659,7 +660,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
 		pgd_t *pgd;
 		pte_t *pte;
 
-		pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK);
+		pgd = __sme_va(read_cr3() & PHYSICAL_PAGE_MASK);
 		pgd += pgd_index(address);
 
 		pte = lookup_address_in_pgd(pgd, address, &level);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 7aaa263..5cf0489 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -20,6 +20,7 @@
 #include <asm/tlbflush.h>
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
+#include <asm/mem_encrypt.h>
 
 #include "physaddr.h"
 
@@ -423,7 +424,7 @@ static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
 {
 	/* Don't assume we're using swapper_pg_dir at this point */
-	pgd_t *base = __va(read_cr3());
+	pgd_t *base = __sme_va(read_cr3());
 	pgd_t *pgd = &base[pgd_index(addr)];
 	pud_t *pud = pud_offset(pgd, addr);
 	pmd_t *pmd = pmd_offset(pud, addr);
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 0493c17..0608dc8 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -68,7 +68,7 @@ static struct notifier_block kasan_die_notifier = {
 void __init kasan_early_init(void)
 {
 	int i;
-	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL;
+	pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL | _PAGE_ENC;
 	pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE;
 	pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE;
 
@@ -130,7 +130,7 @@ void __init kasan_init(void)
 	 */
 	memset(kasan_zero_page, 0, PAGE_SIZE);
 	for (i = 0; i < PTRS_PER_PTE; i++) {
-		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+		pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO | _PAGE_ENC);
 		set_pte(&kasan_zero_pte[i], pte);
 	}
 	/* Flush TLBs again to be sure that write protection applied. */
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
new file mode 100644
index 0000000..00eb705
--- /dev/null
+++ b/arch/x86/mm/mem_encrypt.c
@@ -0,0 +1,30 @@
+/*
+ * AMD Memory Encryption Support
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/mem_encrypt.h>
+
+void __init sme_early_init(void)
+{
+	unsigned int i;
+
+	if (!sme_me_mask)
+		return;
+
+	__supported_pte_mask |= sme_me_mask;
+
+	/* Update the protection map with memory encryption mask */
+	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
+		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
+}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 849dc09..72c292d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1973,6 +1973,9 @@ int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
 	if (!(page_flags & _PAGE_RW))
 		cpa.mask_clr = __pgprot(_PAGE_RW);
 
+	if (!(page_flags & _PAGE_ENC))
+		cpa.mask_clr = __pgprot(pgprot_val(cpa.mask_clr) | _PAGE_ENC);
+
 	cpa.mask_set = __pgprot(_PAGE_PRESENT | page_flags);
 
 	retval = __change_page_attr_set_clr(&cpa, 0);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 08/20] x86: Extend the early_memmap support with additional attrs
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add to the early_memmap support to be able to specify encrypted and
un-encrypted mappings with and without write-protection. The use of
write-protection is necessary when encrypting data "in place". The
write-protect attribute is considered cacheable for loads, but not
stores. This implies that the hardware will never give the core a
dirty line with this memtype.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/fixmap.h        |    9 +++++++++
 arch/x86/include/asm/pgtable_types.h |    8 ++++++++
 arch/x86/mm/ioremap.c                |   28 ++++++++++++++++++++++++++++
 include/asm-generic/early_ioremap.h  |    2 ++
 mm/early_ioremap.c                   |   15 +++++++++++++++
 5 files changed, 62 insertions(+)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 83e91f0..4d41878 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -160,6 +160,15 @@ static inline void __set_fixmap(enum fixed_addresses idx,
  */
 #define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
 
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size);
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size);
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index a01f0e1..50faef8 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -160,6 +160,7 @@ enum page_cache_mode {
 
 #define _PAGE_CACHE_MASK	(_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)
 #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
+#define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
 
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
@@ -188,6 +189,7 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_WP		(__PAGE_KERNEL | _PAGE_CACHE_WP)
 
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
@@ -202,6 +204,12 @@ enum page_cache_mode {
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY | _PAGE_ENC)
 
+#define __PAGE_KERNEL_ENC	(__PAGE_KERNEL | _PAGE_ENC)
+#define __PAGE_KERNEL_ENC_WP	(__PAGE_KERNEL_WP | _PAGE_ENC)
+
+#define __PAGE_KERNEL_DEC	(__PAGE_KERNEL)
+#define __PAGE_KERNEL_DEC_WP	(__PAGE_KERNEL_WP)
+
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
 #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 5cf0489..031db21 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,34 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/* Remap memory with encryption */
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC);
+}
+
+/* Remap memory with encryption and write-protected */
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC_WP);
+}
+
+/* Remap memory without encryption */
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC);
+}
+
+/* Remap memory without encryption and write-protected */
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC_WP);
+}
+
 static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 734ad4d..2edef8d 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -13,6 +13,8 @@ extern void *early_memremap(resource_size_t phys_addr,
 			    unsigned long size);
 extern void *early_memremap_ro(resource_size_t phys_addr,
 			       unsigned long size);
+extern void *early_memremap_prot(resource_size_t phys_addr,
+				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void early_memunmap(void *addr, unsigned long size);
 
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index 6d5717b..d71b98b 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -226,6 +226,14 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 }
 #endif
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (__force void *)__early_ioremap(phys_addr, size,
+					       __pgprot(prot_val));
+}
+
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
@@ -267,6 +275,13 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 	return (void *)phys_addr;
 }
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (void *)phys_addr;
+}
+
 void __init early_iounmap(void __iomem *addr, unsigned long size)
 {
 }

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 08/20] x86: Extend the early_memmap support with additional attrs
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add to the early_memmap support to be able to specify encrypted and
un-encrypted mappings with and without write-protection. The use of
write-protection is necessary when encrypting data "in place". The
write-protect attribute is considered cacheable for loads, but not
stores. This implies that the hardware will never give the core a
dirty line with this memtype.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/fixmap.h        |    9 +++++++++
 arch/x86/include/asm/pgtable_types.h |    8 ++++++++
 arch/x86/mm/ioremap.c                |   28 ++++++++++++++++++++++++++++
 include/asm-generic/early_ioremap.h  |    2 ++
 mm/early_ioremap.c                   |   15 +++++++++++++++
 5 files changed, 62 insertions(+)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 83e91f0..4d41878 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -160,6 +160,15 @@ static inline void __set_fixmap(enum fixed_addresses idx,
  */
 #define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
 
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size);
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size);
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index a01f0e1..50faef8 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -160,6 +160,7 @@ enum page_cache_mode {
 
 #define _PAGE_CACHE_MASK	(_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)
 #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
+#define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
 
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
@@ -188,6 +189,7 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_WP		(__PAGE_KERNEL | _PAGE_CACHE_WP)
 
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
@@ -202,6 +204,12 @@ enum page_cache_mode {
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY | _PAGE_ENC)
 
+#define __PAGE_KERNEL_ENC	(__PAGE_KERNEL | _PAGE_ENC)
+#define __PAGE_KERNEL_ENC_WP	(__PAGE_KERNEL_WP | _PAGE_ENC)
+
+#define __PAGE_KERNEL_DEC	(__PAGE_KERNEL)
+#define __PAGE_KERNEL_DEC_WP	(__PAGE_KERNEL_WP)
+
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
 #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 5cf0489..031db21 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,34 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/* Remap memory with encryption */
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC);
+}
+
+/* Remap memory with encryption and write-protected */
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC_WP);
+}
+
+/* Remap memory without encryption */
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC);
+}
+
+/* Remap memory without encryption and write-protected */
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC_WP);
+}
+
 static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 734ad4d..2edef8d 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -13,6 +13,8 @@ extern void *early_memremap(resource_size_t phys_addr,
 			    unsigned long size);
 extern void *early_memremap_ro(resource_size_t phys_addr,
 			       unsigned long size);
+extern void *early_memremap_prot(resource_size_t phys_addr,
+				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void early_memunmap(void *addr, unsigned long size);
 
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index 6d5717b..d71b98b 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -226,6 +226,14 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 }
 #endif
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (__force void *)__early_ioremap(phys_addr, size,
+					       __pgprot(prot_val));
+}
+
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
@@ -267,6 +275,13 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 	return (void *)phys_addr;
 }
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (void *)phys_addr;
+}
+
 void __init early_iounmap(void __iomem *addr, unsigned long size)
 {
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 08/20] x86: Extend the early_memmap support with additional attrs
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add to the early_memmap support to be able to specify encrypted and
un-encrypted mappings with and without write-protection. The use of
write-protection is necessary when encrypting data "in place". The
write-protect attribute is considered cacheable for loads, but not
stores. This implies that the hardware will never give the core a
dirty line with this memtype.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/fixmap.h        |    9 +++++++++
 arch/x86/include/asm/pgtable_types.h |    8 ++++++++
 arch/x86/mm/ioremap.c                |   28 ++++++++++++++++++++++++++++
 include/asm-generic/early_ioremap.h  |    2 ++
 mm/early_ioremap.c                   |   15 +++++++++++++++
 5 files changed, 62 insertions(+)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 83e91f0..4d41878 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -160,6 +160,15 @@ static inline void __set_fixmap(enum fixed_addresses idx,
  */
 #define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
 
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size);
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size);
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index a01f0e1..50faef8 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -160,6 +160,7 @@ enum page_cache_mode {
 
 #define _PAGE_CACHE_MASK	(_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)
 #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
+#define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
 
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
@@ -188,6 +189,7 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_WP		(__PAGE_KERNEL | _PAGE_CACHE_WP)
 
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
@@ -202,6 +204,12 @@ enum page_cache_mode {
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY | _PAGE_ENC)
 
+#define __PAGE_KERNEL_ENC	(__PAGE_KERNEL | _PAGE_ENC)
+#define __PAGE_KERNEL_ENC_WP	(__PAGE_KERNEL_WP | _PAGE_ENC)
+
+#define __PAGE_KERNEL_DEC	(__PAGE_KERNEL)
+#define __PAGE_KERNEL_DEC_WP	(__PAGE_KERNEL_WP)
+
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
 #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 5cf0489..031db21 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,34 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/* Remap memory with encryption */
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC);
+}
+
+/* Remap memory with encryption and write-protected */
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC_WP);
+}
+
+/* Remap memory without encryption */
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC);
+}
+
+/* Remap memory without encryption and write-protected */
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC_WP);
+}
+
 static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 734ad4d..2edef8d 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -13,6 +13,8 @@ extern void *early_memremap(resource_size_t phys_addr,
 			    unsigned long size);
 extern void *early_memremap_ro(resource_size_t phys_addr,
 			       unsigned long size);
+extern void *early_memremap_prot(resource_size_t phys_addr,
+				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void early_memunmap(void *addr, unsigned long size);
 
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index 6d5717b..d71b98b 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -226,6 +226,14 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 }
 #endif
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (__force void *)__early_ioremap(phys_addr, size,
+					       __pgprot(prot_val));
+}
+
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
@@ -267,6 +275,13 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 	return (void *)phys_addr;
 }
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (void *)phys_addr;
+}
+
 void __init early_iounmap(void __iomem *addr, unsigned long size)
 {
 }


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 08/20] x86: Extend the early_memmap support with additional attrs
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add to the early_memmap support to be able to specify encrypted and
un-encrypted mappings with and without write-protection. The use of
write-protection is necessary when encrypting data "in place". The
write-protect attribute is considered cacheable for loads, but not
stores. This implies that the hardware will never give the core a
dirty line with this memtype.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/fixmap.h        |    9 +++++++++
 arch/x86/include/asm/pgtable_types.h |    8 ++++++++
 arch/x86/mm/ioremap.c                |   28 ++++++++++++++++++++++++++++
 include/asm-generic/early_ioremap.h  |    2 ++
 mm/early_ioremap.c                   |   15 +++++++++++++++
 5 files changed, 62 insertions(+)

diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
index 83e91f0..4d41878 100644
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -160,6 +160,15 @@ static inline void __set_fixmap(enum fixed_addresses idx,
  */
 #define FIXMAP_PAGE_NOCACHE PAGE_KERNEL_IO_NOCACHE
 
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size);
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size);
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size);
+
 #include <asm-generic/fixmap.h>
 
 #define __late_set_fixmap(idx, phys, flags) __set_fixmap(idx, phys, flags)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index a01f0e1..50faef8 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -160,6 +160,7 @@ enum page_cache_mode {
 
 #define _PAGE_CACHE_MASK	(_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)
 #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
+#define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
 
 #define PAGE_NONE	__pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \
@@ -188,6 +189,7 @@ enum page_cache_mode {
 #define __PAGE_KERNEL_VVAR		(__PAGE_KERNEL_RO | _PAGE_USER)
 #define __PAGE_KERNEL_LARGE		(__PAGE_KERNEL | _PAGE_PSE)
 #define __PAGE_KERNEL_LARGE_EXEC	(__PAGE_KERNEL_EXEC | _PAGE_PSE)
+#define __PAGE_KERNEL_WP		(__PAGE_KERNEL | _PAGE_CACHE_WP)
 
 #define __PAGE_KERNEL_IO		(__PAGE_KERNEL)
 #define __PAGE_KERNEL_IO_NOCACHE	(__PAGE_KERNEL_NOCACHE)
@@ -202,6 +204,12 @@ enum page_cache_mode {
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED |	\
 			 _PAGE_DIRTY | _PAGE_ENC)
 
+#define __PAGE_KERNEL_ENC	(__PAGE_KERNEL | _PAGE_ENC)
+#define __PAGE_KERNEL_ENC_WP	(__PAGE_KERNEL_WP | _PAGE_ENC)
+
+#define __PAGE_KERNEL_DEC	(__PAGE_KERNEL)
+#define __PAGE_KERNEL_DEC_WP	(__PAGE_KERNEL_WP)
+
 #define PAGE_KERNEL		__pgprot(__PAGE_KERNEL | _PAGE_ENC)
 #define PAGE_KERNEL_RO		__pgprot(__PAGE_KERNEL_RO | _PAGE_ENC)
 #define PAGE_KERNEL_EXEC	__pgprot(__PAGE_KERNEL_EXEC | _PAGE_ENC)
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 5cf0489..031db21 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,34 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/* Remap memory with encryption */
+void __init *early_memremap_enc(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC);
+}
+
+/* Remap memory with encryption and write-protected */
+void __init *early_memremap_enc_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC_WP);
+}
+
+/* Remap memory without encryption */
+void __init *early_memremap_dec(resource_size_t phys_addr,
+				unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC);
+}
+
+/* Remap memory without encryption and write-protected */
+void __init *early_memremap_dec_wp(resource_size_t phys_addr,
+				   unsigned long size)
+{
+	return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_DEC_WP);
+}
+
 static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss;
 
 static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 734ad4d..2edef8d 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -13,6 +13,8 @@ extern void *early_memremap(resource_size_t phys_addr,
 			    unsigned long size);
 extern void *early_memremap_ro(resource_size_t phys_addr,
 			       unsigned long size);
+extern void *early_memremap_prot(resource_size_t phys_addr,
+				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
 extern void early_memunmap(void *addr, unsigned long size);
 
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index 6d5717b..d71b98b 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -226,6 +226,14 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 }
 #endif
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (__force void *)__early_ioremap(phys_addr, size,
+					       __pgprot(prot_val));
+}
+
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
@@ -267,6 +275,13 @@ early_memremap_ro(resource_size_t phys_addr, unsigned long size)
 	return (void *)phys_addr;
 }
 
+void __init *
+early_memremap_prot(resource_size_t phys_addr, unsigned long size,
+		    unsigned long prot_val)
+{
+	return (void *)phys_addr;
+}
+
 void __init early_iounmap(void __iomem *addr, unsigned long size)
 {
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This adds support to be able to either encrypt or decrypt data during
the early stages of booting the kernel. This does not change the memory
encryption attribute - it is used for ensuring that data present in
either an encrypted or un-encrypted memory area is in the proper state
(for example the initrd will have been loaded by the boot loader and
will not be encrypted, but the memory that it resides in is marked as
encrypted).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   15 +++++
 arch/x86/mm/mem_encrypt.c          |  101 ++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 9f3e762..2785493 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,11 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_mem_enc(resource_size_t paddr,
+			      unsigned long size);
+void __init sme_early_mem_dec(resource_size_t paddr,
+			      unsigned long size);
+
 void __init sme_early_init(void);
 
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
@@ -39,6 +44,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_mem_enc(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
+static inline void __init sme_early_mem_dec(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
 static inline void __init sme_early_init(void)
 {
 }
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 00eb705..f35a646 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,6 +14,107 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+/* Buffer used for early in-place encryption by BSP, no locking needed */
+static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as encrypted but the contents are currently not
+ * encyrpted.
+ */
+void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for non-encrypted write-protected memory */
+		src = early_memremap_dec_wp(paddr, len);
+
+		/* Create a mapping for encrypted memory */
+		dst = early_memremap_enc(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the encryption,
+		 * then encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as not encrypted but the contents are currently
+ * encyrpted.
+ */
+void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for encrypted write-protected memory */
+		src = early_memremap_enc_wp(paddr, len);
+
+		/* Create a mapping for non-encrypted memory */
+		dst = early_memremap_dec(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the decryption,
+		 * then un-encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
 
 void __init sme_early_init(void)
 {

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This adds support to be able to either encrypt or decrypt data during
the early stages of booting the kernel. This does not change the memory
encryption attribute - it is used for ensuring that data present in
either an encrypted or un-encrypted memory area is in the proper state
(for example the initrd will have been loaded by the boot loader and
will not be encrypted, but the memory that it resides in is marked as
encrypted).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   15 +++++
 arch/x86/mm/mem_encrypt.c          |  101 ++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 9f3e762..2785493 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,11 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_mem_enc(resource_size_t paddr,
+			      unsigned long size);
+void __init sme_early_mem_dec(resource_size_t paddr,
+			      unsigned long size);
+
 void __init sme_early_init(void);
 
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
@@ -39,6 +44,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_mem_enc(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
+static inline void __init sme_early_mem_dec(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
 static inline void __init sme_early_init(void)
 {
 }
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 00eb705..f35a646 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,6 +14,107 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+/* Buffer used for early in-place encryption by BSP, no locking needed */
+static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as encrypted but the contents are currently not
+ * encyrpted.
+ */
+void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for non-encrypted write-protected memory */
+		src = early_memremap_dec_wp(paddr, len);
+
+		/* Create a mapping for encrypted memory */
+		dst = early_memremap_enc(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the encryption,
+		 * then encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as not encrypted but the contents are currently
+ * encyrpted.
+ */
+void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for encrypted write-protected memory */
+		src = early_memremap_enc_wp(paddr, len);
+
+		/* Create a mapping for non-encrypted memory */
+		dst = early_memremap_dec(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the decryption,
+		 * then un-encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
 
 void __init sme_early_init(void)
 {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This adds support to be able to either encrypt or decrypt data during
the early stages of booting the kernel. This does not change the memory
encryption attribute - it is used for ensuring that data present in
either an encrypted or un-encrypted memory area is in the proper state
(for example the initrd will have been loaded by the boot loader and
will not be encrypted, but the memory that it resides in is marked as
encrypted).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   15 +++++
 arch/x86/mm/mem_encrypt.c          |  101 ++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 9f3e762..2785493 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,11 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_mem_enc(resource_size_t paddr,
+			      unsigned long size);
+void __init sme_early_mem_dec(resource_size_t paddr,
+			      unsigned long size);
+
 void __init sme_early_init(void);
 
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
@@ -39,6 +44,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_mem_enc(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
+static inline void __init sme_early_mem_dec(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
 static inline void __init sme_early_init(void)
 {
 }
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 00eb705..f35a646 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,6 +14,107 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+/* Buffer used for early in-place encryption by BSP, no locking needed */
+static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as encrypted but the contents are currently not
+ * encyrpted.
+ */
+void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for non-encrypted write-protected memory */
+		src = early_memremap_dec_wp(paddr, len);
+
+		/* Create a mapping for encrypted memory */
+		dst = early_memremap_enc(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the encryption,
+		 * then encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as not encrypted but the contents are currently
+ * encyrpted.
+ */
+void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for encrypted write-protected memory */
+		src = early_memremap_enc_wp(paddr, len);
+
+		/* Create a mapping for non-encrypted memory */
+		dst = early_memremap_dec(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the decryption,
+		 * then un-encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
 
 void __init sme_early_init(void)
 {


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This adds support to be able to either encrypt or decrypt data during
the early stages of booting the kernel. This does not change the memory
encryption attribute - it is used for ensuring that data present in
either an encrypted or un-encrypted memory area is in the proper state
(for example the initrd will have been loaded by the boot loader and
will not be encrypted, but the memory that it resides in is marked as
encrypted).

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |   15 +++++
 arch/x86/mm/mem_encrypt.c          |  101 ++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 9f3e762..2785493 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,11 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+void __init sme_early_mem_enc(resource_size_t paddr,
+			      unsigned long size);
+void __init sme_early_mem_dec(resource_size_t paddr,
+			      unsigned long size);
+
 void __init sme_early_init(void);
 
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
@@ -39,6 +44,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline void __init sme_early_mem_enc(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
+static inline void __init sme_early_mem_dec(resource_size_t paddr,
+					    unsigned long size)
+{
+}
+
 static inline void __init sme_early_init(void)
 {
 }
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 00eb705..f35a646 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,6 +14,107 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/tlbflush.h>
+#include <asm/fixmap.h>
+
+/* Buffer used for early in-place encryption by BSP, no locking needed */
+static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as encrypted but the contents are currently not
+ * encyrpted.
+ */
+void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for non-encrypted write-protected memory */
+		src = early_memremap_dec_wp(paddr, len);
+
+		/* Create a mapping for encrypted memory */
+		dst = early_memremap_enc(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the encryption,
+		 * then encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
+
+/*
+ * This routine does not change the underlying encryption setting of the
+ * page(s) that map this memory. It assumes that eventually the memory is
+ * meant to be accessed as not encrypted but the contents are currently
+ * encyrpted.
+ */
+void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
+{
+	void *src, *dst;
+	size_t len;
+
+	if (!sme_me_mask)
+		return;
+
+	local_flush_tlb();
+	wbinvd();
+
+	/*
+	 * There are limited number of early mapping slots, so map (at most)
+	 * one page at time.
+	 */
+	while (size) {
+		len = min_t(size_t, sizeof(me_early_buffer), size);
+
+		/* Create a mapping for encrypted write-protected memory */
+		src = early_memremap_enc_wp(paddr, len);
+
+		/* Create a mapping for non-encrypted memory */
+		dst = early_memremap_dec(paddr, len);
+
+		/*
+		 * If a mapping can't be obtained to perform the decryption,
+		 * then un-encrypted access to that area will end up causing
+		 * a crash.
+		 */
+		BUG_ON(!src || !dst);
+
+		memcpy(me_early_buffer, src, len);
+		memcpy(dst, me_early_buffer, len);
+
+		early_memunmap(dst, len);
+		early_memunmap(src, len);
+
+		paddr += len;
+		size -= len;
+	}
+}
 
 void __init sme_early_init(void)
 {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Encrypt memory areas in place when possible (e.g. zero page, etc.) so
that special handling isn't needed afterwards.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/setup.c  |    8 ++++
 2 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 88c7bae..358d7bc 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -47,12 +47,12 @@ static void __init reset_early_page_tables(void)
 }
 
 /* Create a new PMD entry */
-int __init early_make_pgtable(unsigned long address)
+static int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 {
 	unsigned long physaddr = address - __PAGE_OFFSET;
 	pgdval_t pgd, *pgd_p;
 	pudval_t pud, *pud_p;
-	pmdval_t pmd, *pmd_p;
+	pmdval_t *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
 	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
@@ -94,12 +94,95 @@ again:
 		memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
 		*pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
 	}
-	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
 	pmd_p[pmd_index(address)] = pmd;
 
 	return 0;
 }
 
+int __init early_make_pgtable(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pmdval_t pmd;
+
+	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
+
+	return __early_make_pgtable(address, pmd);
+}
+
+static void __init create_unencrypted_mapping(void *address, unsigned long size)
+{
+	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
+	pmdval_t pmd_flags, pmd;
+
+	if (!sme_me_mask)
+		return;
+
+	/* Clear the encryption mask from the early_pmd_flags */
+	pmd_flags = early_pmd_flags & ~sme_me_mask;
+
+	do {
+		pmd = (physaddr & PMD_MASK) + pmd_flags;
+		__early_make_pgtable((unsigned long)address, pmd);
+
+		address += PMD_SIZE;
+		physaddr += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init __clear_mapping(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pgdval_t pgd, *pgd_p;
+	pudval_t pud, *pud_p;
+	pmdval_t *pmd_p;
+
+	/* Invalid address or early pgt is done ?  */
+	if (physaddr >= MAXMEM ||
+	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
+		return;
+
+	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
+	pgd = *pgd_p;
+
+	if (!pgd)
+		return;
+
+	/*
+	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
+	 * __early_make_pgtable where the entry was created.
+	 */
+	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pud_p += pud_index(address);
+	pud = *pud_p;
+
+	if (!pud)
+		return;
+
+	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pmd_p[pmd_index(address)] = 0;
+}
+
+static void __init clear_mapping(void *address, unsigned long size)
+{
+	if (!sme_me_mask)
+		return;
+
+	do {
+		__clear_mapping((unsigned long)address);
+
+		address += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init sme_memcpy(void *dst, void *src, unsigned long size)
+{
+	create_unencrypted_mapping(src, size);
+	memcpy(dst, src, size);
+	clear_mapping(src, size);
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
 	char * command_line;
 	unsigned long cmd_line_ptr;
 
-	memcpy(&boot_params, real_mode_data, sizeof boot_params);
+	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
 	sanitize_boot_params(&boot_params);
 	cmd_line_ptr = get_cmd_line_ptr();
 	if (cmd_line_ptr) {
 		command_line = __va(cmd_line_ptr);
-		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	}
 }
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1489da8..1fdaa11 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -114,6 +114,7 @@
 #include <asm/microcode.h>
 #include <asm/mmu_context.h>
 #include <asm/kaslr.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * max_low_pfn_mapped: highest direct mapped pfn under 4GB
@@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
 	    !ramdisk_image || !ramdisk_size)
 		return;		/* No initrd provided by bootloader */
 
+	/*
+	 * This memory is marked encrypted by the kernel but the ramdisk
+	 * was loaded in the clear by the bootloader, so make sure that
+	 * the ramdisk image is encrypted.
+	 */
+	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
+
 	initrd_start = 0;
 
 	mapped_size = memblock_mem_size(max_pfn_mapped);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Encrypt memory areas in place when possible (e.g. zero page, etc.) so
that special handling isn't needed afterwards.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/setup.c  |    8 ++++
 2 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 88c7bae..358d7bc 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -47,12 +47,12 @@ static void __init reset_early_page_tables(void)
 }
 
 /* Create a new PMD entry */
-int __init early_make_pgtable(unsigned long address)
+static int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 {
 	unsigned long physaddr = address - __PAGE_OFFSET;
 	pgdval_t pgd, *pgd_p;
 	pudval_t pud, *pud_p;
-	pmdval_t pmd, *pmd_p;
+	pmdval_t *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
 	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
@@ -94,12 +94,95 @@ again:
 		memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
 		*pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
 	}
-	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
 	pmd_p[pmd_index(address)] = pmd;
 
 	return 0;
 }
 
+int __init early_make_pgtable(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pmdval_t pmd;
+
+	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
+
+	return __early_make_pgtable(address, pmd);
+}
+
+static void __init create_unencrypted_mapping(void *address, unsigned long size)
+{
+	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
+	pmdval_t pmd_flags, pmd;
+
+	if (!sme_me_mask)
+		return;
+
+	/* Clear the encryption mask from the early_pmd_flags */
+	pmd_flags = early_pmd_flags & ~sme_me_mask;
+
+	do {
+		pmd = (physaddr & PMD_MASK) + pmd_flags;
+		__early_make_pgtable((unsigned long)address, pmd);
+
+		address += PMD_SIZE;
+		physaddr += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init __clear_mapping(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pgdval_t pgd, *pgd_p;
+	pudval_t pud, *pud_p;
+	pmdval_t *pmd_p;
+
+	/* Invalid address or early pgt is done ?  */
+	if (physaddr >= MAXMEM ||
+	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
+		return;
+
+	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
+	pgd = *pgd_p;
+
+	if (!pgd)
+		return;
+
+	/*
+	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
+	 * __early_make_pgtable where the entry was created.
+	 */
+	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pud_p += pud_index(address);
+	pud = *pud_p;
+
+	if (!pud)
+		return;
+
+	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pmd_p[pmd_index(address)] = 0;
+}
+
+static void __init clear_mapping(void *address, unsigned long size)
+{
+	if (!sme_me_mask)
+		return;
+
+	do {
+		__clear_mapping((unsigned long)address);
+
+		address += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init sme_memcpy(void *dst, void *src, unsigned long size)
+{
+	create_unencrypted_mapping(src, size);
+	memcpy(dst, src, size);
+	clear_mapping(src, size);
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
 	char * command_line;
 	unsigned long cmd_line_ptr;
 
-	memcpy(&boot_params, real_mode_data, sizeof boot_params);
+	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
 	sanitize_boot_params(&boot_params);
 	cmd_line_ptr = get_cmd_line_ptr();
 	if (cmd_line_ptr) {
 		command_line = __va(cmd_line_ptr);
-		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	}
 }
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1489da8..1fdaa11 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -114,6 +114,7 @@
 #include <asm/microcode.h>
 #include <asm/mmu_context.h>
 #include <asm/kaslr.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * max_low_pfn_mapped: highest direct mapped pfn under 4GB
@@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
 	    !ramdisk_image || !ramdisk_size)
 		return;		/* No initrd provided by bootloader */
 
+	/*
+	 * This memory is marked encrypted by the kernel but the ramdisk
+	 * was loaded in the clear by the bootloader, so make sure that
+	 * the ramdisk image is encrypted.
+	 */
+	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
+
 	initrd_start = 0;
 
 	mapped_size = memblock_mem_size(max_pfn_mapped);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Encrypt memory areas in place when possible (e.g. zero page, etc.) so
that special handling isn't needed afterwards.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/setup.c  |    8 ++++
 2 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 88c7bae..358d7bc 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -47,12 +47,12 @@ static void __init reset_early_page_tables(void)
 }
 
 /* Create a new PMD entry */
-int __init early_make_pgtable(unsigned long address)
+static int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 {
 	unsigned long physaddr = address - __PAGE_OFFSET;
 	pgdval_t pgd, *pgd_p;
 	pudval_t pud, *pud_p;
-	pmdval_t pmd, *pmd_p;
+	pmdval_t *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
 	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
@@ -94,12 +94,95 @@ again:
 		memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
 		*pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
 	}
-	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
 	pmd_p[pmd_index(address)] = pmd;
 
 	return 0;
 }
 
+int __init early_make_pgtable(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pmdval_t pmd;
+
+	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
+
+	return __early_make_pgtable(address, pmd);
+}
+
+static void __init create_unencrypted_mapping(void *address, unsigned long size)
+{
+	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
+	pmdval_t pmd_flags, pmd;
+
+	if (!sme_me_mask)
+		return;
+
+	/* Clear the encryption mask from the early_pmd_flags */
+	pmd_flags = early_pmd_flags & ~sme_me_mask;
+
+	do {
+		pmd = (physaddr & PMD_MASK) + pmd_flags;
+		__early_make_pgtable((unsigned long)address, pmd);
+
+		address += PMD_SIZE;
+		physaddr += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init __clear_mapping(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pgdval_t pgd, *pgd_p;
+	pudval_t pud, *pud_p;
+	pmdval_t *pmd_p;
+
+	/* Invalid address or early pgt is done ?  */
+	if (physaddr >= MAXMEM ||
+	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
+		return;
+
+	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
+	pgd = *pgd_p;
+
+	if (!pgd)
+		return;
+
+	/*
+	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
+	 * __early_make_pgtable where the entry was created.
+	 */
+	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pud_p += pud_index(address);
+	pud = *pud_p;
+
+	if (!pud)
+		return;
+
+	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pmd_p[pmd_index(address)] = 0;
+}
+
+static void __init clear_mapping(void *address, unsigned long size)
+{
+	if (!sme_me_mask)
+		return;
+
+	do {
+		__clear_mapping((unsigned long)address);
+
+		address += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init sme_memcpy(void *dst, void *src, unsigned long size)
+{
+	create_unencrypted_mapping(src, size);
+	memcpy(dst, src, size);
+	clear_mapping(src, size);
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
 	char * command_line;
 	unsigned long cmd_line_ptr;
 
-	memcpy(&boot_params, real_mode_data, sizeof boot_params);
+	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
 	sanitize_boot_params(&boot_params);
 	cmd_line_ptr = get_cmd_line_ptr();
 	if (cmd_line_ptr) {
 		command_line = __va(cmd_line_ptr);
-		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	}
 }
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1489da8..1fdaa11 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -114,6 +114,7 @@
 #include <asm/microcode.h>
 #include <asm/mmu_context.h>
 #include <asm/kaslr.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * max_low_pfn_mapped: highest direct mapped pfn under 4GB
@@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
 	    !ramdisk_image || !ramdisk_size)
 		return;		/* No initrd provided by bootloader */
 
+	/*
+	 * This memory is marked encrypted by the kernel but the ramdisk
+	 * was loaded in the clear by the bootloader, so make sure that
+	 * the ramdisk image is encrypted.
+	 */
+	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
+
 	initrd_start = 0;
 
 	mapped_size = memblock_mem_size(max_pfn_mapped);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Encrypt memory areas in place when possible (e.g. zero page, etc.) so
that special handling isn't needed afterwards.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/setup.c  |    8 ++++
 2 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 88c7bae..358d7bc 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -47,12 +47,12 @@ static void __init reset_early_page_tables(void)
 }
 
 /* Create a new PMD entry */
-int __init early_make_pgtable(unsigned long address)
+static int __init __early_make_pgtable(unsigned long address, pmdval_t pmd)
 {
 	unsigned long physaddr = address - __PAGE_OFFSET;
 	pgdval_t pgd, *pgd_p;
 	pudval_t pud, *pud_p;
-	pmdval_t pmd, *pmd_p;
+	pmdval_t *pmd_p;
 
 	/* Invalid address or early pgt is done ?  */
 	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
@@ -94,12 +94,95 @@ again:
 		memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
 		*pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
 	}
-	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
 	pmd_p[pmd_index(address)] = pmd;
 
 	return 0;
 }
 
+int __init early_make_pgtable(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pmdval_t pmd;
+
+	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
+
+	return __early_make_pgtable(address, pmd);
+}
+
+static void __init create_unencrypted_mapping(void *address, unsigned long size)
+{
+	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
+	pmdval_t pmd_flags, pmd;
+
+	if (!sme_me_mask)
+		return;
+
+	/* Clear the encryption mask from the early_pmd_flags */
+	pmd_flags = early_pmd_flags & ~sme_me_mask;
+
+	do {
+		pmd = (physaddr & PMD_MASK) + pmd_flags;
+		__early_make_pgtable((unsigned long)address, pmd);
+
+		address += PMD_SIZE;
+		physaddr += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init __clear_mapping(unsigned long address)
+{
+	unsigned long physaddr = address - __PAGE_OFFSET;
+	pgdval_t pgd, *pgd_p;
+	pudval_t pud, *pud_p;
+	pmdval_t *pmd_p;
+
+	/* Invalid address or early pgt is done ?  */
+	if (physaddr >= MAXMEM ||
+	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
+		return;
+
+	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
+	pgd = *pgd_p;
+
+	if (!pgd)
+		return;
+
+	/*
+	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
+	 * __early_make_pgtable where the entry was created.
+	 */
+	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pud_p += pud_index(address);
+	pud = *pud_p;
+
+	if (!pud)
+		return;
+
+	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
+	pmd_p[pmd_index(address)] = 0;
+}
+
+static void __init clear_mapping(void *address, unsigned long size)
+{
+	if (!sme_me_mask)
+		return;
+
+	do {
+		__clear_mapping((unsigned long)address);
+
+		address += PMD_SIZE;
+		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
+	} while (size);
+}
+
+static void __init sme_memcpy(void *dst, void *src, unsigned long size)
+{
+	create_unencrypted_mapping(src, size);
+	memcpy(dst, src, size);
+	clear_mapping(src, size);
+}
+
 /* Don't add a printk in there. printk relies on the PDA which is not initialized 
    yet. */
 static void __init clear_bss(void)
@@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
 	char * command_line;
 	unsigned long cmd_line_ptr;
 
-	memcpy(&boot_params, real_mode_data, sizeof boot_params);
+	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
 	sanitize_boot_params(&boot_params);
 	cmd_line_ptr = get_cmd_line_ptr();
 	if (cmd_line_ptr) {
 		command_line = __va(cmd_line_ptr);
-		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	}
 }
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1489da8..1fdaa11 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -114,6 +114,7 @@
 #include <asm/microcode.h>
 #include <asm/mmu_context.h>
 #include <asm/kaslr.h>
+#include <asm/mem_encrypt.h>
 
 /*
  * max_low_pfn_mapped: highest direct mapped pfn under 4GB
@@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
 	    !ramdisk_image || !ramdisk_size)
 		return;		/* No initrd provided by bootloader */
 
+	/*
+	 * This memory is marked encrypted by the kernel but the ramdisk
+	 * was loaded in the clear by the bootloader, so make sure that
+	 * the ramdisk image is encrypted.
+	 */
+	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
+
 	initrd_start = 0;
 
 	mapped_size = memblock_mem_size(max_pfn_mapped);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

BOOT data (such as EFI related data) is not encyrpted when the system is
booted and needs to be accessed as non-encrypted.  Add support to the
early_memremap API to identify the type of data being accessed so that
the proper encryption attribute can be applied.  Currently, two types
of data are defined, KERNEL_DATA and BOOT_DATA.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/arm64/kernel/acpi.c              |    2 +-
 arch/ia64/include/asm/early_ioremap.h |    2 +-
 arch/x86/kernel/devicetree.c          |    6 ++++--
 arch/x86/kernel/e820.c                |    2 +-
 arch/x86/kernel/setup.c               |    9 +++++---
 arch/x86/mm/ioremap.c                 |   19 +++++++++++++++++
 arch/x86/platform/efi/efi.c           |   15 +++++++-------
 arch/x86/platform/efi/efi_64.c        |   13 +++++++++---
 arch/x86/platform/efi/quirks.c        |    4 ++--
 arch/x86/xen/mmu.c                    |    9 +++++---
 arch/x86/xen/setup.c                  |    6 ++++--
 drivers/acpi/tables.c                 |    2 +-
 drivers/firmware/efi/arm-init.c       |   13 +++++++-----
 drivers/firmware/efi/efi.c            |    7 ++++--
 drivers/firmware/efi/esrt.c           |    4 ++--
 drivers/firmware/efi/fake_mem.c       |    3 ++-
 drivers/firmware/efi/memattr.c        |    2 +-
 include/asm-generic/early_ioremap.h   |   15 +++++++++++---
 mm/early_ioremap.c                    |   36 +++++++++++++++++++++++++--------
 19 files changed, 117 insertions(+), 52 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3e4f1a4..33fdedd 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -98,7 +98,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 	if (!size)
 		return NULL;
 
-	return early_memremap(phys, size);
+	return early_memremap(phys, size, BOOT_DATA);
 }
 
 void __init __acpi_unmap_table(char *map, unsigned long size)
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
index eec9e1d..bc8c210 100644
--- a/arch/ia64/include/asm/early_ioremap.h
+++ b/arch/ia64/include/asm/early_ioremap.h
@@ -2,7 +2,7 @@
 #define _ASM_IA64_EARLY_IOREMAP_H
 
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
+#define early_memremap(phys_addr, size, owner) early_ioremap(phys_addr, size)
 
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 #define early_memunmap(addr, size)             early_iounmap(addr, size)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3fe45f8..556e986 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -276,11 +276,13 @@ static void __init x86_flattree_get_config(void)
 
 	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
 
-	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+	initial_boot_params = dt = early_memremap(initial_dtb, map_len,
+						  BOOT_DATA);
 	size = of_get_flat_dt_size();
 	if (map_len < size) {
 		early_memunmap(dt, map_len);
-		initial_boot_params = dt = early_memremap(initial_dtb, size);
+		initial_boot_params = dt = early_memremap(initial_dtb, size,
+							  BOOT_DATA);
 		map_len = size;
 	}
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 621b501..71b237f 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -661,7 +661,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
 	struct e820entry *extmap;
 	struct setup_data *sdata;
 
-	sdata = early_memremap(phys_addr, data_len);
+	sdata = early_memremap(phys_addr, data_len, BOOT_DATA);
 	entries = sdata->len / sizeof(struct e820entry);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1fdaa11..cec8a63 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -344,7 +344,8 @@ static void __init relocate_initrd(void)
 	printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
 	       relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 
-	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
+	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size,
+			    BOOT_DATA);
 
 	printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
 		" [mem %#010llx-%#010llx]\n",
@@ -426,7 +427,7 @@ static void __init parse_setup_data(void)
 	while (pa_data) {
 		u32 data_len, data_type;
 
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		data_len = data->len + sizeof(struct setup_data);
 		data_type = data->type;
 		pa_next = data->next;
@@ -459,7 +460,7 @@ static void __init e820_reserve_setup_data(void)
 		return;
 
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		e820_update_range(pa_data, sizeof(*data)+data->len,
 			 E820_RAM, E820_RESERVED_KERN);
 		pa_data = data->next;
@@ -479,7 +480,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		memblock_reserve(pa_data, sizeof(*data) + data->len);
 		pa_data = data->next;
 		early_memunmap(data, sizeof(*data));
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 031db21..e3bdc5a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/*
+ * Architecure override of __weak function to adjust the protection attributes
+ * used when remapping memory.
+ */
+pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
+					     unsigned long size,
+					     enum memremap_owner owner,
+					     pgprot_t prot)
+{
+	/*
+	 * If memory encryption is enabled and BOOT_DATA is being mapped
+	 * then remove the encryption bit.
+	 */
+	if (_PAGE_ENC && (owner == BOOT_DATA))
+		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
+
+	return prot;
+}
+
 /* Remap memory with encryption */
 void __init *early_memremap_enc(resource_size_t phys_addr,
 				unsigned long size)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1fbb408..2c7e6b0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -239,12 +239,13 @@ static int __init efi_systab_init(void *phys)
 		u64 tmp = 0;
 
 		if (efi_setup) {
-			data = early_memremap(efi_setup, sizeof(*data));
+			data = early_memremap(efi_setup, sizeof(*data),
+					      BOOT_DATA);
 			if (!data)
 				return -ENOMEM;
 		}
 		systab64 = early_memremap((unsigned long)phys,
-					 sizeof(*systab64));
+					  sizeof(*systab64), BOOT_DATA);
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
@@ -293,7 +294,7 @@ static int __init efi_systab_init(void *phys)
 		efi_system_table_32_t *systab32;
 
 		systab32 = early_memremap((unsigned long)phys,
-					 sizeof(*systab32));
+					  sizeof(*systab32), BOOT_DATA);
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			return -ENOMEM;
@@ -338,7 +339,7 @@ static int __init efi_runtime_init32(void)
 	efi_runtime_services_32_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_32_t));
+				 sizeof(efi_runtime_services_32_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -362,7 +363,7 @@ static int __init efi_runtime_init64(void)
 	efi_runtime_services_64_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_64_t));
+				 sizeof(efi_runtime_services_64_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -425,7 +426,7 @@ static int __init efi_memmap_init(void)
 	size = efi.memmap.nr_map * efi.memmap.desc_size;
 	addr = (unsigned long)efi.memmap.phys_map;
 
-	efi.memmap.map = early_memremap(addr, size);
+	efi.memmap.map = early_memremap(addr, size, BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
 		return -ENOMEM;
@@ -471,7 +472,7 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2, BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 677e29e..0871ea4 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -222,7 +222,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return 0;
 
-	efi_scratch.efi_pgt = (pgd_t *)__pa(efi_pgd);
+	/*
+	 * Since the PGD is encrypted, set the encryption mask so that when
+	 * this value is loaded into cr3 the PGD will be decrypted during
+	 * the pagetable walk.
+	 */
+	efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
 	pgd = efi_pgd;
 
 	/*
@@ -261,7 +266,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 		pfn = md->phys_addr >> PAGE_SHIFT;
 		npages = md->num_pages;
 
-		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, _PAGE_RW)) {
+		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages,
+					    _PAGE_RW | _PAGE_ENC)) {
 			pr_err("Failed to map 1:1 memory\n");
 			return 1;
 		}
@@ -278,7 +284,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	text = __pa(_text);
 	pfn = text >> PAGE_SHIFT;
 
-	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, _PAGE_RW)) {
+	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages,
+				    _PAGE_RW | _PAGE_ENC)) {
 		pr_err("Failed to map kernel text 1:1\n");
 		return 1;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 89d1146..606bf551 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -311,7 +311,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 	if (!efi_enabled(EFI_64BIT))
 		return 0;
 
-	data = early_memremap(efi_setup, sizeof(*data));
+	data = early_memremap(efi_setup, sizeof(*data), BOOT_DATA);
 	if (!data) {
 		ret = -ENOMEM;
 		goto out;
@@ -322,7 +322,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 
 	sz = sizeof(efi_config_table_64_t);
 
-	p = tablep = early_memremap(tables, nr_tables * sz);
+	p = tablep = early_memremap(tables, nr_tables * sz, BOOT_DATA);
 	if (!p) {
 		pr_err("Could not map Configuration table!\n");
 		ret = -ENOMEM;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 7d5afdb..00db54a 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2020,7 +2020,7 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 	unsigned long *vaddr;
 	unsigned long val;
 
-	vaddr = early_memremap_ro(addr, sizeof(val));
+	vaddr = early_memremap_ro(addr, sizeof(val), KERNEL_DATA);
 	val = *vaddr;
 	early_memunmap(vaddr, sizeof(val));
 	return val;
@@ -2114,15 +2114,16 @@ void __init xen_relocate_p2m(void)
 	pgd = __va(read_cr3());
 	new_p2m = (unsigned long *)(2 * PGDIR_SIZE);
 	for (idx_pud = 0; idx_pud < n_pud; idx_pud++) {
-		pud = early_memremap(pud_phys, PAGE_SIZE);
+		pud = early_memremap(pud_phys, PAGE_SIZE, KERNEL_DATA);
 		clear_page(pud);
 		for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD);
 		     idx_pmd++) {
-			pmd = early_memremap(pmd_phys, PAGE_SIZE);
+			pmd = early_memremap(pmd_phys, PAGE_SIZE, KERNEL_DATA);
 			clear_page(pmd);
 			for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD);
 			     idx_pt++) {
-				pt = early_memremap(pt_phys, PAGE_SIZE);
+				pt = early_memremap(pt_phys, PAGE_SIZE,
+						    KERNEL_DATA);
 				clear_page(pt);
 				for (idx_pte = 0;
 				     idx_pte < min(n_pte, PTRS_PER_PTE);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 1764252..a8e2724 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -686,8 +686,10 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src,
 		if (src_len > (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off)
 			src_len = (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off;
 		len = min(dest_len, src_len);
-		to = early_memremap(dest - dest_off, dest_len + dest_off);
-		from = early_memremap(src - src_off, src_len + src_off);
+		to = early_memremap(dest - dest_off, dest_len + dest_off,
+				    KERNEL_DATA);
+		from = early_memremap(src - src_off, src_len + src_off,
+				      KERNEL_DATA);
 		memcpy(to, from, len);
 		early_memunmap(to, dest_len + dest_off);
 		early_memunmap(from, src_len + src_off);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 9f0ad6e..06b75a2 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -583,7 +583,7 @@ void __init acpi_table_upgrade(void)
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
 			dest_p = early_memremap(dest_addr & PAGE_MASK,
-						clen + slop);
+						clen + slop, BOOT_DATA);
 			memcpy(dest_p + slop, src_p, clen);
 			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index c49d50e..0a3fd48 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -67,7 +67,8 @@ static void __init init_screen_info(void)
 	struct screen_info *si;
 
 	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
-		si = early_memremap_ro(screen_info_table, sizeof(*si));
+		si = early_memremap_ro(screen_info_table, sizeof(*si),
+				       BOOT_DATA);
 		if (!si) {
 			pr_err("Could not map screen_info config table\n");
 			return;
@@ -94,7 +95,7 @@ static int __init uefi_init(void)
 	int i, retval;
 
 	efi.systab = early_memremap_ro(efi_system_table,
-				       sizeof(efi_system_table_t));
+				       sizeof(efi_system_table_t), BOOT_DATA);
 	if (efi.systab == NULL) {
 		pr_warn("Unable to map EFI system table.\n");
 		return -ENOMEM;
@@ -121,7 +122,8 @@ static int __init uefi_init(void)
 
 	/* Show what we know for posterity */
 	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
-				sizeof(vendor) * sizeof(efi_char16_t));
+				sizeof(vendor) * sizeof(efi_char16_t),
+				BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = c16[i];
@@ -135,7 +137,7 @@ static int __init uefi_init(void)
 
 	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
 	config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
-					  table_size);
+					  table_size, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_warn("Unable to map EFI config table array.\n");
 		retval = -ENOMEM;
@@ -226,7 +228,8 @@ void __init efi_init(void)
 	efi_system_table = params.system_table;
 
 	efi.memmap.phys_map = params.mmap;
-	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
+	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size,
+					   BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631a..f9286c6 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 		 * So just always get our own virtual map on the CPU.
 		 *
 		 */
-		md = early_memremap(p, sizeof (*md));
+		md = early_memremap(p, sizeof (*md), BOOT_DATA);
 		if (!md) {
 			pr_err_once("early_memremap(%pa, %zu) failed.\n",
 				    &p, sizeof (*md));
@@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
 
-		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
+		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
+				     BOOT_DATA);
 		if (tbl == NULL) {
 			pr_err("Could not map Properties table!\n");
 			return -ENOMEM;
@@ -531,7 +532,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	 * Let's see what config tables the firmware passed to us.
 	 */
 	config_tables = early_memremap(efi.systab->tables,
-				       efi.systab->nr_tables * sz);
+				       efi.systab->nr_tables * sz, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_err("Could not map Configuration table!\n");
 		return -ENOMEM;
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 75feb3f..10ee547 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -273,7 +273,7 @@ void __init efi_esrt_init(void)
 		return;
 	}
 
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
@@ -323,7 +323,7 @@ void __init efi_esrt_init(void)
 	/* remap it with our (plausible) new pages */
 	early_memunmap(va, size);
 	size += entries_size;
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 48430ab..8e87388 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -101,7 +101,8 @@ void __init efi_fake_memmap(void)
 
 	/* create new EFI memmap */
 	new_memmap = early_memremap(new_memmap_phy,
-				    efi.memmap.desc_size * new_nr_map);
+				    efi.memmap.desc_size * new_nr_map,
+				    BOOT_DATA);
 	if (!new_memmap) {
 		memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map);
 		return;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 236004b..f351c2a 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -28,7 +28,7 @@ int __init efi_memattr_init(void)
 	if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
 		return 0;
 
-	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl), BOOT_DATA);
 	if (!tbl) {
 		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
 		       efi.mem_attr_table);
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 2edef8d..61de27a 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -3,6 +3,11 @@
 
 #include <linux/types.h>
 
+enum memremap_owner {
+	KERNEL_DATA = 0,
+	BOOT_DATA,
+};
+
 /*
  * early_ioremap() and early_iounmap() are for temporary early boot-time
  * mappings, before the real ioremap() is functional.
@@ -10,9 +15,13 @@
 extern void __iomem *early_ioremap(resource_size_t phys_addr,
 				   unsigned long size);
 extern void *early_memremap(resource_size_t phys_addr,
-			    unsigned long size);
+			    unsigned long size, enum memremap_owner);
 extern void *early_memremap_ro(resource_size_t phys_addr,
-			       unsigned long size);
+			       unsigned long size, enum memremap_owner);
+/*
+ * When supplying the protection value assume the caller knows the
+ * situation, so the memremap_owner data is not required.
+ */
 extern void *early_memremap_prot(resource_size_t phys_addr,
 				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
@@ -41,7 +50,7 @@ extern void early_ioremap_reset(void);
  * Early copy from unmapped memory to kernel mapped memory.
  */
 extern void copy_from_early_mem(void *dest, phys_addr_t src,
-				unsigned long size);
+				unsigned long size, enum memremap_owner owner);
 
 #else
 static inline void early_ioremap_init(void) { }
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index d71b98b..ad40720 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -34,6 +34,14 @@ void __init __weak early_ioremap_shutdown(void)
 {
 }
 
+pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
+						    unsigned long size,
+						    enum memremap_owner owner,
+						    pgprot_t prot)
+{
+	return prot;
+}
+
 void __init early_ioremap_reset(void)
 {
 	early_ioremap_shutdown();
@@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size,
-					       FIXMAP_PAGE_NORMAL);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_NORMAL);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #ifdef FIXMAP_PAGE_RO
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_RO);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #endif
 
@@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
 
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
-void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
+void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
+				enum memremap_owner owner)
 {
 	unsigned long slop, clen;
 	char *p;
@@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
 		clen = size;
 		if (clen > MAX_MAP_CHUNK - slop)
 			clen = MAX_MAP_CHUNK - slop;
-		p = early_memremap(src & PAGE_MASK, clen + slop);
+		p = early_memremap(src & PAGE_MASK, clen + slop, owner);
 		memcpy(dest, p + slop, clen);
 		early_memunmap(p, clen + slop);
 		dest += clen;
@@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

BOOT data (such as EFI related data) is not encyrpted when the system is
booted and needs to be accessed as non-encrypted.  Add support to the
early_memremap API to identify the type of data being accessed so that
the proper encryption attribute can be applied.  Currently, two types
of data are defined, KERNEL_DATA and BOOT_DATA.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/arm64/kernel/acpi.c              |    2 +-
 arch/ia64/include/asm/early_ioremap.h |    2 +-
 arch/x86/kernel/devicetree.c          |    6 ++++--
 arch/x86/kernel/e820.c                |    2 +-
 arch/x86/kernel/setup.c               |    9 +++++---
 arch/x86/mm/ioremap.c                 |   19 +++++++++++++++++
 arch/x86/platform/efi/efi.c           |   15 +++++++-------
 arch/x86/platform/efi/efi_64.c        |   13 +++++++++---
 arch/x86/platform/efi/quirks.c        |    4 ++--
 arch/x86/xen/mmu.c                    |    9 +++++---
 arch/x86/xen/setup.c                  |    6 ++++--
 drivers/acpi/tables.c                 |    2 +-
 drivers/firmware/efi/arm-init.c       |   13 +++++++-----
 drivers/firmware/efi/efi.c            |    7 ++++--
 drivers/firmware/efi/esrt.c           |    4 ++--
 drivers/firmware/efi/fake_mem.c       |    3 ++-
 drivers/firmware/efi/memattr.c        |    2 +-
 include/asm-generic/early_ioremap.h   |   15 +++++++++++---
 mm/early_ioremap.c                    |   36 +++++++++++++++++++++++++--------
 19 files changed, 117 insertions(+), 52 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3e4f1a4..33fdedd 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -98,7 +98,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 	if (!size)
 		return NULL;
 
-	return early_memremap(phys, size);
+	return early_memremap(phys, size, BOOT_DATA);
 }
 
 void __init __acpi_unmap_table(char *map, unsigned long size)
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
index eec9e1d..bc8c210 100644
--- a/arch/ia64/include/asm/early_ioremap.h
+++ b/arch/ia64/include/asm/early_ioremap.h
@@ -2,7 +2,7 @@
 #define _ASM_IA64_EARLY_IOREMAP_H
 
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
+#define early_memremap(phys_addr, size, owner) early_ioremap(phys_addr, size)
 
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 #define early_memunmap(addr, size)             early_iounmap(addr, size)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3fe45f8..556e986 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -276,11 +276,13 @@ static void __init x86_flattree_get_config(void)
 
 	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
 
-	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+	initial_boot_params = dt = early_memremap(initial_dtb, map_len,
+						  BOOT_DATA);
 	size = of_get_flat_dt_size();
 	if (map_len < size) {
 		early_memunmap(dt, map_len);
-		initial_boot_params = dt = early_memremap(initial_dtb, size);
+		initial_boot_params = dt = early_memremap(initial_dtb, size,
+							  BOOT_DATA);
 		map_len = size;
 	}
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 621b501..71b237f 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -661,7 +661,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
 	struct e820entry *extmap;
 	struct setup_data *sdata;
 
-	sdata = early_memremap(phys_addr, data_len);
+	sdata = early_memremap(phys_addr, data_len, BOOT_DATA);
 	entries = sdata->len / sizeof(struct e820entry);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1fdaa11..cec8a63 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -344,7 +344,8 @@ static void __init relocate_initrd(void)
 	printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
 	       relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 
-	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
+	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size,
+			    BOOT_DATA);
 
 	printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
 		" [mem %#010llx-%#010llx]\n",
@@ -426,7 +427,7 @@ static void __init parse_setup_data(void)
 	while (pa_data) {
 		u32 data_len, data_type;
 
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		data_len = data->len + sizeof(struct setup_data);
 		data_type = data->type;
 		pa_next = data->next;
@@ -459,7 +460,7 @@ static void __init e820_reserve_setup_data(void)
 		return;
 
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		e820_update_range(pa_data, sizeof(*data)+data->len,
 			 E820_RAM, E820_RESERVED_KERN);
 		pa_data = data->next;
@@ -479,7 +480,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		memblock_reserve(pa_data, sizeof(*data) + data->len);
 		pa_data = data->next;
 		early_memunmap(data, sizeof(*data));
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 031db21..e3bdc5a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/*
+ * Architecure override of __weak function to adjust the protection attributes
+ * used when remapping memory.
+ */
+pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
+					     unsigned long size,
+					     enum memremap_owner owner,
+					     pgprot_t prot)
+{
+	/*
+	 * If memory encryption is enabled and BOOT_DATA is being mapped
+	 * then remove the encryption bit.
+	 */
+	if (_PAGE_ENC && (owner == BOOT_DATA))
+		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
+
+	return prot;
+}
+
 /* Remap memory with encryption */
 void __init *early_memremap_enc(resource_size_t phys_addr,
 				unsigned long size)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1fbb408..2c7e6b0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -239,12 +239,13 @@ static int __init efi_systab_init(void *phys)
 		u64 tmp = 0;
 
 		if (efi_setup) {
-			data = early_memremap(efi_setup, sizeof(*data));
+			data = early_memremap(efi_setup, sizeof(*data),
+					      BOOT_DATA);
 			if (!data)
 				return -ENOMEM;
 		}
 		systab64 = early_memremap((unsigned long)phys,
-					 sizeof(*systab64));
+					  sizeof(*systab64), BOOT_DATA);
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
@@ -293,7 +294,7 @@ static int __init efi_systab_init(void *phys)
 		efi_system_table_32_t *systab32;
 
 		systab32 = early_memremap((unsigned long)phys,
-					 sizeof(*systab32));
+					  sizeof(*systab32), BOOT_DATA);
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			return -ENOMEM;
@@ -338,7 +339,7 @@ static int __init efi_runtime_init32(void)
 	efi_runtime_services_32_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_32_t));
+				 sizeof(efi_runtime_services_32_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -362,7 +363,7 @@ static int __init efi_runtime_init64(void)
 	efi_runtime_services_64_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_64_t));
+				 sizeof(efi_runtime_services_64_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -425,7 +426,7 @@ static int __init efi_memmap_init(void)
 	size = efi.memmap.nr_map * efi.memmap.desc_size;
 	addr = (unsigned long)efi.memmap.phys_map;
 
-	efi.memmap.map = early_memremap(addr, size);
+	efi.memmap.map = early_memremap(addr, size, BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
 		return -ENOMEM;
@@ -471,7 +472,7 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2, BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 677e29e..0871ea4 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -222,7 +222,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return 0;
 
-	efi_scratch.efi_pgt = (pgd_t *)__pa(efi_pgd);
+	/*
+	 * Since the PGD is encrypted, set the encryption mask so that when
+	 * this value is loaded into cr3 the PGD will be decrypted during
+	 * the pagetable walk.
+	 */
+	efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
 	pgd = efi_pgd;
 
 	/*
@@ -261,7 +266,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 		pfn = md->phys_addr >> PAGE_SHIFT;
 		npages = md->num_pages;
 
-		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, _PAGE_RW)) {
+		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages,
+					    _PAGE_RW | _PAGE_ENC)) {
 			pr_err("Failed to map 1:1 memory\n");
 			return 1;
 		}
@@ -278,7 +284,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	text = __pa(_text);
 	pfn = text >> PAGE_SHIFT;
 
-	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, _PAGE_RW)) {
+	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages,
+				    _PAGE_RW | _PAGE_ENC)) {
 		pr_err("Failed to map kernel text 1:1\n");
 		return 1;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 89d1146..606bf551 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -311,7 +311,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 	if (!efi_enabled(EFI_64BIT))
 		return 0;
 
-	data = early_memremap(efi_setup, sizeof(*data));
+	data = early_memremap(efi_setup, sizeof(*data), BOOT_DATA);
 	if (!data) {
 		ret = -ENOMEM;
 		goto out;
@@ -322,7 +322,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 
 	sz = sizeof(efi_config_table_64_t);
 
-	p = tablep = early_memremap(tables, nr_tables * sz);
+	p = tablep = early_memremap(tables, nr_tables * sz, BOOT_DATA);
 	if (!p) {
 		pr_err("Could not map Configuration table!\n");
 		ret = -ENOMEM;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 7d5afdb..00db54a 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2020,7 +2020,7 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 	unsigned long *vaddr;
 	unsigned long val;
 
-	vaddr = early_memremap_ro(addr, sizeof(val));
+	vaddr = early_memremap_ro(addr, sizeof(val), KERNEL_DATA);
 	val = *vaddr;
 	early_memunmap(vaddr, sizeof(val));
 	return val;
@@ -2114,15 +2114,16 @@ void __init xen_relocate_p2m(void)
 	pgd = __va(read_cr3());
 	new_p2m = (unsigned long *)(2 * PGDIR_SIZE);
 	for (idx_pud = 0; idx_pud < n_pud; idx_pud++) {
-		pud = early_memremap(pud_phys, PAGE_SIZE);
+		pud = early_memremap(pud_phys, PAGE_SIZE, KERNEL_DATA);
 		clear_page(pud);
 		for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD);
 		     idx_pmd++) {
-			pmd = early_memremap(pmd_phys, PAGE_SIZE);
+			pmd = early_memremap(pmd_phys, PAGE_SIZE, KERNEL_DATA);
 			clear_page(pmd);
 			for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD);
 			     idx_pt++) {
-				pt = early_memremap(pt_phys, PAGE_SIZE);
+				pt = early_memremap(pt_phys, PAGE_SIZE,
+						    KERNEL_DATA);
 				clear_page(pt);
 				for (idx_pte = 0;
 				     idx_pte < min(n_pte, PTRS_PER_PTE);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 1764252..a8e2724 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -686,8 +686,10 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src,
 		if (src_len > (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off)
 			src_len = (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off;
 		len = min(dest_len, src_len);
-		to = early_memremap(dest - dest_off, dest_len + dest_off);
-		from = early_memremap(src - src_off, src_len + src_off);
+		to = early_memremap(dest - dest_off, dest_len + dest_off,
+				    KERNEL_DATA);
+		from = early_memremap(src - src_off, src_len + src_off,
+				      KERNEL_DATA);
 		memcpy(to, from, len);
 		early_memunmap(to, dest_len + dest_off);
 		early_memunmap(from, src_len + src_off);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 9f0ad6e..06b75a2 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -583,7 +583,7 @@ void __init acpi_table_upgrade(void)
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
 			dest_p = early_memremap(dest_addr & PAGE_MASK,
-						clen + slop);
+						clen + slop, BOOT_DATA);
 			memcpy(dest_p + slop, src_p, clen);
 			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index c49d50e..0a3fd48 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -67,7 +67,8 @@ static void __init init_screen_info(void)
 	struct screen_info *si;
 
 	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
-		si = early_memremap_ro(screen_info_table, sizeof(*si));
+		si = early_memremap_ro(screen_info_table, sizeof(*si),
+				       BOOT_DATA);
 		if (!si) {
 			pr_err("Could not map screen_info config table\n");
 			return;
@@ -94,7 +95,7 @@ static int __init uefi_init(void)
 	int i, retval;
 
 	efi.systab = early_memremap_ro(efi_system_table,
-				       sizeof(efi_system_table_t));
+				       sizeof(efi_system_table_t), BOOT_DATA);
 	if (efi.systab == NULL) {
 		pr_warn("Unable to map EFI system table.\n");
 		return -ENOMEM;
@@ -121,7 +122,8 @@ static int __init uefi_init(void)
 
 	/* Show what we know for posterity */
 	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
-				sizeof(vendor) * sizeof(efi_char16_t));
+				sizeof(vendor) * sizeof(efi_char16_t),
+				BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = c16[i];
@@ -135,7 +137,7 @@ static int __init uefi_init(void)
 
 	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
 	config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
-					  table_size);
+					  table_size, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_warn("Unable to map EFI config table array.\n");
 		retval = -ENOMEM;
@@ -226,7 +228,8 @@ void __init efi_init(void)
 	efi_system_table = params.system_table;
 
 	efi.memmap.phys_map = params.mmap;
-	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
+	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size,
+					   BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631a..f9286c6 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 		 * So just always get our own virtual map on the CPU.
 		 *
 		 */
-		md = early_memremap(p, sizeof (*md));
+		md = early_memremap(p, sizeof (*md), BOOT_DATA);
 		if (!md) {
 			pr_err_once("early_memremap(%pa, %zu) failed.\n",
 				    &p, sizeof (*md));
@@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
 
-		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
+		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
+				     BOOT_DATA);
 		if (tbl == NULL) {
 			pr_err("Could not map Properties table!\n");
 			return -ENOMEM;
@@ -531,7 +532,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	 * Let's see what config tables the firmware passed to us.
 	 */
 	config_tables = early_memremap(efi.systab->tables,
-				       efi.systab->nr_tables * sz);
+				       efi.systab->nr_tables * sz, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_err("Could not map Configuration table!\n");
 		return -ENOMEM;
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 75feb3f..10ee547 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -273,7 +273,7 @@ void __init efi_esrt_init(void)
 		return;
 	}
 
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
@@ -323,7 +323,7 @@ void __init efi_esrt_init(void)
 	/* remap it with our (plausible) new pages */
 	early_memunmap(va, size);
 	size += entries_size;
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 48430ab..8e87388 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -101,7 +101,8 @@ void __init efi_fake_memmap(void)
 
 	/* create new EFI memmap */
 	new_memmap = early_memremap(new_memmap_phy,
-				    efi.memmap.desc_size * new_nr_map);
+				    efi.memmap.desc_size * new_nr_map,
+				    BOOT_DATA);
 	if (!new_memmap) {
 		memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map);
 		return;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 236004b..f351c2a 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -28,7 +28,7 @@ int __init efi_memattr_init(void)
 	if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
 		return 0;
 
-	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl), BOOT_DATA);
 	if (!tbl) {
 		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
 		       efi.mem_attr_table);
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 2edef8d..61de27a 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -3,6 +3,11 @@
 
 #include <linux/types.h>
 
+enum memremap_owner {
+	KERNEL_DATA = 0,
+	BOOT_DATA,
+};
+
 /*
  * early_ioremap() and early_iounmap() are for temporary early boot-time
  * mappings, before the real ioremap() is functional.
@@ -10,9 +15,13 @@
 extern void __iomem *early_ioremap(resource_size_t phys_addr,
 				   unsigned long size);
 extern void *early_memremap(resource_size_t phys_addr,
-			    unsigned long size);
+			    unsigned long size, enum memremap_owner);
 extern void *early_memremap_ro(resource_size_t phys_addr,
-			       unsigned long size);
+			       unsigned long size, enum memremap_owner);
+/*
+ * When supplying the protection value assume the caller knows the
+ * situation, so the memremap_owner data is not required.
+ */
 extern void *early_memremap_prot(resource_size_t phys_addr,
 				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
@@ -41,7 +50,7 @@ extern void early_ioremap_reset(void);
  * Early copy from unmapped memory to kernel mapped memory.
  */
 extern void copy_from_early_mem(void *dest, phys_addr_t src,
-				unsigned long size);
+				unsigned long size, enum memremap_owner owner);
 
 #else
 static inline void early_ioremap_init(void) { }
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index d71b98b..ad40720 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -34,6 +34,14 @@ void __init __weak early_ioremap_shutdown(void)
 {
 }
 
+pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
+						    unsigned long size,
+						    enum memremap_owner owner,
+						    pgprot_t prot)
+{
+	return prot;
+}
+
 void __init early_ioremap_reset(void)
 {
 	early_ioremap_shutdown();
@@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size,
-					       FIXMAP_PAGE_NORMAL);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_NORMAL);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #ifdef FIXMAP_PAGE_RO
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_RO);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #endif
 
@@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
 
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
-void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
+void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
+				enum memremap_owner owner)
 {
 	unsigned long slop, clen;
 	char *p;
@@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
 		clen = size;
 		if (clen > MAX_MAP_CHUNK - slop)
 			clen = MAX_MAP_CHUNK - slop;
-		p = early_memremap(src & PAGE_MASK, clen + slop);
+		p = early_memremap(src & PAGE_MASK, clen + slop, owner);
 		memcpy(dest, p + slop, clen);
 		early_memunmap(p, clen + slop);
 		dest += clen;
@@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

BOOT data (such as EFI related data) is not encyrpted when the system is
booted and needs to be accessed as non-encrypted.  Add support to the
early_memremap API to identify the type of data being accessed so that
the proper encryption attribute can be applied.  Currently, two types
of data are defined, KERNEL_DATA and BOOT_DATA.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/arm64/kernel/acpi.c              |    2 +-
 arch/ia64/include/asm/early_ioremap.h |    2 +-
 arch/x86/kernel/devicetree.c          |    6 ++++--
 arch/x86/kernel/e820.c                |    2 +-
 arch/x86/kernel/setup.c               |    9 +++++---
 arch/x86/mm/ioremap.c                 |   19 +++++++++++++++++
 arch/x86/platform/efi/efi.c           |   15 +++++++-------
 arch/x86/platform/efi/efi_64.c        |   13 +++++++++---
 arch/x86/platform/efi/quirks.c        |    4 ++--
 arch/x86/xen/mmu.c                    |    9 +++++---
 arch/x86/xen/setup.c                  |    6 ++++--
 drivers/acpi/tables.c                 |    2 +-
 drivers/firmware/efi/arm-init.c       |   13 +++++++-----
 drivers/firmware/efi/efi.c            |    7 ++++--
 drivers/firmware/efi/esrt.c           |    4 ++--
 drivers/firmware/efi/fake_mem.c       |    3 ++-
 drivers/firmware/efi/memattr.c        |    2 +-
 include/asm-generic/early_ioremap.h   |   15 +++++++++++---
 mm/early_ioremap.c                    |   36 +++++++++++++++++++++++++--------
 19 files changed, 117 insertions(+), 52 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3e4f1a4..33fdedd 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -98,7 +98,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 	if (!size)
 		return NULL;
 
-	return early_memremap(phys, size);
+	return early_memremap(phys, size, BOOT_DATA);
 }
 
 void __init __acpi_unmap_table(char *map, unsigned long size)
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
index eec9e1d..bc8c210 100644
--- a/arch/ia64/include/asm/early_ioremap.h
+++ b/arch/ia64/include/asm/early_ioremap.h
@@ -2,7 +2,7 @@
 #define _ASM_IA64_EARLY_IOREMAP_H
 
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
+#define early_memremap(phys_addr, size, owner) early_ioremap(phys_addr, size)
 
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 #define early_memunmap(addr, size)             early_iounmap(addr, size)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3fe45f8..556e986 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -276,11 +276,13 @@ static void __init x86_flattree_get_config(void)
 
 	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
 
-	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+	initial_boot_params = dt = early_memremap(initial_dtb, map_len,
+						  BOOT_DATA);
 	size = of_get_flat_dt_size();
 	if (map_len < size) {
 		early_memunmap(dt, map_len);
-		initial_boot_params = dt = early_memremap(initial_dtb, size);
+		initial_boot_params = dt = early_memremap(initial_dtb, size,
+							  BOOT_DATA);
 		map_len = size;
 	}
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 621b501..71b237f 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -661,7 +661,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
 	struct e820entry *extmap;
 	struct setup_data *sdata;
 
-	sdata = early_memremap(phys_addr, data_len);
+	sdata = early_memremap(phys_addr, data_len, BOOT_DATA);
 	entries = sdata->len / sizeof(struct e820entry);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1fdaa11..cec8a63 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -344,7 +344,8 @@ static void __init relocate_initrd(void)
 	printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
 	       relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 
-	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
+	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size,
+			    BOOT_DATA);
 
 	printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
 		" [mem %#010llx-%#010llx]\n",
@@ -426,7 +427,7 @@ static void __init parse_setup_data(void)
 	while (pa_data) {
 		u32 data_len, data_type;
 
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		data_len = data->len + sizeof(struct setup_data);
 		data_type = data->type;
 		pa_next = data->next;
@@ -459,7 +460,7 @@ static void __init e820_reserve_setup_data(void)
 		return;
 
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		e820_update_range(pa_data, sizeof(*data)+data->len,
 			 E820_RAM, E820_RESERVED_KERN);
 		pa_data = data->next;
@@ -479,7 +480,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		memblock_reserve(pa_data, sizeof(*data) + data->len);
 		pa_data = data->next;
 		early_memunmap(data, sizeof(*data));
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 031db21..e3bdc5a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/*
+ * Architecure override of __weak function to adjust the protection attributes
+ * used when remapping memory.
+ */
+pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
+					     unsigned long size,
+					     enum memremap_owner owner,
+					     pgprot_t prot)
+{
+	/*
+	 * If memory encryption is enabled and BOOT_DATA is being mapped
+	 * then remove the encryption bit.
+	 */
+	if (_PAGE_ENC && (owner == BOOT_DATA))
+		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
+
+	return prot;
+}
+
 /* Remap memory with encryption */
 void __init *early_memremap_enc(resource_size_t phys_addr,
 				unsigned long size)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1fbb408..2c7e6b0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -239,12 +239,13 @@ static int __init efi_systab_init(void *phys)
 		u64 tmp = 0;
 
 		if (efi_setup) {
-			data = early_memremap(efi_setup, sizeof(*data));
+			data = early_memremap(efi_setup, sizeof(*data),
+					      BOOT_DATA);
 			if (!data)
 				return -ENOMEM;
 		}
 		systab64 = early_memremap((unsigned long)phys,
-					 sizeof(*systab64));
+					  sizeof(*systab64), BOOT_DATA);
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
@@ -293,7 +294,7 @@ static int __init efi_systab_init(void *phys)
 		efi_system_table_32_t *systab32;
 
 		systab32 = early_memremap((unsigned long)phys,
-					 sizeof(*systab32));
+					  sizeof(*systab32), BOOT_DATA);
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			return -ENOMEM;
@@ -338,7 +339,7 @@ static int __init efi_runtime_init32(void)
 	efi_runtime_services_32_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_32_t));
+				 sizeof(efi_runtime_services_32_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -362,7 +363,7 @@ static int __init efi_runtime_init64(void)
 	efi_runtime_services_64_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_64_t));
+				 sizeof(efi_runtime_services_64_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -425,7 +426,7 @@ static int __init efi_memmap_init(void)
 	size = efi.memmap.nr_map * efi.memmap.desc_size;
 	addr = (unsigned long)efi.memmap.phys_map;
 
-	efi.memmap.map = early_memremap(addr, size);
+	efi.memmap.map = early_memremap(addr, size, BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
 		return -ENOMEM;
@@ -471,7 +472,7 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2, BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 677e29e..0871ea4 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -222,7 +222,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return 0;
 
-	efi_scratch.efi_pgt = (pgd_t *)__pa(efi_pgd);
+	/*
+	 * Since the PGD is encrypted, set the encryption mask so that when
+	 * this value is loaded into cr3 the PGD will be decrypted during
+	 * the pagetable walk.
+	 */
+	efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
 	pgd = efi_pgd;
 
 	/*
@@ -261,7 +266,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 		pfn = md->phys_addr >> PAGE_SHIFT;
 		npages = md->num_pages;
 
-		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, _PAGE_RW)) {
+		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages,
+					    _PAGE_RW | _PAGE_ENC)) {
 			pr_err("Failed to map 1:1 memory\n");
 			return 1;
 		}
@@ -278,7 +284,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	text = __pa(_text);
 	pfn = text >> PAGE_SHIFT;
 
-	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, _PAGE_RW)) {
+	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages,
+				    _PAGE_RW | _PAGE_ENC)) {
 		pr_err("Failed to map kernel text 1:1\n");
 		return 1;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 89d1146..606bf551 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -311,7 +311,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 	if (!efi_enabled(EFI_64BIT))
 		return 0;
 
-	data = early_memremap(efi_setup, sizeof(*data));
+	data = early_memremap(efi_setup, sizeof(*data), BOOT_DATA);
 	if (!data) {
 		ret = -ENOMEM;
 		goto out;
@@ -322,7 +322,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 
 	sz = sizeof(efi_config_table_64_t);
 
-	p = tablep = early_memremap(tables, nr_tables * sz);
+	p = tablep = early_memremap(tables, nr_tables * sz, BOOT_DATA);
 	if (!p) {
 		pr_err("Could not map Configuration table!\n");
 		ret = -ENOMEM;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 7d5afdb..00db54a 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2020,7 +2020,7 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 	unsigned long *vaddr;
 	unsigned long val;
 
-	vaddr = early_memremap_ro(addr, sizeof(val));
+	vaddr = early_memremap_ro(addr, sizeof(val), KERNEL_DATA);
 	val = *vaddr;
 	early_memunmap(vaddr, sizeof(val));
 	return val;
@@ -2114,15 +2114,16 @@ void __init xen_relocate_p2m(void)
 	pgd = __va(read_cr3());
 	new_p2m = (unsigned long *)(2 * PGDIR_SIZE);
 	for (idx_pud = 0; idx_pud < n_pud; idx_pud++) {
-		pud = early_memremap(pud_phys, PAGE_SIZE);
+		pud = early_memremap(pud_phys, PAGE_SIZE, KERNEL_DATA);
 		clear_page(pud);
 		for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD);
 		     idx_pmd++) {
-			pmd = early_memremap(pmd_phys, PAGE_SIZE);
+			pmd = early_memremap(pmd_phys, PAGE_SIZE, KERNEL_DATA);
 			clear_page(pmd);
 			for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD);
 			     idx_pt++) {
-				pt = early_memremap(pt_phys, PAGE_SIZE);
+				pt = early_memremap(pt_phys, PAGE_SIZE,
+						    KERNEL_DATA);
 				clear_page(pt);
 				for (idx_pte = 0;
 				     idx_pte < min(n_pte, PTRS_PER_PTE);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 1764252..a8e2724 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -686,8 +686,10 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src,
 		if (src_len > (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off)
 			src_len = (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off;
 		len = min(dest_len, src_len);
-		to = early_memremap(dest - dest_off, dest_len + dest_off);
-		from = early_memremap(src - src_off, src_len + src_off);
+		to = early_memremap(dest - dest_off, dest_len + dest_off,
+				    KERNEL_DATA);
+		from = early_memremap(src - src_off, src_len + src_off,
+				      KERNEL_DATA);
 		memcpy(to, from, len);
 		early_memunmap(to, dest_len + dest_off);
 		early_memunmap(from, src_len + src_off);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 9f0ad6e..06b75a2 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -583,7 +583,7 @@ void __init acpi_table_upgrade(void)
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
 			dest_p = early_memremap(dest_addr & PAGE_MASK,
-						clen + slop);
+						clen + slop, BOOT_DATA);
 			memcpy(dest_p + slop, src_p, clen);
 			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index c49d50e..0a3fd48 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -67,7 +67,8 @@ static void __init init_screen_info(void)
 	struct screen_info *si;
 
 	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
-		si = early_memremap_ro(screen_info_table, sizeof(*si));
+		si = early_memremap_ro(screen_info_table, sizeof(*si),
+				       BOOT_DATA);
 		if (!si) {
 			pr_err("Could not map screen_info config table\n");
 			return;
@@ -94,7 +95,7 @@ static int __init uefi_init(void)
 	int i, retval;
 
 	efi.systab = early_memremap_ro(efi_system_table,
-				       sizeof(efi_system_table_t));
+				       sizeof(efi_system_table_t), BOOT_DATA);
 	if (efi.systab == NULL) {
 		pr_warn("Unable to map EFI system table.\n");
 		return -ENOMEM;
@@ -121,7 +122,8 @@ static int __init uefi_init(void)
 
 	/* Show what we know for posterity */
 	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
-				sizeof(vendor) * sizeof(efi_char16_t));
+				sizeof(vendor) * sizeof(efi_char16_t),
+				BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = c16[i];
@@ -135,7 +137,7 @@ static int __init uefi_init(void)
 
 	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
 	config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
-					  table_size);
+					  table_size, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_warn("Unable to map EFI config table array.\n");
 		retval = -ENOMEM;
@@ -226,7 +228,8 @@ void __init efi_init(void)
 	efi_system_table = params.system_table;
 
 	efi.memmap.phys_map = params.mmap;
-	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
+	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size,
+					   BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631a..f9286c6 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 		 * So just always get our own virtual map on the CPU.
 		 *
 		 */
-		md = early_memremap(p, sizeof (*md));
+		md = early_memremap(p, sizeof (*md), BOOT_DATA);
 		if (!md) {
 			pr_err_once("early_memremap(%pa, %zu) failed.\n",
 				    &p, sizeof (*md));
@@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
 
-		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
+		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
+				     BOOT_DATA);
 		if (tbl == NULL) {
 			pr_err("Could not map Properties table!\n");
 			return -ENOMEM;
@@ -531,7 +532,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	 * Let's see what config tables the firmware passed to us.
 	 */
 	config_tables = early_memremap(efi.systab->tables,
-				       efi.systab->nr_tables * sz);
+				       efi.systab->nr_tables * sz, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_err("Could not map Configuration table!\n");
 		return -ENOMEM;
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 75feb3f..10ee547 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -273,7 +273,7 @@ void __init efi_esrt_init(void)
 		return;
 	}
 
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
@@ -323,7 +323,7 @@ void __init efi_esrt_init(void)
 	/* remap it with our (plausible) new pages */
 	early_memunmap(va, size);
 	size += entries_size;
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 48430ab..8e87388 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -101,7 +101,8 @@ void __init efi_fake_memmap(void)
 
 	/* create new EFI memmap */
 	new_memmap = early_memremap(new_memmap_phy,
-				    efi.memmap.desc_size * new_nr_map);
+				    efi.memmap.desc_size * new_nr_map,
+				    BOOT_DATA);
 	if (!new_memmap) {
 		memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map);
 		return;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 236004b..f351c2a 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -28,7 +28,7 @@ int __init efi_memattr_init(void)
 	if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
 		return 0;
 
-	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl), BOOT_DATA);
 	if (!tbl) {
 		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
 		       efi.mem_attr_table);
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 2edef8d..61de27a 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -3,6 +3,11 @@
 
 #include <linux/types.h>
 
+enum memremap_owner {
+	KERNEL_DATA = 0,
+	BOOT_DATA,
+};
+
 /*
  * early_ioremap() and early_iounmap() are for temporary early boot-time
  * mappings, before the real ioremap() is functional.
@@ -10,9 +15,13 @@
 extern void __iomem *early_ioremap(resource_size_t phys_addr,
 				   unsigned long size);
 extern void *early_memremap(resource_size_t phys_addr,
-			    unsigned long size);
+			    unsigned long size, enum memremap_owner);
 extern void *early_memremap_ro(resource_size_t phys_addr,
-			       unsigned long size);
+			       unsigned long size, enum memremap_owner);
+/*
+ * When supplying the protection value assume the caller knows the
+ * situation, so the memremap_owner data is not required.
+ */
 extern void *early_memremap_prot(resource_size_t phys_addr,
 				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
@@ -41,7 +50,7 @@ extern void early_ioremap_reset(void);
  * Early copy from unmapped memory to kernel mapped memory.
  */
 extern void copy_from_early_mem(void *dest, phys_addr_t src,
-				unsigned long size);
+				unsigned long size, enum memremap_owner owner);
 
 #else
 static inline void early_ioremap_init(void) { }
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index d71b98b..ad40720 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -34,6 +34,14 @@ void __init __weak early_ioremap_shutdown(void)
 {
 }
 
+pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
+						    unsigned long size,
+						    enum memremap_owner owner,
+						    pgprot_t prot)
+{
+	return prot;
+}
+
 void __init early_ioremap_reset(void)
 {
 	early_ioremap_shutdown();
@@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size,
-					       FIXMAP_PAGE_NORMAL);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_NORMAL);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #ifdef FIXMAP_PAGE_RO
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_RO);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #endif
 
@@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
 
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
-void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
+void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
+				enum memremap_owner owner)
 {
 	unsigned long slop, clen;
 	char *p;
@@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
 		clen = size;
 		if (clen > MAX_MAP_CHUNK - slop)
 			clen = MAX_MAP_CHUNK - slop;
-		p = early_memremap(src & PAGE_MASK, clen + slop);
+		p = early_memremap(src & PAGE_MASK, clen + slop, owner);
 		memcpy(dest, p + slop, clen);
 		early_memunmap(p, clen + slop);
 		dest += clen;
@@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

BOOT data (such as EFI related data) is not encyrpted when the system is
booted and needs to be accessed as non-encrypted.  Add support to the
early_memremap API to identify the type of data being accessed so that
the proper encryption attribute can be applied.  Currently, two types
of data are defined, KERNEL_DATA and BOOT_DATA.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/arm64/kernel/acpi.c              |    2 +-
 arch/ia64/include/asm/early_ioremap.h |    2 +-
 arch/x86/kernel/devicetree.c          |    6 ++++--
 arch/x86/kernel/e820.c                |    2 +-
 arch/x86/kernel/setup.c               |    9 +++++---
 arch/x86/mm/ioremap.c                 |   19 +++++++++++++++++
 arch/x86/platform/efi/efi.c           |   15 +++++++-------
 arch/x86/platform/efi/efi_64.c        |   13 +++++++++---
 arch/x86/platform/efi/quirks.c        |    4 ++--
 arch/x86/xen/mmu.c                    |    9 +++++---
 arch/x86/xen/setup.c                  |    6 ++++--
 drivers/acpi/tables.c                 |    2 +-
 drivers/firmware/efi/arm-init.c       |   13 +++++++-----
 drivers/firmware/efi/efi.c            |    7 ++++--
 drivers/firmware/efi/esrt.c           |    4 ++--
 drivers/firmware/efi/fake_mem.c       |    3 ++-
 drivers/firmware/efi/memattr.c        |    2 +-
 include/asm-generic/early_ioremap.h   |   15 +++++++++++---
 mm/early_ioremap.c                    |   36 +++++++++++++++++++++++++--------
 19 files changed, 117 insertions(+), 52 deletions(-)

diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index 3e4f1a4..33fdedd 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -98,7 +98,7 @@ char *__init __acpi_map_table(unsigned long phys, unsigned long size)
 	if (!size)
 		return NULL;
 
-	return early_memremap(phys, size);
+	return early_memremap(phys, size, BOOT_DATA);
 }
 
 void __init __acpi_unmap_table(char *map, unsigned long size)
diff --git a/arch/ia64/include/asm/early_ioremap.h b/arch/ia64/include/asm/early_ioremap.h
index eec9e1d..bc8c210 100644
--- a/arch/ia64/include/asm/early_ioremap.h
+++ b/arch/ia64/include/asm/early_ioremap.h
@@ -2,7 +2,7 @@
 #define _ASM_IA64_EARLY_IOREMAP_H
 
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
-#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
+#define early_memremap(phys_addr, size, owner) early_ioremap(phys_addr, size)
 
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 #define early_memunmap(addr, size)             early_iounmap(addr, size)
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3fe45f8..556e986 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -276,11 +276,13 @@ static void __init x86_flattree_get_config(void)
 
 	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
 
-	initial_boot_params = dt = early_memremap(initial_dtb, map_len);
+	initial_boot_params = dt = early_memremap(initial_dtb, map_len,
+						  BOOT_DATA);
 	size = of_get_flat_dt_size();
 	if (map_len < size) {
 		early_memunmap(dt, map_len);
-		initial_boot_params = dt = early_memremap(initial_dtb, size);
+		initial_boot_params = dt = early_memremap(initial_dtb, size,
+							  BOOT_DATA);
 		map_len = size;
 	}
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 621b501..71b237f 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -661,7 +661,7 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
 	struct e820entry *extmap;
 	struct setup_data *sdata;
 
-	sdata = early_memremap(phys_addr, data_len);
+	sdata = early_memremap(phys_addr, data_len, BOOT_DATA);
 	entries = sdata->len / sizeof(struct e820entry);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1fdaa11..cec8a63 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -344,7 +344,8 @@ static void __init relocate_initrd(void)
 	printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
 	       relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
 
-	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
+	copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size,
+			    BOOT_DATA);
 
 	printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
 		" [mem %#010llx-%#010llx]\n",
@@ -426,7 +427,7 @@ static void __init parse_setup_data(void)
 	while (pa_data) {
 		u32 data_len, data_type;
 
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		data_len = data->len + sizeof(struct setup_data);
 		data_type = data->type;
 		pa_next = data->next;
@@ -459,7 +460,7 @@ static void __init e820_reserve_setup_data(void)
 		return;
 
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		e820_update_range(pa_data, sizeof(*data)+data->len,
 			 E820_RAM, E820_RESERVED_KERN);
 		pa_data = data->next;
@@ -479,7 +480,7 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, sizeof(*data));
+		data = early_memremap(pa_data, sizeof(*data), BOOT_DATA);
 		memblock_reserve(pa_data, sizeof(*data) + data->len);
 		pa_data = data->next;
 		early_memunmap(data, sizeof(*data));
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 031db21..e3bdc5a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
 }
 
+/*
+ * Architecure override of __weak function to adjust the protection attributes
+ * used when remapping memory.
+ */
+pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
+					     unsigned long size,
+					     enum memremap_owner owner,
+					     pgprot_t prot)
+{
+	/*
+	 * If memory encryption is enabled and BOOT_DATA is being mapped
+	 * then remove the encryption bit.
+	 */
+	if (_PAGE_ENC && (owner == BOOT_DATA))
+		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
+
+	return prot;
+}
+
 /* Remap memory with encryption */
 void __init *early_memremap_enc(resource_size_t phys_addr,
 				unsigned long size)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 1fbb408..2c7e6b0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -239,12 +239,13 @@ static int __init efi_systab_init(void *phys)
 		u64 tmp = 0;
 
 		if (efi_setup) {
-			data = early_memremap(efi_setup, sizeof(*data));
+			data = early_memremap(efi_setup, sizeof(*data),
+					      BOOT_DATA);
 			if (!data)
 				return -ENOMEM;
 		}
 		systab64 = early_memremap((unsigned long)phys,
-					 sizeof(*systab64));
+					  sizeof(*systab64), BOOT_DATA);
 		if (systab64 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			if (data)
@@ -293,7 +294,7 @@ static int __init efi_systab_init(void *phys)
 		efi_system_table_32_t *systab32;
 
 		systab32 = early_memremap((unsigned long)phys,
-					 sizeof(*systab32));
+					  sizeof(*systab32), BOOT_DATA);
 		if (systab32 == NULL) {
 			pr_err("Couldn't map the system table!\n");
 			return -ENOMEM;
@@ -338,7 +339,7 @@ static int __init efi_runtime_init32(void)
 	efi_runtime_services_32_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_32_t));
+				 sizeof(efi_runtime_services_32_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -362,7 +363,7 @@ static int __init efi_runtime_init64(void)
 	efi_runtime_services_64_t *runtime;
 
 	runtime = early_memremap((unsigned long)efi.systab->runtime,
-			sizeof(efi_runtime_services_64_t));
+				 sizeof(efi_runtime_services_64_t), BOOT_DATA);
 	if (!runtime) {
 		pr_err("Could not map the runtime service table!\n");
 		return -ENOMEM;
@@ -425,7 +426,7 @@ static int __init efi_memmap_init(void)
 	size = efi.memmap.nr_map * efi.memmap.desc_size;
 	addr = (unsigned long)efi.memmap.phys_map;
 
-	efi.memmap.map = early_memremap(addr, size);
+	efi.memmap.map = early_memremap(addr, size, BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
 		return -ENOMEM;
@@ -471,7 +472,7 @@ void __init efi_init(void)
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2, BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = *c16++;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 677e29e..0871ea4 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -222,7 +222,12 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return 0;
 
-	efi_scratch.efi_pgt = (pgd_t *)__pa(efi_pgd);
+	/*
+	 * Since the PGD is encrypted, set the encryption mask so that when
+	 * this value is loaded into cr3 the PGD will be decrypted during
+	 * the pagetable walk.
+	 */
+	efi_scratch.efi_pgt = (pgd_t *)__sme_pa(efi_pgd);
 	pgd = efi_pgd;
 
 	/*
@@ -261,7 +266,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 		pfn = md->phys_addr >> PAGE_SHIFT;
 		npages = md->num_pages;
 
-		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages, _PAGE_RW)) {
+		if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, npages,
+					    _PAGE_RW | _PAGE_ENC)) {
 			pr_err("Failed to map 1:1 memory\n");
 			return 1;
 		}
@@ -278,7 +284,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 	text = __pa(_text);
 	pfn = text >> PAGE_SHIFT;
 
-	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages, _PAGE_RW)) {
+	if (kernel_map_pages_in_pgd(pgd, pfn, text, npages,
+				    _PAGE_RW | _PAGE_ENC)) {
 		pr_err("Failed to map kernel text 1:1\n");
 		return 1;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 89d1146..606bf551 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -311,7 +311,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 	if (!efi_enabled(EFI_64BIT))
 		return 0;
 
-	data = early_memremap(efi_setup, sizeof(*data));
+	data = early_memremap(efi_setup, sizeof(*data), BOOT_DATA);
 	if (!data) {
 		ret = -ENOMEM;
 		goto out;
@@ -322,7 +322,7 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
 
 	sz = sizeof(efi_config_table_64_t);
 
-	p = tablep = early_memremap(tables, nr_tables * sz);
+	p = tablep = early_memremap(tables, nr_tables * sz, BOOT_DATA);
 	if (!p) {
 		pr_err("Could not map Configuration table!\n");
 		ret = -ENOMEM;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 7d5afdb..00db54a 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2020,7 +2020,7 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 	unsigned long *vaddr;
 	unsigned long val;
 
-	vaddr = early_memremap_ro(addr, sizeof(val));
+	vaddr = early_memremap_ro(addr, sizeof(val), KERNEL_DATA);
 	val = *vaddr;
 	early_memunmap(vaddr, sizeof(val));
 	return val;
@@ -2114,15 +2114,16 @@ void __init xen_relocate_p2m(void)
 	pgd = __va(read_cr3());
 	new_p2m = (unsigned long *)(2 * PGDIR_SIZE);
 	for (idx_pud = 0; idx_pud < n_pud; idx_pud++) {
-		pud = early_memremap(pud_phys, PAGE_SIZE);
+		pud = early_memremap(pud_phys, PAGE_SIZE, KERNEL_DATA);
 		clear_page(pud);
 		for (idx_pmd = 0; idx_pmd < min(n_pmd, PTRS_PER_PUD);
 		     idx_pmd++) {
-			pmd = early_memremap(pmd_phys, PAGE_SIZE);
+			pmd = early_memremap(pmd_phys, PAGE_SIZE, KERNEL_DATA);
 			clear_page(pmd);
 			for (idx_pt = 0; idx_pt < min(n_pt, PTRS_PER_PMD);
 			     idx_pt++) {
-				pt = early_memremap(pt_phys, PAGE_SIZE);
+				pt = early_memremap(pt_phys, PAGE_SIZE,
+						    KERNEL_DATA);
 				clear_page(pt);
 				for (idx_pte = 0;
 				     idx_pte < min(n_pte, PTRS_PER_PTE);
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 1764252..a8e2724 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -686,8 +686,10 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src,
 		if (src_len > (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off)
 			src_len = (NR_FIX_BTMAPS << PAGE_SHIFT) - src_off;
 		len = min(dest_len, src_len);
-		to = early_memremap(dest - dest_off, dest_len + dest_off);
-		from = early_memremap(src - src_off, src_len + src_off);
+		to = early_memremap(dest - dest_off, dest_len + dest_off,
+				    KERNEL_DATA);
+		from = early_memremap(src - src_off, src_len + src_off,
+				      KERNEL_DATA);
 		memcpy(to, from, len);
 		early_memunmap(to, dest_len + dest_off);
 		early_memunmap(from, src_len + src_off);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 9f0ad6e..06b75a2 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -583,7 +583,7 @@ void __init acpi_table_upgrade(void)
 			if (clen > MAP_CHUNK_SIZE - slop)
 				clen = MAP_CHUNK_SIZE - slop;
 			dest_p = early_memremap(dest_addr & PAGE_MASK,
-						clen + slop);
+						clen + slop, BOOT_DATA);
 			memcpy(dest_p + slop, src_p, clen);
 			early_memunmap(dest_p, clen + slop);
 			src_p += clen;
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index c49d50e..0a3fd48 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -67,7 +67,8 @@ static void __init init_screen_info(void)
 	struct screen_info *si;
 
 	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
-		si = early_memremap_ro(screen_info_table, sizeof(*si));
+		si = early_memremap_ro(screen_info_table, sizeof(*si),
+				       BOOT_DATA);
 		if (!si) {
 			pr_err("Could not map screen_info config table\n");
 			return;
@@ -94,7 +95,7 @@ static int __init uefi_init(void)
 	int i, retval;
 
 	efi.systab = early_memremap_ro(efi_system_table,
-				       sizeof(efi_system_table_t));
+				       sizeof(efi_system_table_t), BOOT_DATA);
 	if (efi.systab == NULL) {
 		pr_warn("Unable to map EFI system table.\n");
 		return -ENOMEM;
@@ -121,7 +122,8 @@ static int __init uefi_init(void)
 
 	/* Show what we know for posterity */
 	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
-				sizeof(vendor) * sizeof(efi_char16_t));
+				sizeof(vendor) * sizeof(efi_char16_t),
+				BOOT_DATA);
 	if (c16) {
 		for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
 			vendor[i] = c16[i];
@@ -135,7 +137,7 @@ static int __init uefi_init(void)
 
 	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
 	config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
-					  table_size);
+					  table_size, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_warn("Unable to map EFI config table array.\n");
 		retval = -ENOMEM;
@@ -226,7 +228,8 @@ void __init efi_init(void)
 	efi_system_table = params.system_table;
 
 	efi.memmap.phys_map = params.mmap;
-	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
+	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size,
+					   BOOT_DATA);
 	if (efi.memmap.map == NULL) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631a..f9286c6 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 		 * So just always get our own virtual map on the CPU.
 		 *
 		 */
-		md = early_memremap(p, sizeof (*md));
+		md = early_memremap(p, sizeof (*md), BOOT_DATA);
 		if (!md) {
 			pr_err_once("early_memremap(%pa, %zu) failed.\n",
 				    &p, sizeof (*md));
@@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
 
-		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
+		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
+				     BOOT_DATA);
 		if (tbl == NULL) {
 			pr_err("Could not map Properties table!\n");
 			return -ENOMEM;
@@ -531,7 +532,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	 * Let's see what config tables the firmware passed to us.
 	 */
 	config_tables = early_memremap(efi.systab->tables,
-				       efi.systab->nr_tables * sz);
+				       efi.systab->nr_tables * sz, BOOT_DATA);
 	if (config_tables == NULL) {
 		pr_err("Could not map Configuration table!\n");
 		return -ENOMEM;
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 75feb3f..10ee547 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -273,7 +273,7 @@ void __init efi_esrt_init(void)
 		return;
 	}
 
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
@@ -323,7 +323,7 @@ void __init efi_esrt_init(void)
 	/* remap it with our (plausible) new pages */
 	early_memunmap(va, size);
 	size += entries_size;
-	va = early_memremap(efi.esrt, size);
+	va = early_memremap(efi.esrt, size, BOOT_DATA);
 	if (!va) {
 		pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt,
 		       size);
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index 48430ab..8e87388 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -101,7 +101,8 @@ void __init efi_fake_memmap(void)
 
 	/* create new EFI memmap */
 	new_memmap = early_memremap(new_memmap_phy,
-				    efi.memmap.desc_size * new_nr_map);
+				    efi.memmap.desc_size * new_nr_map,
+				    BOOT_DATA);
 	if (!new_memmap) {
 		memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map);
 		return;
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c
index 236004b..f351c2a 100644
--- a/drivers/firmware/efi/memattr.c
+++ b/drivers/firmware/efi/memattr.c
@@ -28,7 +28,7 @@ int __init efi_memattr_init(void)
 	if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
 		return 0;
 
-	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl), BOOT_DATA);
 	if (!tbl) {
 		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
 		       efi.mem_attr_table);
diff --git a/include/asm-generic/early_ioremap.h b/include/asm-generic/early_ioremap.h
index 2edef8d..61de27a 100644
--- a/include/asm-generic/early_ioremap.h
+++ b/include/asm-generic/early_ioremap.h
@@ -3,6 +3,11 @@
 
 #include <linux/types.h>
 
+enum memremap_owner {
+	KERNEL_DATA = 0,
+	BOOT_DATA,
+};
+
 /*
  * early_ioremap() and early_iounmap() are for temporary early boot-time
  * mappings, before the real ioremap() is functional.
@@ -10,9 +15,13 @@
 extern void __iomem *early_ioremap(resource_size_t phys_addr,
 				   unsigned long size);
 extern void *early_memremap(resource_size_t phys_addr,
-			    unsigned long size);
+			    unsigned long size, enum memremap_owner);
 extern void *early_memremap_ro(resource_size_t phys_addr,
-			       unsigned long size);
+			       unsigned long size, enum memremap_owner);
+/*
+ * When supplying the protection value assume the caller knows the
+ * situation, so the memremap_owner data is not required.
+ */
 extern void *early_memremap_prot(resource_size_t phys_addr,
 				 unsigned long size, unsigned long prot_val);
 extern void early_iounmap(void __iomem *addr, unsigned long size);
@@ -41,7 +50,7 @@ extern void early_ioremap_reset(void);
  * Early copy from unmapped memory to kernel mapped memory.
  */
 extern void copy_from_early_mem(void *dest, phys_addr_t src,
-				unsigned long size);
+				unsigned long size, enum memremap_owner owner);
 
 #else
 static inline void early_ioremap_init(void) { }
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index d71b98b..ad40720 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -34,6 +34,14 @@ void __init __weak early_ioremap_shutdown(void)
 {
 }
 
+pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
+						    unsigned long size,
+						    enum memremap_owner owner,
+						    pgprot_t prot)
+{
+	return prot;
+}
+
 void __init early_ioremap_reset(void)
 {
 	early_ioremap_shutdown();
@@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size,
-					       FIXMAP_PAGE_NORMAL);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_NORMAL);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #ifdef FIXMAP_PAGE_RO
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
-	return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
+	pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
+						     FIXMAP_PAGE_RO);
+
+	return (__force void *)__early_ioremap(phys_addr, size, prot);
 }
 #endif
 
@@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
 
 #define MAX_MAP_CHUNK	(NR_FIX_BTMAPS << PAGE_SHIFT)
 
-void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
+void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
+				enum memremap_owner owner)
 {
 	unsigned long slop, clen;
 	char *p;
@@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
 		clen = size;
 		if (clen > MAX_MAP_CHUNK - slop)
 			clen = MAX_MAP_CHUNK - slop;
-		p = early_memremap(src & PAGE_MASK, clen + slop);
+		p = early_memremap(src & PAGE_MASK, clen + slop, owner);
 		memcpy(dest, p + slop, clen);
 		early_memunmap(p, clen + slop);
 		dest += clen;
@@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
 
 /* Remap memory */
 void __init *
-early_memremap(resource_size_t phys_addr, unsigned long size)
+early_memremap(resource_size_t phys_addr, unsigned long size,
+	       enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }
 void __init *
-early_memremap_ro(resource_size_t phys_addr, unsigned long size)
+early_memremap_ro(resource_size_t phys_addr, unsigned long size,
+		  enum memremap_owner owner)
 {
 	return (void *)phys_addr;
 }

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds support to be change the memory encryption attribute for
one or more memory pages.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cacheflush.h  |    3 +
 arch/x86/include/asm/mem_encrypt.h |   13 ++++++
 arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
 arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)

diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 61518cf..bfb08e5 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -13,6 +13,7 @@
  * Executability : eXeutable, NoteXecutable
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
+ * Encryption    : ENCrypted, DECrypted
  *
  * Within a category, the attributes are mutually exclusive.
  *
@@ -48,6 +49,8 @@ int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
+int set_memory_enc(unsigned long addr, int numpages);
+int set_memory_dec(unsigned long addr, int numpages);
 
 int set_memory_array_uc(unsigned long *addr, int addrinarray);
 int set_memory_array_wc(unsigned long *addr, int addrinarray);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 2785493..5616ed1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,9 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size);
+int sme_set_mem_dec(void *vaddr, unsigned long size);
+
 void __init sme_early_mem_enc(resource_size_t paddr,
 			      unsigned long size);
 void __init sme_early_mem_dec(resource_size_t paddr,
@@ -44,6 +47,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
+static inline int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
 static inline void __init sme_early_mem_enc(resource_size_t paddr,
 					    unsigned long size)
 {
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index f35a646..b0f39c5 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,12 +14,55 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_enc(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_enc);
+
+int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_dec(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_dec);
+
 /*
  * This routine does not change the underlying encryption setting of the
  * page(s) that map this memory. It assumes that eventually the memory is
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 72c292d..0ba9382 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
 					__pgprot(0), 1, 0, NULL);
 }
 
+static int __set_memory_enc_dec(struct cpa_data *cpa)
+{
+	unsigned long addr;
+	int numpages;
+	int ret;
+
+	if (*cpa->vaddr & ~PAGE_MASK) {
+		*cpa->vaddr &= PAGE_MASK;
+
+		/* People should not be passing in unaligned addresses */
+		WARN_ON_ONCE(1);
+	}
+
+	addr = *cpa->vaddr;
+	numpages = cpa->numpages;
+
+	/* Must avoid aliasing mappings in the highmem code */
+	kmap_flush_unused();
+	vm_unmap_aliases();
+
+	ret = __change_page_attr_set_clr(cpa, 1);
+
+	/* Check whether we really changed something */
+	if (!(cpa->flags & CPA_FLUSHTLB))
+		goto out;
+
+	/*
+	 * On success we use CLFLUSH, when the CPU supports it to
+	 * avoid the WBINVD.
+	 */
+	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
+		cpa_flush_range(addr, numpages, 1);
+	else
+		cpa_flush_all(1);
+
+out:
+	return ret;
+}
+
+int set_memory_enc(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(_PAGE_ENC);
+	cpa.mask_clr = __pgprot(0);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_enc);
+
+int set_memory_dec(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(0);
+	cpa.mask_clr = __pgprot(_PAGE_ENC);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_dec);
+
 int set_pages_uc(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds support to be change the memory encryption attribute for
one or more memory pages.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cacheflush.h  |    3 +
 arch/x86/include/asm/mem_encrypt.h |   13 ++++++
 arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
 arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)

diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 61518cf..bfb08e5 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -13,6 +13,7 @@
  * Executability : eXeutable, NoteXecutable
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
+ * Encryption    : ENCrypted, DECrypted
  *
  * Within a category, the attributes are mutually exclusive.
  *
@@ -48,6 +49,8 @@ int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
+int set_memory_enc(unsigned long addr, int numpages);
+int set_memory_dec(unsigned long addr, int numpages);
 
 int set_memory_array_uc(unsigned long *addr, int addrinarray);
 int set_memory_array_wc(unsigned long *addr, int addrinarray);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 2785493..5616ed1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,9 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size);
+int sme_set_mem_dec(void *vaddr, unsigned long size);
+
 void __init sme_early_mem_enc(resource_size_t paddr,
 			      unsigned long size);
 void __init sme_early_mem_dec(resource_size_t paddr,
@@ -44,6 +47,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
+static inline int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
 static inline void __init sme_early_mem_enc(resource_size_t paddr,
 					    unsigned long size)
 {
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index f35a646..b0f39c5 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,12 +14,55 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_enc(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_enc);
+
+int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_dec(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_dec);
+
 /*
  * This routine does not change the underlying encryption setting of the
  * page(s) that map this memory. It assumes that eventually the memory is
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 72c292d..0ba9382 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
 					__pgprot(0), 1, 0, NULL);
 }
 
+static int __set_memory_enc_dec(struct cpa_data *cpa)
+{
+	unsigned long addr;
+	int numpages;
+	int ret;
+
+	if (*cpa->vaddr & ~PAGE_MASK) {
+		*cpa->vaddr &= PAGE_MASK;
+
+		/* People should not be passing in unaligned addresses */
+		WARN_ON_ONCE(1);
+	}
+
+	addr = *cpa->vaddr;
+	numpages = cpa->numpages;
+
+	/* Must avoid aliasing mappings in the highmem code */
+	kmap_flush_unused();
+	vm_unmap_aliases();
+
+	ret = __change_page_attr_set_clr(cpa, 1);
+
+	/* Check whether we really changed something */
+	if (!(cpa->flags & CPA_FLUSHTLB))
+		goto out;
+
+	/*
+	 * On success we use CLFLUSH, when the CPU supports it to
+	 * avoid the WBINVD.
+	 */
+	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
+		cpa_flush_range(addr, numpages, 1);
+	else
+		cpa_flush_all(1);
+
+out:
+	return ret;
+}
+
+int set_memory_enc(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(_PAGE_ENC);
+	cpa.mask_clr = __pgprot(0);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_enc);
+
+int set_memory_dec(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(0);
+	cpa.mask_clr = __pgprot(_PAGE_ENC);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_dec);
+
 int set_pages_uc(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds support to be change the memory encryption attribute for
one or more memory pages.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cacheflush.h  |    3 +
 arch/x86/include/asm/mem_encrypt.h |   13 ++++++
 arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
 arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)

diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 61518cf..bfb08e5 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -13,6 +13,7 @@
  * Executability : eXeutable, NoteXecutable
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
+ * Encryption    : ENCrypted, DECrypted
  *
  * Within a category, the attributes are mutually exclusive.
  *
@@ -48,6 +49,8 @@ int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
+int set_memory_enc(unsigned long addr, int numpages);
+int set_memory_dec(unsigned long addr, int numpages);
 
 int set_memory_array_uc(unsigned long *addr, int addrinarray);
 int set_memory_array_wc(unsigned long *addr, int addrinarray);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 2785493..5616ed1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,9 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size);
+int sme_set_mem_dec(void *vaddr, unsigned long size);
+
 void __init sme_early_mem_enc(resource_size_t paddr,
 			      unsigned long size);
 void __init sme_early_mem_dec(resource_size_t paddr,
@@ -44,6 +47,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
+static inline int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
 static inline void __init sme_early_mem_enc(resource_size_t paddr,
 					    unsigned long size)
 {
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index f35a646..b0f39c5 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,12 +14,55 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_enc(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_enc);
+
+int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_dec(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_dec);
+
 /*
  * This routine does not change the underlying encryption setting of the
  * page(s) that map this memory. It assumes that eventually the memory is
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 72c292d..0ba9382 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
 					__pgprot(0), 1, 0, NULL);
 }
 
+static int __set_memory_enc_dec(struct cpa_data *cpa)
+{
+	unsigned long addr;
+	int numpages;
+	int ret;
+
+	if (*cpa->vaddr & ~PAGE_MASK) {
+		*cpa->vaddr &= PAGE_MASK;
+
+		/* People should not be passing in unaligned addresses */
+		WARN_ON_ONCE(1);
+	}
+
+	addr = *cpa->vaddr;
+	numpages = cpa->numpages;
+
+	/* Must avoid aliasing mappings in the highmem code */
+	kmap_flush_unused();
+	vm_unmap_aliases();
+
+	ret = __change_page_attr_set_clr(cpa, 1);
+
+	/* Check whether we really changed something */
+	if (!(cpa->flags & CPA_FLUSHTLB))
+		goto out;
+
+	/*
+	 * On success we use CLFLUSH, when the CPU supports it to
+	 * avoid the WBINVD.
+	 */
+	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
+		cpa_flush_range(addr, numpages, 1);
+	else
+		cpa_flush_all(1);
+
+out:
+	return ret;
+}
+
+int set_memory_enc(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(_PAGE_ENC);
+	cpa.mask_clr = __pgprot(0);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_enc);
+
+int set_memory_dec(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(0);
+	cpa.mask_clr = __pgprot(_PAGE_ENC);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_dec);
+
 int set_pages_uc(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds support to be change the memory encryption attribute for
one or more memory pages.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/cacheflush.h  |    3 +
 arch/x86/include/asm/mem_encrypt.h |   13 ++++++
 arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
 arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)

diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 61518cf..bfb08e5 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -13,6 +13,7 @@
  * Executability : eXeutable, NoteXecutable
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
+ * Encryption    : ENCrypted, DECrypted
  *
  * Within a category, the attributes are mutually exclusive.
  *
@@ -48,6 +49,8 @@ int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
+int set_memory_enc(unsigned long addr, int numpages);
+int set_memory_dec(unsigned long addr, int numpages);
 
 int set_memory_array_uc(unsigned long *addr, int addrinarray);
 int set_memory_array_wc(unsigned long *addr, int addrinarray);
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 2785493..5616ed1 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -23,6 +23,9 @@ extern unsigned long sme_me_mask;
 
 u8 sme_get_me_loss(void);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size);
+int sme_set_mem_dec(void *vaddr, unsigned long size);
+
 void __init sme_early_mem_enc(resource_size_t paddr,
 			      unsigned long size);
 void __init sme_early_mem_dec(resource_size_t paddr,
@@ -44,6 +47,16 @@ static inline u8 sme_get_me_loss(void)
 	return 0;
 }
 
+static inline int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
+static inline int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	return 0;
+}
+
 static inline void __init sme_early_mem_enc(resource_size_t paddr,
 					    unsigned long size)
 {
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index f35a646..b0f39c5 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -14,12 +14,55 @@
 #include <linux/mm.h>
 
 #include <asm/mem_encrypt.h>
+#include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
 /* Buffer used for early in-place encryption by BSP, no locking needed */
 static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
 
+int sme_set_mem_enc(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_enc(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_enc);
+
+int sme_set_mem_dec(void *vaddr, unsigned long size)
+{
+	unsigned long addr, numpages;
+
+	if (!sme_me_mask)
+		return 0;
+
+	addr = (unsigned long)vaddr & PAGE_MASK;
+	numpages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	/*
+	 * The set_memory_xxx functions take an integer for numpages, make
+	 * sure it doesn't exceed that.
+	 */
+	if (numpages > INT_MAX)
+		return -EINVAL;
+
+	return set_memory_dec(addr, numpages);
+}
+EXPORT_SYMBOL_GPL(sme_set_mem_dec);
+
 /*
  * This routine does not change the underlying encryption setting of the
  * page(s) that map this memory. It assumes that eventually the memory is
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 72c292d..0ba9382 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
 					__pgprot(0), 1, 0, NULL);
 }
 
+static int __set_memory_enc_dec(struct cpa_data *cpa)
+{
+	unsigned long addr;
+	int numpages;
+	int ret;
+
+	if (*cpa->vaddr & ~PAGE_MASK) {
+		*cpa->vaddr &= PAGE_MASK;
+
+		/* People should not be passing in unaligned addresses */
+		WARN_ON_ONCE(1);
+	}
+
+	addr = *cpa->vaddr;
+	numpages = cpa->numpages;
+
+	/* Must avoid aliasing mappings in the highmem code */
+	kmap_flush_unused();
+	vm_unmap_aliases();
+
+	ret = __change_page_attr_set_clr(cpa, 1);
+
+	/* Check whether we really changed something */
+	if (!(cpa->flags & CPA_FLUSHTLB))
+		goto out;
+
+	/*
+	 * On success we use CLFLUSH, when the CPU supports it to
+	 * avoid the WBINVD.
+	 */
+	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
+		cpa_flush_range(addr, numpages, 1);
+	else
+		cpa_flush_all(1);
+
+out:
+	return ret;
+}
+
+int set_memory_enc(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(_PAGE_ENC);
+	cpa.mask_clr = __pgprot(0);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_enc);
+
+int set_memory_dec(unsigned long addr, int numpages)
+{
+	struct cpa_data cpa;
+
+	if (!sme_me_mask)
+		return 0;
+
+	memset(&cpa, 0, sizeof(cpa));
+	cpa.vaddr = &addr;
+	cpa.numpages = numpages;
+	cpa.mask_set = __pgprot(0);
+	cpa.mask_clr = __pgprot(_PAGE_ENC);
+	cpa.pgd = init_mm.pgd;
+
+	return __set_memory_enc_dec(&cpa);
+}
+EXPORT_SYMBOL(set_memory_dec);
+
 int set_pages_uc(struct page *page, int numpages)
 {
 	unsigned long addr = (unsigned long)page_address(page);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:37   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When Secure Memory Encryption is enabled, the trampoline area must not
be encrypted. A cpu running in real mode will not be able to decrypt
memory that has been encrypted because it will not be able to use addresses
with the memory encryption mask.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 5db706f1..f74925f 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -6,6 +6,7 @@
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
+#include <asm/mem_encrypt.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
 	unsigned long text_start =
 		(unsigned long) __va(real_mode_header->text_start);
 
+	/*
+	 * If memory encryption is active, the trampoline area will need to
+	 * be in non-encrypted memory in order to bring up other processors
+	 * successfully.
+	 */
+	sme_early_mem_dec(__pa(base), size);
+	sme_set_mem_dec(base, size);
+
 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
 	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When Secure Memory Encryption is enabled, the trampoline area must not
be encrypted. A cpu running in real mode will not be able to decrypt
memory that has been encrypted because it will not be able to use addresses
with the memory encryption mask.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 5db706f1..f74925f 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -6,6 +6,7 @@
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
+#include <asm/mem_encrypt.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
 	unsigned long text_start =
 		(unsigned long) __va(real_mode_header->text_start);
 
+	/*
+	 * If memory encryption is active, the trampoline area will need to
+	 * be in non-encrypted memory in order to bring up other processors
+	 * successfully.
+	 */
+	sme_early_mem_dec(__pa(base), size);
+	sme_set_mem_dec(base, size);
+
 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
 	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When Secure Memory Encryption is enabled, the trampoline area must not
be encrypted. A cpu running in real mode will not be able to decrypt
memory that has been encrypted because it will not be able to use addresses
with the memory encryption mask.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 5db706f1..f74925f 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -6,6 +6,7 @@
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
+#include <asm/mem_encrypt.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
 	unsigned long text_start =
 		(unsigned long) __va(real_mode_header->text_start);
 
+	/*
+	 * If memory encryption is active, the trampoline area will need to
+	 * be in non-encrypted memory in order to bring up other processors
+	 * successfully.
+	 */
+	sme_early_mem_dec(__pa(base), size);
+	sme_set_mem_dec(base, size);
+
 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
 	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-08-22 22:37   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:37 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

When Secure Memory Encryption is enabled, the trampoline area must not
be encrypted. A cpu running in real mode will not be able to decrypt
memory that has been encrypted because it will not be able to use addresses
with the memory encryption mask.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/realmode/init.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 5db706f1..f74925f 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -6,6 +6,7 @@
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
+#include <asm/mem_encrypt.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
 	unsigned long text_start =
 		(unsigned long) __va(real_mode_header->text_start);
 
+	/*
+	 * If memory encryption is active, the trampoline area will need to
+	 * be in non-encrypted memory in order to bring up other processors
+	 * successfully.
+	 */
+	sme_early_mem_dec(__pa(base), size);
+	sme_set_mem_dec(base, size);
+
 	set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
 	set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
 	set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since DMA addresses will effectively look like 48-bit addresses when the
memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
device performing the DMA does not support 48-bits. SWIOTLB will be
initialized to create un-encrypted bounce buffers for use by these devices.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/dma-mapping.h |    5 ++-
 arch/x86/include/asm/mem_encrypt.h |    6 +++
 arch/x86/kernel/pci-dma.c          |   11 ++++--
 arch/x86/kernel/pci-nommu.c        |    2 +
 arch/x86/kernel/pci-swiotlb.c      |    8 +++--
 arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
 include/linux/swiotlb.h            |    1 +
 init/main.c                        |   13 +++++++
 lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
 9 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4446162..c9cdcae 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -69,12 +70,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr;
+	return paddr | sme_me_mask;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr;
+	return daddr & ~sme_me_mask;
 }
 #endif /* CONFIG_X86_DMA_REMAP */
 
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 5616ed1..384fdfb 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -33,6 +33,12 @@ void __init sme_early_mem_dec(resource_size_t paddr,
 
 void __init sme_early_init(void);
 
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void);
+
+unsigned long swiotlb_get_me_mask(void);
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
+
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
 #define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d30c377..0ce28df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -92,9 +92,12 @@ again:
 	/* CMA can be used only in the context which permits sleeping */
 	if (gfpflags_allow_blocking(flag)) {
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
-		if (page && page_to_phys(page) + size > dma_mask) {
-			dma_release_from_contiguous(dev, page, count);
-			page = NULL;
+		if (page) {
+			addr = phys_to_dma(dev, page_to_phys(page));
+			if (addr + size > dma_mask) {
+				dma_release_from_contiguous(dev, page, count);
+				page = NULL;
+			}
 		}
 	}
 	/* fallback */
@@ -103,7 +106,7 @@ again:
 	if (!page)
 		return NULL;
 
-	addr = page_to_phys(page);
+	addr = phys_to_dma(dev, page_to_phys(page));
 	if (addr + size > dma_mask) {
 		__free_pages(page, get_order(size));
 
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 00e71ce..922c10d 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -30,7 +30,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
 				 enum dma_data_direction dir,
 				 unsigned long attrs)
 {
-	dma_addr_t bus = page_to_phys(page) + offset;
+	dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
 	WARN_ON(size == 0);
 	if (!check_addr("map_single", dev, bus, size))
 		return DMA_ERROR_CODE;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index b47edb8..34a9e524 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -12,6 +12,8 @@
 #include <asm/dma.h>
 #include <asm/xen/swiotlb-xen.h>
 #include <asm/iommu_table.h>
+#include <asm/mem_encrypt.h>
+
 int swiotlb __read_mostly;
 
 void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -64,13 +66,15 @@ static struct dma_map_ops swiotlb_dma_ops = {
  * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
- * option).
+ * option). If memory encryption is enabled then swiotlb will be set
+ * to 1 so that bounce buffers are allocated and used for devices that
+ * do not support the addressing range required for the encryption mask.
  */
 int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	if (swiotlb_force)
+	if (swiotlb_force || sme_me_mask)
 		swiotlb = 1;
 
 	return use_swiotlb;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index b0f39c5..6b2e8bf 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,8 @@
 
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 
 #include <asm/mem_encrypt.h>
 #include <asm/cacheflush.h>
@@ -172,3 +174,23 @@ void __init sme_early_init(void)
 	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
 		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
 }
+
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void)
+{
+	if (!sme_me_mask)
+		return;
+
+	/* Make SWIOTLB use an unencrypted DMA area */
+	swiotlb_clear_encryption();
+}
+
+unsigned long swiotlb_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+	sme_set_mem_dec(vaddr, size);
+}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 5f81f8a..5c909fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
+extern void __init swiotlb_clear_encryption(void);
 
 /*
  * Enumeration for sync targets
diff --git a/init/main.c b/init/main.c
index a8a58e2..82c7cd9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
 }
 #endif
 
+void __init __weak mem_encrypt_init(void)
+{
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
 	 */
 	locking_selftest();
 
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the swiotlb bounce buffers.
+	 * This call will mark the bounce buffers as un-encrypted so
+	 * that the usage of them will not cause "plain-text" data
+	 * to be decrypted when accessed.
+	 */
+	mem_encrypt_init();
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 22e13a0..15d5741 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
 	return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to these functions will be provided.
+ */
+unsigned long __weak swiotlb_get_me_mask(void)
+{
+	return 0;
+}
+
+void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+}
+
+/* For swiotlb, clear memory encryption mask from dma addresses */
+static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
+				      phys_addr_t address)
+{
+	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -159,6 +179,30 @@ void swiotlb_print_info(void)
 	       bytes >> 20, vstart, vend - 1);
 }
 
+/*
+ * If memory encryption is active, the DMA address for an encrypted page may
+ * be beyond the range of the device. If bounce buffers are required be sure
+ * that they are not on an encrypted page. This should be called before the
+ * iotlb area is used.
+ */
+void __init swiotlb_clear_encryption(void)
+{
+	void *vaddr;
+	unsigned long bytes;
+
+	if (no_iotlb_memory || !io_tlb_start || late_alloc)
+		return;
+
+	vaddr = phys_to_virt(io_tlb_start);
+	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
+	swiotlb_set_mem_dec(vaddr, bytes);
+	memset(vaddr, 0, bytes);
+
+	vaddr = phys_to_virt(io_tlb_overflow_buffer);
+	bytes = PAGE_ALIGN(io_tlb_overflow);
+	swiotlb_set_mem_dec(vaddr, bytes);
+}
+
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
 	void *v_overflow_buffer;
@@ -294,6 +338,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
+	/* Keep TLB in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(tlb, bytes);
 	memset(tlb, 0, bytes);
 
 	/*
@@ -304,6 +350,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	if (!v_overflow_buffer)
 		goto cleanup2;
 
+	/* Keep overflow in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(v_overflow_buffer, io_tlb_overflow);
 	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
@@ -541,7 +589,7 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -659,7 +707,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			goto err_warn;
 
 		ret = phys_to_virt(paddr);
-		dev_addr = phys_to_dma(hwdev, paddr);
+		dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
 
 		/* Confirm address can be DMA'd by device */
 		if (dev_addr + size - 1 > dma_mask) {
@@ -758,15 +806,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	map = map_single(dev, phys, size, dir);
 	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = phys_to_dma(dev, map);
+	dev_addr = swiotlb_phys_to_dma(dev, map);
 
 	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -901,7 +949,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
-			sg->dma_address = phys_to_dma(hwdev, map);
+			sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg_dma_len(sg) = sg->length;
@@ -985,7 +1033,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -998,6 +1046,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Since DMA addresses will effectively look like 48-bit addresses when the
memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
device performing the DMA does not support 48-bits. SWIOTLB will be
initialized to create un-encrypted bounce buffers for use by these devices.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/dma-mapping.h |    5 ++-
 arch/x86/include/asm/mem_encrypt.h |    6 +++
 arch/x86/kernel/pci-dma.c          |   11 ++++--
 arch/x86/kernel/pci-nommu.c        |    2 +
 arch/x86/kernel/pci-swiotlb.c      |    8 +++--
 arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
 include/linux/swiotlb.h            |    1 +
 init/main.c                        |   13 +++++++
 lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
 9 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4446162..c9cdcae 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -69,12 +70,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr;
+	return paddr | sme_me_mask;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr;
+	return daddr & ~sme_me_mask;
 }
 #endif /* CONFIG_X86_DMA_REMAP */
 
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 5616ed1..384fdfb 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -33,6 +33,12 @@ void __init sme_early_mem_dec(resource_size_t paddr,
 
 void __init sme_early_init(void);
 
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void);
+
+unsigned long swiotlb_get_me_mask(void);
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
+
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
 #define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d30c377..0ce28df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -92,9 +92,12 @@ again:
 	/* CMA can be used only in the context which permits sleeping */
 	if (gfpflags_allow_blocking(flag)) {
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
-		if (page && page_to_phys(page) + size > dma_mask) {
-			dma_release_from_contiguous(dev, page, count);
-			page = NULL;
+		if (page) {
+			addr = phys_to_dma(dev, page_to_phys(page));
+			if (addr + size > dma_mask) {
+				dma_release_from_contiguous(dev, page, count);
+				page = NULL;
+			}
 		}
 	}
 	/* fallback */
@@ -103,7 +106,7 @@ again:
 	if (!page)
 		return NULL;
 
-	addr = page_to_phys(page);
+	addr = phys_to_dma(dev, page_to_phys(page));
 	if (addr + size > dma_mask) {
 		__free_pages(page, get_order(size));
 
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 00e71ce..922c10d 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -30,7 +30,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
 				 enum dma_data_direction dir,
 				 unsigned long attrs)
 {
-	dma_addr_t bus = page_to_phys(page) + offset;
+	dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
 	WARN_ON(size == 0);
 	if (!check_addr("map_single", dev, bus, size))
 		return DMA_ERROR_CODE;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index b47edb8..34a9e524 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -12,6 +12,8 @@
 #include <asm/dma.h>
 #include <asm/xen/swiotlb-xen.h>
 #include <asm/iommu_table.h>
+#include <asm/mem_encrypt.h>
+
 int swiotlb __read_mostly;
 
 void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -64,13 +66,15 @@ static struct dma_map_ops swiotlb_dma_ops = {
  * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
- * option).
+ * option). If memory encryption is enabled then swiotlb will be set
+ * to 1 so that bounce buffers are allocated and used for devices that
+ * do not support the addressing range required for the encryption mask.
  */
 int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	if (swiotlb_force)
+	if (swiotlb_force || sme_me_mask)
 		swiotlb = 1;
 
 	return use_swiotlb;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index b0f39c5..6b2e8bf 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,8 @@
 
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 
 #include <asm/mem_encrypt.h>
 #include <asm/cacheflush.h>
@@ -172,3 +174,23 @@ void __init sme_early_init(void)
 	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
 		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
 }
+
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void)
+{
+	if (!sme_me_mask)
+		return;
+
+	/* Make SWIOTLB use an unencrypted DMA area */
+	swiotlb_clear_encryption();
+}
+
+unsigned long swiotlb_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+	sme_set_mem_dec(vaddr, size);
+}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 5f81f8a..5c909fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
+extern void __init swiotlb_clear_encryption(void);
 
 /*
  * Enumeration for sync targets
diff --git a/init/main.c b/init/main.c
index a8a58e2..82c7cd9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
 }
 #endif
 
+void __init __weak mem_encrypt_init(void)
+{
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
 	 */
 	locking_selftest();
 
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the swiotlb bounce buffers.
+	 * This call will mark the bounce buffers as un-encrypted so
+	 * that the usage of them will not cause "plain-text" data
+	 * to be decrypted when accessed.
+	 */
+	mem_encrypt_init();
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 22e13a0..15d5741 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
 	return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to these functions will be provided.
+ */
+unsigned long __weak swiotlb_get_me_mask(void)
+{
+	return 0;
+}
+
+void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+}
+
+/* For swiotlb, clear memory encryption mask from dma addresses */
+static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
+				      phys_addr_t address)
+{
+	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -159,6 +179,30 @@ void swiotlb_print_info(void)
 	       bytes >> 20, vstart, vend - 1);
 }
 
+/*
+ * If memory encryption is active, the DMA address for an encrypted page may
+ * be beyond the range of the device. If bounce buffers are required be sure
+ * that they are not on an encrypted page. This should be called before the
+ * iotlb area is used.
+ */
+void __init swiotlb_clear_encryption(void)
+{
+	void *vaddr;
+	unsigned long bytes;
+
+	if (no_iotlb_memory || !io_tlb_start || late_alloc)
+		return;
+
+	vaddr = phys_to_virt(io_tlb_start);
+	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
+	swiotlb_set_mem_dec(vaddr, bytes);
+	memset(vaddr, 0, bytes);
+
+	vaddr = phys_to_virt(io_tlb_overflow_buffer);
+	bytes = PAGE_ALIGN(io_tlb_overflow);
+	swiotlb_set_mem_dec(vaddr, bytes);
+}
+
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
 	void *v_overflow_buffer;
@@ -294,6 +338,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
+	/* Keep TLB in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(tlb, bytes);
 	memset(tlb, 0, bytes);
 
 	/*
@@ -304,6 +350,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	if (!v_overflow_buffer)
 		goto cleanup2;
 
+	/* Keep overflow in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(v_overflow_buffer, io_tlb_overflow);
 	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
@@ -541,7 +589,7 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -659,7 +707,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			goto err_warn;
 
 		ret = phys_to_virt(paddr);
-		dev_addr = phys_to_dma(hwdev, paddr);
+		dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
 
 		/* Confirm address can be DMA'd by device */
 		if (dev_addr + size - 1 > dma_mask) {
@@ -758,15 +806,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	map = map_single(dev, phys, size, dir);
 	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = phys_to_dma(dev, map);
+	dev_addr = swiotlb_phys_to_dma(dev, map);
 
 	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -901,7 +949,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
-			sg->dma_address = phys_to_dma(hwdev, map);
+			sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg_dma_len(sg) = sg->length;
@@ -985,7 +1033,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -998,6 +1046,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since DMA addresses will effectively look like 48-bit addresses when the
memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
device performing the DMA does not support 48-bits. SWIOTLB will be
initialized to create un-encrypted bounce buffers for use by these devices.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/dma-mapping.h |    5 ++-
 arch/x86/include/asm/mem_encrypt.h |    6 +++
 arch/x86/kernel/pci-dma.c          |   11 ++++--
 arch/x86/kernel/pci-nommu.c        |    2 +
 arch/x86/kernel/pci-swiotlb.c      |    8 +++--
 arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
 include/linux/swiotlb.h            |    1 +
 init/main.c                        |   13 +++++++
 lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
 9 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4446162..c9cdcae 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -69,12 +70,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr;
+	return paddr | sme_me_mask;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr;
+	return daddr & ~sme_me_mask;
 }
 #endif /* CONFIG_X86_DMA_REMAP */
 
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 5616ed1..384fdfb 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -33,6 +33,12 @@ void __init sme_early_mem_dec(resource_size_t paddr,
 
 void __init sme_early_init(void);
 
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void);
+
+unsigned long swiotlb_get_me_mask(void);
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
+
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
 #define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d30c377..0ce28df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -92,9 +92,12 @@ again:
 	/* CMA can be used only in the context which permits sleeping */
 	if (gfpflags_allow_blocking(flag)) {
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
-		if (page && page_to_phys(page) + size > dma_mask) {
-			dma_release_from_contiguous(dev, page, count);
-			page = NULL;
+		if (page) {
+			addr = phys_to_dma(dev, page_to_phys(page));
+			if (addr + size > dma_mask) {
+				dma_release_from_contiguous(dev, page, count);
+				page = NULL;
+			}
 		}
 	}
 	/* fallback */
@@ -103,7 +106,7 @@ again:
 	if (!page)
 		return NULL;
 
-	addr = page_to_phys(page);
+	addr = phys_to_dma(dev, page_to_phys(page));
 	if (addr + size > dma_mask) {
 		__free_pages(page, get_order(size));
 
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 00e71ce..922c10d 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -30,7 +30,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
 				 enum dma_data_direction dir,
 				 unsigned long attrs)
 {
-	dma_addr_t bus = page_to_phys(page) + offset;
+	dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
 	WARN_ON(size == 0);
 	if (!check_addr("map_single", dev, bus, size))
 		return DMA_ERROR_CODE;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index b47edb8..34a9e524 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -12,6 +12,8 @@
 #include <asm/dma.h>
 #include <asm/xen/swiotlb-xen.h>
 #include <asm/iommu_table.h>
+#include <asm/mem_encrypt.h>
+
 int swiotlb __read_mostly;
 
 void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -64,13 +66,15 @@ static struct dma_map_ops swiotlb_dma_ops = {
  * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
- * option).
+ * option). If memory encryption is enabled then swiotlb will be set
+ * to 1 so that bounce buffers are allocated and used for devices that
+ * do not support the addressing range required for the encryption mask.
  */
 int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	if (swiotlb_force)
+	if (swiotlb_force || sme_me_mask)
 		swiotlb = 1;
 
 	return use_swiotlb;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index b0f39c5..6b2e8bf 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,8 @@
 
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 
 #include <asm/mem_encrypt.h>
 #include <asm/cacheflush.h>
@@ -172,3 +174,23 @@ void __init sme_early_init(void)
 	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
 		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
 }
+
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void)
+{
+	if (!sme_me_mask)
+		return;
+
+	/* Make SWIOTLB use an unencrypted DMA area */
+	swiotlb_clear_encryption();
+}
+
+unsigned long swiotlb_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+	sme_set_mem_dec(vaddr, size);
+}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 5f81f8a..5c909fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
+extern void __init swiotlb_clear_encryption(void);
 
 /*
  * Enumeration for sync targets
diff --git a/init/main.c b/init/main.c
index a8a58e2..82c7cd9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
 }
 #endif
 
+void __init __weak mem_encrypt_init(void)
+{
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
 	 */
 	locking_selftest();
 
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the swiotlb bounce buffers.
+	 * This call will mark the bounce buffers as un-encrypted so
+	 * that the usage of them will not cause "plain-text" data
+	 * to be decrypted when accessed.
+	 */
+	mem_encrypt_init();
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 22e13a0..15d5741 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
 	return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to these functions will be provided.
+ */
+unsigned long __weak swiotlb_get_me_mask(void)
+{
+	return 0;
+}
+
+void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+}
+
+/* For swiotlb, clear memory encryption mask from dma addresses */
+static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
+				      phys_addr_t address)
+{
+	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -159,6 +179,30 @@ void swiotlb_print_info(void)
 	       bytes >> 20, vstart, vend - 1);
 }
 
+/*
+ * If memory encryption is active, the DMA address for an encrypted page may
+ * be beyond the range of the device. If bounce buffers are required be sure
+ * that they are not on an encrypted page. This should be called before the
+ * iotlb area is used.
+ */
+void __init swiotlb_clear_encryption(void)
+{
+	void *vaddr;
+	unsigned long bytes;
+
+	if (no_iotlb_memory || !io_tlb_start || late_alloc)
+		return;
+
+	vaddr = phys_to_virt(io_tlb_start);
+	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
+	swiotlb_set_mem_dec(vaddr, bytes);
+	memset(vaddr, 0, bytes);
+
+	vaddr = phys_to_virt(io_tlb_overflow_buffer);
+	bytes = PAGE_ALIGN(io_tlb_overflow);
+	swiotlb_set_mem_dec(vaddr, bytes);
+}
+
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
 	void *v_overflow_buffer;
@@ -294,6 +338,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
+	/* Keep TLB in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(tlb, bytes);
 	memset(tlb, 0, bytes);
 
 	/*
@@ -304,6 +350,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	if (!v_overflow_buffer)
 		goto cleanup2;
 
+	/* Keep overflow in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(v_overflow_buffer, io_tlb_overflow);
 	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
@@ -541,7 +589,7 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -659,7 +707,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			goto err_warn;
 
 		ret = phys_to_virt(paddr);
-		dev_addr = phys_to_dma(hwdev, paddr);
+		dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
 
 		/* Confirm address can be DMA'd by device */
 		if (dev_addr + size - 1 > dma_mask) {
@@ -758,15 +806,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	map = map_single(dev, phys, size, dir);
 	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = phys_to_dma(dev, map);
+	dev_addr = swiotlb_phys_to_dma(dev, map);
 
 	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -901,7 +949,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
-			sg->dma_address = phys_to_dma(hwdev, map);
+			sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg_dma_len(sg) = sg->length;
@@ -985,7 +1033,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -998,6 +1046,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Since DMA addresses will effectively look like 48-bit addresses when the
memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
device performing the DMA does not support 48-bits. SWIOTLB will be
initialized to create un-encrypted bounce buffers for use by these devices.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/dma-mapping.h |    5 ++-
 arch/x86/include/asm/mem_encrypt.h |    6 +++
 arch/x86/kernel/pci-dma.c          |   11 ++++--
 arch/x86/kernel/pci-nommu.c        |    2 +
 arch/x86/kernel/pci-swiotlb.c      |    8 +++--
 arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
 include/linux/swiotlb.h            |    1 +
 init/main.c                        |   13 +++++++
 lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
 9 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4446162..c9cdcae 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -69,12 +70,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr;
+	return paddr | sme_me_mask;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr;
+	return daddr & ~sme_me_mask;
 }
 #endif /* CONFIG_X86_DMA_REMAP */
 
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 5616ed1..384fdfb 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -33,6 +33,12 @@ void __init sme_early_mem_dec(resource_size_t paddr,
 
 void __init sme_early_init(void);
 
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void);
+
+unsigned long swiotlb_get_me_mask(void);
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
+
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
 #define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d30c377..0ce28df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -92,9 +92,12 @@ again:
 	/* CMA can be used only in the context which permits sleeping */
 	if (gfpflags_allow_blocking(flag)) {
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
-		if (page && page_to_phys(page) + size > dma_mask) {
-			dma_release_from_contiguous(dev, page, count);
-			page = NULL;
+		if (page) {
+			addr = phys_to_dma(dev, page_to_phys(page));
+			if (addr + size > dma_mask) {
+				dma_release_from_contiguous(dev, page, count);
+				page = NULL;
+			}
 		}
 	}
 	/* fallback */
@@ -103,7 +106,7 @@ again:
 	if (!page)
 		return NULL;
 
-	addr = page_to_phys(page);
+	addr = phys_to_dma(dev, page_to_phys(page));
 	if (addr + size > dma_mask) {
 		__free_pages(page, get_order(size));
 
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 00e71ce..922c10d 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -30,7 +30,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
 				 enum dma_data_direction dir,
 				 unsigned long attrs)
 {
-	dma_addr_t bus = page_to_phys(page) + offset;
+	dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
 	WARN_ON(size == 0);
 	if (!check_addr("map_single", dev, bus, size))
 		return DMA_ERROR_CODE;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index b47edb8..34a9e524 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -12,6 +12,8 @@
 #include <asm/dma.h>
 #include <asm/xen/swiotlb-xen.h>
 #include <asm/iommu_table.h>
+#include <asm/mem_encrypt.h>
+
 int swiotlb __read_mostly;
 
 void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -64,13 +66,15 @@ static struct dma_map_ops swiotlb_dma_ops = {
  * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
- * option).
+ * option). If memory encryption is enabled then swiotlb will be set
+ * to 1 so that bounce buffers are allocated and used for devices that
+ * do not support the addressing range required for the encryption mask.
  */
 int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	if (swiotlb_force)
+	if (swiotlb_force || sme_me_mask)
 		swiotlb = 1;
 
 	return use_swiotlb;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index b0f39c5..6b2e8bf 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,8 @@
 
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 
 #include <asm/mem_encrypt.h>
 #include <asm/cacheflush.h>
@@ -172,3 +174,23 @@ void __init sme_early_init(void)
 	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
 		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
 }
+
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void)
+{
+	if (!sme_me_mask)
+		return;
+
+	/* Make SWIOTLB use an unencrypted DMA area */
+	swiotlb_clear_encryption();
+}
+
+unsigned long swiotlb_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+	sme_set_mem_dec(vaddr, size);
+}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 5f81f8a..5c909fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
+extern void __init swiotlb_clear_encryption(void);
 
 /*
  * Enumeration for sync targets
diff --git a/init/main.c b/init/main.c
index a8a58e2..82c7cd9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
 }
 #endif
 
+void __init __weak mem_encrypt_init(void)
+{
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
 	 */
 	locking_selftest();
 
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the swiotlb bounce buffers.
+	 * This call will mark the bounce buffers as un-encrypted so
+	 * that the usage of them will not cause "plain-text" data
+	 * to be decrypted when accessed.
+	 */
+	mem_encrypt_init();
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 22e13a0..15d5741 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
 	return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to these functions will be provided.
+ */
+unsigned long __weak swiotlb_get_me_mask(void)
+{
+	return 0;
+}
+
+void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+}
+
+/* For swiotlb, clear memory encryption mask from dma addresses */
+static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
+				      phys_addr_t address)
+{
+	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -159,6 +179,30 @@ void swiotlb_print_info(void)
 	       bytes >> 20, vstart, vend - 1);
 }
 
+/*
+ * If memory encryption is active, the DMA address for an encrypted page may
+ * be beyond the range of the device. If bounce buffers are required be sure
+ * that they are not on an encrypted page. This should be called before the
+ * iotlb area is used.
+ */
+void __init swiotlb_clear_encryption(void)
+{
+	void *vaddr;
+	unsigned long bytes;
+
+	if (no_iotlb_memory || !io_tlb_start || late_alloc)
+		return;
+
+	vaddr = phys_to_virt(io_tlb_start);
+	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
+	swiotlb_set_mem_dec(vaddr, bytes);
+	memset(vaddr, 0, bytes);
+
+	vaddr = phys_to_virt(io_tlb_overflow_buffer);
+	bytes = PAGE_ALIGN(io_tlb_overflow);
+	swiotlb_set_mem_dec(vaddr, bytes);
+}
+
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
 	void *v_overflow_buffer;
@@ -294,6 +338,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
+	/* Keep TLB in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(tlb, bytes);
 	memset(tlb, 0, bytes);
 
 	/*
@@ -304,6 +350,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	if (!v_overflow_buffer)
 		goto cleanup2;
 
+	/* Keep overflow in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(v_overflow_buffer, io_tlb_overflow);
 	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
@@ -541,7 +589,7 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -659,7 +707,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			goto err_warn;
 
 		ret = phys_to_virt(paddr);
-		dev_addr = phys_to_dma(hwdev, paddr);
+		dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
 
 		/* Confirm address can be DMA'd by device */
 		if (dev_addr + size - 1 > dma_mask) {
@@ -758,15 +806,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	map = map_single(dev, phys, size, dir);
 	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = phys_to_dma(dev, map);
+	dev_addr = swiotlb_phys_to_dma(dev, map);
 
 	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -901,7 +949,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
-			sg->dma_address = phys_to_dma(hwdev, map);
+			sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg_dma_len(sg) = sg->length;
@@ -985,7 +1033,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -998,6 +1046,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since DMA addresses will effectively look like 48-bit addresses when the
memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
device performing the DMA does not support 48-bits. SWIOTLB will be
initialized to create un-encrypted bounce buffers for use by these devices.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/dma-mapping.h |    5 ++-
 arch/x86/include/asm/mem_encrypt.h |    6 +++
 arch/x86/kernel/pci-dma.c          |   11 ++++--
 arch/x86/kernel/pci-nommu.c        |    2 +
 arch/x86/kernel/pci-swiotlb.c      |    8 +++--
 arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
 include/linux/swiotlb.h            |    1 +
 init/main.c                        |   13 +++++++
 lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
 9 files changed, 115 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4446162..c9cdcae 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/swiotlb.h>
 #include <linux/dma-contiguous.h>
+#include <asm/mem_encrypt.h>
 
 #ifdef CONFIG_ISA
 # define ISA_DMA_BIT_MASK DMA_BIT_MASK(24)
@@ -69,12 +70,12 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
 {
-	return paddr;
+	return paddr | sme_me_mask;
 }
 
 static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
 {
-	return daddr;
+	return daddr & ~sme_me_mask;
 }
 #endif /* CONFIG_X86_DMA_REMAP */
 
diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 5616ed1..384fdfb 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -33,6 +33,12 @@ void __init sme_early_mem_dec(resource_size_t paddr,
 
 void __init sme_early_init(void);
 
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void);
+
+unsigned long swiotlb_get_me_mask(void);
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
+
 #define __sme_pa(x)		(__pa((x)) | sme_me_mask)
 #define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
 
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index d30c377..0ce28df 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -92,9 +92,12 @@ again:
 	/* CMA can be used only in the context which permits sleeping */
 	if (gfpflags_allow_blocking(flag)) {
 		page = dma_alloc_from_contiguous(dev, count, get_order(size));
-		if (page && page_to_phys(page) + size > dma_mask) {
-			dma_release_from_contiguous(dev, page, count);
-			page = NULL;
+		if (page) {
+			addr = phys_to_dma(dev, page_to_phys(page));
+			if (addr + size > dma_mask) {
+				dma_release_from_contiguous(dev, page, count);
+				page = NULL;
+			}
 		}
 	}
 	/* fallback */
@@ -103,7 +106,7 @@ again:
 	if (!page)
 		return NULL;
 
-	addr = page_to_phys(page);
+	addr = phys_to_dma(dev, page_to_phys(page));
 	if (addr + size > dma_mask) {
 		__free_pages(page, get_order(size));
 
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 00e71ce..922c10d 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -30,7 +30,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
 				 enum dma_data_direction dir,
 				 unsigned long attrs)
 {
-	dma_addr_t bus = page_to_phys(page) + offset;
+	dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
 	WARN_ON(size == 0);
 	if (!check_addr("map_single", dev, bus, size))
 		return DMA_ERROR_CODE;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index b47edb8..34a9e524 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -12,6 +12,8 @@
 #include <asm/dma.h>
 #include <asm/xen/swiotlb-xen.h>
 #include <asm/iommu_table.h>
+#include <asm/mem_encrypt.h>
+
 int swiotlb __read_mostly;
 
 void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
@@ -64,13 +66,15 @@ static struct dma_map_ops swiotlb_dma_ops = {
  * pci_swiotlb_detect_override - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
- * option).
+ * option). If memory encryption is enabled then swiotlb will be set
+ * to 1 so that bounce buffers are allocated and used for devices that
+ * do not support the addressing range required for the encryption mask.
  */
 int __init pci_swiotlb_detect_override(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
-	if (swiotlb_force)
+	if (swiotlb_force || sme_me_mask)
 		swiotlb = 1;
 
 	return use_swiotlb;
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index b0f39c5..6b2e8bf 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -12,6 +12,8 @@
 
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 
 #include <asm/mem_encrypt.h>
 #include <asm/cacheflush.h>
@@ -172,3 +174,23 @@ void __init sme_early_init(void)
 	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
 		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
 }
+
+/* Architecture __weak replacement functions */
+void __init mem_encrypt_init(void)
+{
+	if (!sme_me_mask)
+		return;
+
+	/* Make SWIOTLB use an unencrypted DMA area */
+	swiotlb_clear_encryption();
+}
+
+unsigned long swiotlb_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
+void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+	sme_set_mem_dec(vaddr, size);
+}
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 5f81f8a..5c909fc 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
 extern unsigned long swiotlb_nr_tbl(void);
 unsigned long swiotlb_size_or_default(void);
 extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
+extern void __init swiotlb_clear_encryption(void);
 
 /*
  * Enumeration for sync targets
diff --git a/init/main.c b/init/main.c
index a8a58e2..82c7cd9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
 }
 #endif
 
+void __init __weak mem_encrypt_init(void)
+{
+}
+
 /*
  * Set up kernel memory allocators
  */
@@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
 	 */
 	locking_selftest();
 
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the swiotlb bounce buffers.
+	 * This call will mark the bounce buffers as un-encrypted so
+	 * that the usage of them will not cause "plain-text" data
+	 * to be decrypted when accessed.
+	 */
+	mem_encrypt_init();
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start && !initrd_below_start_ok &&
 	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 22e13a0..15d5741 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
 	return size ? size : (IO_TLB_DEFAULT_SIZE);
 }
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to these functions will be provided.
+ */
+unsigned long __weak swiotlb_get_me_mask(void)
+{
+	return 0;
+}
+
+void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
+{
+}
+
+/* For swiotlb, clear memory encryption mask from dma addresses */
+static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
+				      phys_addr_t address)
+{
+	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
+}
+
 /* Note that this doesn't work with highmem page */
 static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
 				      volatile void *address)
@@ -159,6 +179,30 @@ void swiotlb_print_info(void)
 	       bytes >> 20, vstart, vend - 1);
 }
 
+/*
+ * If memory encryption is active, the DMA address for an encrypted page may
+ * be beyond the range of the device. If bounce buffers are required be sure
+ * that they are not on an encrypted page. This should be called before the
+ * iotlb area is used.
+ */
+void __init swiotlb_clear_encryption(void)
+{
+	void *vaddr;
+	unsigned long bytes;
+
+	if (no_iotlb_memory || !io_tlb_start || late_alloc)
+		return;
+
+	vaddr = phys_to_virt(io_tlb_start);
+	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
+	swiotlb_set_mem_dec(vaddr, bytes);
+	memset(vaddr, 0, bytes);
+
+	vaddr = phys_to_virt(io_tlb_overflow_buffer);
+	bytes = PAGE_ALIGN(io_tlb_overflow);
+	swiotlb_set_mem_dec(vaddr, bytes);
+}
+
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
 	void *v_overflow_buffer;
@@ -294,6 +338,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	io_tlb_start = virt_to_phys(tlb);
 	io_tlb_end = io_tlb_start + bytes;
 
+	/* Keep TLB in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(tlb, bytes);
 	memset(tlb, 0, bytes);
 
 	/*
@@ -304,6 +350,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 	if (!v_overflow_buffer)
 		goto cleanup2;
 
+	/* Keep overflow in unencrypted memory if memory encryption is active */
+	swiotlb_set_mem_dec(v_overflow_buffer, io_tlb_overflow);
 	io_tlb_overflow_buffer = virt_to_phys(v_overflow_buffer);
 
 	/*
@@ -541,7 +589,7 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
 	   enum dma_data_direction dir)
 {
-	dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+	dma_addr_t start_dma_addr = swiotlb_phys_to_dma(hwdev, io_tlb_start);
 
 	return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
 }
@@ -659,7 +707,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 			goto err_warn;
 
 		ret = phys_to_virt(paddr);
-		dev_addr = phys_to_dma(hwdev, paddr);
+		dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
 
 		/* Confirm address can be DMA'd by device */
 		if (dev_addr + size - 1 > dma_mask) {
@@ -758,15 +806,15 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 	map = map_single(dev, phys, size, dir);
 	if (map == SWIOTLB_MAP_ERROR) {
 		swiotlb_full(dev, size, dir, 1);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
-	dev_addr = phys_to_dma(dev, map);
+	dev_addr = swiotlb_phys_to_dma(dev, map);
 
 	/* Ensure that the address returned is DMA'ble */
 	if (!dma_capable(dev, dev_addr, size)) {
 		swiotlb_tbl_unmap_single(dev, map, size, dir);
-		return phys_to_dma(dev, io_tlb_overflow_buffer);
+		return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 	}
 
 	return dev_addr;
@@ -901,7 +949,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
 				sg_dma_len(sgl) = 0;
 				return 0;
 			}
-			sg->dma_address = phys_to_dma(hwdev, map);
+			sg->dma_address = swiotlb_phys_to_dma(hwdev, map);
 		} else
 			sg->dma_address = dev_addr;
 		sg_dma_len(sg) = sg->length;
@@ -985,7 +1033,7 @@ EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
-	return (dma_addr == phys_to_dma(hwdev, io_tlb_overflow_buffer));
+	return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
@@ -998,6 +1046,6 @@ EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 int
 swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-	return phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
+	return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:38   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to the AMD IOMMU driver to set the memory encryption mask if
memory encryption is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |    2 ++
 arch/x86/mm/mem_encrypt.c          |    5 +++++
 drivers/iommu/amd_iommu.c          |   10 ++++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 384fdfb..e395729 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -36,6 +36,8 @@ void __init sme_early_init(void);
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void);
 
+unsigned long amd_iommu_get_me_mask(void);
+
 unsigned long swiotlb_get_me_mask(void);
 void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
 
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 6b2e8bf..2f28d87 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
 	swiotlb_clear_encryption();
 }
 
+unsigned long amd_iommu_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
 unsigned long swiotlb_get_me_mask(void)
 {
 	return sme_me_mask;
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 96de97a..63995e3 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -166,6 +166,15 @@ struct dma_ops_domain {
 static struct iova_domain reserved_iova_ranges;
 static struct lock_class_key reserved_rbtree_key;
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to this function will be provided.
+ */
+unsigned long __weak amd_iommu_get_me_mask(void)
+{
+	return 0;
+}
+
 /****************************************************************************
  *
  * Helper functions
@@ -2302,6 +2311,7 @@ static dma_addr_t __map_single(struct device *dev,
 
 	prot = dir2prot(direction);
 
+	paddr |= amd_iommu_get_me_mask();
 	start = address;
 	for (i = 0; i < pages; ++i) {
 		ret = iommu_map_page(&dma_dom->domain, start, paddr,

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to the AMD IOMMU driver to set the memory encryption mask if
memory encryption is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |    2 ++
 arch/x86/mm/mem_encrypt.c          |    5 +++++
 drivers/iommu/amd_iommu.c          |   10 ++++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 384fdfb..e395729 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -36,6 +36,8 @@ void __init sme_early_init(void);
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void);
 
+unsigned long amd_iommu_get_me_mask(void);
+
 unsigned long swiotlb_get_me_mask(void);
 void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
 
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 6b2e8bf..2f28d87 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
 	swiotlb_clear_encryption();
 }
 
+unsigned long amd_iommu_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
 unsigned long swiotlb_get_me_mask(void)
 {
 	return sme_me_mask;
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 96de97a..63995e3 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -166,6 +166,15 @@ struct dma_ops_domain {
 static struct iova_domain reserved_iova_ranges;
 static struct lock_class_key reserved_rbtree_key;
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to this function will be provided.
+ */
+unsigned long __weak amd_iommu_get_me_mask(void)
+{
+	return 0;
+}
+
 /****************************************************************************
  *
  * Helper functions
@@ -2302,6 +2311,7 @@ static dma_addr_t __map_single(struct device *dev,
 
 	prot = dir2prot(direction);
 
+	paddr |= amd_iommu_get_me_mask();
 	start = address;
 	for (i = 0; i < pages; ++i) {
 		ret = iommu_map_page(&dma_dom->domain, start, paddr,

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to the AMD IOMMU driver to set the memory encryption mask if
memory encryption is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |    2 ++
 arch/x86/mm/mem_encrypt.c          |    5 +++++
 drivers/iommu/amd_iommu.c          |   10 ++++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 384fdfb..e395729 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -36,6 +36,8 @@ void __init sme_early_init(void);
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void);
 
+unsigned long amd_iommu_get_me_mask(void);
+
 unsigned long swiotlb_get_me_mask(void);
 void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
 
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 6b2e8bf..2f28d87 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
 	swiotlb_clear_encryption();
 }
 
+unsigned long amd_iommu_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
 unsigned long swiotlb_get_me_mask(void)
 {
 	return sme_me_mask;
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 96de97a..63995e3 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -166,6 +166,15 @@ struct dma_ops_domain {
 static struct iova_domain reserved_iova_ranges;
 static struct lock_class_key reserved_rbtree_key;
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to this function will be provided.
+ */
+unsigned long __weak amd_iommu_get_me_mask(void)
+{
+	return 0;
+}
+
 /****************************************************************************
  *
  * Helper functions
@@ -2302,6 +2311,7 @@ static dma_addr_t __map_single(struct device *dev,
 
 	prot = dir2prot(direction);
 
+	paddr |= amd_iommu_get_me_mask();
 	start = address;
 	for (i = 0; i < pages; ++i) {
 		ret = iommu_map_page(&dma_dom->domain, start, paddr,


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to the AMD IOMMU driver to set the memory encryption mask if
memory encryption is enabled.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/mem_encrypt.h |    2 ++
 arch/x86/mm/mem_encrypt.c          |    5 +++++
 drivers/iommu/amd_iommu.c          |   10 ++++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
index 384fdfb..e395729 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -36,6 +36,8 @@ void __init sme_early_init(void);
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_init(void);
 
+unsigned long amd_iommu_get_me_mask(void);
+
 unsigned long swiotlb_get_me_mask(void);
 void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
 
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 6b2e8bf..2f28d87 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
 	swiotlb_clear_encryption();
 }
 
+unsigned long amd_iommu_get_me_mask(void)
+{
+	return sme_me_mask;
+}
+
 unsigned long swiotlb_get_me_mask(void)
 {
 	return sme_me_mask;
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 96de97a..63995e3 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -166,6 +166,15 @@ struct dma_ops_domain {
 static struct iova_domain reserved_iova_ranges;
 static struct lock_class_key reserved_rbtree_key;
 
+/*
+ * Support for memory encryption. If memory encryption is supported, then an
+ * override to this function will be provided.
+ */
+unsigned long __weak amd_iommu_get_me_mask(void)
+{
+	return 0;
+}
+
 /****************************************************************************
  *
  * Helper functions
@@ -2302,6 +2311,7 @@ static dma_addr_t __map_single(struct device *dev,
 
 	prot = dir2prot(direction);
 
+	paddr |= amd_iommu_get_me_mask();
 	start = address;
 	for (i = 0; i < pages; ++i) {
 		ret = iommu_map_page(&dma_dom->domain, start, paddr,

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:38   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to check if memory encryption is active in the kernel and that
it has been enabled on the AP. If memory encryption is active in the kernel
but has not been enabled on the AP then do not allow the AP to continue
start up.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/msr-index.h     |    2 ++
 arch/x86/include/asm/realmode.h      |   12 ++++++++++++
 arch/x86/realmode/init.c             |    4 ++++
 arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 56f4c66..797d228 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -336,6 +336,8 @@
 #define MSR_K8_TOP_MEM1			0xc001001a
 #define MSR_K8_TOP_MEM2			0xc001001d
 #define MSR_K8_SYSCFG			0xc0010010
+#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT	23
+#define MSR_K8_SYSCFG_MEM_ENCRYPT	(1ULL << MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
 #define MSR_K8_INT_PENDING_MSG		0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK		0x18000000
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 230e190..c89e326 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -1,6 +1,15 @@
 #ifndef _ARCH_X86_REALMODE_H
 #define _ARCH_X86_REALMODE_H
 
+/*
+ * Flag bit definitions for use with the flags field of the trampoline header
+ * when configured for X86_64
+ */
+#define TH_FLAGS_SME_ENABLE_BIT		0
+#define TH_FLAGS_SME_ENABLE		(1ULL << TH_FLAGS_SME_ENABLE_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/io.h>
 
@@ -38,6 +47,7 @@ struct trampoline_header {
 	u64 start;
 	u64 efer;
 	u32 cr4;
+	u32 flags;
 #endif
 };
 
@@ -69,4 +79,6 @@ static inline size_t real_mode_size_needed(void)
 void set_real_mode_mem(phys_addr_t mem, size_t size);
 void reserve_real_mode(void);
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ARCH_X86_REALMODE_H */
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f74925f..c3edb49 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -101,6 +101,10 @@ static void __init setup_real_mode(void)
 	trampoline_cr4_features = &trampoline_header->cr4;
 	*trampoline_cr4_features = mmu_cr4_features;
 
+	trampoline_header->flags = 0;
+	if (sme_me_mask)
+		trampoline_header->flags |= TH_FLAGS_SME_ENABLE;
+
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
 	trampoline_pgd[511] = init_level4_pgt[511].pgd;
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index dac7b20..94e29f4 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/realmode.h>
 #include "realmode.h"
 
 	.text
@@ -92,6 +93,23 @@ ENTRY(startup_32)
 	movl	%edx, %fs
 	movl	%edx, %gs
 
+	/* Check for memory encryption support */
+	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
+	jnc	.Ldone
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jc	.Ldone
+
+	/*
+	 * Memory encryption is enabled but the MSR has not been set on this
+	 * CPU so we can't continue
+	 */
+.Lno_sme:
+	hlt
+	jmp	.Lno_sme
+.Ldone:
+
 	movl	pa_tr_cr4, %eax
 	movl	%eax, %cr4		# Enable PAE mode
 
@@ -147,6 +165,7 @@ GLOBAL(trampoline_header)
 	tr_start:		.space	8
 	GLOBAL(tr_efer)		.space	8
 	GLOBAL(tr_cr4)		.space	4
+	GLOBAL(tr_flags)	.space	4
 END(trampoline_header)
 
 #include "trampoline_common.S"

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to check if memory encryption is active in the kernel and that
it has been enabled on the AP. If memory encryption is active in the kernel
but has not been enabled on the AP then do not allow the AP to continue
start up.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/msr-index.h     |    2 ++
 arch/x86/include/asm/realmode.h      |   12 ++++++++++++
 arch/x86/realmode/init.c             |    4 ++++
 arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 56f4c66..797d228 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -336,6 +336,8 @@
 #define MSR_K8_TOP_MEM1			0xc001001a
 #define MSR_K8_TOP_MEM2			0xc001001d
 #define MSR_K8_SYSCFG			0xc0010010
+#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT	23
+#define MSR_K8_SYSCFG_MEM_ENCRYPT	(1ULL << MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
 #define MSR_K8_INT_PENDING_MSG		0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK		0x18000000
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 230e190..c89e326 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -1,6 +1,15 @@
 #ifndef _ARCH_X86_REALMODE_H
 #define _ARCH_X86_REALMODE_H
 
+/*
+ * Flag bit definitions for use with the flags field of the trampoline header
+ * when configured for X86_64
+ */
+#define TH_FLAGS_SME_ENABLE_BIT		0
+#define TH_FLAGS_SME_ENABLE		(1ULL << TH_FLAGS_SME_ENABLE_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/io.h>
 
@@ -38,6 +47,7 @@ struct trampoline_header {
 	u64 start;
 	u64 efer;
 	u32 cr4;
+	u32 flags;
 #endif
 };
 
@@ -69,4 +79,6 @@ static inline size_t real_mode_size_needed(void)
 void set_real_mode_mem(phys_addr_t mem, size_t size);
 void reserve_real_mode(void);
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ARCH_X86_REALMODE_H */
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f74925f..c3edb49 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -101,6 +101,10 @@ static void __init setup_real_mode(void)
 	trampoline_cr4_features = &trampoline_header->cr4;
 	*trampoline_cr4_features = mmu_cr4_features;
 
+	trampoline_header->flags = 0;
+	if (sme_me_mask)
+		trampoline_header->flags |= TH_FLAGS_SME_ENABLE;
+
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
 	trampoline_pgd[511] = init_level4_pgt[511].pgd;
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index dac7b20..94e29f4 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/realmode.h>
 #include "realmode.h"
 
 	.text
@@ -92,6 +93,23 @@ ENTRY(startup_32)
 	movl	%edx, %fs
 	movl	%edx, %gs
 
+	/* Check for memory encryption support */
+	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
+	jnc	.Ldone
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jc	.Ldone
+
+	/*
+	 * Memory encryption is enabled but the MSR has not been set on this
+	 * CPU so we can't continue
+	 */
+.Lno_sme:
+	hlt
+	jmp	.Lno_sme
+.Ldone:
+
 	movl	pa_tr_cr4, %eax
 	movl	%eax, %cr4		# Enable PAE mode
 
@@ -147,6 +165,7 @@ GLOBAL(trampoline_header)
 	tr_start:		.space	8
 	GLOBAL(tr_efer)		.space	8
 	GLOBAL(tr_cr4)		.space	4
+	GLOBAL(tr_flags)	.space	4
 END(trampoline_header)
 
 #include "trampoline_common.S"

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to check if memory encryption is active in the kernel and that
it has been enabled on the AP. If memory encryption is active in the kernel
but has not been enabled on the AP then do not allow the AP to continue
start up.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/msr-index.h     |    2 ++
 arch/x86/include/asm/realmode.h      |   12 ++++++++++++
 arch/x86/realmode/init.c             |    4 ++++
 arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 56f4c66..797d228 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -336,6 +336,8 @@
 #define MSR_K8_TOP_MEM1			0xc001001a
 #define MSR_K8_TOP_MEM2			0xc001001d
 #define MSR_K8_SYSCFG			0xc0010010
+#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT	23
+#define MSR_K8_SYSCFG_MEM_ENCRYPT	(1ULL << MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
 #define MSR_K8_INT_PENDING_MSG		0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK		0x18000000
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 230e190..c89e326 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -1,6 +1,15 @@
 #ifndef _ARCH_X86_REALMODE_H
 #define _ARCH_X86_REALMODE_H
 
+/*
+ * Flag bit definitions for use with the flags field of the trampoline header
+ * when configured for X86_64
+ */
+#define TH_FLAGS_SME_ENABLE_BIT		0
+#define TH_FLAGS_SME_ENABLE		(1ULL << TH_FLAGS_SME_ENABLE_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/io.h>
 
@@ -38,6 +47,7 @@ struct trampoline_header {
 	u64 start;
 	u64 efer;
 	u32 cr4;
+	u32 flags;
 #endif
 };
 
@@ -69,4 +79,6 @@ static inline size_t real_mode_size_needed(void)
 void set_real_mode_mem(phys_addr_t mem, size_t size);
 void reserve_real_mode(void);
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ARCH_X86_REALMODE_H */
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f74925f..c3edb49 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -101,6 +101,10 @@ static void __init setup_real_mode(void)
 	trampoline_cr4_features = &trampoline_header->cr4;
 	*trampoline_cr4_features = mmu_cr4_features;
 
+	trampoline_header->flags = 0;
+	if (sme_me_mask)
+		trampoline_header->flags |= TH_FLAGS_SME_ENABLE;
+
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
 	trampoline_pgd[511] = init_level4_pgt[511].pgd;
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index dac7b20..94e29f4 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/realmode.h>
 #include "realmode.h"
 
 	.text
@@ -92,6 +93,23 @@ ENTRY(startup_32)
 	movl	%edx, %fs
 	movl	%edx, %gs
 
+	/* Check for memory encryption support */
+	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
+	jnc	.Ldone
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jc	.Ldone
+
+	/*
+	 * Memory encryption is enabled but the MSR has not been set on this
+	 * CPU so we can't continue
+	 */
+.Lno_sme:
+	hlt
+	jmp	.Lno_sme
+.Ldone:
+
 	movl	pa_tr_cr4, %eax
 	movl	%eax, %cr4		# Enable PAE mode
 
@@ -147,6 +165,7 @@ GLOBAL(trampoline_header)
 	tr_start:		.space	8
 	GLOBAL(tr_efer)		.space	8
 	GLOBAL(tr_cr4)		.space	4
+	GLOBAL(tr_flags)	.space	4
 END(trampoline_header)
 
 #include "trampoline_common.S"


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Add support to check if memory encryption is active in the kernel and that
it has been enabled on the AP. If memory encryption is active in the kernel
but has not been enabled on the AP then do not allow the AP to continue
start up.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/msr-index.h     |    2 ++
 arch/x86/include/asm/realmode.h      |   12 ++++++++++++
 arch/x86/realmode/init.c             |    4 ++++
 arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 56f4c66..797d228 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -336,6 +336,8 @@
 #define MSR_K8_TOP_MEM1			0xc001001a
 #define MSR_K8_TOP_MEM2			0xc001001d
 #define MSR_K8_SYSCFG			0xc0010010
+#define MSR_K8_SYSCFG_MEM_ENCRYPT_BIT	23
+#define MSR_K8_SYSCFG_MEM_ENCRYPT	(1ULL << MSR_K8_SYSCFG_MEM_ENCRYPT_BIT)
 #define MSR_K8_INT_PENDING_MSG		0xc0010055
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK		0x18000000
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 230e190..c89e326 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -1,6 +1,15 @@
 #ifndef _ARCH_X86_REALMODE_H
 #define _ARCH_X86_REALMODE_H
 
+/*
+ * Flag bit definitions for use with the flags field of the trampoline header
+ * when configured for X86_64
+ */
+#define TH_FLAGS_SME_ENABLE_BIT		0
+#define TH_FLAGS_SME_ENABLE		(1ULL << TH_FLAGS_SME_ENABLE_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <asm/io.h>
 
@@ -38,6 +47,7 @@ struct trampoline_header {
 	u64 start;
 	u64 efer;
 	u32 cr4;
+	u32 flags;
 #endif
 };
 
@@ -69,4 +79,6 @@ static inline size_t real_mode_size_needed(void)
 void set_real_mode_mem(phys_addr_t mem, size_t size);
 void reserve_real_mode(void);
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ARCH_X86_REALMODE_H */
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f74925f..c3edb49 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -101,6 +101,10 @@ static void __init setup_real_mode(void)
 	trampoline_cr4_features = &trampoline_header->cr4;
 	*trampoline_cr4_features = mmu_cr4_features;
 
+	trampoline_header->flags = 0;
+	if (sme_me_mask)
+		trampoline_header->flags |= TH_FLAGS_SME_ENABLE;
+
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
 	trampoline_pgd[511] = init_level4_pgt[511].pgd;
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index dac7b20..94e29f4 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
+#include <asm/realmode.h>
 #include "realmode.h"
 
 	.text
@@ -92,6 +93,23 @@ ENTRY(startup_32)
 	movl	%edx, %fs
 	movl	%edx, %gs
 
+	/* Check for memory encryption support */
+	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
+	jnc	.Ldone
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jc	.Ldone
+
+	/*
+	 * Memory encryption is enabled but the MSR has not been set on this
+	 * CPU so we can't continue
+	 */
+.Lno_sme:
+	hlt
+	jmp	.Lno_sme
+.Ldone:
+
 	movl	pa_tr_cr4, %eax
 	movl	%eax, %cr4		# Enable PAE mode
 
@@ -147,6 +165,7 @@ GLOBAL(trampoline_header)
 	tr_start:		.space	8
 	GLOBAL(tr_efer)		.space	8
 	GLOBAL(tr_cr4)		.space	4
+	GLOBAL(tr_flags)	.space	4
 END(trampoline_header)
 
 #include "trampoline_common.S"

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 17/20] x86: Do not specify encrypted memory for VGA mapping
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:38   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the VGA memory needs to be accessed unencrypted be sure that the
memory encryption mask is not set for the VGA range being mapped.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/vga.h |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h
index c4b9dc2..55fe164 100644
--- a/arch/x86/include/asm/vga.h
+++ b/arch/x86/include/asm/vga.h
@@ -7,12 +7,25 @@
 #ifndef _ASM_X86_VGA_H
 #define _ASM_X86_VGA_H
 
+#include <asm/mem_encrypt.h>
+
 /*
  *	On the PC, we can just recalculate addresses and then
  *	access the videoram directly without any black magic.
+ *	To support memory encryption however, we need to access
+ *	the videoram as un-encrypted memory.
  */
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define VGA_MAP_MEM(x, s)					\
+({								\
+	unsigned long start = (unsigned long)phys_to_virt(x);	\
+	sme_set_mem_dec((void *)start, s);			\
+	start;							\
+})
+#else
 #define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+#endif
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 17/20] x86: Do not specify encrypted memory for VGA mapping
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the VGA memory needs to be accessed unencrypted be sure that the
memory encryption mask is not set for the VGA range being mapped.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/vga.h |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h
index c4b9dc2..55fe164 100644
--- a/arch/x86/include/asm/vga.h
+++ b/arch/x86/include/asm/vga.h
@@ -7,12 +7,25 @@
 #ifndef _ASM_X86_VGA_H
 #define _ASM_X86_VGA_H
 
+#include <asm/mem_encrypt.h>
+
 /*
  *	On the PC, we can just recalculate addresses and then
  *	access the videoram directly without any black magic.
+ *	To support memory encryption however, we need to access
+ *	the videoram as un-encrypted memory.
  */
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define VGA_MAP_MEM(x, s)					\
+({								\
+	unsigned long start = (unsigned long)phys_to_virt(x);	\
+	sme_set_mem_dec((void *)start, s);			\
+	start;							\
+})
+#else
 #define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+#endif
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 17/20] x86: Do not specify encrypted memory for VGA mapping
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the VGA memory needs to be accessed unencrypted be sure that the
memory encryption mask is not set for the VGA range being mapped.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/vga.h |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h
index c4b9dc2..55fe164 100644
--- a/arch/x86/include/asm/vga.h
+++ b/arch/x86/include/asm/vga.h
@@ -7,12 +7,25 @@
 #ifndef _ASM_X86_VGA_H
 #define _ASM_X86_VGA_H
 
+#include <asm/mem_encrypt.h>
+
 /*
  *	On the PC, we can just recalculate addresses and then
  *	access the videoram directly without any black magic.
+ *	To support memory encryption however, we need to access
+ *	the videoram as un-encrypted memory.
  */
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define VGA_MAP_MEM(x, s)					\
+({								\
+	unsigned long start = (unsigned long)phys_to_virt(x);	\
+	sme_set_mem_dec((void *)start, s);			\
+	start;							\
+})
+#else
 #define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+#endif
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 17/20] x86: Do not specify encrypted memory for VGA mapping
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the VGA memory needs to be accessed unencrypted be sure that the
memory encryption mask is not set for the VGA range being mapped.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/vga.h |   13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h
index c4b9dc2..55fe164 100644
--- a/arch/x86/include/asm/vga.h
+++ b/arch/x86/include/asm/vga.h
@@ -7,12 +7,25 @@
 #ifndef _ASM_X86_VGA_H
 #define _ASM_X86_VGA_H
 
+#include <asm/mem_encrypt.h>
+
 /*
  *	On the PC, we can just recalculate addresses and then
  *	access the videoram directly without any black magic.
+ *	To support memory encryption however, we need to access
+ *	the videoram as un-encrypted memory.
  */
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+#define VGA_MAP_MEM(x, s)					\
+({								\
+	unsigned long start = (unsigned long)phys_to_virt(x);	\
+	sme_set_mem_dec((void *)start, s);			\
+	start;							\
+})
+#else
 #define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
+#endif
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x, y) (*(y) = (x))

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the KVM support to include the memory encryption mask when creating
and using nested page tables.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    3 ++-
 arch/x86/kvm/mmu.c              |    8 ++++++--
 arch/x86/kvm/vmx.c              |    3 ++-
 arch/x86/kvm/x86.c              |    3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 33ae3a4..c51c1cb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3d4cc8cc..a7040f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
 					    * PT32_LEVEL_BITS))) - 1))
 
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
-			| shadow_x_mask | shadow_nx_mask)
+			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -177,6 +177,7 @@ static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
 static u64 __read_mostly shadow_present_mask;
+static u64 __read_mostly shadow_me_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -284,7 +285,8 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
@@ -292,6 +294,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
 	shadow_present_mask = p_mask;
+	shadow_me_mask = me_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2553,6 +2556,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
+	spte |= shadow_me_mask;
 
 	if (pte_access & ACC_WRITE_MASK) {
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 87eaa6b..9040645 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6485,7 +6485,8 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK,
+			0ull);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 19f9f9e..d432894 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -65,6 +65,7 @@
 #include <asm/pvclock.h>
 #include <asm/div64.h>
 #include <asm/irq_remapping.h>
+#include <asm/mem_encrypt.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -5875,7 +5876,7 @@ int kvm_arch_init(void *opaque)
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0,
-			PT_PRESENT_MASK);
+			PT_PRESENT_MASK, sme_me_mask);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Update the KVM support to include the memory encryption mask when creating
and using nested page tables.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/kvm_host.h |    3 ++-
 arch/x86/kvm/mmu.c              |    8 ++++++--
 arch/x86/kvm/vmx.c              |    3 ++-
 arch/x86/kvm/x86.c              |    3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 33ae3a4..c51c1cb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3d4cc8cc..a7040f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
 					    * PT32_LEVEL_BITS))) - 1))
 
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
-			| shadow_x_mask | shadow_nx_mask)
+			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -177,6 +177,7 @@ static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
 static u64 __read_mostly shadow_present_mask;
+static u64 __read_mostly shadow_me_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -284,7 +285,8 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
@@ -292,6 +294,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
 	shadow_present_mask = p_mask;
+	shadow_me_mask = me_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2553,6 +2556,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
+	spte |= shadow_me_mask;
 
 	if (pte_access & ACC_WRITE_MASK) {
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 87eaa6b..9040645 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6485,7 +6485,8 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK,
+			0ull);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 19f9f9e..d432894 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -65,6 +65,7 @@
 #include <asm/pvclock.h>
 #include <asm/div64.h>
 #include <asm/irq_remapping.h>
+#include <asm/mem_encrypt.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -5875,7 +5876,7 @@ int kvm_arch_init(void *opaque)
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0,
-			PT_PRESENT_MASK);
+			PT_PRESENT_MASK, sme_me_mask);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the KVM support to include the memory encryption mask when creating
and using nested page tables.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    3 ++-
 arch/x86/kvm/mmu.c              |    8 ++++++--
 arch/x86/kvm/vmx.c              |    3 ++-
 arch/x86/kvm/x86.c              |    3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 33ae3a4..c51c1cb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3d4cc8cc..a7040f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
 					    * PT32_LEVEL_BITS))) - 1))
 
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
-			| shadow_x_mask | shadow_nx_mask)
+			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -177,6 +177,7 @@ static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
 static u64 __read_mostly shadow_present_mask;
+static u64 __read_mostly shadow_me_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -284,7 +285,8 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
@@ -292,6 +294,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
 	shadow_present_mask = p_mask;
+	shadow_me_mask = me_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2553,6 +2556,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
+	spte |= shadow_me_mask;
 
 	if (pte_access & ACC_WRITE_MASK) {
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 87eaa6b..9040645 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6485,7 +6485,8 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK,
+			0ull);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 19f9f9e..d432894 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -65,6 +65,7 @@
 #include <asm/pvclock.h>
 #include <asm/div64.h>
 #include <asm/irq_remapping.h>
+#include <asm/mem_encrypt.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -5875,7 +5876,7 @@ int kvm_arch_init(void *opaque)
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0,
-			PT_PRESENT_MASK);
+			PT_PRESENT_MASK, sme_me_mask);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
	Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
	Dmitry Vyukov

Update the KVM support to include the memory encryption mask when creating
and using nested page tables.

Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
---
 arch/x86/include/asm/kvm_host.h |    3 ++-
 arch/x86/kvm/mmu.c              |    8 ++++++--
 arch/x86/kvm/vmx.c              |    3 ++-
 arch/x86/kvm/x86.c              |    3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 33ae3a4..c51c1cb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3d4cc8cc..a7040f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
 					    * PT32_LEVEL_BITS))) - 1))
 
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
-			| shadow_x_mask | shadow_nx_mask)
+			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -177,6 +177,7 @@ static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
 static u64 __read_mostly shadow_present_mask;
+static u64 __read_mostly shadow_me_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -284,7 +285,8 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
@@ -292,6 +294,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
 	shadow_present_mask = p_mask;
+	shadow_me_mask = me_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2553,6 +2556,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
+	spte |= shadow_me_mask;
 
 	if (pte_access & ACC_WRITE_MASK) {
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 87eaa6b..9040645 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6485,7 +6485,8 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK,
+			0ull);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 19f9f9e..d432894 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -65,6 +65,7 @@
 #include <asm/pvclock.h>
 #include <asm/div64.h>
 #include <asm/irq_remapping.h>
+#include <asm/mem_encrypt.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -5875,7 +5876,7 @@ int kvm_arch_init(void *opaque)
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0,
-			PT_PRESENT_MASK);
+			PT_PRESENT_MASK, sme_me_mask);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Update the KVM support to include the memory encryption mask when creating
and using nested page tables.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/include/asm/kvm_host.h |    3 ++-
 arch/x86/kvm/mmu.c              |    8 ++++++--
 arch/x86/kvm/vmx.c              |    3 ++-
 arch/x86/kvm/x86.c              |    3 ++-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 33ae3a4..c51c1cb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
 void kvm_mmu_init_vm(struct kvm *kvm);
 void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask);
 
 void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
 void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 3d4cc8cc..a7040f4 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
 					    * PT32_LEVEL_BITS))) - 1))
 
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
-			| shadow_x_mask | shadow_nx_mask)
+			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
 
 #define ACC_EXEC_MASK    1
 #define ACC_WRITE_MASK   PT_WRITABLE_MASK
@@ -177,6 +177,7 @@ static u64 __read_mostly shadow_accessed_mask;
 static u64 __read_mostly shadow_dirty_mask;
 static u64 __read_mostly shadow_mmio_mask;
 static u64 __read_mostly shadow_present_mask;
+static u64 __read_mostly shadow_me_mask;
 
 static void mmu_spte_set(u64 *sptep, u64 spte);
 static void mmu_free_roots(struct kvm_vcpu *vcpu);
@@ -284,7 +285,8 @@ static bool check_mmio_spte(struct kvm_vcpu *vcpu, u64 spte)
 }
 
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
-		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask)
+		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
+		u64 me_mask)
 {
 	shadow_user_mask = user_mask;
 	shadow_accessed_mask = accessed_mask;
@@ -292,6 +294,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
 	shadow_nx_mask = nx_mask;
 	shadow_x_mask = x_mask;
 	shadow_present_mask = p_mask;
+	shadow_me_mask = me_mask;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
 
@@ -2553,6 +2556,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 		pte_access &= ~ACC_WRITE_MASK;
 
 	spte |= (u64)pfn << PAGE_SHIFT;
+	spte |= shadow_me_mask;
 
 	if (pte_access & ACC_WRITE_MASK) {
 
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 87eaa6b..9040645 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6485,7 +6485,8 @@ static __init int hardware_setup(void)
 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull,
 			0ull, VMX_EPT_EXECUTABLE_MASK,
 			cpu_has_vmx_ept_execute_only() ?
-				      0ull : VMX_EPT_READABLE_MASK);
+				      0ull : VMX_EPT_READABLE_MASK,
+			0ull);
 		ept_set_mmio_spte_mask();
 		kvm_enable_tdp();
 	} else
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 19f9f9e..d432894 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -65,6 +65,7 @@
 #include <asm/pvclock.h>
 #include <asm/div64.h>
 #include <asm/irq_remapping.h>
+#include <asm/mem_encrypt.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -5875,7 +5876,7 @@ int kvm_arch_init(void *opaque)
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0,
-			PT_PRESENT_MASK);
+			PT_PRESENT_MASK, sme_me_mask);
 	kvm_timer_init();
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:38   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the setup data is in memory in the clear, it must be accessed as
un-encrypted.  Always use ioremap (similar to sysfs setup data support)
to map the data.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index bdb83e4..a58a82e 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
 
 	pa = node->paddr + sizeof(struct setup_data) + pos;
 	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
-	if (PageHighMem(pg)) {
-		p = ioremap_cache(pa, count);
-		if (!p)
-			return -ENXIO;
-	} else
-		p = __va(pa);
+	p = ioremap_cache(pa, count);
+	if (!p)
+		return -ENXIO;
 
 	remain = copy_to_user(user_buf, p, count);
 
-	if (PageHighMem(pg))
-		iounmap(p);
+	iounmap(p);
 
 	if (remain)
 		return -EFAULT;
@@ -127,15 +123,12 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		}
 
 		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
-		if (PageHighMem(pg)) {
-			data = ioremap_cache(pa_data, sizeof(*data));
-			if (!data) {
-				kfree(node);
-				error = -ENXIO;
-				goto err_dir;
-			}
-		} else
-			data = __va(pa_data);
+		data = ioremap_cache(pa_data, sizeof(*data));
+		if (!data) {
+			kfree(node);
+			error = -ENXIO;
+			goto err_dir;
+		}
 
 		node->paddr = pa_data;
 		node->type = data->type;
@@ -143,8 +136,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		error = create_setup_data_node(d, no, node);
 		pa_data = data->next;
 
-		if (PageHighMem(pg))
-			iounmap(data);
+		iounmap(data);
 		if (error)
 			goto err_dir;
 		no++;

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the setup data is in memory in the clear, it must be accessed as
un-encrypted.  Always use ioremap (similar to sysfs setup data support)
to map the data.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index bdb83e4..a58a82e 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
 
 	pa = node->paddr + sizeof(struct setup_data) + pos;
 	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
-	if (PageHighMem(pg)) {
-		p = ioremap_cache(pa, count);
-		if (!p)
-			return -ENXIO;
-	} else
-		p = __va(pa);
+	p = ioremap_cache(pa, count);
+	if (!p)
+		return -ENXIO;
 
 	remain = copy_to_user(user_buf, p, count);
 
-	if (PageHighMem(pg))
-		iounmap(p);
+	iounmap(p);
 
 	if (remain)
 		return -EFAULT;
@@ -127,15 +123,12 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		}
 
 		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
-		if (PageHighMem(pg)) {
-			data = ioremap_cache(pa_data, sizeof(*data));
-			if (!data) {
-				kfree(node);
-				error = -ENXIO;
-				goto err_dir;
-			}
-		} else
-			data = __va(pa_data);
+		data = ioremap_cache(pa_data, sizeof(*data));
+		if (!data) {
+			kfree(node);
+			error = -ENXIO;
+			goto err_dir;
+		}
 
 		node->paddr = pa_data;
 		node->type = data->type;
@@ -143,8 +136,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		error = create_setup_data_node(d, no, node);
 		pa_data = data->next;
 
-		if (PageHighMem(pg))
-			iounmap(data);
+		iounmap(data);
 		if (error)
 			goto err_dir;
 		no++;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the setup data is in memory in the clear, it must be accessed as
un-encrypted.  Always use ioremap (similar to sysfs setup data support)
to map the data.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index bdb83e4..a58a82e 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
 
 	pa = node->paddr + sizeof(struct setup_data) + pos;
 	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
-	if (PageHighMem(pg)) {
-		p = ioremap_cache(pa, count);
-		if (!p)
-			return -ENXIO;
-	} else
-		p = __va(pa);
+	p = ioremap_cache(pa, count);
+	if (!p)
+		return -ENXIO;
 
 	remain = copy_to_user(user_buf, p, count);
 
-	if (PageHighMem(pg))
-		iounmap(p);
+	iounmap(p);
 
 	if (remain)
 		return -EFAULT;
@@ -127,15 +123,12 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		}
 
 		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
-		if (PageHighMem(pg)) {
-			data = ioremap_cache(pa_data, sizeof(*data));
-			if (!data) {
-				kfree(node);
-				error = -ENXIO;
-				goto err_dir;
-			}
-		} else
-			data = __va(pa_data);
+		data = ioremap_cache(pa_data, sizeof(*data));
+		if (!data) {
+			kfree(node);
+			error = -ENXIO;
+			goto err_dir;
+		}
 
 		node->paddr = pa_data;
 		node->type = data->type;
@@ -143,8 +136,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		error = create_setup_data_node(d, no, node);
 		pa_data = data->next;
 
-		if (PageHighMem(pg))
-			iounmap(data);
+		iounmap(data);
 		if (error)
 			goto err_dir;
 		no++;


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-08-22 22:38   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:38 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

Since the setup data is in memory in the clear, it must be accessed as
un-encrypted.  Always use ioremap (similar to sysfs setup data support)
to map the data.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index bdb83e4..a58a82e 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
 
 	pa = node->paddr + sizeof(struct setup_data) + pos;
 	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
-	if (PageHighMem(pg)) {
-		p = ioremap_cache(pa, count);
-		if (!p)
-			return -ENXIO;
-	} else
-		p = __va(pa);
+	p = ioremap_cache(pa, count);
+	if (!p)
+		return -ENXIO;
 
 	remain = copy_to_user(user_buf, p, count);
 
-	if (PageHighMem(pg))
-		iounmap(p);
+	iounmap(p);
 
 	if (remain)
 		return -EFAULT;
@@ -127,15 +123,12 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		}
 
 		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);
-		if (PageHighMem(pg)) {
-			data = ioremap_cache(pa_data, sizeof(*data));
-			if (!data) {
-				kfree(node);
-				error = -ENXIO;
-				goto err_dir;
-			}
-		} else
-			data = __va(pa_data);
+		data = ioremap_cache(pa_data, sizeof(*data));
+		if (!data) {
+			kfree(node);
+			error = -ENXIO;
+			goto err_dir;
+		}
 
 		node->paddr = pa_data;
 		node->type = data->type;
@@ -143,8 +136,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 		error = create_setup_data_node(d, no, node);
 		pa_data = data->next;
 
-		if (PageHighMem(pg))
-			iounmap(data);
+		iounmap(data);
 		if (error)
 			goto err_dir;
 		no++;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
  2016-08-22 22:35 ` Tom Lendacky
  (?)
  (?)
@ 2016-08-22 22:39   ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:39 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds the support to check if SME has been enabled and if the
mem_encrypt=on command line option is set. If both of these conditions
are true, then the encryption mask is set and the kernel is encrypted
"in place."

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/kernel-parameters.txt |    3 
 arch/x86/kernel/asm-offsets.c       |    2 
 arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
 arch/x86/mm/mem_encrypt.c           |    2 
 4 files changed, 309 insertions(+)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 46c030a..a1986c8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			memory contents and reserves bad memory
 			regions that are detected.
 
+	mem_encrypt=on	[X86_64] Enable memory encryption on processors
+			that support this feature.
+
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
 
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 2bd5c6f..e485ada 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -85,6 +85,8 @@ void common(void) {
 	OFFSET(BP_init_size, boot_params, hdr.init_size);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
+	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
 
 	BLANK();
 	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index f2e0536..bf9f6a9 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -12,13 +12,230 @@
 
 #include <linux/linkage.h>
 
+#include <asm/processor-flags.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/asm-offsets.h>
+
 	.text
 	.code64
 ENTRY(sme_enable)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* Check for AMD processor */
+	xorl	%eax, %eax
+	cpuid
+	cmpl    $0x68747541, %ebx	# AuthenticAMD
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x69746e65, %edx
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x444d4163, %ecx
+	jne     .Lmem_encrypt_exit
+
+	/* Check for memory encryption leaf */
+	movl	$0x80000000, %eax
+	cpuid
+	cmpl	$0x8000001f, %eax
+	jb	.Lmem_encrypt_exit
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 *     Secure Memory Encryption support
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
+	 *     Reduction in physical address space (in bits) when enabled
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check if BIOS/UEFI has allowed memory encryption */
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check for the mem_encrypt=on command line option */
+	push	%rsi			/* Save RSI (real_mode_data) */
+	push	%rbx			/* Save CPUID information */
+	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
+	shlq	$32, %rcx
+	movl	BP_cmd_line_ptr(%rsi), %edi
+	addq	%rcx, %rdi
+	leaq	mem_encrypt_enable_option(%rip), %rsi
+	call	cmdline_find_option_bool
+	pop	%rbx			/* Restore CPUID information */
+	pop	%rsi			/* Restore RSI (real_mode_data) */
+	testl	%eax, %eax
+	jz	.Lno_mem_encrypt
+
+	/* Set memory encryption mask */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	bts	%ecx, sme_me_mask(%rip)
+
+.Lno_mem_encrypt:
+	/*
+	 * BIOS/UEFI has allowed memory encryption so we need to set
+	 * the amount of physical address space reduction even if
+	 * the user decides not to use memory encryption.
+	 */
+	movl	%ebx, %ecx
+	shrl	$6, %ecx
+	andl	$0x3f, %ecx
+	movb	%cl, sme_me_loss(%rip)
+
+.Lmem_encrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_enable)
 
 ENTRY(sme_encrypt_kernel)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* If SME is not active then no need to encrypt the kernel */
+	cmpq	$0, sme_me_mask(%rip)
+	jz	.Lencrypt_exit
+
+	/*
+	 * Encrypt the kernel.
+	 * Pagetables for performing kernel encryption:
+	 *   0x0000000000 - 0x00FFFFFFFF will map just the memory occupied by
+	 *				 the kernel as encrypted memory
+	 *   0x8000000000 - 0x80FFFFFFFF will map all memory as write-protected,
+	 *				 non-encrypted
+	 *
+	 * The use of write-protected memory will prevent any of the
+	 * non-encrypted memory from being cached.
+	 *
+	 * 0x00... and 0x80... represent the first and second PGD entries.
+	 *
+	 * This collection of entries will be created in an area outside
+	 * of the area that is being encrypted (outside the kernel) and
+	 * requires 11 4K pages:
+	 *   1 - PGD
+	 *   2 - PUDs (1 for each mapping)
+	 *   8 - PMDs (4 for each mapping)
+	 */
+	leaq	_end(%rip), %rdi
+	addq	$~PMD_PAGE_MASK, %rdi
+	andq	$PMD_PAGE_MASK, %rdi	/* RDI points to the new PGD */
+
+	/* Clear the pagetable memory */
+	movq	%rdi, %rbx		/* Save pointer to PGD */
+	movl	$(4096 * 11), %ecx
+	xorl	%eax, %eax
+	rep	stosb
+	movq	%rbx, %rdi		/* Restore pointer to PGD */
+
+	/* Set up PGD entries for the two mappings */
+	leaq	(0x1000 + 0x03)(%rdi), %rbx	/* PUD for encrypted kernel */
+	movq	%rbx, (%rdi)
+	leaq	(0x2000 + 0x03)(%rdi), %rbx	/* PUD for unencrypted kernel */
+	movq	%rbx, 8(%rdi)
+
+	/* Set up PUD entries (4 per mapping) for the two mappings */
+	leaq	(0x3000 + 0x03)(%rdi), %rbx	/* PMD for encrypted kernel */
+	leaq	(0x7000 + 0x03)(%rdi), %rdx	/* PMD for unencrypted kernel */
+	xorq	%rcx, %rcx
+1:
+	/* Populate the PUD entries in each mapping */
+	movq	%rbx, 0x1000(%rdi, %rcx, 8)
+	movq	%rdx, 0x2000(%rdi, %rcx, 8)
+	addq	$0x1000, %rbx
+	addq	$0x1000, %rdx
+	incq	%rcx
+	cmpq	$4, %rcx
+	jb	1b
+
+	/*
+	 * Set up PMD entries (4GB worth) for the two mappings.
+	 *   For the encrypted kernel mapping, when R11 is above RDX
+	 *   and below RDI then we know we are in the kernel and we
+	 *   set the encryption mask for that PMD entry.
+	 *
+	 *   The use of _PAGE_PAT and _PAGE_PWT will provide for the
+	 *   write-protected mapping.
+	 */
+	movq	sme_me_mask(%rip), %r10
+	movq	$__PAGE_KERNEL_LARGE_EXEC, %r11
+	andq	$~_PAGE_GLOBAL, %r11
+	movq	%r11, %r12
+	andq	$~_PAGE_CACHE_MASK, %r12
+	orq	$(_PAGE_PAT | _PAGE_PWT), %r12	/* PA5 index */
+	xorq	%rcx, %rcx
+	leaq	_text(%rip), %rdx	/* RDX points to start of kernel */
+1:
+	/* Populate the PMD entries in each mapping */
+	movq	%r11, 0x3000(%rdi, %rcx, 8)
+	movq	%r12, 0x7000(%rdi, %rcx, 8)
+
+	/*
+	 * Check if we are in the kernel range, and if so, set the
+	 * memory encryption mask.
+	 */
+	cmpq	%r11, %rdx
+	jae	2f
+	cmpq	%r11, %rdi
+	jbe	2f
+	orq	%r10, 0x3000(%rdi, %rcx, 8)
+2:
+	addq	$PMD_SIZE, %r11
+	addq	$PMD_SIZE, %r12
+	incq	%rcx
+	cmpq	$2048, %rcx
+	jb	1b
+
+	/*
+	 * Set up a one page stack in the non-encrypted memory area.
+	 *   Set RAX to point to the next page in memory after all the
+	 *   page tables. The stack grows from the bottom so point to
+	 *   the end of the page.
+	 */
+	leaq	(4096 * 11)(%rdi), %rax
+	addq	$PAGE_SIZE, %rax
+	movq	%rsp, %rbp
+	movq	%rax, %rsp
+	push	%rbp			/* Save original stack pointer */
+
+	push	%rsi			/* Save RSI (real mode data) */
+
+	/*
+	 * Copy encryption routine into safe memory
+	 *   - RAX points to the page after all the page tables and stack
+	 *     where the routine will copied
+	 *   - RDI points to the PGD table
+	 *   - Setup registers for call
+	 * and then call it
+	 */
+	movq	%rdi, %rbx
+
+	leaq	.Lencrypt_start(%rip), %rsi
+	movq	%rax, %rdi
+	movq	$(.Lencrypt_stop - .Lencrypt_start), %rcx
+	rep	movsb
+
+	leaq	_text(%rip), %rsi	/* Kernel start */
+	movq	%rbx, %rcx		/* New PGD start */
+	subq	%rsi, %rcx		/* Size of area to encrypt */
+
+	movq	%rsi, %rdi		/* Encrypted kernel space start */
+	movq	$1, %rsi
+	shlq	$PGDIR_SHIFT, %rsi
+	addq	%rdi, %rsi		/* Non-encrypted kernel start */
+
+	/* Call the encryption routine */
+	call	*%rax
+
+	pop	%rsi			/* Restore RSI (real mode data ) */
+
+	pop	%rsp			/* Restore original stack pointer */
+.Lencrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_encrypt_kernel)
 
@@ -28,6 +245,87 @@ ENTRY(sme_get_me_loss)
 	ret
 ENDPROC(sme_get_me_loss)
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * Routine used to encrypt kernel.
+ *   This routine must be run outside of the kernel proper since
+ *   the kernel will be encrypted during the process. So this
+ *   routine is defined here and then copied to an area outside
+ *   of the kernel where it will remain and run un-encrypted
+ *   during execution.
+ *
+ *   On entry the registers must be:
+ *   - RAX points to this routine
+ *   - RBX points to new PGD to use
+ *   - RCX contains the kernel length
+ *   - RSI points to the non-encrypted kernel space
+ *   - RDI points to the encrypted kernel space
+ *
+ * The kernel will be encrypted by copying from the non-encrypted
+ * kernel space to a temporary buffer and then copying from the
+ * temporary buffer back to the encrypted kernel space. The physical
+ * addresses of the two kernel space mappings are the same which
+ * results in the kernel being encrypted "in place".
+ */
+.Lencrypt_start:
+	/* Enable the new page tables */
+	mov	%rbx, %cr3
+
+	/* Flush any global TLBs */
+	mov	%cr4, %rbx
+	andq	$~X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+	orq	$X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+
+	/* Set the PAT register PA5 entry to write-protect */
+	push	%rax
+	push	%rcx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	push	%rdx			/* Save original PAT value */
+	andl	$0xffff00ff, %edx	/* Clear PA5 */
+	orl	$0x00000500, %edx	/* Set PA5 to WP */
+	wrmsr
+	pop	%rdx			/* RDX contains original PAT value */
+	pop	%rcx
+	pop	%rax
+
+	movq	%rsi, %r10		/* Save source address */
+	movq	%rdi, %r11		/* Save destination address */
+	movq	%rcx, %r12		/* Save length */
+	addq	$PAGE_SIZE, %rax	/* RAX now points to temp copy page */
+
+	wbinvd				/* Invalidate any cache entries */
+
+	/* Copy/encrypt 2MB at a time */
+1:
+	movq	%r10, %rsi
+	movq	%rax, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	movq	%rax, %rsi
+	movq	%r11, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	addq	$PMD_PAGE_SIZE, %r10
+	addq	$PMD_PAGE_SIZE, %r11
+	subq	$PMD_PAGE_SIZE, %r12
+	jnz	1b
+
+	/* Restore PAT register */
+	push	%rdx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	pop	%rdx
+	wrmsr
+
+	ret
+.Lencrypt_stop:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	.data
 	.align 16
 ENTRY(sme_me_mask)
@@ -35,3 +333,7 @@ ENTRY(sme_me_mask)
 sme_me_loss:
 	.byte	0x00
 	.align	8
+
+mem_encrypt_enable_option:
+	.asciz "mem_encrypt=on"
+	.align	8
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 2f28d87..1154353 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
 
 	/* Make SWIOTLB use an unencrypted DMA area */
 	swiotlb_clear_encryption();
+
+	pr_info("memory encryption active\n");
 }
 
 unsigned long amd_iommu_get_me_mask(void)

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-08-22 22:39   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:39 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds the support to check if SME has been enabled and if the
mem_encrypt=on command line option is set. If both of these conditions
are true, then the encryption mask is set and the kernel is encrypted
"in place."

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/kernel-parameters.txt |    3 
 arch/x86/kernel/asm-offsets.c       |    2 
 arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
 arch/x86/mm/mem_encrypt.c           |    2 
 4 files changed, 309 insertions(+)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 46c030a..a1986c8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			memory contents and reserves bad memory
 			regions that are detected.
 
+	mem_encrypt=on	[X86_64] Enable memory encryption on processors
+			that support this feature.
+
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
 
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 2bd5c6f..e485ada 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -85,6 +85,8 @@ void common(void) {
 	OFFSET(BP_init_size, boot_params, hdr.init_size);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
+	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
 
 	BLANK();
 	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index f2e0536..bf9f6a9 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -12,13 +12,230 @@
 
 #include <linux/linkage.h>
 
+#include <asm/processor-flags.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/asm-offsets.h>
+
 	.text
 	.code64
 ENTRY(sme_enable)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* Check for AMD processor */
+	xorl	%eax, %eax
+	cpuid
+	cmpl    $0x68747541, %ebx	# AuthenticAMD
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x69746e65, %edx
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x444d4163, %ecx
+	jne     .Lmem_encrypt_exit
+
+	/* Check for memory encryption leaf */
+	movl	$0x80000000, %eax
+	cpuid
+	cmpl	$0x8000001f, %eax
+	jb	.Lmem_encrypt_exit
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 *     Secure Memory Encryption support
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
+	 *     Reduction in physical address space (in bits) when enabled
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check if BIOS/UEFI has allowed memory encryption */
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check for the mem_encrypt=on command line option */
+	push	%rsi			/* Save RSI (real_mode_data) */
+	push	%rbx			/* Save CPUID information */
+	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
+	shlq	$32, %rcx
+	movl	BP_cmd_line_ptr(%rsi), %edi
+	addq	%rcx, %rdi
+	leaq	mem_encrypt_enable_option(%rip), %rsi
+	call	cmdline_find_option_bool
+	pop	%rbx			/* Restore CPUID information */
+	pop	%rsi			/* Restore RSI (real_mode_data) */
+	testl	%eax, %eax
+	jz	.Lno_mem_encrypt
+
+	/* Set memory encryption mask */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	bts	%ecx, sme_me_mask(%rip)
+
+.Lno_mem_encrypt:
+	/*
+	 * BIOS/UEFI has allowed memory encryption so we need to set
+	 * the amount of physical address space reduction even if
+	 * the user decides not to use memory encryption.
+	 */
+	movl	%ebx, %ecx
+	shrl	$6, %ecx
+	andl	$0x3f, %ecx
+	movb	%cl, sme_me_loss(%rip)
+
+.Lmem_encrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_enable)
 
 ENTRY(sme_encrypt_kernel)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* If SME is not active then no need to encrypt the kernel */
+	cmpq	$0, sme_me_mask(%rip)
+	jz	.Lencrypt_exit
+
+	/*
+	 * Encrypt the kernel.
+	 * Pagetables for performing kernel encryption:
+	 *   0x0000000000 - 0x00FFFFFFFF will map just the memory occupied by
+	 *				 the kernel as encrypted memory
+	 *   0x8000000000 - 0x80FFFFFFFF will map all memory as write-protected,
+	 *				 non-encrypted
+	 *
+	 * The use of write-protected memory will prevent any of the
+	 * non-encrypted memory from being cached.
+	 *
+	 * 0x00... and 0x80... represent the first and second PGD entries.
+	 *
+	 * This collection of entries will be created in an area outside
+	 * of the area that is being encrypted (outside the kernel) and
+	 * requires 11 4K pages:
+	 *   1 - PGD
+	 *   2 - PUDs (1 for each mapping)
+	 *   8 - PMDs (4 for each mapping)
+	 */
+	leaq	_end(%rip), %rdi
+	addq	$~PMD_PAGE_MASK, %rdi
+	andq	$PMD_PAGE_MASK, %rdi	/* RDI points to the new PGD */
+
+	/* Clear the pagetable memory */
+	movq	%rdi, %rbx		/* Save pointer to PGD */
+	movl	$(4096 * 11), %ecx
+	xorl	%eax, %eax
+	rep	stosb
+	movq	%rbx, %rdi		/* Restore pointer to PGD */
+
+	/* Set up PGD entries for the two mappings */
+	leaq	(0x1000 + 0x03)(%rdi), %rbx	/* PUD for encrypted kernel */
+	movq	%rbx, (%rdi)
+	leaq	(0x2000 + 0x03)(%rdi), %rbx	/* PUD for unencrypted kernel */
+	movq	%rbx, 8(%rdi)
+
+	/* Set up PUD entries (4 per mapping) for the two mappings */
+	leaq	(0x3000 + 0x03)(%rdi), %rbx	/* PMD for encrypted kernel */
+	leaq	(0x7000 + 0x03)(%rdi), %rdx	/* PMD for unencrypted kernel */
+	xorq	%rcx, %rcx
+1:
+	/* Populate the PUD entries in each mapping */
+	movq	%rbx, 0x1000(%rdi, %rcx, 8)
+	movq	%rdx, 0x2000(%rdi, %rcx, 8)
+	addq	$0x1000, %rbx
+	addq	$0x1000, %rdx
+	incq	%rcx
+	cmpq	$4, %rcx
+	jb	1b
+
+	/*
+	 * Set up PMD entries (4GB worth) for the two mappings.
+	 *   For the encrypted kernel mapping, when R11 is above RDX
+	 *   and below RDI then we know we are in the kernel and we
+	 *   set the encryption mask for that PMD entry.
+	 *
+	 *   The use of _PAGE_PAT and _PAGE_PWT will provide for the
+	 *   write-protected mapping.
+	 */
+	movq	sme_me_mask(%rip), %r10
+	movq	$__PAGE_KERNEL_LARGE_EXEC, %r11
+	andq	$~_PAGE_GLOBAL, %r11
+	movq	%r11, %r12
+	andq	$~_PAGE_CACHE_MASK, %r12
+	orq	$(_PAGE_PAT | _PAGE_PWT), %r12	/* PA5 index */
+	xorq	%rcx, %rcx
+	leaq	_text(%rip), %rdx	/* RDX points to start of kernel */
+1:
+	/* Populate the PMD entries in each mapping */
+	movq	%r11, 0x3000(%rdi, %rcx, 8)
+	movq	%r12, 0x7000(%rdi, %rcx, 8)
+
+	/*
+	 * Check if we are in the kernel range, and if so, set the
+	 * memory encryption mask.
+	 */
+	cmpq	%r11, %rdx
+	jae	2f
+	cmpq	%r11, %rdi
+	jbe	2f
+	orq	%r10, 0x3000(%rdi, %rcx, 8)
+2:
+	addq	$PMD_SIZE, %r11
+	addq	$PMD_SIZE, %r12
+	incq	%rcx
+	cmpq	$2048, %rcx
+	jb	1b
+
+	/*
+	 * Set up a one page stack in the non-encrypted memory area.
+	 *   Set RAX to point to the next page in memory after all the
+	 *   page tables. The stack grows from the bottom so point to
+	 *   the end of the page.
+	 */
+	leaq	(4096 * 11)(%rdi), %rax
+	addq	$PAGE_SIZE, %rax
+	movq	%rsp, %rbp
+	movq	%rax, %rsp
+	push	%rbp			/* Save original stack pointer */
+
+	push	%rsi			/* Save RSI (real mode data) */
+
+	/*
+	 * Copy encryption routine into safe memory
+	 *   - RAX points to the page after all the page tables and stack
+	 *     where the routine will copied
+	 *   - RDI points to the PGD table
+	 *   - Setup registers for call
+	 * and then call it
+	 */
+	movq	%rdi, %rbx
+
+	leaq	.Lencrypt_start(%rip), %rsi
+	movq	%rax, %rdi
+	movq	$(.Lencrypt_stop - .Lencrypt_start), %rcx
+	rep	movsb
+
+	leaq	_text(%rip), %rsi	/* Kernel start */
+	movq	%rbx, %rcx		/* New PGD start */
+	subq	%rsi, %rcx		/* Size of area to encrypt */
+
+	movq	%rsi, %rdi		/* Encrypted kernel space start */
+	movq	$1, %rsi
+	shlq	$PGDIR_SHIFT, %rsi
+	addq	%rdi, %rsi		/* Non-encrypted kernel start */
+
+	/* Call the encryption routine */
+	call	*%rax
+
+	pop	%rsi			/* Restore RSI (real mode data ) */
+
+	pop	%rsp			/* Restore original stack pointer */
+.Lencrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_encrypt_kernel)
 
@@ -28,6 +245,87 @@ ENTRY(sme_get_me_loss)
 	ret
 ENDPROC(sme_get_me_loss)
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * Routine used to encrypt kernel.
+ *   This routine must be run outside of the kernel proper since
+ *   the kernel will be encrypted during the process. So this
+ *   routine is defined here and then copied to an area outside
+ *   of the kernel where it will remain and run un-encrypted
+ *   during execution.
+ *
+ *   On entry the registers must be:
+ *   - RAX points to this routine
+ *   - RBX points to new PGD to use
+ *   - RCX contains the kernel length
+ *   - RSI points to the non-encrypted kernel space
+ *   - RDI points to the encrypted kernel space
+ *
+ * The kernel will be encrypted by copying from the non-encrypted
+ * kernel space to a temporary buffer and then copying from the
+ * temporary buffer back to the encrypted kernel space. The physical
+ * addresses of the two kernel space mappings are the same which
+ * results in the kernel being encrypted "in place".
+ */
+.Lencrypt_start:
+	/* Enable the new page tables */
+	mov	%rbx, %cr3
+
+	/* Flush any global TLBs */
+	mov	%cr4, %rbx
+	andq	$~X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+	orq	$X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+
+	/* Set the PAT register PA5 entry to write-protect */
+	push	%rax
+	push	%rcx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	push	%rdx			/* Save original PAT value */
+	andl	$0xffff00ff, %edx	/* Clear PA5 */
+	orl	$0x00000500, %edx	/* Set PA5 to WP */
+	wrmsr
+	pop	%rdx			/* RDX contains original PAT value */
+	pop	%rcx
+	pop	%rax
+
+	movq	%rsi, %r10		/* Save source address */
+	movq	%rdi, %r11		/* Save destination address */
+	movq	%rcx, %r12		/* Save length */
+	addq	$PAGE_SIZE, %rax	/* RAX now points to temp copy page */
+
+	wbinvd				/* Invalidate any cache entries */
+
+	/* Copy/encrypt 2MB at a time */
+1:
+	movq	%r10, %rsi
+	movq	%rax, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	movq	%rax, %rsi
+	movq	%r11, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	addq	$PMD_PAGE_SIZE, %r10
+	addq	$PMD_PAGE_SIZE, %r11
+	subq	$PMD_PAGE_SIZE, %r12
+	jnz	1b
+
+	/* Restore PAT register */
+	push	%rdx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	pop	%rdx
+	wrmsr
+
+	ret
+.Lencrypt_stop:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	.data
 	.align 16
 ENTRY(sme_me_mask)
@@ -35,3 +333,7 @@ ENTRY(sme_me_mask)
 sme_me_loss:
 	.byte	0x00
 	.align	8
+
+mem_encrypt_enable_option:
+	.asciz "mem_encrypt=on"
+	.align	8
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 2f28d87..1154353 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
 
 	/* Make SWIOTLB use an unencrypted DMA area */
 	swiotlb_clear_encryption();
+
+	pr_info("memory encryption active\n");
 }
 
 unsigned long amd_iommu_get_me_mask(void)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-08-22 22:39   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:39 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds the support to check if SME has been enabled and if the
mem_encrypt=on command line option is set. If both of these conditions
are true, then the encryption mask is set and the kernel is encrypted
"in place."

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/kernel-parameters.txt |    3 
 arch/x86/kernel/asm-offsets.c       |    2 
 arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
 arch/x86/mm/mem_encrypt.c           |    2 
 4 files changed, 309 insertions(+)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 46c030a..a1986c8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			memory contents and reserves bad memory
 			regions that are detected.
 
+	mem_encrypt=on	[X86_64] Enable memory encryption on processors
+			that support this feature.
+
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
 
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 2bd5c6f..e485ada 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -85,6 +85,8 @@ void common(void) {
 	OFFSET(BP_init_size, boot_params, hdr.init_size);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
+	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
 
 	BLANK();
 	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index f2e0536..bf9f6a9 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -12,13 +12,230 @@
 
 #include <linux/linkage.h>
 
+#include <asm/processor-flags.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/asm-offsets.h>
+
 	.text
 	.code64
 ENTRY(sme_enable)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* Check for AMD processor */
+	xorl	%eax, %eax
+	cpuid
+	cmpl    $0x68747541, %ebx	# AuthenticAMD
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x69746e65, %edx
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x444d4163, %ecx
+	jne     .Lmem_encrypt_exit
+
+	/* Check for memory encryption leaf */
+	movl	$0x80000000, %eax
+	cpuid
+	cmpl	$0x8000001f, %eax
+	jb	.Lmem_encrypt_exit
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 *     Secure Memory Encryption support
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
+	 *     Reduction in physical address space (in bits) when enabled
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check if BIOS/UEFI has allowed memory encryption */
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check for the mem_encrypt=on command line option */
+	push	%rsi			/* Save RSI (real_mode_data) */
+	push	%rbx			/* Save CPUID information */
+	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
+	shlq	$32, %rcx
+	movl	BP_cmd_line_ptr(%rsi), %edi
+	addq	%rcx, %rdi
+	leaq	mem_encrypt_enable_option(%rip), %rsi
+	call	cmdline_find_option_bool
+	pop	%rbx			/* Restore CPUID information */
+	pop	%rsi			/* Restore RSI (real_mode_data) */
+	testl	%eax, %eax
+	jz	.Lno_mem_encrypt
+
+	/* Set memory encryption mask */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	bts	%ecx, sme_me_mask(%rip)
+
+.Lno_mem_encrypt:
+	/*
+	 * BIOS/UEFI has allowed memory encryption so we need to set
+	 * the amount of physical address space reduction even if
+	 * the user decides not to use memory encryption.
+	 */
+	movl	%ebx, %ecx
+	shrl	$6, %ecx
+	andl	$0x3f, %ecx
+	movb	%cl, sme_me_loss(%rip)
+
+.Lmem_encrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_enable)
 
 ENTRY(sme_encrypt_kernel)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* If SME is not active then no need to encrypt the kernel */
+	cmpq	$0, sme_me_mask(%rip)
+	jz	.Lencrypt_exit
+
+	/*
+	 * Encrypt the kernel.
+	 * Pagetables for performing kernel encryption:
+	 *   0x0000000000 - 0x00FFFFFFFF will map just the memory occupied by
+	 *				 the kernel as encrypted memory
+	 *   0x8000000000 - 0x80FFFFFFFF will map all memory as write-protected,
+	 *				 non-encrypted
+	 *
+	 * The use of write-protected memory will prevent any of the
+	 * non-encrypted memory from being cached.
+	 *
+	 * 0x00... and 0x80... represent the first and second PGD entries.
+	 *
+	 * This collection of entries will be created in an area outside
+	 * of the area that is being encrypted (outside the kernel) and
+	 * requires 11 4K pages:
+	 *   1 - PGD
+	 *   2 - PUDs (1 for each mapping)
+	 *   8 - PMDs (4 for each mapping)
+	 */
+	leaq	_end(%rip), %rdi
+	addq	$~PMD_PAGE_MASK, %rdi
+	andq	$PMD_PAGE_MASK, %rdi	/* RDI points to the new PGD */
+
+	/* Clear the pagetable memory */
+	movq	%rdi, %rbx		/* Save pointer to PGD */
+	movl	$(4096 * 11), %ecx
+	xorl	%eax, %eax
+	rep	stosb
+	movq	%rbx, %rdi		/* Restore pointer to PGD */
+
+	/* Set up PGD entries for the two mappings */
+	leaq	(0x1000 + 0x03)(%rdi), %rbx	/* PUD for encrypted kernel */
+	movq	%rbx, (%rdi)
+	leaq	(0x2000 + 0x03)(%rdi), %rbx	/* PUD for unencrypted kernel */
+	movq	%rbx, 8(%rdi)
+
+	/* Set up PUD entries (4 per mapping) for the two mappings */
+	leaq	(0x3000 + 0x03)(%rdi), %rbx	/* PMD for encrypted kernel */
+	leaq	(0x7000 + 0x03)(%rdi), %rdx	/* PMD for unencrypted kernel */
+	xorq	%rcx, %rcx
+1:
+	/* Populate the PUD entries in each mapping */
+	movq	%rbx, 0x1000(%rdi, %rcx, 8)
+	movq	%rdx, 0x2000(%rdi, %rcx, 8)
+	addq	$0x1000, %rbx
+	addq	$0x1000, %rdx
+	incq	%rcx
+	cmpq	$4, %rcx
+	jb	1b
+
+	/*
+	 * Set up PMD entries (4GB worth) for the two mappings.
+	 *   For the encrypted kernel mapping, when R11 is above RDX
+	 *   and below RDI then we know we are in the kernel and we
+	 *   set the encryption mask for that PMD entry.
+	 *
+	 *   The use of _PAGE_PAT and _PAGE_PWT will provide for the
+	 *   write-protected mapping.
+	 */
+	movq	sme_me_mask(%rip), %r10
+	movq	$__PAGE_KERNEL_LARGE_EXEC, %r11
+	andq	$~_PAGE_GLOBAL, %r11
+	movq	%r11, %r12
+	andq	$~_PAGE_CACHE_MASK, %r12
+	orq	$(_PAGE_PAT | _PAGE_PWT), %r12	/* PA5 index */
+	xorq	%rcx, %rcx
+	leaq	_text(%rip), %rdx	/* RDX points to start of kernel */
+1:
+	/* Populate the PMD entries in each mapping */
+	movq	%r11, 0x3000(%rdi, %rcx, 8)
+	movq	%r12, 0x7000(%rdi, %rcx, 8)
+
+	/*
+	 * Check if we are in the kernel range, and if so, set the
+	 * memory encryption mask.
+	 */
+	cmpq	%r11, %rdx
+	jae	2f
+	cmpq	%r11, %rdi
+	jbe	2f
+	orq	%r10, 0x3000(%rdi, %rcx, 8)
+2:
+	addq	$PMD_SIZE, %r11
+	addq	$PMD_SIZE, %r12
+	incq	%rcx
+	cmpq	$2048, %rcx
+	jb	1b
+
+	/*
+	 * Set up a one page stack in the non-encrypted memory area.
+	 *   Set RAX to point to the next page in memory after all the
+	 *   page tables. The stack grows from the bottom so point to
+	 *   the end of the page.
+	 */
+	leaq	(4096 * 11)(%rdi), %rax
+	addq	$PAGE_SIZE, %rax
+	movq	%rsp, %rbp
+	movq	%rax, %rsp
+	push	%rbp			/* Save original stack pointer */
+
+	push	%rsi			/* Save RSI (real mode data) */
+
+	/*
+	 * Copy encryption routine into safe memory
+	 *   - RAX points to the page after all the page tables and stack
+	 *     where the routine will copied
+	 *   - RDI points to the PGD table
+	 *   - Setup registers for call
+	 * and then call it
+	 */
+	movq	%rdi, %rbx
+
+	leaq	.Lencrypt_start(%rip), %rsi
+	movq	%rax, %rdi
+	movq	$(.Lencrypt_stop - .Lencrypt_start), %rcx
+	rep	movsb
+
+	leaq	_text(%rip), %rsi	/* Kernel start */
+	movq	%rbx, %rcx		/* New PGD start */
+	subq	%rsi, %rcx		/* Size of area to encrypt */
+
+	movq	%rsi, %rdi		/* Encrypted kernel space start */
+	movq	$1, %rsi
+	shlq	$PGDIR_SHIFT, %rsi
+	addq	%rdi, %rsi		/* Non-encrypted kernel start */
+
+	/* Call the encryption routine */
+	call	*%rax
+
+	pop	%rsi			/* Restore RSI (real mode data ) */
+
+	pop	%rsp			/* Restore original stack pointer */
+.Lencrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_encrypt_kernel)
 
@@ -28,6 +245,87 @@ ENTRY(sme_get_me_loss)
 	ret
 ENDPROC(sme_get_me_loss)
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * Routine used to encrypt kernel.
+ *   This routine must be run outside of the kernel proper since
+ *   the kernel will be encrypted during the process. So this
+ *   routine is defined here and then copied to an area outside
+ *   of the kernel where it will remain and run un-encrypted
+ *   during execution.
+ *
+ *   On entry the registers must be:
+ *   - RAX points to this routine
+ *   - RBX points to new PGD to use
+ *   - RCX contains the kernel length
+ *   - RSI points to the non-encrypted kernel space
+ *   - RDI points to the encrypted kernel space
+ *
+ * The kernel will be encrypted by copying from the non-encrypted
+ * kernel space to a temporary buffer and then copying from the
+ * temporary buffer back to the encrypted kernel space. The physical
+ * addresses of the two kernel space mappings are the same which
+ * results in the kernel being encrypted "in place".
+ */
+.Lencrypt_start:
+	/* Enable the new page tables */
+	mov	%rbx, %cr3
+
+	/* Flush any global TLBs */
+	mov	%cr4, %rbx
+	andq	$~X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+	orq	$X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+
+	/* Set the PAT register PA5 entry to write-protect */
+	push	%rax
+	push	%rcx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	push	%rdx			/* Save original PAT value */
+	andl	$0xffff00ff, %edx	/* Clear PA5 */
+	orl	$0x00000500, %edx	/* Set PA5 to WP */
+	wrmsr
+	pop	%rdx			/* RDX contains original PAT value */
+	pop	%rcx
+	pop	%rax
+
+	movq	%rsi, %r10		/* Save source address */
+	movq	%rdi, %r11		/* Save destination address */
+	movq	%rcx, %r12		/* Save length */
+	addq	$PAGE_SIZE, %rax	/* RAX now points to temp copy page */
+
+	wbinvd				/* Invalidate any cache entries */
+
+	/* Copy/encrypt 2MB at a time */
+1:
+	movq	%r10, %rsi
+	movq	%rax, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	movq	%rax, %rsi
+	movq	%r11, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	addq	$PMD_PAGE_SIZE, %r10
+	addq	$PMD_PAGE_SIZE, %r11
+	subq	$PMD_PAGE_SIZE, %r12
+	jnz	1b
+
+	/* Restore PAT register */
+	push	%rdx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	pop	%rdx
+	wrmsr
+
+	ret
+.Lencrypt_stop:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	.data
 	.align 16
 ENTRY(sme_me_mask)
@@ -35,3 +333,7 @@ ENTRY(sme_me_mask)
 sme_me_loss:
 	.byte	0x00
 	.align	8
+
+mem_encrypt_enable_option:
+	.asciz "mem_encrypt=on"
+	.align	8
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 2f28d87..1154353 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
 
 	/* Make SWIOTLB use an unencrypted DMA area */
 	swiotlb_clear_encryption();
+
+	pr_info("memory encryption active\n");
 }
 
 unsigned long amd_iommu_get_me_mask(void)


^ permalink raw reply related	[flat|nested] 229+ messages in thread

* [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-08-22 22:39   ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-22 22:39 UTC (permalink / raw)
  To: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu
  Cc: Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

This patch adds the support to check if SME has been enabled and if the
mem_encrypt=on command line option is set. If both of these conditions
are true, then the encryption mask is set and the kernel is encrypted
"in place."

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 Documentation/kernel-parameters.txt |    3 
 arch/x86/kernel/asm-offsets.c       |    2 
 arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
 arch/x86/mm/mem_encrypt.c           |    2 
 4 files changed, 309 insertions(+)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 46c030a..a1986c8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			memory contents and reserves bad memory
 			regions that are detected.
 
+	mem_encrypt=on	[X86_64] Enable memory encryption on processors
+			that support this feature.
+
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
 
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 2bd5c6f..e485ada 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -85,6 +85,8 @@ void common(void) {
 	OFFSET(BP_init_size, boot_params, hdr.init_size);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
+	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
 
 	BLANK();
 	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
index f2e0536..bf9f6a9 100644
--- a/arch/x86/kernel/mem_encrypt.S
+++ b/arch/x86/kernel/mem_encrypt.S
@@ -12,13 +12,230 @@
 
 #include <linux/linkage.h>
 
+#include <asm/processor-flags.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/msr.h>
+#include <asm/asm-offsets.h>
+
 	.text
 	.code64
 ENTRY(sme_enable)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* Check for AMD processor */
+	xorl	%eax, %eax
+	cpuid
+	cmpl    $0x68747541, %ebx	# AuthenticAMD
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x69746e65, %edx
+	jne     .Lmem_encrypt_exit
+	cmpl    $0x444d4163, %ecx
+	jne     .Lmem_encrypt_exit
+
+	/* Check for memory encryption leaf */
+	movl	$0x80000000, %eax
+	cpuid
+	cmpl	$0x8000001f, %eax
+	jb	.Lmem_encrypt_exit
+
+	/*
+	 * Check for memory encryption feature:
+	 *   CPUID Fn8000_001F[EAX] - Bit 0
+	 *     Secure Memory Encryption support
+	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
+	 *     Pagetable bit position used to indicate encryption
+	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
+	 *     Reduction in physical address space (in bits) when enabled
+	 */
+	movl	$0x8000001f, %eax
+	cpuid
+	bt	$0, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check if BIOS/UEFI has allowed memory encryption */
+	movl	$MSR_K8_SYSCFG, %ecx
+	rdmsr
+	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
+	jnc	.Lmem_encrypt_exit
+
+	/* Check for the mem_encrypt=on command line option */
+	push	%rsi			/* Save RSI (real_mode_data) */
+	push	%rbx			/* Save CPUID information */
+	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
+	shlq	$32, %rcx
+	movl	BP_cmd_line_ptr(%rsi), %edi
+	addq	%rcx, %rdi
+	leaq	mem_encrypt_enable_option(%rip), %rsi
+	call	cmdline_find_option_bool
+	pop	%rbx			/* Restore CPUID information */
+	pop	%rsi			/* Restore RSI (real_mode_data) */
+	testl	%eax, %eax
+	jz	.Lno_mem_encrypt
+
+	/* Set memory encryption mask */
+	movl	%ebx, %ecx
+	andl	$0x3f, %ecx
+	bts	%ecx, sme_me_mask(%rip)
+
+.Lno_mem_encrypt:
+	/*
+	 * BIOS/UEFI has allowed memory encryption so we need to set
+	 * the amount of physical address space reduction even if
+	 * the user decides not to use memory encryption.
+	 */
+	movl	%ebx, %ecx
+	shrl	$6, %ecx
+	andl	$0x3f, %ecx
+	movb	%cl, sme_me_loss(%rip)
+
+.Lmem_encrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_enable)
 
 ENTRY(sme_encrypt_kernel)
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+	/* If SME is not active then no need to encrypt the kernel */
+	cmpq	$0, sme_me_mask(%rip)
+	jz	.Lencrypt_exit
+
+	/*
+	 * Encrypt the kernel.
+	 * Pagetables for performing kernel encryption:
+	 *   0x0000000000 - 0x00FFFFFFFF will map just the memory occupied by
+	 *				 the kernel as encrypted memory
+	 *   0x8000000000 - 0x80FFFFFFFF will map all memory as write-protected,
+	 *				 non-encrypted
+	 *
+	 * The use of write-protected memory will prevent any of the
+	 * non-encrypted memory from being cached.
+	 *
+	 * 0x00... and 0x80... represent the first and second PGD entries.
+	 *
+	 * This collection of entries will be created in an area outside
+	 * of the area that is being encrypted (outside the kernel) and
+	 * requires 11 4K pages:
+	 *   1 - PGD
+	 *   2 - PUDs (1 for each mapping)
+	 *   8 - PMDs (4 for each mapping)
+	 */
+	leaq	_end(%rip), %rdi
+	addq	$~PMD_PAGE_MASK, %rdi
+	andq	$PMD_PAGE_MASK, %rdi	/* RDI points to the new PGD */
+
+	/* Clear the pagetable memory */
+	movq	%rdi, %rbx		/* Save pointer to PGD */
+	movl	$(4096 * 11), %ecx
+	xorl	%eax, %eax
+	rep	stosb
+	movq	%rbx, %rdi		/* Restore pointer to PGD */
+
+	/* Set up PGD entries for the two mappings */
+	leaq	(0x1000 + 0x03)(%rdi), %rbx	/* PUD for encrypted kernel */
+	movq	%rbx, (%rdi)
+	leaq	(0x2000 + 0x03)(%rdi), %rbx	/* PUD for unencrypted kernel */
+	movq	%rbx, 8(%rdi)
+
+	/* Set up PUD entries (4 per mapping) for the two mappings */
+	leaq	(0x3000 + 0x03)(%rdi), %rbx	/* PMD for encrypted kernel */
+	leaq	(0x7000 + 0x03)(%rdi), %rdx	/* PMD for unencrypted kernel */
+	xorq	%rcx, %rcx
+1:
+	/* Populate the PUD entries in each mapping */
+	movq	%rbx, 0x1000(%rdi, %rcx, 8)
+	movq	%rdx, 0x2000(%rdi, %rcx, 8)
+	addq	$0x1000, %rbx
+	addq	$0x1000, %rdx
+	incq	%rcx
+	cmpq	$4, %rcx
+	jb	1b
+
+	/*
+	 * Set up PMD entries (4GB worth) for the two mappings.
+	 *   For the encrypted kernel mapping, when R11 is above RDX
+	 *   and below RDI then we know we are in the kernel and we
+	 *   set the encryption mask for that PMD entry.
+	 *
+	 *   The use of _PAGE_PAT and _PAGE_PWT will provide for the
+	 *   write-protected mapping.
+	 */
+	movq	sme_me_mask(%rip), %r10
+	movq	$__PAGE_KERNEL_LARGE_EXEC, %r11
+	andq	$~_PAGE_GLOBAL, %r11
+	movq	%r11, %r12
+	andq	$~_PAGE_CACHE_MASK, %r12
+	orq	$(_PAGE_PAT | _PAGE_PWT), %r12	/* PA5 index */
+	xorq	%rcx, %rcx
+	leaq	_text(%rip), %rdx	/* RDX points to start of kernel */
+1:
+	/* Populate the PMD entries in each mapping */
+	movq	%r11, 0x3000(%rdi, %rcx, 8)
+	movq	%r12, 0x7000(%rdi, %rcx, 8)
+
+	/*
+	 * Check if we are in the kernel range, and if so, set the
+	 * memory encryption mask.
+	 */
+	cmpq	%r11, %rdx
+	jae	2f
+	cmpq	%r11, %rdi
+	jbe	2f
+	orq	%r10, 0x3000(%rdi, %rcx, 8)
+2:
+	addq	$PMD_SIZE, %r11
+	addq	$PMD_SIZE, %r12
+	incq	%rcx
+	cmpq	$2048, %rcx
+	jb	1b
+
+	/*
+	 * Set up a one page stack in the non-encrypted memory area.
+	 *   Set RAX to point to the next page in memory after all the
+	 *   page tables. The stack grows from the bottom so point to
+	 *   the end of the page.
+	 */
+	leaq	(4096 * 11)(%rdi), %rax
+	addq	$PAGE_SIZE, %rax
+	movq	%rsp, %rbp
+	movq	%rax, %rsp
+	push	%rbp			/* Save original stack pointer */
+
+	push	%rsi			/* Save RSI (real mode data) */
+
+	/*
+	 * Copy encryption routine into safe memory
+	 *   - RAX points to the page after all the page tables and stack
+	 *     where the routine will copied
+	 *   - RDI points to the PGD table
+	 *   - Setup registers for call
+	 * and then call it
+	 */
+	movq	%rdi, %rbx
+
+	leaq	.Lencrypt_start(%rip), %rsi
+	movq	%rax, %rdi
+	movq	$(.Lencrypt_stop - .Lencrypt_start), %rcx
+	rep	movsb
+
+	leaq	_text(%rip), %rsi	/* Kernel start */
+	movq	%rbx, %rcx		/* New PGD start */
+	subq	%rsi, %rcx		/* Size of area to encrypt */
+
+	movq	%rsi, %rdi		/* Encrypted kernel space start */
+	movq	$1, %rsi
+	shlq	$PGDIR_SHIFT, %rsi
+	addq	%rdi, %rsi		/* Non-encrypted kernel start */
+
+	/* Call the encryption routine */
+	call	*%rax
+
+	pop	%rsi			/* Restore RSI (real mode data ) */
+
+	pop	%rsp			/* Restore original stack pointer */
+.Lencrypt_exit:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	ret
 ENDPROC(sme_encrypt_kernel)
 
@@ -28,6 +245,87 @@ ENTRY(sme_get_me_loss)
 	ret
 ENDPROC(sme_get_me_loss)
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * Routine used to encrypt kernel.
+ *   This routine must be run outside of the kernel proper since
+ *   the kernel will be encrypted during the process. So this
+ *   routine is defined here and then copied to an area outside
+ *   of the kernel where it will remain and run un-encrypted
+ *   during execution.
+ *
+ *   On entry the registers must be:
+ *   - RAX points to this routine
+ *   - RBX points to new PGD to use
+ *   - RCX contains the kernel length
+ *   - RSI points to the non-encrypted kernel space
+ *   - RDI points to the encrypted kernel space
+ *
+ * The kernel will be encrypted by copying from the non-encrypted
+ * kernel space to a temporary buffer and then copying from the
+ * temporary buffer back to the encrypted kernel space. The physical
+ * addresses of the two kernel space mappings are the same which
+ * results in the kernel being encrypted "in place".
+ */
+.Lencrypt_start:
+	/* Enable the new page tables */
+	mov	%rbx, %cr3
+
+	/* Flush any global TLBs */
+	mov	%cr4, %rbx
+	andq	$~X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+	orq	$X86_CR4_PGE, %rbx
+	mov	%rbx, %cr4
+
+	/* Set the PAT register PA5 entry to write-protect */
+	push	%rax
+	push	%rcx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	push	%rdx			/* Save original PAT value */
+	andl	$0xffff00ff, %edx	/* Clear PA5 */
+	orl	$0x00000500, %edx	/* Set PA5 to WP */
+	wrmsr
+	pop	%rdx			/* RDX contains original PAT value */
+	pop	%rcx
+	pop	%rax
+
+	movq	%rsi, %r10		/* Save source address */
+	movq	%rdi, %r11		/* Save destination address */
+	movq	%rcx, %r12		/* Save length */
+	addq	$PAGE_SIZE, %rax	/* RAX now points to temp copy page */
+
+	wbinvd				/* Invalidate any cache entries */
+
+	/* Copy/encrypt 2MB at a time */
+1:
+	movq	%r10, %rsi
+	movq	%rax, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	movq	%rax, %rsi
+	movq	%r11, %rdi
+	movq	$PMD_PAGE_SIZE, %rcx
+	rep	movsb
+
+	addq	$PMD_PAGE_SIZE, %r10
+	addq	$PMD_PAGE_SIZE, %r11
+	subq	$PMD_PAGE_SIZE, %r12
+	jnz	1b
+
+	/* Restore PAT register */
+	push	%rdx
+	movl	$MSR_IA32_CR_PAT, %ecx
+	rdmsr
+	pop	%rdx
+	wrmsr
+
+	ret
+.Lencrypt_stop:
+#endif	/* CONFIG_AMD_MEM_ENCRYPT */
+
 	.data
 	.align 16
 ENTRY(sme_me_mask)
@@ -35,3 +333,7 @@ ENTRY(sme_me_mask)
 sme_me_loss:
 	.byte	0x00
 	.align	8
+
+mem_encrypt_enable_option:
+	.asciz "mem_encrypt=on"
+	.align	8
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 2f28d87..1154353 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
 
 	/* Make SWIOTLB use an unencrypted DMA area */
 	swiotlb_clear_encryption();
+
+	pr_info("memory encryption active\n");
 }
 
 unsigned long amd_iommu_get_me_mask(void)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
@ 2016-08-25  3:58     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-08-25  3:58 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:35:50PM -0500, Tom Lendacky wrote:
> For processors that support PAT, set the write-protect cache mode
> (_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/mm/pat.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Acked-by: Borislav Petkov <bp@suse.de>

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support
@ 2016-08-25  3:58     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-08-25  3:58 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:35:50PM -0500, Tom Lendacky wrote:
> For processors that support PAT, set the write-protect cache mode
> (_PAGE_CACHE_MODE_WP) entry to the actual write-protect value (x05).
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/mm/pat.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Acked-by: Borislav Petkov <bp-l3A5Bk7waGM@public.gmane.org>

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
  2016-08-22 22:36   ` Tom Lendacky
@ 2016-08-25 13:04     ` Thomas Gleixner
  -1 siblings, 0 replies; 229+ messages in thread
From: Thomas Gleixner @ 2016-08-25 13:04 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Dmitry Vyukov

On Mon, 22 Aug 2016, Tom Lendacky wrote:

> Provide support for Secure Memory Encryption (SME). This initial support
> defines the memory encryption mask as a variable for quick access and an
> accessor for retrieving the number of physical addressing bits lost if
> SME is enabled.

What is the reason that this needs to live in assembly code?
 
Thanks,

	tglx

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-25 13:04     ` Thomas Gleixner
  0 siblings, 0 replies; 229+ messages in thread
From: Thomas Gleixner @ 2016-08-25 13:04 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Dmitry Vyukov

On Mon, 22 Aug 2016, Tom Lendacky wrote:

> Provide support for Secure Memory Encryption (SME). This initial support
> defines the memory encryption mask as a variable for quick access and an
> accessor for retrieving the number of physical addressing bits lost if
> SME is enabled.

What is the reason that this needs to live in assembly code?
 
Thanks,

	tglx

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
  2016-08-25 13:04     ` Thomas Gleixner
@ 2016-08-30 13:19       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-30 13:19 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Dmitry Vyukov

On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
> On Mon, 22 Aug 2016, Tom Lendacky wrote:
> 
>> Provide support for Secure Memory Encryption (SME). This initial support
>> defines the memory encryption mask as a variable for quick access and an
>> accessor for retrieving the number of physical addressing bits lost if
>> SME is enabled.
> 
> What is the reason that this needs to live in assembly code?

In later patches this code is expanded and deals with a lot of page
table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
was best to do it this way.

Thanks,
Tom

>  
> Thanks,
> 
> 	tglx
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-30 13:19       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-30 13:19 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Borislav Petkov, Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Dmitry Vyukov

On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
> On Mon, 22 Aug 2016, Tom Lendacky wrote:
> 
>> Provide support for Secure Memory Encryption (SME). This initial support
>> defines the memory encryption mask as a variable for quick access and an
>> accessor for retrieving the number of physical addressing bits lost if
>> SME is enabled.
> 
> What is the reason that this needs to live in assembly code?

In later patches this code is expanded and deals with a lot of page
table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
was best to do it this way.

Thanks,
Tom

>  
> Thanks,
> 
> 	tglx
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-30 14:57         ` Andy Lutomirski
  0 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-08-30 14:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: kasan-dev, linux-efi, linux-arch, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>
> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
> > On Mon, 22 Aug 2016, Tom Lendacky wrote:
> >
> >> Provide support for Secure Memory Encryption (SME). This initial support
> >> defines the memory encryption mask as a variable for quick access and an
> >> accessor for retrieving the number of physical addressing bits lost if
> >> SME is enabled.
> >
> > What is the reason that this needs to live in assembly code?
>
> In later patches this code is expanded and deals with a lot of page
> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
> was best to do it this way.

None of that sounds like it needs to be in asm, though.

I, at least, have a strong preference for minimizing the amount of asm
in the low-level arch code.

--Andy

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-30 14:57         ` Andy Lutomirski
  0 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-08-30 14:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: kasan-dev, linux-efi-u79uwXL29TY76Z2rM5mHXA, linux-arch,
	Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	Matt Fleming, Alexander Potapenko,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Dmitry Vyukov,
	Arnd Bergmann

On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky-5C7GfCeVMHo@public.gmane.org> wrote:
>
> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
> > On Mon, 22 Aug 2016, Tom Lendacky wrote:
> >
> >> Provide support for Secure Memory Encryption (SME). This initial support
> >> defines the memory encryption mask as a variable for quick access and an
> >> accessor for retrieving the number of physical addressing bits lost if
> >> SME is enabled.
> >
> > What is the reason that this needs to live in assembly code?
>
> In later patches this code is expanded and deals with a lot of page
> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
> was best to do it this way.

None of that sounds like it needs to be in asm, though.

I, at least, have a strong preference for minimizing the amount of asm
in the low-level arch code.

--Andy

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-30 14:57         ` Andy Lutomirski
  0 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-08-30 14:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: kasan-dev, linux-efi, linux-arch, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>
> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
> > On Mon, 22 Aug 2016, Tom Lendacky wrote:
> >
> >> Provide support for Secure Memory Encryption (SME). This initial support
> >> defines the memory encryption mask as a variable for quick access and an
> >> accessor for retrieving the number of physical addressing bits lost if
> >> SME is enabled.
> >
> > What is the reason that this needs to live in assembly code?
>
> In later patches this code is expanded and deals with a lot of page
> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
> was best to do it this way.

None of that sounds like it needs to be in asm, though.

I, at least, have a strong preference for minimizing the amount of asm
in the low-level arch code.

--Andy

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
  2016-08-30 14:57         ` Andy Lutomirski
  (?)
@ 2016-08-31 13:26           ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-31 13:26 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: kasan-dev, linux-efi, linux-arch, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On 08/30/2016 09:57 AM, Andy Lutomirski wrote:
> On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>
>> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
>>> On Mon, 22 Aug 2016, Tom Lendacky wrote:
>>>
>>>> Provide support for Secure Memory Encryption (SME). This initial support
>>>> defines the memory encryption mask as a variable for quick access and an
>>>> accessor for retrieving the number of physical addressing bits lost if
>>>> SME is enabled.
>>>
>>> What is the reason that this needs to live in assembly code?
>>
>> In later patches this code is expanded and deals with a lot of page
>> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
>> was best to do it this way.
> 
> None of that sounds like it needs to be in asm, though.
> 
> I, at least, have a strong preference for minimizing the amount of asm
> in the low-level arch code.

I can take a look at converting it over to C code.

Thanks,
Tom

> 
> --Andy
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-31 13:26           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-31 13:26 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: kasan-dev, linux-efi, linux-arch, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann

On 08/30/2016 09:57 AM, Andy Lutomirski wrote:
> On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>
>> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
>>> On Mon, 22 Aug 2016, Tom Lendacky wrote:
>>>
>>>> Provide support for Secure Memory Encryption (SME). This initial support
>>>> defines the memory encryption mask as a variable for quick access and an
>>>> accessor for retrieving the number of physical addressing bits lost if
>>>> SME is enabled.
>>>
>>> What is the reason that this needs to live in assembly code?
>>
>> In later patches this code is expanded and deals with a lot of page
>> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
>> was best to do it this way.
> 
> None of that sounds like it needs to be in asm, though.
> 
> I, at least, have a strong preference for minimizing the amount of asm
> in the low-level arch code.

I can take a look at converting it over to C code.

Thanks,
Tom

> 
> --Andy
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support
@ 2016-08-31 13:26           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-08-31 13:26 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: kasan-dev, linux-efi, linux-arch, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On 08/30/2016 09:57 AM, Andy Lutomirski wrote:
> On Aug 30, 2016 6:34 AM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>
>> On 08/25/2016 08:04 AM, Thomas Gleixner wrote:
>>> On Mon, 22 Aug 2016, Tom Lendacky wrote:
>>>
>>>> Provide support for Secure Memory Encryption (SME). This initial support
>>>> defines the memory encryption mask as a variable for quick access and an
>>>> accessor for retrieving the number of physical addressing bits lost if
>>>> SME is enabled.
>>>
>>> What is the reason that this needs to live in assembly code?
>>
>> In later patches this code is expanded and deals with a lot of page
>> table manipulation, cpuid/rdmsr instructions, etc. and so I thought it
>> was best to do it this way.
> 
> None of that sounds like it needs to be in asm, though.
> 
> I, at least, have a strong preference for minimizing the amount of asm
> in the low-level arch code.

I can take a look at converting it over to C code.

Thanks,
Tom

> 
> --Andy
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-02  8:50     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02  8:50 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:35:39PM -0500, Tom Lendacky wrote:
> This patch adds a Documenation entry to decribe the AMD Secure Memory
> Encryption (SME) feature.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/x86/amd-memory-encryption.txt
> 
> diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
> new file mode 100644
> index 0000000..f19c555
> --- /dev/null
> +++ b/Documentation/x86/amd-memory-encryption.txt
> @@ -0,0 +1,35 @@
> +Secure Memory Encryption (SME) is a feature found on AMD processors.
> +
> +SME provides the ability to mark individual pages of memory as encrypted using
> +the standard x86 page tables.  A page that is marked encrpyted will be

s/encrpyted/encrypted/

> +automatically decrypted when read from DRAM and encrypted when written to
> +DRAM.  SME can therefore be used to protect the contents of DRAM from physical
> +attacks on the system.
> +
> +Support for SME can be determined through the CPUID instruction. The CPUID
> +function 0x8000001f reports information related to SME:
> +
> +	0x8000001f[eax]:
> +		Bit[0] indicates support for SME
> +	0x8000001f[ebx]:
> +		Bit[5:0]  pagetable bit number used to enable memory encryption
> +		Bit[11:6] reduction in physical address space, in bits, when
> +			  memory encryption is enabled (this only affects system
> +			  physical addresses, not guest physical addresses)
> +
> +If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
> +determine if SME is enabled and/or to enable memory encryption:
> +
> +	0xc0010010:
> +		Bit[23]   0 = memory encryption features are disabled
> +			  1 = memory encryption features are enabled
> +
> +Linux relies on BIOS to set this bit if BIOS has determined that the reduction
> +in the physical address space as a result of enabling memory encryption (see
> +CPUID information above) will not conflict with the address space resource
> +requirements for the system.  If this bit is not set upon Linux startup then
> +Linux itself will not set it and memory encryption will not be possible.
> +
> +SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
> +option.

" ... is configurable through CONFIG_AMD_MEM_ENCRYPT."

> Additionally, the mem_encrypt=on command line parameter is required
> +to activate memory encryption.

I think you want to rewrite the logic here to say that people should use
the BIOS option and if none is present for whatever reason, resort to
the alternative "mem_encrypt=on" kernel command line option, no?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-02  8:50     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02  8:50 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:35:39PM -0500, Tom Lendacky wrote:
> This patch adds a Documenation entry to decribe the AMD Secure Memory
> Encryption (SME) feature.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/x86/amd-memory-encryption.txt
> 
> diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
> new file mode 100644
> index 0000000..f19c555
> --- /dev/null
> +++ b/Documentation/x86/amd-memory-encryption.txt
> @@ -0,0 +1,35 @@
> +Secure Memory Encryption (SME) is a feature found on AMD processors.
> +
> +SME provides the ability to mark individual pages of memory as encrypted using
> +the standard x86 page tables.  A page that is marked encrpyted will be

s/encrpyted/encrypted/

> +automatically decrypted when read from DRAM and encrypted when written to
> +DRAM.  SME can therefore be used to protect the contents of DRAM from physical
> +attacks on the system.
> +
> +Support for SME can be determined through the CPUID instruction. The CPUID
> +function 0x8000001f reports information related to SME:
> +
> +	0x8000001f[eax]:
> +		Bit[0] indicates support for SME
> +	0x8000001f[ebx]:
> +		Bit[5:0]  pagetable bit number used to enable memory encryption
> +		Bit[11:6] reduction in physical address space, in bits, when
> +			  memory encryption is enabled (this only affects system
> +			  physical addresses, not guest physical addresses)
> +
> +If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
> +determine if SME is enabled and/or to enable memory encryption:
> +
> +	0xc0010010:
> +		Bit[23]   0 = memory encryption features are disabled
> +			  1 = memory encryption features are enabled
> +
> +Linux relies on BIOS to set this bit if BIOS has determined that the reduction
> +in the physical address space as a result of enabling memory encryption (see
> +CPUID information above) will not conflict with the address space resource
> +requirements for the system.  If this bit is not set upon Linux startup then
> +Linux itself will not set it and memory encryption will not be possible.
> +
> +SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
> +option.

" ... is configurable through CONFIG_AMD_MEM_ENCRYPT."

> Additionally, the mem_encrypt=on command line parameter is required
> +to activate memory encryption.

I think you want to rewrite the logic here to say that people should use
the BIOS option and if none is present for whatever reason, resort to
the alternative "mem_encrypt=on" kernel command line option, no?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-09-02 11:03     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 11:03 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:35:59PM -0500, Tom Lendacky wrote:
> Provide the Kconfig support to build the SME support in the kernel.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/Kconfig |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index c580d8c..131f329 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
>  	  supports them), so don't confuse the user by printing
>  	  that we have them enabled.
>  
> +config AMD_MEM_ENCRYPT
> +	bool "Secure Memory Encryption support for AMD"

	     "AMD Secure Memory Encryption support"

> +	depends on X86_64 && CPU_SUP_AMD
> +	---help---
> +	  Say yes to enable the encryption of system memory. This requires
> +	  an AMD processor that supports Secure Memory Encryption (SME).
> +	  The encryption of system memory is disabled by default but can be
> +	  enabled with the mem_encrypt=on command line option.
> +
>  # Common NUMA Features
>  config NUMA
>  	bool "Numa Memory Allocation and Scheduler Support"

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-09-02 11:03     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 11:03 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:35:59PM -0500, Tom Lendacky wrote:
> Provide the Kconfig support to build the SME support in the kernel.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/Kconfig |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index c580d8c..131f329 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
>  	  supports them), so don't confuse the user by printing
>  	  that we have them enabled.
>  
> +config AMD_MEM_ENCRYPT
> +	bool "Secure Memory Encryption support for AMD"

	     "AMD Secure Memory Encryption support"

> +	depends on X86_64 && CPU_SUP_AMD
> +	---help---
> +	  Say yes to enable the encryption of system memory. This requires
> +	  an AMD processor that supports Secure Memory Encryption (SME).
> +	  The encryption of system memory is disabled by default but can be
> +	  enabled with the mem_encrypt=on command line option.
> +
>  # Common NUMA Features
>  config NUMA
>  	bool "Numa Memory Allocation and Scheduler Support"

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-09-02 14:09     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 14:09 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:22PM -0500, Tom Lendacky wrote:
> Update the cpu features to include identifying and reporting on the
> Secure Memory Encryption feature.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/cpufeature.h        |    7 +++++--
>  arch/x86/include/asm/cpufeatures.h       |    5 ++++-
>  arch/x86/include/asm/disabled-features.h |    3 ++-
>  arch/x86/include/asm/required-features.h |    3 ++-
>  arch/x86/kernel/cpu/scattered.c          |    1 +
>  5 files changed, 14 insertions(+), 5 deletions(-)

...

> diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
> index 8cb57df..d86d9a5 100644
> --- a/arch/x86/kernel/cpu/scattered.c
> +++ b/arch/x86/kernel/cpu/scattered.c
> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },

If this is in scattered CPUID features, it doesn't need any of the
(snipped) changes above - you solely need to reuse one of the free
defines, i.e., something like this:

---
--- a/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:49:08.853374323 +0200
+++ b/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:52:34.477365610 +0200
@@ -100,7 +100,7 @@
 #define X86_FEATURE_XTOPOLOGY	( 3*32+22) /* cpu topology enum extensions */
 #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
 #define X86_FEATURE_NONSTOP_TSC	( 3*32+24) /* TSC does not stop in C states */
-/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_SME		( 3*32+25) /* Secure Memory Encryption */
 #define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
 #define X86_FEATURE_APERFMPERF	( 3*32+28) /* APERFMPERF */
--- a/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:48:52.753375005 +0200
+++ b/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:51:32.437368239 +0200
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struc
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-09-02 14:09     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 14:09 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:36:22PM -0500, Tom Lendacky wrote:
> Update the cpu features to include identifying and reporting on the
> Secure Memory Encryption feature.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/include/asm/cpufeature.h        |    7 +++++--
>  arch/x86/include/asm/cpufeatures.h       |    5 ++++-
>  arch/x86/include/asm/disabled-features.h |    3 ++-
>  arch/x86/include/asm/required-features.h |    3 ++-
>  arch/x86/kernel/cpu/scattered.c          |    1 +
>  5 files changed, 14 insertions(+), 5 deletions(-)

...

> diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
> index 8cb57df..d86d9a5 100644
> --- a/arch/x86/kernel/cpu/scattered.c
> +++ b/arch/x86/kernel/cpu/scattered.c
> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },

If this is in scattered CPUID features, it doesn't need any of the
(snipped) changes above - you solely need to reuse one of the free
defines, i.e., something like this:

---
--- a/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:49:08.853374323 +0200
+++ b/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:52:34.477365610 +0200
@@ -100,7 +100,7 @@
 #define X86_FEATURE_XTOPOLOGY	( 3*32+22) /* cpu topology enum extensions */
 #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
 #define X86_FEATURE_NONSTOP_TSC	( 3*32+24) /* TSC does not stop in C states */
-/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_SME		( 3*32+25) /* Secure Memory Encryption */
 #define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
 #define X86_FEATURE_APERFMPERF	( 3*32+28) /* APERFMPERF */
--- a/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:48:52.753375005 +0200
+++ b/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:51:32.437368239 +0200
@@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struc
 		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
 		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
 		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
+		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
 		{ 0, 0, 0, 0, 0 }
 	};

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-08-22 22:36   ` Tom Lendacky
@ 2016-09-02 18:14     ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 18:14 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
> index 747fc52..9f3e762 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -15,12 +15,21 @@
>  
>  #ifndef __ASSEMBLY__
>  
> +#include <linux/init.h>
> +
>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>  
>  extern unsigned long sme_me_mask;
>  
>  u8 sme_get_me_loss(void);
>  
> +void __init sme_early_init(void);
> +
> +#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
> +#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
> +
> +#define __sme_va(x)		(__va((x) & ~sme_me_mask))

So I'm wondering: why not push the masking off of the SME mask into the
__va() macro instead of defining a specific __sme_va() one?

I mean, do you even see cases where __va() would need to have to
sme_mask left in the virtual address?

Because if not, you could mask it out in __va() so that all __va() users
get the "clean" va, without the enc bits.

Hmmm.

Btw, this patch is huuuge. It would be nice if you could split it, if
possible...

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-02 18:14     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-02 18:14 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
> index 747fc52..9f3e762 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -15,12 +15,21 @@
>  
>  #ifndef __ASSEMBLY__
>  
> +#include <linux/init.h>
> +
>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>  
>  extern unsigned long sme_me_mask;
>  
>  u8 sme_get_me_loss(void);
>  
> +void __init sme_early_init(void);
> +
> +#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
> +#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
> +
> +#define __sme_va(x)		(__va((x) & ~sme_me_mask))

So I'm wondering: why not push the masking off of the SME mask into the
__va() macro instead of defining a specific __sme_va() one?

I mean, do you even see cases where __va() would need to have to
sme_mask left in the virtual address?

Because if not, you could mask it out in __va() so that all __va() users
get the "clean" va, without the enc bits.

Hmmm.

Btw, this patch is huuuge. It would be nice if you could split it, if
possible...

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-08-22 22:36   ` Tom Lendacky
@ 2016-09-05  8:48     ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-05  8:48 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
> index f1218f5..a01f0e1 100644
> --- a/arch/x86/include/asm/pgtable_types.h
> +++ b/arch/x86/include/asm/pgtable_types.h
> @@ -3,6 +3,7 @@
>  
>  #include <linux/const.h>
>  #include <asm/page_types.h>
> +#include <asm/mem_encrypt.h>
>  
>  #define FIRST_USER_ADDRESS	0UL
>  
> @@ -121,9 +122,9 @@
>  
>  #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
>  
> -#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
> +#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>  			 _PAGE_ACCESSED | _PAGE_DIRTY)

Hmm, so this naming looks confusing and error-prone: the only difference
is a single "_".

How about this instead:

#define _PAGE_TABLE_NO_ENC	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
	  			 _PAGE_ACCESSED | _PAGE_DIRTY)

#define _PAGE_TABLE (_PAGE_TABLE_NO_ENC | _PAGE_ENC)

Or call it _PAGE_TABLE_BASE or whatever.

Ditto for __KERNPG_TABLE.

This way you can differentiate between the two and use the _NO_ENC one
to define _PAGE_TABLE. And it will be absolutely clear when you use the
_NO_ENC one, what you mean and that you don't want to have the enc mask
in the PTE.

Should be less confusing IMO too.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-05  8:48     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-05  8:48 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
> index f1218f5..a01f0e1 100644
> --- a/arch/x86/include/asm/pgtable_types.h
> +++ b/arch/x86/include/asm/pgtable_types.h
> @@ -3,6 +3,7 @@
>  
>  #include <linux/const.h>
>  #include <asm/page_types.h>
> +#include <asm/mem_encrypt.h>
>  
>  #define FIRST_USER_ADDRESS	0UL
>  
> @@ -121,9 +122,9 @@
>  
>  #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
>  
> -#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
> +#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>  			 _PAGE_ACCESSED | _PAGE_DIRTY)

Hmm, so this naming looks confusing and error-prone: the only difference
is a single "_".

How about this instead:

#define _PAGE_TABLE_NO_ENC	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
	  			 _PAGE_ACCESSED | _PAGE_DIRTY)

#define _PAGE_TABLE (_PAGE_TABLE_NO_ENC | _PAGE_ENC)

Or call it _PAGE_TABLE_BASE or whatever.

Ditto for __KERNPG_TABLE.

This way you can differentiate between the two and use the _NO_ENC one
to define _PAGE_TABLE. And it will be absolutely clear when you use the
_NO_ENC one, what you mean and that you don't want to have the enc mask
in the PTE.

Should be less confusing IMO too.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-05 15:22     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-05 15:22 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>

...

> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
> index c98a559..30f7715 100644
> --- a/arch/x86/kernel/head_64.S
> +++ b/arch/x86/kernel/head_64.S
> @@ -95,6 +95,13 @@ startup_64:
>  	jnz	bad_address
>  
>  	/*
> +	 * Enable memory encryption (if available). Add the memory encryption
> +	 * mask to %rbp to include it in the the page table fixup.
> +	 */
> +	call	sme_enable
> +	addq	sme_me_mask(%rip), %rbp
> +
> +	/*
>  	 * Fixup the physical addresses in the page table
>  	 */
>  	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
> @@ -116,7 +123,8 @@ startup_64:
>  	movq	%rdi, %rax
>  	shrq	$PGDIR_SHIFT, %rax
>  
> -	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
> +	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
> +	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */

Please add comments over the line and not at the side...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-05 15:22     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-05 15:22 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>

...

> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
> index c98a559..30f7715 100644
> --- a/arch/x86/kernel/head_64.S
> +++ b/arch/x86/kernel/head_64.S
> @@ -95,6 +95,13 @@ startup_64:
>  	jnz	bad_address
>  
>  	/*
> +	 * Enable memory encryption (if available). Add the memory encryption
> +	 * mask to %rbp to include it in the the page table fixup.
> +	 */
> +	call	sme_enable
> +	addq	sme_me_mask(%rip), %rbp
> +
> +	/*
>  	 * Fixup the physical addresses in the page table
>  	 */
>  	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
> @@ -116,7 +123,8 @@ startup_64:
>  	movq	%rdi, %rax
>  	shrq	$PGDIR_SHIFT, %rax
>  
> -	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
> +	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
> +	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */

Please add comments over the line and not at the side...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-06  9:31     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-06  9:31 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>

...

> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 54a2372..88c7bae 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -28,6 +28,7 @@
>  #include <asm/bootparam_utils.h>
>  #include <asm/microcode.h>
>  #include <asm/kasan.h>
> +#include <asm/mem_encrypt.h>
>  
>  /*
>   * Manage page tables very early on.
> @@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
>  {
>  	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
>  	next_early_pgt = 0;
> -	write_cr3(__pa_nodebug(early_level4_pgt));
> +	write_cr3(__sme_pa_nodebug(early_level4_pgt));
>  }
>  
>  /* Create a new PMD entry */
> @@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
>  	pmdval_t pmd, *pmd_p;
>  
>  	/* Invalid address or early pgt is done ?  */
> -	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
> +	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>  		return -1;
>  
>  again:
> @@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>  
>  	clear_page(init_level4_pgt);
>  
> +	/* Update the early_pmd_flags with the memory encryption mask */
> +	early_pmd_flags |= _PAGE_ENC;
> +
> +	sme_early_init();
> +

So maybe this comes later but you're setting _PAGE_ENC unconditionally
*before* sme_early_init().

I think you should set it in sme_early_init() and iff SME is enabled.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-06  9:31     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-06  9:31 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
> Adding general kernel support for memory encryption includes:
> - Modify and create some page table macros to include the Secure Memory
>   Encryption (SME) memory encryption mask
> - Update kernel boot support to call an SME routine that checks for and
>   sets the SME capability (the SME routine will grow later and for now
>   is just a stub routine)
> - Update kernel boot support to call an SME routine that encrypts the
>   kernel (the SME routine will grow later and for now is just a stub
>   routine)
> - Provide an SME initialization routine to update the protection map with
>   the memory encryption mask so that it is used by default
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>

...

> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 54a2372..88c7bae 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -28,6 +28,7 @@
>  #include <asm/bootparam_utils.h>
>  #include <asm/microcode.h>
>  #include <asm/kasan.h>
> +#include <asm/mem_encrypt.h>
>  
>  /*
>   * Manage page tables very early on.
> @@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
>  {
>  	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
>  	next_early_pgt = 0;
> -	write_cr3(__pa_nodebug(early_level4_pgt));
> +	write_cr3(__sme_pa_nodebug(early_level4_pgt));
>  }
>  
>  /* Create a new PMD entry */
> @@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
>  	pmdval_t pmd, *pmd_p;
>  
>  	/* Invalid address or early pgt is done ?  */
> -	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
> +	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>  		return -1;
>  
>  again:
> @@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>  
>  	clear_page(init_level4_pgt);
>  
> +	/* Update the early_pmd_flags with the memory encryption mask */
> +	early_pmd_flags |= _PAGE_ENC;
> +
> +	sme_early_init();
> +

So maybe this comes later but you're setting _PAGE_ENC unconditionally
*before* sme_early_init().

I think you should set it in sme_early_init() and iff SME is enabled.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
@ 2016-09-06 16:12     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-06 16:12 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:10PM -0500, Tom Lendacky wrote:
> This adds support to be able to either encrypt or decrypt data during
> the early stages of booting the kernel. This does not change the memory
> encryption attribute - it is used for ensuring that data present in
> either an encrypted or un-encrypted memory area is in the proper state
> (for example the initrd will have been loaded by the boot loader and
> will not be encrypted, but the memory that it resides in is marked as
> encrypted).
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 00eb705..f35a646 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -14,6 +14,107 @@
>  #include <linux/mm.h>
>  
>  #include <asm/mem_encrypt.h>
> +#include <asm/tlbflush.h>
> +#include <asm/fixmap.h>
> +
> +/* Buffer used for early in-place encryption by BSP, no locking needed */
> +static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
> +
> +/*
> + * This routine does not change the underlying encryption setting of the
> + * page(s) that map this memory. It assumes that eventually the memory is
> + * meant to be accessed as encrypted but the contents are currently not
> + * encyrpted.

s/encyrpted/encrypted/

Ditto below.

> + */
> +void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
> +{
> +	void *src, *dst;
> +	size_t len;
> +
> +	if (!sme_me_mask)
> +		return;
> +
> +	local_flush_tlb();
> +	wbinvd();
> +
> +	/*
> +	 * There are limited number of early mapping slots, so map (at most)
> +	 * one page at time.
> +	 */
> +	while (size) {
> +		len = min_t(size_t, sizeof(me_early_buffer), size);
> +
> +		/* Create a mapping for non-encrypted write-protected memory */
> +		src = early_memremap_dec_wp(paddr, len);
> +
> +		/* Create a mapping for encrypted memory */
> +		dst = early_memremap_enc(paddr, len);
> +
> +		/*
> +		 * If a mapping can't be obtained to perform the encryption,
> +		 * then encrypted access to that area will end up causing
> +		 * a crash.
> +		 */
> +		BUG_ON(!src || !dst);
> +
> +		memcpy(me_early_buffer, src, len);
> +		memcpy(dst, me_early_buffer, len);
> +
> +		early_memunmap(dst, len);
> +		early_memunmap(src, len);
> +
> +		paddr += len;
> +		size -= len;
> +	}
> +}
> +
> +/*
> + * This routine does not change the underlying encryption setting of the
> + * page(s) that map this memory. It assumes that eventually the memory is
> + * meant to be accessed as not encrypted but the contents are currently
> + * encyrpted.
> + */
> +void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
> +{

...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory
@ 2016-09-06 16:12     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-06 16:12 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:37:10PM -0500, Tom Lendacky wrote:
> This adds support to be able to either encrypt or decrypt data during
> the early stages of booting the kernel. This does not change the memory
> encryption attribute - it is used for ensuring that data present in
> either an encrypted or un-encrypted memory area is in the proper state
> (for example the initrd will have been loaded by the boot loader and
> will not be encrypted, but the memory that it resides in is marked as
> encrypted).
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---

...

> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 00eb705..f35a646 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -14,6 +14,107 @@
>  #include <linux/mm.h>
>  
>  #include <asm/mem_encrypt.h>
> +#include <asm/tlbflush.h>
> +#include <asm/fixmap.h>
> +
> +/* Buffer used for early in-place encryption by BSP, no locking needed */
> +static char me_early_buffer[PAGE_SIZE] __aligned(PAGE_SIZE);
> +
> +/*
> + * This routine does not change the underlying encryption setting of the
> + * page(s) that map this memory. It assumes that eventually the memory is
> + * meant to be accessed as encrypted but the contents are currently not
> + * encyrpted.

s/encyrpted/encrypted/

Ditto below.

> + */
> +void __init sme_early_mem_enc(resource_size_t paddr, unsigned long size)
> +{
> +	void *src, *dst;
> +	size_t len;
> +
> +	if (!sme_me_mask)
> +		return;
> +
> +	local_flush_tlb();
> +	wbinvd();
> +
> +	/*
> +	 * There are limited number of early mapping slots, so map (at most)
> +	 * one page at time.
> +	 */
> +	while (size) {
> +		len = min_t(size_t, sizeof(me_early_buffer), size);
> +
> +		/* Create a mapping for non-encrypted write-protected memory */
> +		src = early_memremap_dec_wp(paddr, len);
> +
> +		/* Create a mapping for encrypted memory */
> +		dst = early_memremap_enc(paddr, len);
> +
> +		/*
> +		 * If a mapping can't be obtained to perform the encryption,
> +		 * then encrypted access to that area will end up causing
> +		 * a crash.
> +		 */
> +		BUG_ON(!src || !dst);
> +
> +		memcpy(me_early_buffer, src, len);
> +		memcpy(dst, me_early_buffer, len);
> +
> +		early_memunmap(dst, len);
> +		early_memunmap(src, len);
> +
> +		paddr += len;
> +		size -= len;
> +	}
> +}
> +
> +/*
> + * This routine does not change the underlying encryption setting of the
> + * page(s) that map this memory. It assumes that eventually the memory is
> + * meant to be accessed as not encrypted but the contents are currently
> + * encyrpted.
> + */
> +void __init sme_early_mem_dec(resource_size_t paddr, unsigned long size)
> +{

...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
  2016-09-02  8:50     ` Borislav Petkov
  (?)
@ 2016-09-07 14:02       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:02 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 03:50 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:35:39PM -0500, Tom Lendacky wrote:
>> This patch adds a Documenation entry to decribe the AMD Secure Memory
>> Encryption (SME) feature.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/x86/amd-memory-encryption.txt
>>
>> diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
>> new file mode 100644
>> index 0000000..f19c555
>> --- /dev/null
>> +++ b/Documentation/x86/amd-memory-encryption.txt
>> @@ -0,0 +1,35 @@
>> +Secure Memory Encryption (SME) is a feature found on AMD processors.
>> +
>> +SME provides the ability to mark individual pages of memory as encrypted using
>> +the standard x86 page tables.  A page that is marked encrpyted will be
> 
> s/encrpyted/encrypted/

Ugh..  I thought I caught all of these.  Obviously not.  I'll go through
all the patches on this.

> 
>> +automatically decrypted when read from DRAM and encrypted when written to
>> +DRAM.  SME can therefore be used to protect the contents of DRAM from physical
>> +attacks on the system.
>> +
>> +Support for SME can be determined through the CPUID instruction. The CPUID
>> +function 0x8000001f reports information related to SME:
>> +
>> +	0x8000001f[eax]:
>> +		Bit[0] indicates support for SME
>> +	0x8000001f[ebx]:
>> +		Bit[5:0]  pagetable bit number used to enable memory encryption
>> +		Bit[11:6] reduction in physical address space, in bits, when
>> +			  memory encryption is enabled (this only affects system
>> +			  physical addresses, not guest physical addresses)
>> +
>> +If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
>> +determine if SME is enabled and/or to enable memory encryption:
>> +
>> +	0xc0010010:
>> +		Bit[23]   0 = memory encryption features are disabled
>> +			  1 = memory encryption features are enabled
>> +
>> +Linux relies on BIOS to set this bit if BIOS has determined that the reduction
>> +in the physical address space as a result of enabling memory encryption (see
>> +CPUID information above) will not conflict with the address space resource
>> +requirements for the system.  If this bit is not set upon Linux startup then
>> +Linux itself will not set it and memory encryption will not be possible.
>> +
>> +SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
>> +option.
> 
> " ... is configurable through CONFIG_AMD_MEM_ENCRYPT."

Ok.

> 
>> Additionally, the mem_encrypt=on command line parameter is required
>> +to activate memory encryption.
> 
> I think you want to rewrite the logic here to say that people should use
> the BIOS option and if none is present for whatever reason, resort to
> the alternative "mem_encrypt=on" kernel command line option, no?

Yes, I'll work on rewording this section.

Thanks,
Tom
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-07 14:02       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:02 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/02/2016 03:50 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:35:39PM -0500, Tom Lendacky wrote:
>> This patch adds a Documenation entry to decribe the AMD Secure Memory
>> Encryption (SME) feature.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/x86/amd-memory-encryption.txt
>>
>> diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
>> new file mode 100644
>> index 0000000..f19c555
>> --- /dev/null
>> +++ b/Documentation/x86/amd-memory-encryption.txt
>> @@ -0,0 +1,35 @@
>> +Secure Memory Encryption (SME) is a feature found on AMD processors.
>> +
>> +SME provides the ability to mark individual pages of memory as encrypted using
>> +the standard x86 page tables.  A page that is marked encrpyted will be
> 
> s/encrpyted/encrypted/

Ugh..  I thought I caught all of these.  Obviously not.  I'll go through
all the patches on this.

> 
>> +automatically decrypted when read from DRAM and encrypted when written to
>> +DRAM.  SME can therefore be used to protect the contents of DRAM from physical
>> +attacks on the system.
>> +
>> +Support for SME can be determined through the CPUID instruction. The CPUID
>> +function 0x8000001f reports information related to SME:
>> +
>> +	0x8000001f[eax]:
>> +		Bit[0] indicates support for SME
>> +	0x8000001f[ebx]:
>> +		Bit[5:0]  pagetable bit number used to enable memory encryption
>> +		Bit[11:6] reduction in physical address space, in bits, when
>> +			  memory encryption is enabled (this only affects system
>> +			  physical addresses, not guest physical addresses)
>> +
>> +If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
>> +determine if SME is enabled and/or to enable memory encryption:
>> +
>> +	0xc0010010:
>> +		Bit[23]   0 = memory encryption features are disabled
>> +			  1 = memory encryption features are enabled
>> +
>> +Linux relies on BIOS to set this bit if BIOS has determined that the reduction
>> +in the physical address space as a result of enabling memory encryption (see
>> +CPUID information above) will not conflict with the address space resource
>> +requirements for the system.  If this bit is not set upon Linux startup then
>> +Linux itself will not set it and memory encryption will not be possible.
>> +
>> +SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
>> +option.
> 
> " ... is configurable through CONFIG_AMD_MEM_ENCRYPT."

Ok.

> 
>> Additionally, the mem_encrypt=on command line parameter is required
>> +to activate memory encryption.
> 
> I think you want to rewrite the logic here to say that people should use
> the BIOS option and if none is present for whatever reason, resort to
> the alternative "mem_encrypt=on" kernel command line option, no?

Yes, I'll work on rewording this section.

Thanks,
Tom
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-07 14:02       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:02 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 03:50 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:35:39PM -0500, Tom Lendacky wrote:
>> This patch adds a Documenation entry to decribe the AMD Secure Memory
>> Encryption (SME) feature.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  Documentation/x86/amd-memory-encryption.txt |   35 +++++++++++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/x86/amd-memory-encryption.txt
>>
>> diff --git a/Documentation/x86/amd-memory-encryption.txt b/Documentation/x86/amd-memory-encryption.txt
>> new file mode 100644
>> index 0000000..f19c555
>> --- /dev/null
>> +++ b/Documentation/x86/amd-memory-encryption.txt
>> @@ -0,0 +1,35 @@
>> +Secure Memory Encryption (SME) is a feature found on AMD processors.
>> +
>> +SME provides the ability to mark individual pages of memory as encrypted using
>> +the standard x86 page tables.  A page that is marked encrpyted will be
> 
> s/encrpyted/encrypted/

Ugh..  I thought I caught all of these.  Obviously not.  I'll go through
all the patches on this.

> 
>> +automatically decrypted when read from DRAM and encrypted when written to
>> +DRAM.  SME can therefore be used to protect the contents of DRAM from physical
>> +attacks on the system.
>> +
>> +Support for SME can be determined through the CPUID instruction. The CPUID
>> +function 0x8000001f reports information related to SME:
>> +
>> +	0x8000001f[eax]:
>> +		Bit[0] indicates support for SME
>> +	0x8000001f[ebx]:
>> +		Bit[5:0]  pagetable bit number used to enable memory encryption
>> +		Bit[11:6] reduction in physical address space, in bits, when
>> +			  memory encryption is enabled (this only affects system
>> +			  physical addresses, not guest physical addresses)
>> +
>> +If support for SME is present, MSR 0xc00100010 (SYS_CFG) can be used to
>> +determine if SME is enabled and/or to enable memory encryption:
>> +
>> +	0xc0010010:
>> +		Bit[23]   0 = memory encryption features are disabled
>> +			  1 = memory encryption features are enabled
>> +
>> +Linux relies on BIOS to set this bit if BIOS has determined that the reduction
>> +in the physical address space as a result of enabling memory encryption (see
>> +CPUID information above) will not conflict with the address space resource
>> +requirements for the system.  If this bit is not set upon Linux startup then
>> +Linux itself will not set it and memory encryption will not be possible.
>> +
>> +SME support is configurable in the kernel through the AMD_MEM_ENCRYPT config
>> +option.
> 
> " ... is configurable through CONFIG_AMD_MEM_ENCRYPT."

Ok.

> 
>> Additionally, the mem_encrypt=on command line parameter is required
>> +to activate memory encryption.
> 
> I think you want to rewrite the logic here to say that people should use
> the BIOS option and if none is present for whatever reason, resort to
> the alternative "mem_encrypt=on" kernel command line option, no?

Yes, I'll work on rewording this section.

Thanks,
Tom
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
  2016-09-02 11:03     ` Borislav Petkov
@ 2016-09-07 14:03       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:03 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 06:03 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:35:59PM -0500, Tom Lendacky wrote:
>> Provide the Kconfig support to build the SME support in the kernel.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/Kconfig |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index c580d8c..131f329 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
>>  	  supports them), so don't confuse the user by printing
>>  	  that we have them enabled.
>>  
>> +config AMD_MEM_ENCRYPT
>> +	bool "Secure Memory Encryption support for AMD"
> 
> 	     "AMD Secure Memory Encryption support"

Ok.

Thanks,
Tom

> 
>> +	depends on X86_64 && CPU_SUP_AMD
>> +	---help---
>> +	  Say yes to enable the encryption of system memory. This requires
>> +	  an AMD processor that supports Secure Memory Encryption (SME).
>> +	  The encryption of system memory is disabled by default but can be
>> +	  enabled with the mem_encrypt=on command line option.
>> +
>>  # Common NUMA Features
>>  config NUMA
>>  	bool "Numa Memory Allocation and Scheduler Support"
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement
@ 2016-09-07 14:03       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:03 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 06:03 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:35:59PM -0500, Tom Lendacky wrote:
>> Provide the Kconfig support to build the SME support in the kernel.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/Kconfig |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index c580d8c..131f329 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -1357,6 +1357,15 @@ config X86_DIRECT_GBPAGES
>>  	  supports them), so don't confuse the user by printing
>>  	  that we have them enabled.
>>  
>> +config AMD_MEM_ENCRYPT
>> +	bool "Secure Memory Encryption support for AMD"
> 
> 	     "AMD Secure Memory Encryption support"

Ok.

Thanks,
Tom

> 
>> +	depends on X86_64 && CPU_SUP_AMD
>> +	---help---
>> +	  Say yes to enable the encryption of system memory. This requires
>> +	  an AMD processor that supports Secure Memory Encryption (SME).
>> +	  The encryption of system memory is disabled by default but can be
>> +	  enabled with the mem_encrypt=on command line option.
>> +
>>  # Common NUMA Features
>>  config NUMA
>>  	bool "Numa Memory Allocation and Scheduler Support"
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
  2016-09-02 14:09     ` Borislav Petkov
@ 2016-09-07 14:07       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:07 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 09:09 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:22PM -0500, Tom Lendacky wrote:
>> Update the cpu features to include identifying and reporting on the
>> Secure Memory Encryption feature.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/cpufeature.h        |    7 +++++--
>>  arch/x86/include/asm/cpufeatures.h       |    5 ++++-
>>  arch/x86/include/asm/disabled-features.h |    3 ++-
>>  arch/x86/include/asm/required-features.h |    3 ++-
>>  arch/x86/kernel/cpu/scattered.c          |    1 +
>>  5 files changed, 14 insertions(+), 5 deletions(-)
> 
> ...
> 
>> diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
>> index 8cb57df..d86d9a5 100644
>> --- a/arch/x86/kernel/cpu/scattered.c
>> +++ b/arch/x86/kernel/cpu/scattered.c
>> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
>>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
>> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
> 
> If this is in scattered CPUID features, it doesn't need any of the
> (snipped) changes above - you solely need to reuse one of the free
> defines, i.e., something like this:

Ok, that's much easier. I'll do that.

Thanks,
Tom

> 
> ---
> --- a/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:49:08.853374323 +0200
> +++ b/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:52:34.477365610 +0200
> @@ -100,7 +100,7 @@
>  #define X86_FEATURE_XTOPOLOGY	( 3*32+22) /* cpu topology enum extensions */
>  #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
>  #define X86_FEATURE_NONSTOP_TSC	( 3*32+24) /* TSC does not stop in C states */
> -/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
> +#define X86_FEATURE_SME		( 3*32+25) /* Secure Memory Encryption */
>  #define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
>  #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
>  #define X86_FEATURE_APERFMPERF	( 3*32+28) /* APERFMPERF */
> --- a/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:48:52.753375005 +0200
> +++ b/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:51:32.437368239 +0200
> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struc
>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
>  		{ 0, 0, 0, 0, 0 }
>  	};
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature
@ 2016-09-07 14:07       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:07 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 09:09 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:22PM -0500, Tom Lendacky wrote:
>> Update the cpu features to include identifying and reporting on the
>> Secure Memory Encryption feature.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/cpufeature.h        |    7 +++++--
>>  arch/x86/include/asm/cpufeatures.h       |    5 ++++-
>>  arch/x86/include/asm/disabled-features.h |    3 ++-
>>  arch/x86/include/asm/required-features.h |    3 ++-
>>  arch/x86/kernel/cpu/scattered.c          |    1 +
>>  5 files changed, 14 insertions(+), 5 deletions(-)
> 
> ...
> 
>> diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
>> index 8cb57df..d86d9a5 100644
>> --- a/arch/x86/kernel/cpu/scattered.c
>> +++ b/arch/x86/kernel/cpu/scattered.c
>> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
>>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
>> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
> 
> If this is in scattered CPUID features, it doesn't need any of the
> (snipped) changes above - you solely need to reuse one of the free
> defines, i.e., something like this:

Ok, that's much easier. I'll do that.

Thanks,
Tom

> 
> ---
> --- a/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:49:08.853374323 +0200
> +++ b/arch/x86/include/asm/cpufeatures.h	2016-09-02 15:52:34.477365610 +0200
> @@ -100,7 +100,7 @@
>  #define X86_FEATURE_XTOPOLOGY	( 3*32+22) /* cpu topology enum extensions */
>  #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
>  #define X86_FEATURE_NONSTOP_TSC	( 3*32+24) /* TSC does not stop in C states */
> -/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
> +#define X86_FEATURE_SME		( 3*32+25) /* Secure Memory Encryption */
>  #define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
>  #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
>  #define X86_FEATURE_APERFMPERF	( 3*32+28) /* APERFMPERF */
> --- a/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:48:52.753375005 +0200
> +++ b/arch/x86/kernel/cpu/scattered.c	2016-09-02 15:51:32.437368239 +0200
> @@ -37,6 +37,7 @@ void init_scattered_cpuid_features(struc
>  		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
>  		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
>  		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
> +		{ X86_FEATURE_SME,		CR_EAX, 0, 0x8000001f, 0 },
>  		{ 0, 0, 0, 0, 0 }
>  	};
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-09-02 18:14     ` Borislav Petkov
@ 2016-09-07 14:11       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 01:14 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
>> index 747fc52..9f3e762 100644
>> --- a/arch/x86/include/asm/mem_encrypt.h
>> +++ b/arch/x86/include/asm/mem_encrypt.h
>> @@ -15,12 +15,21 @@
>>  
>>  #ifndef __ASSEMBLY__
>>  
>> +#include <linux/init.h>
>> +
>>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>>  
>>  extern unsigned long sme_me_mask;
>>  
>>  u8 sme_get_me_loss(void);
>>  
>> +void __init sme_early_init(void);
>> +
>> +#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
>> +#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
>> +
>> +#define __sme_va(x)		(__va((x) & ~sme_me_mask))
> 
> So I'm wondering: why not push the masking off of the SME mask into the
> __va() macro instead of defining a specific __sme_va() one?
> 
> I mean, do you even see cases where __va() would need to have to
> sme_mask left in the virtual address?
> 
> Because if not, you could mask it out in __va() so that all __va() users
> get the "clean" va, without the enc bits.

That's a good point, yes, it could go in __va().  I'll make that change.

> 
> Hmmm.
> 
> Btw, this patch is huuuge. It would be nice if you could split it, if
> possible...

Ok, I'll look at how to make this a bit more manageable.

Thanks,
Tom

> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:11       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/02/2016 01:14 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
>> index 747fc52..9f3e762 100644
>> --- a/arch/x86/include/asm/mem_encrypt.h
>> +++ b/arch/x86/include/asm/mem_encrypt.h
>> @@ -15,12 +15,21 @@
>>  
>>  #ifndef __ASSEMBLY__
>>  
>> +#include <linux/init.h>
>> +
>>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>>  
>>  extern unsigned long sme_me_mask;
>>  
>>  u8 sme_get_me_loss(void);
>>  
>> +void __init sme_early_init(void);
>> +
>> +#define __sme_pa(x)		(__pa((x)) | sme_me_mask)
>> +#define __sme_pa_nodebug(x)	(__pa_nodebug((x)) | sme_me_mask)
>> +
>> +#define __sme_va(x)		(__va((x) & ~sme_me_mask))
> 
> So I'm wondering: why not push the masking off of the SME mask into the
> __va() macro instead of defining a specific __sme_va() one?
> 
> I mean, do you even see cases where __va() would need to have to
> sme_mask left in the virtual address?
> 
> Because if not, you could mask it out in __va() so that all __va() users
> get the "clean" va, without the enc bits.

That's a good point, yes, it could go in __va().  I'll make that change.

> 
> Hmmm.
> 
> Btw, this patch is huuuge. It would be nice if you could split it, if
> possible...

Ok, I'll look at how to make this a bit more manageable.

Thanks,
Tom

> 
> Thanks.
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-09-05  8:48     ` Borislav Petkov
@ 2016-09-07 14:16       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:16 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/05/2016 03:48 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
>> index f1218f5..a01f0e1 100644
>> --- a/arch/x86/include/asm/pgtable_types.h
>> +++ b/arch/x86/include/asm/pgtable_types.h
>> @@ -3,6 +3,7 @@
>>  
>>  #include <linux/const.h>
>>  #include <asm/page_types.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  #define FIRST_USER_ADDRESS	0UL
>>  
>> @@ -121,9 +122,9 @@
>>  
>>  #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
>>  
>> -#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>> +#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>>  			 _PAGE_ACCESSED | _PAGE_DIRTY)
> 
> Hmm, so this naming looks confusing and error-prone: the only difference
> is a single "_".
> 
> How about this instead:
> 
> #define _PAGE_TABLE_NO_ENC	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
> 	  			 _PAGE_ACCESSED | _PAGE_DIRTY)
> 
> #define _PAGE_TABLE (_PAGE_TABLE_NO_ENC | _PAGE_ENC)
> 
> Or call it _PAGE_TABLE_BASE or whatever.
> 
> Ditto for __KERNPG_TABLE.
> 
> This way you can differentiate between the two and use the _NO_ENC one
> to define _PAGE_TABLE. And it will be absolutely clear when you use the
> _NO_ENC one, what you mean and that you don't want to have the enc mask
> in the PTE.
> 
> Should be less confusing IMO too.

Yup, makes sense.  I'll rework/rename.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:16       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:16 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/05/2016 03:48 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
>> index f1218f5..a01f0e1 100644
>> --- a/arch/x86/include/asm/pgtable_types.h
>> +++ b/arch/x86/include/asm/pgtable_types.h
>> @@ -3,6 +3,7 @@
>>  
>>  #include <linux/const.h>
>>  #include <asm/page_types.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  #define FIRST_USER_ADDRESS	0UL
>>  
>> @@ -121,9 +122,9 @@
>>  
>>  #define _PAGE_PROTNONE	(_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
>>  
>> -#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>> +#define __PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
>>  			 _PAGE_ACCESSED | _PAGE_DIRTY)
> 
> Hmm, so this naming looks confusing and error-prone: the only difference
> is a single "_".
> 
> How about this instead:
> 
> #define _PAGE_TABLE_NO_ENC	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER |	\
> 	  			 _PAGE_ACCESSED | _PAGE_DIRTY)
> 
> #define _PAGE_TABLE (_PAGE_TABLE_NO_ENC | _PAGE_ENC)
> 
> Or call it _PAGE_TABLE_BASE or whatever.
> 
> Ditto for __KERNPG_TABLE.
> 
> This way you can differentiate between the two and use the _NO_ENC one
> to define _PAGE_TABLE. And it will be absolutely clear when you use the
> _NO_ENC one, what you mean and that you don't want to have the enc mask
> in the PTE.
> 
> Should be less confusing IMO too.

Yup, makes sense.  I'll rework/rename.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-09-05 15:22     ` Borislav Petkov
  (?)
@ 2016-09-07 14:19       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:19 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/05/2016 10:22 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
>> index c98a559..30f7715 100644
>> --- a/arch/x86/kernel/head_64.S
>> +++ b/arch/x86/kernel/head_64.S
>> @@ -95,6 +95,13 @@ startup_64:
>>  	jnz	bad_address
>>  
>>  	/*
>> +	 * Enable memory encryption (if available). Add the memory encryption
>> +	 * mask to %rbp to include it in the the page table fixup.
>> +	 */
>> +	call	sme_enable
>> +	addq	sme_me_mask(%rip), %rbp
>> +
>> +	/*
>>  	 * Fixup the physical addresses in the page table
>>  	 */
>>  	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
>> @@ -116,7 +123,8 @@ startup_64:
>>  	movq	%rdi, %rax
>>  	shrq	$PGDIR_SHIFT, %rax
>>  
>> -	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
>> +	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
>> +	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
> 
> Please add comments over the line and not at the side...

Ok, will do.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:19       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:19 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/05/2016 10:22 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
>> index c98a559..30f7715 100644
>> --- a/arch/x86/kernel/head_64.S
>> +++ b/arch/x86/kernel/head_64.S
>> @@ -95,6 +95,13 @@ startup_64:
>>  	jnz	bad_address
>>  
>>  	/*
>> +	 * Enable memory encryption (if available). Add the memory encryption
>> +	 * mask to %rbp to include it in the the page table fixup.
>> +	 */
>> +	call	sme_enable
>> +	addq	sme_me_mask(%rip), %rbp
>> +
>> +	/*
>>  	 * Fixup the physical addresses in the page table
>>  	 */
>>  	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
>> @@ -116,7 +123,8 @@ startup_64:
>>  	movq	%rdi, %rax
>>  	shrq	$PGDIR_SHIFT, %rax
>>  
>> -	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
>> +	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
>> +	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
> 
> Please add comments over the line and not at the side...

Ok, will do.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:19       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:19 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/05/2016 10:22 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
>> index c98a559..30f7715 100644
>> --- a/arch/x86/kernel/head_64.S
>> +++ b/arch/x86/kernel/head_64.S
>> @@ -95,6 +95,13 @@ startup_64:
>>  	jnz	bad_address
>>  
>>  	/*
>> +	 * Enable memory encryption (if available). Add the memory encryption
>> +	 * mask to %rbp to include it in the the page table fixup.
>> +	 */
>> +	call	sme_enable
>> +	addq	sme_me_mask(%rip), %rbp
>> +
>> +	/*
>>  	 * Fixup the physical addresses in the page table
>>  	 */
>>  	addq	%rbp, early_level4_pgt + (L4_START_KERNEL*8)(%rip)
>> @@ -116,7 +123,8 @@ startup_64:
>>  	movq	%rdi, %rax
>>  	shrq	$PGDIR_SHIFT, %rax
>>  
>> -	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
>> +	leaq	(4096 + __KERNPG_TABLE)(%rbx), %rdx
>> +	addq	sme_me_mask(%rip), %rdx		/* Apply mem encryption mask */
> 
> Please add comments over the line and not at the side...

Ok, will do.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:30       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:30 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/06/2016 04:31 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>> index 54a2372..88c7bae 100644
>> --- a/arch/x86/kernel/head64.c
>> +++ b/arch/x86/kernel/head64.c
>> @@ -28,6 +28,7 @@
>>  #include <asm/bootparam_utils.h>
>>  #include <asm/microcode.h>
>>  #include <asm/kasan.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * Manage page tables very early on.
>> @@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
>>  {
>>  	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
>>  	next_early_pgt = 0;
>> -	write_cr3(__pa_nodebug(early_level4_pgt));
>> +	write_cr3(__sme_pa_nodebug(early_level4_pgt));
>>  }
>>  
>>  /* Create a new PMD entry */
>> @@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
>>  	pmdval_t pmd, *pmd_p;
>>  
>>  	/* Invalid address or early pgt is done ?  */
>> -	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
>> +	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>>  		return -1;
>>  
>>  again:
>> @@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>>  
>>  	clear_page(init_level4_pgt);
>>  
>> +	/* Update the early_pmd_flags with the memory encryption mask */
>> +	early_pmd_flags |= _PAGE_ENC;
>> +
>> +	sme_early_init();
>> +
> 
> So maybe this comes later but you're setting _PAGE_ENC unconditionally
> *before* sme_early_init().
> 
> I think you should set it in sme_early_init() and iff SME is enabled.

_PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
set (or not set) at this point - so it will be the mask if SME is
active or 0 if SME is not active.  sme_early_init() is merely
propagating the mask to other structures.  Since early_pmd_flags is
mainly used in this file (one line in head_64.S is the other place) I
felt it best to modify it here.  But it can always be moved if you feel
that is best.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:30       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:30 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/06/2016 04:31 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>> index 54a2372..88c7bae 100644
>> --- a/arch/x86/kernel/head64.c
>> +++ b/arch/x86/kernel/head64.c
>> @@ -28,6 +28,7 @@
>>  #include <asm/bootparam_utils.h>
>>  #include <asm/microcode.h>
>>  #include <asm/kasan.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * Manage page tables very early on.
>> @@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
>>  {
>>  	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
>>  	next_early_pgt = 0;
>> -	write_cr3(__pa_nodebug(early_level4_pgt));
>> +	write_cr3(__sme_pa_nodebug(early_level4_pgt));
>>  }
>>  
>>  /* Create a new PMD entry */
>> @@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
>>  	pmdval_t pmd, *pmd_p;
>>  
>>  	/* Invalid address or early pgt is done ?  */
>> -	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
>> +	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>>  		return -1;
>>  
>>  again:
>> @@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>>  
>>  	clear_page(init_level4_pgt);
>>  
>> +	/* Update the early_pmd_flags with the memory encryption mask */
>> +	early_pmd_flags |= _PAGE_ENC;
>> +
>> +	sme_early_init();
>> +
> 
> So maybe this comes later but you're setting _PAGE_ENC unconditionally
> *before* sme_early_init().
> 
> I think you should set it in sme_early_init() and iff SME is enabled.

_PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
set (or not set) at this point - so it will be the mask if SME is
active or 0 if SME is not active.  sme_early_init() is merely
propagating the mask to other structures.  Since early_pmd_flags is
mainly used in this file (one line in head_64.S is the other place) I
felt it best to modify it here.  But it can always be moved if you feel
that is best.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 14:30       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-07 14:30 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/06/2016 04:31 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:36:46PM -0500, Tom Lendacky wrote:
>> Adding general kernel support for memory encryption includes:
>> - Modify and create some page table macros to include the Secure Memory
>>   Encryption (SME) memory encryption mask
>> - Update kernel boot support to call an SME routine that checks for and
>>   sets the SME capability (the SME routine will grow later and for now
>>   is just a stub routine)
>> - Update kernel boot support to call an SME routine that encrypts the
>>   kernel (the SME routine will grow later and for now is just a stub
>>   routine)
>> - Provide an SME initialization routine to update the protection map with
>>   the memory encryption mask so that it is used by default
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> 
> ...
> 
>> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
>> index 54a2372..88c7bae 100644
>> --- a/arch/x86/kernel/head64.c
>> +++ b/arch/x86/kernel/head64.c
>> @@ -28,6 +28,7 @@
>>  #include <asm/bootparam_utils.h>
>>  #include <asm/microcode.h>
>>  #include <asm/kasan.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * Manage page tables very early on.
>> @@ -42,7 +43,7 @@ static void __init reset_early_page_tables(void)
>>  {
>>  	memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
>>  	next_early_pgt = 0;
>> -	write_cr3(__pa_nodebug(early_level4_pgt));
>> +	write_cr3(__sme_pa_nodebug(early_level4_pgt));
>>  }
>>  
>>  /* Create a new PMD entry */
>> @@ -54,7 +55,7 @@ int __init early_make_pgtable(unsigned long address)
>>  	pmdval_t pmd, *pmd_p;
>>  
>>  	/* Invalid address or early pgt is done ?  */
>> -	if (physaddr >= MAXMEM || read_cr3() != __pa_nodebug(early_level4_pgt))
>> +	if (physaddr >= MAXMEM || read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>>  		return -1;
>>  
>>  again:
>> @@ -157,6 +158,11 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>>  
>>  	clear_page(init_level4_pgt);
>>  
>> +	/* Update the early_pmd_flags with the memory encryption mask */
>> +	early_pmd_flags |= _PAGE_ENC;
>> +
>> +	sme_early_init();
>> +
> 
> So maybe this comes later but you're setting _PAGE_ENC unconditionally
> *before* sme_early_init().
> 
> I think you should set it in sme_early_init() and iff SME is enabled.

_PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
set (or not set) at this point - so it will be the mask if SME is
active or 0 if SME is not active.  sme_early_init() is merely
propagating the mask to other structures.  Since early_pmd_flags is
mainly used in this file (one line in head_64.S is the other place) I
felt it best to modify it here.  But it can always be moved if you feel
that is best.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-07 15:23         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-07 15:23 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 07, 2016 at 09:02:38AM -0500, Tom Lendacky wrote:
> Ugh..  I thought I caught all of these.  Obviously not.  I'll go through
> all the patches on this.

What you could do is run all patches through scripts/checkpatch.pl
and fix those issues which make sense to you. What I'm saying is, you
shouldn't take its output to the letter but some of the stuff it catches
are valid.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME)
@ 2016-09-07 15:23         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-07 15:23 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Wed, Sep 07, 2016 at 09:02:38AM -0500, Tom Lendacky wrote:
> Ugh..  I thought I caught all of these.  Obviously not.  I'll go through
> all the patches on this.

What you could do is run all patches through scripts/checkpatch.pl
and fix those issues which make sense to you. What I'm saying is, you
shouldn't take its output to the letter but some of the stuff it catches
are valid.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 15:55         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-07 15:55 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 07, 2016 at 09:30:54AM -0500, Tom Lendacky wrote:
> _PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
> set (or not set) at this point - so it will be the mask if SME is
> active or 0 if SME is not active.

Yeah, I remember :-)

> sme_early_init() is merely propagating the mask to other structures.
> Since early_pmd_flags is mainly used in this file (one line in
> head_64.S is the other place) I felt it best to modify it here. But it
> can always be moved if you feel that is best.

Hmm, so would it work then if you stick it in early_pmd_flags'
definition like you do with the other masks? I.e.,

pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE | _PAGE_ENC & ~(_PAGE_GLOBAL | _PAGE_NX);

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-07 15:55         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-07 15:55 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 07, 2016 at 09:30:54AM -0500, Tom Lendacky wrote:
> _PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
> set (or not set) at this point - so it will be the mask if SME is
> active or 0 if SME is not active.

Yeah, I remember :-)

> sme_early_init() is merely propagating the mask to other structures.
> Since early_pmd_flags is mainly used in this file (one line in
> head_64.S is the other place) I felt it best to modify it here. But it
> can always be moved if you feel that is best.

Hmm, so would it work then if you stick it in early_pmd_flags'
definition like you do with the other masks? I.e.,

pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE | _PAGE_ENC & ~(_PAGE_GLOBAL | _PAGE_NX);

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-08 13:26           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-08 13:26 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/07/2016 10:55 AM, Borislav Petkov wrote:
> On Wed, Sep 07, 2016 at 09:30:54AM -0500, Tom Lendacky wrote:
>> _PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
>> set (or not set) at this point - so it will be the mask if SME is
>> active or 0 if SME is not active.
> 
> Yeah, I remember :-)
> 
>> sme_early_init() is merely propagating the mask to other structures.
>> Since early_pmd_flags is mainly used in this file (one line in
>> head_64.S is the other place) I felt it best to modify it here. But it
>> can always be moved if you feel that is best.
> 
> Hmm, so would it work then if you stick it in early_pmd_flags'
> definition like you do with the other masks? I.e.,
> 
> pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE | _PAGE_ENC & ~(_PAGE_GLOBAL | _PAGE_NX);

When does this value get initialized?  Since _PAGE_ENC is #defined to
sme_me_mask, which is not set until the boot process begins, I'm afraid
we'd end up using the initial value of sme_me_mask, which is zero.  Do
I have that right?

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-08 13:26           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-08 13:26 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/07/2016 10:55 AM, Borislav Petkov wrote:
> On Wed, Sep 07, 2016 at 09:30:54AM -0500, Tom Lendacky wrote:
>> _PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
>> set (or not set) at this point - so it will be the mask if SME is
>> active or 0 if SME is not active.
> 
> Yeah, I remember :-)
> 
>> sme_early_init() is merely propagating the mask to other structures.
>> Since early_pmd_flags is mainly used in this file (one line in
>> head_64.S is the other place) I felt it best to modify it here. But it
>> can always be moved if you feel that is best.
> 
> Hmm, so would it work then if you stick it in early_pmd_flags'
> definition like you do with the other masks? I.e.,
> 
> pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE | _PAGE_ENC & ~(_PAGE_GLOBAL | _PAGE_NX);

When does this value get initialized?  Since _PAGE_ENC is #defined to
sme_me_mask, which is not set until the boot process begins, I'm afraid
we'd end up using the initial value of sme_me_mask, which is zero.  Do
I have that right?

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-08 13:26           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-08 13:26 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/07/2016 10:55 AM, Borislav Petkov wrote:
> On Wed, Sep 07, 2016 at 09:30:54AM -0500, Tom Lendacky wrote:
>> _PAGE_ENC is #defined as sme_me_mask and sme_me_mask has already been
>> set (or not set) at this point - so it will be the mask if SME is
>> active or 0 if SME is not active.
> 
> Yeah, I remember :-)
> 
>> sme_early_init() is merely propagating the mask to other structures.
>> Since early_pmd_flags is mainly used in this file (one line in
>> head_64.S is the other place) I felt it best to modify it here. But it
>> can always be moved if you feel that is best.
> 
> Hmm, so would it work then if you stick it in early_pmd_flags'
> definition like you do with the other masks? I.e.,
> 
> pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE | _PAGE_ENC & ~(_PAGE_GLOBAL | _PAGE_NX);

When does this value get initialized?  Since _PAGE_ENC is #defined to
sme_me_mask, which is not set until the boot process begins, I'm afraid
we'd end up using the initial value of sme_me_mask, which is zero.  Do
I have that right?

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-08 13:55             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-08 13:55 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Thu, Sep 08, 2016 at 08:26:27AM -0500, Tom Lendacky wrote:
> When does this value get initialized?  Since _PAGE_ENC is #defined to
> sme_me_mask, which is not set until the boot process begins, I'm afraid
> we'd end up using the initial value of sme_me_mask, which is zero.  Do
> I have that right?

Hmm, but then that would hold true for all the other defines where you
OR-in _PAGE_ENC, no?

In any case, the preprocessed source looks like this:

pmdval_t early_pmd_flags = (((((((pteval_t)(1)) << 0) | (((pteval_t)(1)) << 1) | (((pteval_t)(1)) << 6) | (((pteval_t)(1)) << 5) | (((pteval_t)(1)) << 8)) | (((pteval_t)(1)) << 63)) | (((pteval_t)(1)) << 7)) | sme_me_mask) & ~((((pteval_t)(1)) << 8) | (((pteval_t)(1)) << 63));

but the problem is later, when building:

arch/x86/kernel/head64.c:39:28: error: initializer element is not constant
 pmdval_t early_pmd_flags = (__PAGE_KERNEL_LARGE | _PAGE_ENC) & ~(_PAGE_GLOBAL | _PAGE_NX);
                            ^
scripts/Makefile.build:153: recipe for target 'arch/x86/kernel/head64.s' failed

so I guess not. :-\

Ok, then at least please put the early_pmd_flags init after
sme_early_init() along with a small comment explaning what happens.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-08 13:55             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-08 13:55 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Thu, Sep 08, 2016 at 08:26:27AM -0500, Tom Lendacky wrote:
> When does this value get initialized?  Since _PAGE_ENC is #defined to
> sme_me_mask, which is not set until the boot process begins, I'm afraid
> we'd end up using the initial value of sme_me_mask, which is zero.  Do
> I have that right?

Hmm, but then that would hold true for all the other defines where you
OR-in _PAGE_ENC, no?

In any case, the preprocessed source looks like this:

pmdval_t early_pmd_flags = (((((((pteval_t)(1)) << 0) | (((pteval_t)(1)) << 1) | (((pteval_t)(1)) << 6) | (((pteval_t)(1)) << 5) | (((pteval_t)(1)) << 8)) | (((pteval_t)(1)) << 63)) | (((pteval_t)(1)) << 7)) | sme_me_mask) & ~((((pteval_t)(1)) << 8) | (((pteval_t)(1)) << 63));

but the problem is later, when building:

arch/x86/kernel/head64.c:39:28: error: initializer element is not constant
 pmdval_t early_pmd_flags = (__PAGE_KERNEL_LARGE | _PAGE_ENC) & ~(_PAGE_GLOBAL | _PAGE_NX);
                            ^
scripts/Makefile.build:153: recipe for target 'arch/x86/kernel/head64.s' failed

so I guess not. :-\

Ok, then at least please put the early_pmd_flags init after
sme_early_init() along with a small comment explaning what happens.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
  2016-08-22 22:37   ` Tom Lendacky
@ 2016-09-09 15:53     ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 15:53 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
> that special handling isn't needed afterwards.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
>  arch/x86/kernel/setup.c  |    8 ++++
>  2 files changed, 96 insertions(+), 5 deletions(-)

...

> +int __init early_make_pgtable(unsigned long address)
> +{
> +	unsigned long physaddr = address - __PAGE_OFFSET;
> +	pmdval_t pmd;
> +
> +	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
> +
> +	return __early_make_pgtable(address, pmd);
> +}
> +
> +static void __init create_unencrypted_mapping(void *address, unsigned long size)
> +{
> +	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
> +	pmdval_t pmd_flags, pmd;
> +
> +	if (!sme_me_mask)
> +		return;
> +
> +	/* Clear the encryption mask from the early_pmd_flags */
> +	pmd_flags = early_pmd_flags & ~sme_me_mask;
> +
> +	do {
> +		pmd = (physaddr & PMD_MASK) + pmd_flags;
> +		__early_make_pgtable((unsigned long)address, pmd);
> +
> +		address += PMD_SIZE;
> +		physaddr += PMD_SIZE;
> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> +	} while (size);
> +}
> +
> +static void __init __clear_mapping(unsigned long address)

Should be called something with "pmd" in the name as it clears a PMD,
i.e. __clear_pmd_mapping or so.

> +{
> +	unsigned long physaddr = address - __PAGE_OFFSET;
> +	pgdval_t pgd, *pgd_p;
> +	pudval_t pud, *pud_p;
> +	pmdval_t *pmd_p;
> +
> +	/* Invalid address or early pgt is done ?  */
> +	if (physaddr >= MAXMEM ||
> +	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
> +		return;
> +
> +	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
> +	pgd = *pgd_p;
> +
> +	if (!pgd)
> +		return;
> +
> +	/*
> +	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
> +	 * __early_make_pgtable where the entry was created.
> +	 */
> +	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
> +	pud_p += pud_index(address);
> +	pud = *pud_p;
> +
> +	if (!pud)
> +		return;
> +
> +	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
> +	pmd_p[pmd_index(address)] = 0;
> +}
> +
> +static void __init clear_mapping(void *address, unsigned long size)
> +{
> +	if (!sme_me_mask)
> +		return;
> +
> +	do {
> +		__clear_mapping((unsigned long)address);
> +
> +		address += PMD_SIZE;
> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> +	} while (size);
> +}
> +
> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
> +{
> +	create_unencrypted_mapping(src, size);
> +	memcpy(dst, src, size);
> +	clear_mapping(src, size);
> +}
> +

In any case, this whole functionality is SME-specific and should be
somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

>  /* Don't add a printk in there. printk relies on the PDA which is not initialized 
>     yet. */
>  static void __init clear_bss(void)
> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>  	char * command_line;
>  	unsigned long cmd_line_ptr;
>  
> -	memcpy(&boot_params, real_mode_data, sizeof boot_params);
> +	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

checkpatch.pl:

WARNING: sizeof boot_params should be sizeof(boot_params)
#155: FILE: arch/x86/kernel/head64.c:208:
+       sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

>  	sanitize_boot_params(&boot_params);
>  	cmd_line_ptr = get_cmd_line_ptr();
>  	if (cmd_line_ptr) {
>  		command_line = __va(cmd_line_ptr);
> -		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
> +		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>  	}
>  }
>  
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 1489da8..1fdaa11 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -114,6 +114,7 @@
>  #include <asm/microcode.h>
>  #include <asm/mmu_context.h>
>  #include <asm/kaslr.h>
> +#include <asm/mem_encrypt.h>
>  
>  /*
>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>  	    !ramdisk_image || !ramdisk_size)
>  		return;		/* No initrd provided by bootloader */
>  
> +	/*
> +	 * This memory is marked encrypted by the kernel but the ramdisk
> +	 * was loaded in the clear by the bootloader, so make sure that
> +	 * the ramdisk image is encrypted.
> +	 */
> +	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);

What happens if we go and relocate the ramdisk? I.e., the function above
this one: relocate_initrd(). We have to encrypt it then too, I presume.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-09 15:53     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 15:53 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
> that special handling isn't needed afterwards.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
>  arch/x86/kernel/setup.c  |    8 ++++
>  2 files changed, 96 insertions(+), 5 deletions(-)

...

> +int __init early_make_pgtable(unsigned long address)
> +{
> +	unsigned long physaddr = address - __PAGE_OFFSET;
> +	pmdval_t pmd;
> +
> +	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
> +
> +	return __early_make_pgtable(address, pmd);
> +}
> +
> +static void __init create_unencrypted_mapping(void *address, unsigned long size)
> +{
> +	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
> +	pmdval_t pmd_flags, pmd;
> +
> +	if (!sme_me_mask)
> +		return;
> +
> +	/* Clear the encryption mask from the early_pmd_flags */
> +	pmd_flags = early_pmd_flags & ~sme_me_mask;
> +
> +	do {
> +		pmd = (physaddr & PMD_MASK) + pmd_flags;
> +		__early_make_pgtable((unsigned long)address, pmd);
> +
> +		address += PMD_SIZE;
> +		physaddr += PMD_SIZE;
> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> +	} while (size);
> +}
> +
> +static void __init __clear_mapping(unsigned long address)

Should be called something with "pmd" in the name as it clears a PMD,
i.e. __clear_pmd_mapping or so.

> +{
> +	unsigned long physaddr = address - __PAGE_OFFSET;
> +	pgdval_t pgd, *pgd_p;
> +	pudval_t pud, *pud_p;
> +	pmdval_t *pmd_p;
> +
> +	/* Invalid address or early pgt is done ?  */
> +	if (physaddr >= MAXMEM ||
> +	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
> +		return;
> +
> +	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
> +	pgd = *pgd_p;
> +
> +	if (!pgd)
> +		return;
> +
> +	/*
> +	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
> +	 * __early_make_pgtable where the entry was created.
> +	 */
> +	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
> +	pud_p += pud_index(address);
> +	pud = *pud_p;
> +
> +	if (!pud)
> +		return;
> +
> +	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
> +	pmd_p[pmd_index(address)] = 0;
> +}
> +
> +static void __init clear_mapping(void *address, unsigned long size)
> +{
> +	if (!sme_me_mask)
> +		return;
> +
> +	do {
> +		__clear_mapping((unsigned long)address);
> +
> +		address += PMD_SIZE;
> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
> +	} while (size);
> +}
> +
> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
> +{
> +	create_unencrypted_mapping(src, size);
> +	memcpy(dst, src, size);
> +	clear_mapping(src, size);
> +}
> +

In any case, this whole functionality is SME-specific and should be
somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

>  /* Don't add a printk in there. printk relies on the PDA which is not initialized 
>     yet. */
>  static void __init clear_bss(void)
> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>  	char * command_line;
>  	unsigned long cmd_line_ptr;
>  
> -	memcpy(&boot_params, real_mode_data, sizeof boot_params);
> +	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

checkpatch.pl:

WARNING: sizeof boot_params should be sizeof(boot_params)
#155: FILE: arch/x86/kernel/head64.c:208:
+       sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

>  	sanitize_boot_params(&boot_params);
>  	cmd_line_ptr = get_cmd_line_ptr();
>  	if (cmd_line_ptr) {
>  		command_line = __va(cmd_line_ptr);
> -		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
> +		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>  	}
>  }
>  
> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
> index 1489da8..1fdaa11 100644
> --- a/arch/x86/kernel/setup.c
> +++ b/arch/x86/kernel/setup.c
> @@ -114,6 +114,7 @@
>  #include <asm/microcode.h>
>  #include <asm/mmu_context.h>
>  #include <asm/kaslr.h>
> +#include <asm/mem_encrypt.h>
>  
>  /*
>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>  	    !ramdisk_image || !ramdisk_size)
>  		return;		/* No initrd provided by bootloader */
>  
> +	/*
> +	 * This memory is marked encrypted by the kernel but the ramdisk
> +	 * was loaded in the clear by the bootloader, so make sure that
> +	 * the ramdisk image is encrypted.
> +	 */
> +	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);

What happens if we go and relocate the ramdisk? I.e., the function above
this one: relocate_initrd(). We have to encrypt it then too, I presume.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
  2016-08-22 22:37   ` Tom Lendacky
@ 2016-09-09 16:38     ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 16:38 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
> index 031db21..e3bdc5a 100644
> --- a/arch/x86/mm/ioremap.c
> +++ b/arch/x86/mm/ioremap.c
> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>  	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>  }
>  
> +/*
> + * Architecure override of __weak function to adjust the protection attributes
> + * used when remapping memory.
> + */
> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
> +					     unsigned long size,
> +					     enum memremap_owner owner,
> +					     pgprot_t prot)
> +{
> +	/*
> +	 * If memory encryption is enabled and BOOT_DATA is being mapped
> +	 * then remove the encryption bit.
> +	 */
> +	if (_PAGE_ENC && (owner == BOOT_DATA))
> +		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
> +
> +	return prot;
> +}
> +

Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
is BOOT_DATA.

So instead of touching so many files and changing early_memremap(),
why can't you remove _PAGE_ENC by default on x86 and define a specific
early_memremap() for arch/x86/xen/ which you call there?

That would make this patch soo much smaller and the change simpler.

...

> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 5a2631a..f9286c6 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
>  		 * So just always get our own virtual map on the CPU.
>  		 *
>  		 */
> -		md = early_memremap(p, sizeof (*md));
> +		md = early_memremap(p, sizeof (*md), BOOT_DATA);

WARNING: space prohibited between function name and open parenthesis '('
#432: FILE: drivers/firmware/efi/efi.c:389:
+               md = early_memremap(p, sizeof (*md), BOOT_DATA);

Please integrate checkpatch.pl into your workflow so that you can catch
small style nits like this. And don't take its output too seriously... :-)

>  		if (!md) {
>  			pr_err_once("early_memremap(%pa, %zu) failed.\n",
>  				    &p, sizeof (*md));
> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>  	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>  		efi_properties_table_t *tbl;
>  
> -		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
> +		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
> +				     BOOT_DATA);
>  		if (tbl == NULL) {
>  			pr_err("Could not map Properties table!\n");
>  			return -ENOMEM;
-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-09 16:38     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 16:38 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---

...

> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
> index 031db21..e3bdc5a 100644
> --- a/arch/x86/mm/ioremap.c
> +++ b/arch/x86/mm/ioremap.c
> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>  	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>  }
>  
> +/*
> + * Architecure override of __weak function to adjust the protection attributes
> + * used when remapping memory.
> + */
> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
> +					     unsigned long size,
> +					     enum memremap_owner owner,
> +					     pgprot_t prot)
> +{
> +	/*
> +	 * If memory encryption is enabled and BOOT_DATA is being mapped
> +	 * then remove the encryption bit.
> +	 */
> +	if (_PAGE_ENC && (owner == BOOT_DATA))
> +		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
> +
> +	return prot;
> +}
> +

Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
is BOOT_DATA.

So instead of touching so many files and changing early_memremap(),
why can't you remove _PAGE_ENC by default on x86 and define a specific
early_memremap() for arch/x86/xen/ which you call there?

That would make this patch soo much smaller and the change simpler.

...

> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 5a2631a..f9286c6 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
>  		 * So just always get our own virtual map on the CPU.
>  		 *
>  		 */
> -		md = early_memremap(p, sizeof (*md));
> +		md = early_memremap(p, sizeof (*md), BOOT_DATA);

WARNING: space prohibited between function name and open parenthesis '('
#432: FILE: drivers/firmware/efi/efi.c:389:
+               md = early_memremap(p, sizeof (*md), BOOT_DATA);

Please integrate checkpatch.pl into your workflow so that you can catch
small style nits like this. And don't take its output too seriously... :-)

>  		if (!md) {
>  			pr_err_once("early_memremap(%pa, %zu) failed.\n",
>  				    &p, sizeof (*md));
> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>  	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>  		efi_properties_table_t *tbl;
>  
> -		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
> +		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
> +				     BOOT_DATA);
>  		if (tbl == NULL) {
>  			pr_err("Could not map Properties table!\n");
>  			return -ENOMEM;
-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-09 17:23     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 17:23 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
> This patch adds support to be change the memory encryption attribute for
> one or more memory pages.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/cacheflush.h  |    3 +
>  arch/x86/include/asm/mem_encrypt.h |   13 ++++++
>  arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
>  arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 134 insertions(+)

...

> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
> index 72c292d..0ba9382 100644
> --- a/arch/x86/mm/pageattr.c
> +++ b/arch/x86/mm/pageattr.c
> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>  					__pgprot(0), 1, 0, NULL);
>  }
>  
> +static int __set_memory_enc_dec(struct cpa_data *cpa)
> +{
> +	unsigned long addr;
> +	int numpages;
> +	int ret;
> +
> +	if (*cpa->vaddr & ~PAGE_MASK) {
> +		*cpa->vaddr &= PAGE_MASK;
> +
> +		/* People should not be passing in unaligned addresses */
> +		WARN_ON_ONCE(1);

Let's make this more user-friendly:

	if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", *cpa->vaddr))
		*cpa->vaddr &= PAGE_MASK;

> +	}
> +
> +	addr = *cpa->vaddr;
> +	numpages = cpa->numpages;
> +
> +	/* Must avoid aliasing mappings in the highmem code */
> +	kmap_flush_unused();
> +	vm_unmap_aliases();
> +
> +	ret = __change_page_attr_set_clr(cpa, 1);
> +
> +	/* Check whether we really changed something */
> +	if (!(cpa->flags & CPA_FLUSHTLB))
> +		goto out;
> +
> +	/*
> +	 * On success we use CLFLUSH, when the CPU supports it to
> +	 * avoid the WBINVD.
> +	 */
> +	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
> +		cpa_flush_range(addr, numpages, 1);
> +	else
> +		cpa_flush_all(1);

So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
have to?

Don't you want this instead:

        ret = __change_page_attr_set_clr(cpa, 1);
        if (ret)
                goto out;

        /* Check whether we really changed something */
        if (!(cpa->flags & CPA_FLUSHTLB))
                goto out;

        /*
         * On success we use CLFLUSH, when the CPU supports it to
         * avoid the WBINVD.
         */
        if (static_cpu_has(X86_FEATURE_CLFLUSH))
                cpa_flush_range(addr, numpages, 1);
        else
                cpa_flush_all(1);

out:
        return ret;
}

?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-09 17:23     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 17:23 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
> This patch adds support to be change the memory encryption attribute for
> one or more memory pages.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/include/asm/cacheflush.h  |    3 +
>  arch/x86/include/asm/mem_encrypt.h |   13 ++++++
>  arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
>  arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 134 insertions(+)

...

> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
> index 72c292d..0ba9382 100644
> --- a/arch/x86/mm/pageattr.c
> +++ b/arch/x86/mm/pageattr.c
> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>  					__pgprot(0), 1, 0, NULL);
>  }
>  
> +static int __set_memory_enc_dec(struct cpa_data *cpa)
> +{
> +	unsigned long addr;
> +	int numpages;
> +	int ret;
> +
> +	if (*cpa->vaddr & ~PAGE_MASK) {
> +		*cpa->vaddr &= PAGE_MASK;
> +
> +		/* People should not be passing in unaligned addresses */
> +		WARN_ON_ONCE(1);

Let's make this more user-friendly:

	if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", *cpa->vaddr))
		*cpa->vaddr &= PAGE_MASK;

> +	}
> +
> +	addr = *cpa->vaddr;
> +	numpages = cpa->numpages;
> +
> +	/* Must avoid aliasing mappings in the highmem code */
> +	kmap_flush_unused();
> +	vm_unmap_aliases();
> +
> +	ret = __change_page_attr_set_clr(cpa, 1);
> +
> +	/* Check whether we really changed something */
> +	if (!(cpa->flags & CPA_FLUSHTLB))
> +		goto out;
> +
> +	/*
> +	 * On success we use CLFLUSH, when the CPU supports it to
> +	 * avoid the WBINVD.
> +	 */
> +	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
> +		cpa_flush_range(addr, numpages, 1);
> +	else
> +		cpa_flush_all(1);

So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
have to?

Don't you want this instead:

        ret = __change_page_attr_set_clr(cpa, 1);
        if (ret)
                goto out;

        /* Check whether we really changed something */
        if (!(cpa->flags & CPA_FLUSHTLB))
                goto out;

        /*
         * On success we use CLFLUSH, when the CPU supports it to
         * avoid the WBINVD.
         */
        if (static_cpu_has(X86_FEATURE_CLFLUSH))
                cpa_flush_range(addr, numpages, 1);
        else
                cpa_flush_all(1);

out:
        return ret;
}

?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-09-09 17:34     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 17:34 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:37:57PM -0500, Tom Lendacky wrote:
> When Secure Memory Encryption is enabled, the trampoline area must not
> be encrypted. A cpu running in real mode will not be able to decrypt

s/cpu/CPU/... always :-)

> memory that has been encrypted because it will not be able to use addresses
> with the memory encryption mask.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/realmode/init.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
> index 5db706f1..f74925f 100644
> --- a/arch/x86/realmode/init.c
> +++ b/arch/x86/realmode/init.c
> @@ -6,6 +6,7 @@
>  #include <asm/pgtable.h>
>  #include <asm/realmode.h>
>  #include <asm/tlbflush.h>
> +#include <asm/mem_encrypt.h>
>  
>  struct real_mode_header *real_mode_header;
>  u32 *trampoline_cr4_features;
> @@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
>  	unsigned long text_start =
>  		(unsigned long) __va(real_mode_header->text_start);
>  
> +	/*
> +	 * If memory encryption is active, the trampoline area will need to
> +	 * be in non-encrypted memory in order to bring up other processors

Let's stick with either "unencrypted" - I'd prefer that one - or
"non-encrypted" nomenclature so that there's no distraction. I see both
versions in the patchset.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-09-09 17:34     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-09 17:34 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:37:57PM -0500, Tom Lendacky wrote:
> When Secure Memory Encryption is enabled, the trampoline area must not
> be encrypted. A cpu running in real mode will not be able to decrypt

s/cpu/CPU/... always :-)

> memory that has been encrypted because it will not be able to use addresses
> with the memory encryption mask.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/realmode/init.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
> index 5db706f1..f74925f 100644
> --- a/arch/x86/realmode/init.c
> +++ b/arch/x86/realmode/init.c
> @@ -6,6 +6,7 @@
>  #include <asm/pgtable.h>
>  #include <asm/realmode.h>
>  #include <asm/tlbflush.h>
> +#include <asm/mem_encrypt.h>
>  
>  struct real_mode_header *real_mode_header;
>  u32 *trampoline_cr4_features;
> @@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
>  	unsigned long text_start =
>  		(unsigned long) __va(real_mode_header->text_start);
>  
> +	/*
> +	 * If memory encryption is active, the trampoline area will need to
> +	 * be in non-encrypted memory in order to bring up other processors

Let's stick with either "unencrypted" - I'd prefer that one - or
"non-encrypted" nomenclature so that there's no distraction. I see both
versions in the patchset.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-09-12 10:58     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 10:58 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:07PM -0500, Tom Lendacky wrote:
> Since DMA addresses will effectively look like 48-bit addresses when the
> memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
> device performing the DMA does not support 48-bits. SWIOTLB will be
> initialized to create un-encrypted bounce buffers for use by these devices.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/dma-mapping.h |    5 ++-
>  arch/x86/include/asm/mem_encrypt.h |    6 +++
>  arch/x86/kernel/pci-dma.c          |   11 ++++--
>  arch/x86/kernel/pci-nommu.c        |    2 +
>  arch/x86/kernel/pci-swiotlb.c      |    8 +++--
>  arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
>  include/linux/swiotlb.h            |    1 +
>  init/main.c                        |   13 +++++++
>  lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
>  9 files changed, 115 insertions(+), 17 deletions(-)

...

> @@ -172,3 +174,23 @@ void __init sme_early_init(void)
>  	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
>  		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
>  }
> +
> +/* Architecture __weak replacement functions */
> +void __init mem_encrypt_init(void)
> +{
> +	if (!sme_me_mask)
> +		return;
> +
> +	/* Make SWIOTLB use an unencrypted DMA area */
> +	swiotlb_clear_encryption();
> +}
> +
> +unsigned long swiotlb_get_me_mask(void)

This could just as well be named to something more generic:

swiotlb_get_clear_dma_mask() or so which basically means the mask of
bits which get cleared before returning DMA addresses...

> +{
> +	return sme_me_mask;
> +}
> +
> +void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
> +{
> +	sme_set_mem_dec(vaddr, size);
> +}
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 5f81f8a..5c909fc 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>  extern unsigned long swiotlb_nr_tbl(void);
>  unsigned long swiotlb_size_or_default(void);
>  extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
> +extern void __init swiotlb_clear_encryption(void);
>  
>  /*
>   * Enumeration for sync targets
> diff --git a/init/main.c b/init/main.c
> index a8a58e2..82c7cd9 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
>  }
>  #endif
>  
> +void __init __weak mem_encrypt_init(void)
> +{
> +}
> +
>  /*
>   * Set up kernel memory allocators
>   */
> @@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
>  	 */
>  	locking_selftest();
>  
> +	/*
> +	 * This needs to be called before any devices perform DMA
> +	 * operations that might use the swiotlb bounce buffers.
> +	 * This call will mark the bounce buffers as un-encrypted so
> +	 * that the usage of them will not cause "plain-text" data

	...that their usage will not cause ...

> +	 * to be decrypted when accessed.
> +	 */
> +	mem_encrypt_init();
> +
>  #ifdef CONFIG_BLK_DEV_INITRD
>  	if (initrd_start && !initrd_below_start_ok &&
>  	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 22e13a0..15d5741 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
>  	return size ? size : (IO_TLB_DEFAULT_SIZE);
>  }
>  
> +/*
> + * Support for memory encryption. If memory encryption is supported, then an
> + * override to these functions will be provided.
> + */

No need for that comment.

> +unsigned long __weak swiotlb_get_me_mask(void)
> +{
> +	return 0;
> +}
> +
> +void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
> +{
> +}
> +
> +/* For swiotlb, clear memory encryption mask from dma addresses */
> +static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
> +				      phys_addr_t address)
> +{
> +	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
> +}
> +
>  /* Note that this doesn't work with highmem page */
>  static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
>  				      volatile void *address)
> @@ -159,6 +179,30 @@ void swiotlb_print_info(void)
>  	       bytes >> 20, vstart, vend - 1);
>  }
>  
> +/*
> + * If memory encryption is active, the DMA address for an encrypted page may
> + * be beyond the range of the device. If bounce buffers are required be sure
> + * that they are not on an encrypted page. This should be called before the
> + * iotlb area is used.
> + */
> +void __init swiotlb_clear_encryption(void)
> +{
> +	void *vaddr;
> +	unsigned long bytes;
> +
> +	if (no_iotlb_memory || !io_tlb_start || late_alloc)
> +		return;
> +
> +	vaddr = phys_to_virt(io_tlb_start);
> +	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
> +	swiotlb_set_mem_dec(vaddr, bytes);
> +	memset(vaddr, 0, bytes);

io_tlb_start is cleared...

> +
> +	vaddr = phys_to_virt(io_tlb_overflow_buffer);
> +	bytes = PAGE_ALIGN(io_tlb_overflow);
> +	swiotlb_set_mem_dec(vaddr, bytes);

... but io_tlb_overflow_buffer isn't? I don't see the difference here.

> +}
> +
>  int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
>  {
>  	void *v_overflow_buffer;
-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-09-12 10:58     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 10:58 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:38:07PM -0500, Tom Lendacky wrote:
> Since DMA addresses will effectively look like 48-bit addresses when the
> memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
> device performing the DMA does not support 48-bits. SWIOTLB will be
> initialized to create un-encrypted bounce buffers for use by these devices.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/include/asm/dma-mapping.h |    5 ++-
>  arch/x86/include/asm/mem_encrypt.h |    6 +++
>  arch/x86/kernel/pci-dma.c          |   11 ++++--
>  arch/x86/kernel/pci-nommu.c        |    2 +
>  arch/x86/kernel/pci-swiotlb.c      |    8 +++--
>  arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
>  include/linux/swiotlb.h            |    1 +
>  init/main.c                        |   13 +++++++
>  lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
>  9 files changed, 115 insertions(+), 17 deletions(-)

...

> @@ -172,3 +174,23 @@ void __init sme_early_init(void)
>  	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
>  		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
>  }
> +
> +/* Architecture __weak replacement functions */
> +void __init mem_encrypt_init(void)
> +{
> +	if (!sme_me_mask)
> +		return;
> +
> +	/* Make SWIOTLB use an unencrypted DMA area */
> +	swiotlb_clear_encryption();
> +}
> +
> +unsigned long swiotlb_get_me_mask(void)

This could just as well be named to something more generic:

swiotlb_get_clear_dma_mask() or so which basically means the mask of
bits which get cleared before returning DMA addresses...

> +{
> +	return sme_me_mask;
> +}
> +
> +void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
> +{
> +	sme_set_mem_dec(vaddr, size);
> +}
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 5f81f8a..5c909fc 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>  extern unsigned long swiotlb_nr_tbl(void);
>  unsigned long swiotlb_size_or_default(void);
>  extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
> +extern void __init swiotlb_clear_encryption(void);
>  
>  /*
>   * Enumeration for sync targets
> diff --git a/init/main.c b/init/main.c
> index a8a58e2..82c7cd9 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
>  }
>  #endif
>  
> +void __init __weak mem_encrypt_init(void)
> +{
> +}
> +
>  /*
>   * Set up kernel memory allocators
>   */
> @@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
>  	 */
>  	locking_selftest();
>  
> +	/*
> +	 * This needs to be called before any devices perform DMA
> +	 * operations that might use the swiotlb bounce buffers.
> +	 * This call will mark the bounce buffers as un-encrypted so
> +	 * that the usage of them will not cause "plain-text" data

	...that their usage will not cause ...

> +	 * to be decrypted when accessed.
> +	 */
> +	mem_encrypt_init();
> +
>  #ifdef CONFIG_BLK_DEV_INITRD
>  	if (initrd_start && !initrd_below_start_ok &&
>  	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index 22e13a0..15d5741 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
>  	return size ? size : (IO_TLB_DEFAULT_SIZE);
>  }
>  
> +/*
> + * Support for memory encryption. If memory encryption is supported, then an
> + * override to these functions will be provided.
> + */

No need for that comment.

> +unsigned long __weak swiotlb_get_me_mask(void)
> +{
> +	return 0;
> +}
> +
> +void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
> +{
> +}
> +
> +/* For swiotlb, clear memory encryption mask from dma addresses */
> +static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
> +				      phys_addr_t address)
> +{
> +	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
> +}
> +
>  /* Note that this doesn't work with highmem page */
>  static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
>  				      volatile void *address)
> @@ -159,6 +179,30 @@ void swiotlb_print_info(void)
>  	       bytes >> 20, vstart, vend - 1);
>  }
>  
> +/*
> + * If memory encryption is active, the DMA address for an encrypted page may
> + * be beyond the range of the device. If bounce buffers are required be sure
> + * that they are not on an encrypted page. This should be called before the
> + * iotlb area is used.
> + */
> +void __init swiotlb_clear_encryption(void)
> +{
> +	void *vaddr;
> +	unsigned long bytes;
> +
> +	if (no_iotlb_memory || !io_tlb_start || late_alloc)
> +		return;
> +
> +	vaddr = phys_to_virt(io_tlb_start);
> +	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
> +	swiotlb_set_mem_dec(vaddr, bytes);
> +	memset(vaddr, 0, bytes);

io_tlb_start is cleared...

> +
> +	vaddr = phys_to_virt(io_tlb_overflow_buffer);
> +	bytes = PAGE_ALIGN(io_tlb_overflow);
> +	swiotlb_set_mem_dec(vaddr, bytes);

... but io_tlb_overflow_buffer isn't? I don't see the difference here.

> +}
> +
>  int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
>  {
>  	void *v_overflow_buffer;
-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-12 11:45     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 11:45 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:20PM -0500, Tom Lendacky wrote:
> Add support to the AMD IOMMU driver to set the memory encryption mask if
> memory encryption is enabled.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/mem_encrypt.h |    2 ++
>  arch/x86/mm/mem_encrypt.c          |    5 +++++
>  drivers/iommu/amd_iommu.c          |   10 ++++++++++
>  3 files changed, 17 insertions(+)
> 
> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
> index 384fdfb..e395729 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -36,6 +36,8 @@ void __init sme_early_init(void);
>  /* Architecture __weak replacement functions */
>  void __init mem_encrypt_init(void);
>  
> +unsigned long amd_iommu_get_me_mask(void);
> +
>  unsigned long swiotlb_get_me_mask(void);
>  void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
>  
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 6b2e8bf..2f28d87 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
>  	swiotlb_clear_encryption();
>  }
>  
> +unsigned long amd_iommu_get_me_mask(void)
> +{
> +	return sme_me_mask;
> +}
> +
>  unsigned long swiotlb_get_me_mask(void)
>  {
>  	return sme_me_mask;
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index 96de97a..63995e3 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -166,6 +166,15 @@ struct dma_ops_domain {
>  static struct iova_domain reserved_iova_ranges;
>  static struct lock_class_key reserved_rbtree_key;
>  
> +/*
> + * Support for memory encryption. If memory encryption is supported, then an
> + * override to this function will be provided.
> + */
> +unsigned long __weak amd_iommu_get_me_mask(void)
> +{
> +	return 0;
> +}

So instead of adding a function each time which returns sme_me_mask
for each user it has, why don't you add a single function which
returns sme_me_mask in mem_encrypt.c and add an inline in the header
mem_encrypt.h which returns 0 for the !CONFIG_AMD_MEM_ENCRYPT case.

This all is still funny because we access sme_me_mask directly for the
different KERNEL_* masks but then you're adding an accessor function.

So what you should do instead, IMHO, is either hide sme_me_mask
altogether and use the accessor functions only (not sure if that would
work in all cases) or expose sme_me_mask unconditionally and have it be
0 if CONFIG_AMD_MEM_ENCRYPT is not enabled so that it just works.

Or is there a third, more graceful variant?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-12 11:45     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 11:45 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:38:20PM -0500, Tom Lendacky wrote:
> Add support to the AMD IOMMU driver to set the memory encryption mask if
> memory encryption is enabled.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/include/asm/mem_encrypt.h |    2 ++
>  arch/x86/mm/mem_encrypt.c          |    5 +++++
>  drivers/iommu/amd_iommu.c          |   10 ++++++++++
>  3 files changed, 17 insertions(+)
> 
> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
> index 384fdfb..e395729 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -36,6 +36,8 @@ void __init sme_early_init(void);
>  /* Architecture __weak replacement functions */
>  void __init mem_encrypt_init(void);
>  
> +unsigned long amd_iommu_get_me_mask(void);
> +
>  unsigned long swiotlb_get_me_mask(void);
>  void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
>  
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 6b2e8bf..2f28d87 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
>  	swiotlb_clear_encryption();
>  }
>  
> +unsigned long amd_iommu_get_me_mask(void)
> +{
> +	return sme_me_mask;
> +}
> +
>  unsigned long swiotlb_get_me_mask(void)
>  {
>  	return sme_me_mask;
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index 96de97a..63995e3 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -166,6 +166,15 @@ struct dma_ops_domain {
>  static struct iova_domain reserved_iova_ranges;
>  static struct lock_class_key reserved_rbtree_key;
>  
> +/*
> + * Support for memory encryption. If memory encryption is supported, then an
> + * override to this function will be provided.
> + */
> +unsigned long __weak amd_iommu_get_me_mask(void)
> +{
> +	return 0;
> +}

So instead of adding a function each time which returns sme_me_mask
for each user it has, why don't you add a single function which
returns sme_me_mask in mem_encrypt.c and add an inline in the header
mem_encrypt.h which returns 0 for the !CONFIG_AMD_MEM_ENCRYPT case.

This all is still funny because we access sme_me_mask directly for the
different KERNEL_* masks but then you're adding an accessor function.

So what you should do instead, IMHO, is either hide sme_me_mask
altogether and use the accessor functions only (not sure if that would
work in all cases) or expose sme_me_mask unconditionally and have it be
0 if CONFIG_AMD_MEM_ENCRYPT is not enabled so that it just works.

Or is there a third, more graceful variant?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-12 12:17     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 12:17 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
> Add support to check if memory encryption is active in the kernel and that
> it has been enabled on the AP. If memory encryption is active in the kernel
> but has not been enabled on the AP then do not allow the AP to continue
> start up.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/msr-index.h     |    2 ++
>  arch/x86/include/asm/realmode.h      |   12 ++++++++++++
>  arch/x86/realmode/init.c             |    4 ++++
>  arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
>  4 files changed, 37 insertions(+)

...

> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
> index dac7b20..94e29f4 100644
> --- a/arch/x86/realmode/rm/trampoline_64.S
> +++ b/arch/x86/realmode/rm/trampoline_64.S
> @@ -30,6 +30,7 @@
>  #include <asm/msr.h>
>  #include <asm/segment.h>
>  #include <asm/processor-flags.h>
> +#include <asm/realmode.h>
>  #include "realmode.h"
>  
>  	.text
> @@ -92,6 +93,23 @@ ENTRY(startup_32)
>  	movl	%edx, %fs
>  	movl	%edx, %gs
>  
> +	/* Check for memory encryption support */
> +	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
> +	jnc	.Ldone
> +	movl	$MSR_K8_SYSCFG, %ecx
> +	rdmsr
> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
> +	jc	.Ldone
> +
> +	/*
> +	 * Memory encryption is enabled but the MSR has not been set on this
> +	 * CPU so we can't continue

Hmm, let me try to parse this correctly: BSP has SME enabled but the
BIOS might not've set this on the AP? Really? Is that even possible?

Because if SME is enabled, that means that MSR_K8_SYSCFG[23] on the BSP
is set, right?

Also, I want to rule out here simple BIOS idiocy: if the only problem
with the bit not being set in the AP is because some BIOS monkey forgot
to do so, then we should try to set it ourselves and not die for no real
reason.

Or is there another issue?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-12 12:17     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 12:17 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
> Add support to check if memory encryption is active in the kernel and that
> it has been enabled on the AP. If memory encryption is active in the kernel
> but has not been enabled on the AP then do not allow the AP to continue
> start up.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/include/asm/msr-index.h     |    2 ++
>  arch/x86/include/asm/realmode.h      |   12 ++++++++++++
>  arch/x86/realmode/init.c             |    4 ++++
>  arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
>  4 files changed, 37 insertions(+)

...

> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
> index dac7b20..94e29f4 100644
> --- a/arch/x86/realmode/rm/trampoline_64.S
> +++ b/arch/x86/realmode/rm/trampoline_64.S
> @@ -30,6 +30,7 @@
>  #include <asm/msr.h>
>  #include <asm/segment.h>
>  #include <asm/processor-flags.h>
> +#include <asm/realmode.h>
>  #include "realmode.h"
>  
>  	.text
> @@ -92,6 +93,23 @@ ENTRY(startup_32)
>  	movl	%edx, %fs
>  	movl	%edx, %gs
>  
> +	/* Check for memory encryption support */
> +	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
> +	jnc	.Ldone
> +	movl	$MSR_K8_SYSCFG, %ecx
> +	rdmsr
> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
> +	jc	.Ldone
> +
> +	/*
> +	 * Memory encryption is enabled but the MSR has not been set on this
> +	 * CPU so we can't continue

Hmm, let me try to parse this correctly: BSP has SME enabled but the
BIOS might not've set this on the AP? Really? Is that even possible?

Because if SME is enabled, that means that MSR_K8_SYSCFG[23] on the BSP
is set, right?

Also, I want to rule out here simple BIOS idiocy: if the only problem
with the bit not being set in the AP is because some BIOS monkey forgot
to do so, then we should try to set it ourselves and not die for no real
reason.

Or is there another issue?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
  2016-09-08 13:55             ` Borislav Petkov
@ 2016-09-12 13:43               ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 13:43 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/08/2016 08:55 AM, Borislav Petkov wrote:
> On Thu, Sep 08, 2016 at 08:26:27AM -0500, Tom Lendacky wrote:
>> When does this value get initialized?  Since _PAGE_ENC is #defined to
>> sme_me_mask, which is not set until the boot process begins, I'm afraid
>> we'd end up using the initial value of sme_me_mask, which is zero.  Do
>> I have that right?
> 
> Hmm, but then that would hold true for all the other defines where you
> OR-in _PAGE_ENC, no?

As long as the #define is not a global variable like this one it's ok.

> 
> In any case, the preprocessed source looks like this:
> 
> pmdval_t early_pmd_flags = (((((((pteval_t)(1)) << 0) | (((pteval_t)(1)) << 1) | (((pteval_t)(1)) << 6) | (((pteval_t)(1)) << 5) | (((pteval_t)(1)) << 8)) | (((pteval_t)(1)) << 63)) | (((pteval_t)(1)) << 7)) | sme_me_mask) & ~((((pteval_t)(1)) << 8) | (((pteval_t)(1)) << 63));
> 
> but the problem is later, when building:
> 
> arch/x86/kernel/head64.c:39:28: error: initializer element is not constant
>  pmdval_t early_pmd_flags = (__PAGE_KERNEL_LARGE | _PAGE_ENC) & ~(_PAGE_GLOBAL | _PAGE_NX);
>                             ^
> scripts/Makefile.build:153: recipe for target 'arch/x86/kernel/head64.s' failed
> 
> so I guess not. :-\
> 
> Ok, then at least please put the early_pmd_flags init after
> sme_early_init() along with a small comment explaning what happens.

Let me verify that we won't possibly take any kind of page fault during
sme_early_init() and cause a page to be not be marked encrypted. Or... I
can add a comment indicating I need to set this as early as possible to
cover any page faults that might occur.

Thanks,
Tom

> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption
@ 2016-09-12 13:43               ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 13:43 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/08/2016 08:55 AM, Borislav Petkov wrote:
> On Thu, Sep 08, 2016 at 08:26:27AM -0500, Tom Lendacky wrote:
>> When does this value get initialized?  Since _PAGE_ENC is #defined to
>> sme_me_mask, which is not set until the boot process begins, I'm afraid
>> we'd end up using the initial value of sme_me_mask, which is zero.  Do
>> I have that right?
> 
> Hmm, but then that would hold true for all the other defines where you
> OR-in _PAGE_ENC, no?

As long as the #define is not a global variable like this one it's ok.

> 
> In any case, the preprocessed source looks like this:
> 
> pmdval_t early_pmd_flags = (((((((pteval_t)(1)) << 0) | (((pteval_t)(1)) << 1) | (((pteval_t)(1)) << 6) | (((pteval_t)(1)) << 5) | (((pteval_t)(1)) << 8)) | (((pteval_t)(1)) << 63)) | (((pteval_t)(1)) << 7)) | sme_me_mask) & ~((((pteval_t)(1)) << 8) | (((pteval_t)(1)) << 63));
> 
> but the problem is later, when building:
> 
> arch/x86/kernel/head64.c:39:28: error: initializer element is not constant
>  pmdval_t early_pmd_flags = (__PAGE_KERNEL_LARGE | _PAGE_ENC) & ~(_PAGE_GLOBAL | _PAGE_NX);
>                             ^
> scripts/Makefile.build:153: recipe for target 'arch/x86/kernel/head64.s' failed
> 
> so I guess not. :-\
> 
> Ok, then at least please put the early_pmd_flags init after
> sme_early_init() along with a small comment explaning what happens.

Let me verify that we won't possibly take any kind of page fault during
sme_early_init() and cause a page to be not be marked encrypted. Or... I
can add a comment indicating I need to set this as early as possible to
cover any page faults that might occur.

Thanks,
Tom

> 
> Thanks.
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
  2016-08-22 22:38   ` Tom Lendacky
@ 2016-09-12 14:35     ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 14:35 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:49PM -0500, Tom Lendacky wrote:
> Update the KVM support to include the memory encryption mask when creating
> and using nested page tables.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/kvm_host.h |    3 ++-
>  arch/x86/kvm/mmu.c              |    8 ++++++--
>  arch/x86/kvm/vmx.c              |    3 ++-
>  arch/x86/kvm/x86.c              |    3 ++-
>  4 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 33ae3a4..c51c1cb 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
>  void kvm_mmu_init_vm(struct kvm *kvm);
>  void kvm_mmu_uninit_vm(struct kvm *kvm);
>  void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
> -		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
> +		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
> +		u64 me_mask);

Why do you need a separate mask?

arch/x86/kvm/mmu.c::set_spte() ORs in shadow_present_mask
unconditionally. So you can simply do:


	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
			      PT_DIRTY_MASK, PT64_NX_MASK, 0,
			      PT_PRESENT_MASK | sme_me_mask);

and have this change much simpler.

>  void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
>  void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 3d4cc8cc..a7040f4 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
>  					    * PT32_LEVEL_BITS))) - 1))
>  
>  #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
> -			| shadow_x_mask | shadow_nx_mask)
> +			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)

This would be sme_me_mask, of course, like with the baremetal masks.

Or am I missing something?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-09-12 14:35     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 14:35 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:49PM -0500, Tom Lendacky wrote:
> Update the KVM support to include the memory encryption mask when creating
> and using nested page tables.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/include/asm/kvm_host.h |    3 ++-
>  arch/x86/kvm/mmu.c              |    8 ++++++--
>  arch/x86/kvm/vmx.c              |    3 ++-
>  arch/x86/kvm/x86.c              |    3 ++-
>  4 files changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 33ae3a4..c51c1cb 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
>  void kvm_mmu_init_vm(struct kvm *kvm);
>  void kvm_mmu_uninit_vm(struct kvm *kvm);
>  void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
> -		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
> +		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
> +		u64 me_mask);

Why do you need a separate mask?

arch/x86/kvm/mmu.c::set_spte() ORs in shadow_present_mask
unconditionally. So you can simply do:


	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
			      PT_DIRTY_MASK, PT64_NX_MASK, 0,
			      PT_PRESENT_MASK | sme_me_mask);

and have this change much simpler.

>  void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
>  void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 3d4cc8cc..a7040f4 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
>  					    * PT32_LEVEL_BITS))) - 1))
>  
>  #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
> -			| shadow_x_mask | shadow_nx_mask)
> +			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)

This would be sme_me_mask, of course, like with the baremetal masks.

Or am I missing something?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-12 15:05       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:05 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 10:53 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
>> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
>> that special handling isn't needed afterwards.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
>>  arch/x86/kernel/setup.c  |    8 ++++
>>  2 files changed, 96 insertions(+), 5 deletions(-)
> 
> ...
> 
>> +int __init early_make_pgtable(unsigned long address)
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pmdval_t pmd;
>> +
>> +	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
>> +
>> +	return __early_make_pgtable(address, pmd);
>> +}
>> +
>> +static void __init create_unencrypted_mapping(void *address, unsigned long size)
>> +{
>> +	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
>> +	pmdval_t pmd_flags, pmd;
>> +
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Clear the encryption mask from the early_pmd_flags */
>> +	pmd_flags = early_pmd_flags & ~sme_me_mask;
>> +
>> +	do {
>> +		pmd = (physaddr & PMD_MASK) + pmd_flags;
>> +		__early_make_pgtable((unsigned long)address, pmd);
>> +
>> +		address += PMD_SIZE;
>> +		physaddr += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init __clear_mapping(unsigned long address)
> 
> Should be called something with "pmd" in the name as it clears a PMD,
> i.e. __clear_pmd_mapping or so.

Ok.

> 
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pgdval_t pgd, *pgd_p;
>> +	pudval_t pud, *pud_p;
>> +	pmdval_t *pmd_p;
>> +
>> +	/* Invalid address or early pgt is done ?  */
>> +	if (physaddr >= MAXMEM ||
>> +	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>> +		return;
>> +
>> +	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
>> +	pgd = *pgd_p;
>> +
>> +	if (!pgd)
>> +		return;
>> +
>> +	/*
>> +	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
>> +	 * __early_make_pgtable where the entry was created.
>> +	 */
>> +	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pud_p += pud_index(address);
>> +	pud = *pud_p;
>> +
>> +	if (!pud)
>> +		return;
>> +
>> +	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pmd_p[pmd_index(address)] = 0;
>> +}
>> +
>> +static void __init clear_mapping(void *address, unsigned long size)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	do {
>> +		__clear_mapping((unsigned long)address);
>> +
>> +		address += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
>> +{
>> +	create_unencrypted_mapping(src, size);
>> +	memcpy(dst, src, size);
>> +	clear_mapping(src, size);
>> +}
>> +
> 
> In any case, this whole functionality is SME-specific and should be
> somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

I can look into that.  The reason I put this here is this is all the
early page fault support that is very specific to this file. I modified
an existing static function to take advantage of the mapping support.

> 
>>  /* Don't add a printk in there. printk relies on the PDA which is not initialized 
>>     yet. */
>>  static void __init clear_bss(void)
>> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>>  	char * command_line;
>>  	unsigned long cmd_line_ptr;
>>  
>> -	memcpy(&boot_params, real_mode_data, sizeof boot_params);
>> +	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
> 
> checkpatch.pl:
> 
> WARNING: sizeof boot_params should be sizeof(boot_params)
> #155: FILE: arch/x86/kernel/head64.c:208:
> +       sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

I can fix that.

> 
>>  	sanitize_boot_params(&boot_params);
>>  	cmd_line_ptr = get_cmd_line_ptr();
>>  	if (cmd_line_ptr) {
>>  		command_line = __va(cmd_line_ptr);
>> -		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>> +		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>>  	}
>>  }
>>  
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 1489da8..1fdaa11 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -114,6 +114,7 @@
>>  #include <asm/microcode.h>
>>  #include <asm/mmu_context.h>
>>  #include <asm/kaslr.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
>> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>>  	    !ramdisk_image || !ramdisk_size)
>>  		return;		/* No initrd provided by bootloader */
>>  
>> +	/*
>> +	 * This memory is marked encrypted by the kernel but the ramdisk
>> +	 * was loaded in the clear by the bootloader, so make sure that
>> +	 * the ramdisk image is encrypted.
>> +	 */
>> +	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
> 
> What happens if we go and relocate the ramdisk? I.e., the function above
> this one: relocate_initrd(). We have to encrypt it then too, I presume.

Hmmm, maybe... With the change to the early_memremap() the initrd is now
identified as BOOT_DATA in relocate_initrd() and so it will be mapped
and copied as non-encyrpted data. But since it was encrypted before the
call to relocate_initrd() it will copy encrypted bytes which will later
be accessed encrypted. That isn't clear though, so I'll rework
reserve_initrd() to perform the sme_early_mem_enc() once at the end
whether the initrd is re-located or not.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-12 15:05       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:05 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/09/2016 10:53 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
>> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
>> that special handling isn't needed afterwards.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
>> ---
>>  arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
>>  arch/x86/kernel/setup.c  |    8 ++++
>>  2 files changed, 96 insertions(+), 5 deletions(-)
> 
> ...
> 
>> +int __init early_make_pgtable(unsigned long address)
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pmdval_t pmd;
>> +
>> +	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
>> +
>> +	return __early_make_pgtable(address, pmd);
>> +}
>> +
>> +static void __init create_unencrypted_mapping(void *address, unsigned long size)
>> +{
>> +	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
>> +	pmdval_t pmd_flags, pmd;
>> +
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Clear the encryption mask from the early_pmd_flags */
>> +	pmd_flags = early_pmd_flags & ~sme_me_mask;
>> +
>> +	do {
>> +		pmd = (physaddr & PMD_MASK) + pmd_flags;
>> +		__early_make_pgtable((unsigned long)address, pmd);
>> +
>> +		address += PMD_SIZE;
>> +		physaddr += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init __clear_mapping(unsigned long address)
> 
> Should be called something with "pmd" in the name as it clears a PMD,
> i.e. __clear_pmd_mapping or so.

Ok.

> 
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pgdval_t pgd, *pgd_p;
>> +	pudval_t pud, *pud_p;
>> +	pmdval_t *pmd_p;
>> +
>> +	/* Invalid address or early pgt is done ?  */
>> +	if (physaddr >= MAXMEM ||
>> +	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>> +		return;
>> +
>> +	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
>> +	pgd = *pgd_p;
>> +
>> +	if (!pgd)
>> +		return;
>> +
>> +	/*
>> +	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
>> +	 * __early_make_pgtable where the entry was created.
>> +	 */
>> +	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pud_p += pud_index(address);
>> +	pud = *pud_p;
>> +
>> +	if (!pud)
>> +		return;
>> +
>> +	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pmd_p[pmd_index(address)] = 0;
>> +}
>> +
>> +static void __init clear_mapping(void *address, unsigned long size)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	do {
>> +		__clear_mapping((unsigned long)address);
>> +
>> +		address += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
>> +{
>> +	create_unencrypted_mapping(src, size);
>> +	memcpy(dst, src, size);
>> +	clear_mapping(src, size);
>> +}
>> +
> 
> In any case, this whole functionality is SME-specific and should be
> somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

I can look into that.  The reason I put this here is this is all the
early page fault support that is very specific to this file. I modified
an existing static function to take advantage of the mapping support.

> 
>>  /* Don't add a printk in there. printk relies on the PDA which is not initialized 
>>     yet. */
>>  static void __init clear_bss(void)
>> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>>  	char * command_line;
>>  	unsigned long cmd_line_ptr;
>>  
>> -	memcpy(&boot_params, real_mode_data, sizeof boot_params);
>> +	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
> 
> checkpatch.pl:
> 
> WARNING: sizeof boot_params should be sizeof(boot_params)
> #155: FILE: arch/x86/kernel/head64.c:208:
> +       sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

I can fix that.

> 
>>  	sanitize_boot_params(&boot_params);
>>  	cmd_line_ptr = get_cmd_line_ptr();
>>  	if (cmd_line_ptr) {
>>  		command_line = __va(cmd_line_ptr);
>> -		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>> +		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>>  	}
>>  }
>>  
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 1489da8..1fdaa11 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -114,6 +114,7 @@
>>  #include <asm/microcode.h>
>>  #include <asm/mmu_context.h>
>>  #include <asm/kaslr.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
>> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>>  	    !ramdisk_image || !ramdisk_size)
>>  		return;		/* No initrd provided by bootloader */
>>  
>> +	/*
>> +	 * This memory is marked encrypted by the kernel but the ramdisk
>> +	 * was loaded in the clear by the bootloader, so make sure that
>> +	 * the ramdisk image is encrypted.
>> +	 */
>> +	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
> 
> What happens if we go and relocate the ramdisk? I.e., the function above
> this one: relocate_initrd(). We have to encrypt it then too, I presume.

Hmmm, maybe... With the change to the early_memremap() the initrd is now
identified as BOOT_DATA in relocate_initrd() and so it will be mapped
and copied as non-encyrpted data. But since it was encrypted before the
call to relocate_initrd() it will copy encrypted bytes which will later
be accessed encrypted. That isn't clear though, so I'll rework
reserve_initrd() to perform the sme_early_mem_enc() once at the end
whether the initrd is re-located or not.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-12 15:05       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:05 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 10:53 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote:
>> Encrypt memory areas in place when possible (e.g. zero page, etc.) so
>> that special handling isn't needed afterwards.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/kernel/head64.c |   93 ++++++++++++++++++++++++++++++++++++++++++++--
>>  arch/x86/kernel/setup.c  |    8 ++++
>>  2 files changed, 96 insertions(+), 5 deletions(-)
> 
> ...
> 
>> +int __init early_make_pgtable(unsigned long address)
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pmdval_t pmd;
>> +
>> +	pmd = (physaddr & PMD_MASK) + early_pmd_flags;
>> +
>> +	return __early_make_pgtable(address, pmd);
>> +}
>> +
>> +static void __init create_unencrypted_mapping(void *address, unsigned long size)
>> +{
>> +	unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET;
>> +	pmdval_t pmd_flags, pmd;
>> +
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Clear the encryption mask from the early_pmd_flags */
>> +	pmd_flags = early_pmd_flags & ~sme_me_mask;
>> +
>> +	do {
>> +		pmd = (physaddr & PMD_MASK) + pmd_flags;
>> +		__early_make_pgtable((unsigned long)address, pmd);
>> +
>> +		address += PMD_SIZE;
>> +		physaddr += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init __clear_mapping(unsigned long address)
> 
> Should be called something with "pmd" in the name as it clears a PMD,
> i.e. __clear_pmd_mapping or so.

Ok.

> 
>> +{
>> +	unsigned long physaddr = address - __PAGE_OFFSET;
>> +	pgdval_t pgd, *pgd_p;
>> +	pudval_t pud, *pud_p;
>> +	pmdval_t *pmd_p;
>> +
>> +	/* Invalid address or early pgt is done ?  */
>> +	if (physaddr >= MAXMEM ||
>> +	    read_cr3() != __sme_pa_nodebug(early_level4_pgt))
>> +		return;
>> +
>> +	pgd_p = &early_level4_pgt[pgd_index(address)].pgd;
>> +	pgd = *pgd_p;
>> +
>> +	if (!pgd)
>> +		return;
>> +
>> +	/*
>> +	 * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches
>> +	 * __early_make_pgtable where the entry was created.
>> +	 */
>> +	pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pud_p += pud_index(address);
>> +	pud = *pud_p;
>> +
>> +	if (!pud)
>> +		return;
>> +
>> +	pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base);
>> +	pmd_p[pmd_index(address)] = 0;
>> +}
>> +
>> +static void __init clear_mapping(void *address, unsigned long size)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	do {
>> +		__clear_mapping((unsigned long)address);
>> +
>> +		address += PMD_SIZE;
>> +		size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE;
>> +	} while (size);
>> +}
>> +
>> +static void __init sme_memcpy(void *dst, void *src, unsigned long size)
>> +{
>> +	create_unencrypted_mapping(src, size);
>> +	memcpy(dst, src, size);
>> +	clear_mapping(src, size);
>> +}
>> +
> 
> In any case, this whole functionality is SME-specific and should be
> somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so...

I can look into that.  The reason I put this here is this is all the
early page fault support that is very specific to this file. I modified
an existing static function to take advantage of the mapping support.

> 
>>  /* Don't add a printk in there. printk relies on the PDA which is not initialized 
>>     yet. */
>>  static void __init clear_bss(void)
>> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data)
>>  	char * command_line;
>>  	unsigned long cmd_line_ptr;
>>  
>> -	memcpy(&boot_params, real_mode_data, sizeof boot_params);
>> +	sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);
> 
> checkpatch.pl:
> 
> WARNING: sizeof boot_params should be sizeof(boot_params)
> #155: FILE: arch/x86/kernel/head64.c:208:
> +       sme_memcpy(&boot_params, real_mode_data, sizeof boot_params);

I can fix that.

> 
>>  	sanitize_boot_params(&boot_params);
>>  	cmd_line_ptr = get_cmd_line_ptr();
>>  	if (cmd_line_ptr) {
>>  		command_line = __va(cmd_line_ptr);
>> -		memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>> +		sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>>  	}
>>  }
>>  
>> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
>> index 1489da8..1fdaa11 100644
>> --- a/arch/x86/kernel/setup.c
>> +++ b/arch/x86/kernel/setup.c
>> @@ -114,6 +114,7 @@
>>  #include <asm/microcode.h>
>>  #include <asm/mmu_context.h>
>>  #include <asm/kaslr.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  /*
>>   * max_low_pfn_mapped: highest direct mapped pfn under 4GB
>> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void)
>>  	    !ramdisk_image || !ramdisk_size)
>>  		return;		/* No initrd provided by bootloader */
>>  
>> +	/*
>> +	 * This memory is marked encrypted by the kernel but the ramdisk
>> +	 * was loaded in the clear by the bootloader, so make sure that
>> +	 * the ramdisk image is encrypted.
>> +	 */
>> +	sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image);
> 
> What happens if we go and relocate the ramdisk? I.e., the function above
> this one: relocate_initrd(). We have to encrypt it then too, I presume.

Hmmm, maybe... With the change to the early_memremap() the initrd is now
identified as BOOT_DATA in relocate_initrd() and so it will be mapped
and copied as non-encyrpted data. But since it was encrypted before the
call to relocate_initrd() it will copy encrypted bytes which will later
be accessed encrypted. That isn't clear though, so I'll rework
reserve_initrd() to perform the sme_early_mem_enc() once at the end
whether the initrd is re-located or not.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 15:14       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:14 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 11:38 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
>> index 031db21..e3bdc5a 100644
>> --- a/arch/x86/mm/ioremap.c
>> +++ b/arch/x86/mm/ioremap.c
>> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>>  	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>>  }
>>  
>> +/*
>> + * Architecure override of __weak function to adjust the protection attributes
>> + * used when remapping memory.
>> + */
>> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
>> +					     unsigned long size,
>> +					     enum memremap_owner owner,
>> +					     pgprot_t prot)
>> +{
>> +	/*
>> +	 * If memory encryption is enabled and BOOT_DATA is being mapped
>> +	 * then remove the encryption bit.
>> +	 */
>> +	if (_PAGE_ENC && (owner == BOOT_DATA))
>> +		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
>> +
>> +	return prot;
>> +}
>> +
> 
> Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
> is BOOT_DATA.
> 
> So instead of touching so many files and changing early_memremap(),
> why can't you remove _PAGE_ENC by default on x86 and define a specific
> early_memremap() for arch/x86/xen/ which you call there?
> 
> That would make this patch soo much smaller and the change simpler.

Yes it would.  I'll take a look into that.

> 
> ...
> 
>> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
>> index 5a2631a..f9286c6 100644
>> --- a/drivers/firmware/efi/efi.c
>> +++ b/drivers/firmware/efi/efi.c
>> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
>>  		 * So just always get our own virtual map on the CPU.
>>  		 *
>>  		 */
>> -		md = early_memremap(p, sizeof (*md));
>> +		md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> WARNING: space prohibited between function name and open parenthesis '('
> #432: FILE: drivers/firmware/efi/efi.c:389:
> +               md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> Please integrate checkpatch.pl into your workflow so that you can catch
> small style nits like this. And don't take its output too seriously... :-)

I did run checkpatch against everything, but was always under the
assumption that I shouldn't change existing warnings/errors like this.
If it's considered ok since I'm touching that line of code then I'll
take care of those situations.

Thanks,
Tom

> 
>>  		if (!md) {
>>  			pr_err_once("early_memremap(%pa, %zu) failed.\n",
>>  				    &p, sizeof (*md));
>> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>>  	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>>  		efi_properties_table_t *tbl;
>>  
>> -		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
>> +		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
>> +				     BOOT_DATA);
>>  		if (tbl == NULL) {
>>  			pr_err("Could not map Properties table!\n");
>>  			return -ENOMEM;

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 15:14       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:14 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/09/2016 11:38 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
>> index 031db21..e3bdc5a 100644
>> --- a/arch/x86/mm/ioremap.c
>> +++ b/arch/x86/mm/ioremap.c
>> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>>  	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>>  }
>>  
>> +/*
>> + * Architecure override of __weak function to adjust the protection attributes
>> + * used when remapping memory.
>> + */
>> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
>> +					     unsigned long size,
>> +					     enum memremap_owner owner,
>> +					     pgprot_t prot)
>> +{
>> +	/*
>> +	 * If memory encryption is enabled and BOOT_DATA is being mapped
>> +	 * then remove the encryption bit.
>> +	 */
>> +	if (_PAGE_ENC && (owner == BOOT_DATA))
>> +		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
>> +
>> +	return prot;
>> +}
>> +
> 
> Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
> is BOOT_DATA.
> 
> So instead of touching so many files and changing early_memremap(),
> why can't you remove _PAGE_ENC by default on x86 and define a specific
> early_memremap() for arch/x86/xen/ which you call there?
> 
> That would make this patch soo much smaller and the change simpler.

Yes it would.  I'll take a look into that.

> 
> ...
> 
>> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
>> index 5a2631a..f9286c6 100644
>> --- a/drivers/firmware/efi/efi.c
>> +++ b/drivers/firmware/efi/efi.c
>> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
>>  		 * So just always get our own virtual map on the CPU.
>>  		 *
>>  		 */
>> -		md = early_memremap(p, sizeof (*md));
>> +		md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> WARNING: space prohibited between function name and open parenthesis '('
> #432: FILE: drivers/firmware/efi/efi.c:389:
> +               md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> Please integrate checkpatch.pl into your workflow so that you can catch
> small style nits like this. And don't take its output too seriously... :-)

I did run checkpatch against everything, but was always under the
assumption that I shouldn't change existing warnings/errors like this.
If it's considered ok since I'm touching that line of code then I'll
take care of those situations.

Thanks,
Tom

> 
>>  		if (!md) {
>>  			pr_err_once("early_memremap(%pa, %zu) failed.\n",
>>  				    &p, sizeof (*md));
>> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>>  	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>>  		efi_properties_table_t *tbl;
>>  
>> -		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
>> +		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
>> +				     BOOT_DATA);
>>  		if (tbl == NULL) {
>>  			pr_err("Could not map Properties table!\n");
>>  			return -ENOMEM;

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 15:14       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:14 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 11:38 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:38PM -0500, Tom Lendacky wrote:
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
> 
> ...
> 
>> diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
>> index 031db21..e3bdc5a 100644
>> --- a/arch/x86/mm/ioremap.c
>> +++ b/arch/x86/mm/ioremap.c
>> @@ -419,6 +419,25 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
>>  	iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
>>  }
>>  
>> +/*
>> + * Architecure override of __weak function to adjust the protection attributes
>> + * used when remapping memory.
>> + */
>> +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
>> +					     unsigned long size,
>> +					     enum memremap_owner owner,
>> +					     pgprot_t prot)
>> +{
>> +	/*
>> +	 * If memory encryption is enabled and BOOT_DATA is being mapped
>> +	 * then remove the encryption bit.
>> +	 */
>> +	if (_PAGE_ENC && (owner == BOOT_DATA))
>> +		prot = __pgprot(pgprot_val(prot) & ~_PAGE_ENC);
>> +
>> +	return prot;
>> +}
>> +
> 
> Hmm, so AFAICT, only arch/x86/xen needs KERNEL_DATA and everything else
> is BOOT_DATA.
> 
> So instead of touching so many files and changing early_memremap(),
> why can't you remove _PAGE_ENC by default on x86 and define a specific
> early_memremap() for arch/x86/xen/ which you call there?
> 
> That would make this patch soo much smaller and the change simpler.

Yes it would.  I'll take a look into that.

> 
> ...
> 
>> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
>> index 5a2631a..f9286c6 100644
>> --- a/drivers/firmware/efi/efi.c
>> +++ b/drivers/firmware/efi/efi.c
>> @@ -386,7 +386,7 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
>>  		 * So just always get our own virtual map on the CPU.
>>  		 *
>>  		 */
>> -		md = early_memremap(p, sizeof (*md));
>> +		md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> WARNING: space prohibited between function name and open parenthesis '('
> #432: FILE: drivers/firmware/efi/efi.c:389:
> +               md = early_memremap(p, sizeof (*md), BOOT_DATA);
> 
> Please integrate checkpatch.pl into your workflow so that you can catch
> small style nits like this. And don't take its output too seriously... :-)

I did run checkpatch against everything, but was always under the
assumption that I shouldn't change existing warnings/errors like this.
If it's considered ok since I'm touching that line of code then I'll
take care of those situations.

Thanks,
Tom

> 
>>  		if (!md) {
>>  			pr_err_once("early_memremap(%pa, %zu) failed.\n",
>>  				    &p, sizeof (*md));
>> @@ -501,7 +501,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
>>  	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
>>  		efi_properties_table_t *tbl;
>>  
>> -		tbl = early_memremap(efi.properties_table, sizeof(*tbl));
>> +		tbl = early_memremap(efi.properties_table, sizeof(*tbl),
>> +				     BOOT_DATA);
>>  		if (tbl == NULL) {
>>  			pr_err("Could not map Properties table!\n");
>>  			return -ENOMEM;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-12 15:41       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:41 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 12:23 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
>> This patch adds support to be change the memory encryption attribute for
>> one or more memory pages.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/cacheflush.h  |    3 +
>>  arch/x86/include/asm/mem_encrypt.h |   13 ++++++
>>  arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
>>  arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
>>  4 files changed, 134 insertions(+)
> 
> ...
> 
>> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
>> index 72c292d..0ba9382 100644
>> --- a/arch/x86/mm/pageattr.c
>> +++ b/arch/x86/mm/pageattr.c
>> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>>  					__pgprot(0), 1, 0, NULL);
>>  }
>>  
>> +static int __set_memory_enc_dec(struct cpa_data *cpa)
>> +{
>> +	unsigned long addr;
>> +	int numpages;
>> +	int ret;
>> +
>> +	if (*cpa->vaddr & ~PAGE_MASK) {
>> +		*cpa->vaddr &= PAGE_MASK;
>> +
>> +		/* People should not be passing in unaligned addresses */
>> +		WARN_ON_ONCE(1);
> 
> Let's make this more user-friendly:
> 
> 	if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", *cpa->vaddr))
> 		*cpa->vaddr &= PAGE_MASK;

Will do.

> 
>> +	}
>> +
>> +	addr = *cpa->vaddr;
>> +	numpages = cpa->numpages;
>> +
>> +	/* Must avoid aliasing mappings in the highmem code */
>> +	kmap_flush_unused();
>> +	vm_unmap_aliases();
>> +
>> +	ret = __change_page_attr_set_clr(cpa, 1);
>> +
>> +	/* Check whether we really changed something */
>> +	if (!(cpa->flags & CPA_FLUSHTLB))
>> +		goto out;
>> +
>> +	/*
>> +	 * On success we use CLFLUSH, when the CPU supports it to
>> +	 * avoid the WBINVD.
>> +	 */
>> +	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
>> +		cpa_flush_range(addr, numpages, 1);
>> +	else
>> +		cpa_flush_all(1);
> 
> So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
> have to?

Looking at __change_page_attr_set_clr() isn't it possible for some of
the pages to be changed before an error is encountered since it is
looping?  If so, we may still need to flush. The CPA_FLUSHTLB flag
should take care of a failing case where no attributes have actually
been changed.

Thanks,
Tom

> 
> Don't you want this instead:
> 
>         ret = __change_page_attr_set_clr(cpa, 1);
>         if (ret)
>                 goto out;
> 
>         /* Check whether we really changed something */
>         if (!(cpa->flags & CPA_FLUSHTLB))
>                 goto out;
> 
>         /*
>          * On success we use CLFLUSH, when the CPU supports it to
>          * avoid the WBINVD.
>          */
>         if (static_cpu_has(X86_FEATURE_CLFLUSH))
>                 cpa_flush_range(addr, numpages, 1);
>         else
>                 cpa_flush_all(1);
> 
> out:
>         return ret;
> }
> 
> ?
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-12 15:41       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:41 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/09/2016 12:23 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
>> This patch adds support to be change the memory encryption attribute for
>> one or more memory pages.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
>> ---
>>  arch/x86/include/asm/cacheflush.h  |    3 +
>>  arch/x86/include/asm/mem_encrypt.h |   13 ++++++
>>  arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
>>  arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
>>  4 files changed, 134 insertions(+)
> 
> ...
> 
>> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
>> index 72c292d..0ba9382 100644
>> --- a/arch/x86/mm/pageattr.c
>> +++ b/arch/x86/mm/pageattr.c
>> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>>  					__pgprot(0), 1, 0, NULL);
>>  }
>>  
>> +static int __set_memory_enc_dec(struct cpa_data *cpa)
>> +{
>> +	unsigned long addr;
>> +	int numpages;
>> +	int ret;
>> +
>> +	if (*cpa->vaddr & ~PAGE_MASK) {
>> +		*cpa->vaddr &= PAGE_MASK;
>> +
>> +		/* People should not be passing in unaligned addresses */
>> +		WARN_ON_ONCE(1);
> 
> Let's make this more user-friendly:
> 
> 	if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", *cpa->vaddr))
> 		*cpa->vaddr &= PAGE_MASK;

Will do.

> 
>> +	}
>> +
>> +	addr = *cpa->vaddr;
>> +	numpages = cpa->numpages;
>> +
>> +	/* Must avoid aliasing mappings in the highmem code */
>> +	kmap_flush_unused();
>> +	vm_unmap_aliases();
>> +
>> +	ret = __change_page_attr_set_clr(cpa, 1);
>> +
>> +	/* Check whether we really changed something */
>> +	if (!(cpa->flags & CPA_FLUSHTLB))
>> +		goto out;
>> +
>> +	/*
>> +	 * On success we use CLFLUSH, when the CPU supports it to
>> +	 * avoid the WBINVD.
>> +	 */
>> +	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
>> +		cpa_flush_range(addr, numpages, 1);
>> +	else
>> +		cpa_flush_all(1);
> 
> So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
> have to?

Looking at __change_page_attr_set_clr() isn't it possible for some of
the pages to be changed before an error is encountered since it is
looping?  If so, we may still need to flush. The CPA_FLUSHTLB flag
should take care of a failing case where no attributes have actually
been changed.

Thanks,
Tom

> 
> Don't you want this instead:
> 
>         ret = __change_page_attr_set_clr(cpa, 1);
>         if (ret)
>                 goto out;
> 
>         /* Check whether we really changed something */
>         if (!(cpa->flags & CPA_FLUSHTLB))
>                 goto out;
> 
>         /*
>          * On success we use CLFLUSH, when the CPU supports it to
>          * avoid the WBINVD.
>          */
>         if (static_cpu_has(X86_FEATURE_CLFLUSH))
>                 cpa_flush_range(addr, numpages, 1);
>         else
>                 cpa_flush_all(1);
> 
> out:
>         return ret;
> }
> 
> ?
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-12 15:41       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:41 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 12:23 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:49PM -0500, Tom Lendacky wrote:
>> This patch adds support to be change the memory encryption attribute for
>> one or more memory pages.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/cacheflush.h  |    3 +
>>  arch/x86/include/asm/mem_encrypt.h |   13 ++++++
>>  arch/x86/mm/mem_encrypt.c          |   43 +++++++++++++++++++++
>>  arch/x86/mm/pageattr.c             |   75 ++++++++++++++++++++++++++++++++++++
>>  4 files changed, 134 insertions(+)
> 
> ...
> 
>> diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
>> index 72c292d..0ba9382 100644
>> --- a/arch/x86/mm/pageattr.c
>> +++ b/arch/x86/mm/pageattr.c
>> @@ -1728,6 +1728,81 @@ int set_memory_4k(unsigned long addr, int numpages)
>>  					__pgprot(0), 1, 0, NULL);
>>  }
>>  
>> +static int __set_memory_enc_dec(struct cpa_data *cpa)
>> +{
>> +	unsigned long addr;
>> +	int numpages;
>> +	int ret;
>> +
>> +	if (*cpa->vaddr & ~PAGE_MASK) {
>> +		*cpa->vaddr &= PAGE_MASK;
>> +
>> +		/* People should not be passing in unaligned addresses */
>> +		WARN_ON_ONCE(1);
> 
> Let's make this more user-friendly:
> 
> 	if (WARN_ONCE(*cpa->vaddr & ~PAGE_MASK, "Misaligned address: 0x%lx\n", *cpa->vaddr))
> 		*cpa->vaddr &= PAGE_MASK;

Will do.

> 
>> +	}
>> +
>> +	addr = *cpa->vaddr;
>> +	numpages = cpa->numpages;
>> +
>> +	/* Must avoid aliasing mappings in the highmem code */
>> +	kmap_flush_unused();
>> +	vm_unmap_aliases();
>> +
>> +	ret = __change_page_attr_set_clr(cpa, 1);
>> +
>> +	/* Check whether we really changed something */
>> +	if (!(cpa->flags & CPA_FLUSHTLB))
>> +		goto out;
>> +
>> +	/*
>> +	 * On success we use CLFLUSH, when the CPU supports it to
>> +	 * avoid the WBINVD.
>> +	 */
>> +	if (!ret && static_cpu_has(X86_FEATURE_CLFLUSH))
>> +		cpa_flush_range(addr, numpages, 1);
>> +	else
>> +		cpa_flush_all(1);
> 
> So if we fail (ret != 0) we do WBINVD unconditionally even if we don't
> have to?

Looking at __change_page_attr_set_clr() isn't it possible for some of
the pages to be changed before an error is encountered since it is
looping?  If so, we may still need to flush. The CPA_FLUSHTLB flag
should take care of a failing case where no attributes have actually
been changed.

Thanks,
Tom

> 
> Don't you want this instead:
> 
>         ret = __change_page_attr_set_clr(cpa, 1);
>         if (ret)
>                 goto out;
> 
>         /* Check whether we really changed something */
>         if (!(cpa->flags & CPA_FLUSHTLB))
>                 goto out;
> 
>         /*
>          * On success we use CLFLUSH, when the CPU supports it to
>          * avoid the WBINVD.
>          */
>         if (static_cpu_has(X86_FEATURE_CLFLUSH))
>                 cpa_flush_range(addr, numpages, 1);
>         else
>                 cpa_flush_all(1);
> 
> out:
>         return ret;
> }
> 
> ?
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
  2016-09-09 17:34     ` Borislav Petkov
@ 2016-09-12 15:43       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:43 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 12:34 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:57PM -0500, Tom Lendacky wrote:
>> When Secure Memory Encryption is enabled, the trampoline area must not
>> be encrypted. A cpu running in real mode will not be able to decrypt
> 
> s/cpu/CPU/... always :-)

Ok.

> 
>> memory that has been encrypted because it will not be able to use addresses
>> with the memory encryption mask.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/realmode/init.c |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
>> index 5db706f1..f74925f 100644
>> --- a/arch/x86/realmode/init.c
>> +++ b/arch/x86/realmode/init.c
>> @@ -6,6 +6,7 @@
>>  #include <asm/pgtable.h>
>>  #include <asm/realmode.h>
>>  #include <asm/tlbflush.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  struct real_mode_header *real_mode_header;
>>  u32 *trampoline_cr4_features;
>> @@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
>>  	unsigned long text_start =
>>  		(unsigned long) __va(real_mode_header->text_start);
>>  
>> +	/*
>> +	 * If memory encryption is active, the trampoline area will need to
>> +	 * be in non-encrypted memory in order to bring up other processors
> 
> Let's stick with either "unencrypted" - I'd prefer that one - or
> "non-encrypted" nomenclature so that there's no distraction. I see both
> versions in the patchset.

Yup, I'll audit the code and make everything consistent.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active
@ 2016-09-12 15:43       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-12 15:43 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/09/2016 12:34 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:37:57PM -0500, Tom Lendacky wrote:
>> When Secure Memory Encryption is enabled, the trampoline area must not
>> be encrypted. A cpu running in real mode will not be able to decrypt
> 
> s/cpu/CPU/... always :-)

Ok.

> 
>> memory that has been encrypted because it will not be able to use addresses
>> with the memory encryption mask.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/realmode/init.c |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
>> index 5db706f1..f74925f 100644
>> --- a/arch/x86/realmode/init.c
>> +++ b/arch/x86/realmode/init.c
>> @@ -6,6 +6,7 @@
>>  #include <asm/pgtable.h>
>>  #include <asm/realmode.h>
>>  #include <asm/tlbflush.h>
>> +#include <asm/mem_encrypt.h>
>>  
>>  struct real_mode_header *real_mode_header;
>>  u32 *trampoline_cr4_features;
>> @@ -130,6 +131,14 @@ static void __init set_real_mode_permissions(void)
>>  	unsigned long text_start =
>>  		(unsigned long) __va(real_mode_header->text_start);
>>  
>> +	/*
>> +	 * If memory encryption is active, the trampoline area will need to
>> +	 * be in non-encrypted memory in order to bring up other processors
> 
> Let's stick with either "unencrypted" - I'd prefer that one - or
> "non-encrypted" nomenclature so that there's no distraction. I see both
> versions in the patchset.

Yup, I'll audit the code and make everything consistent.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
  2016-09-12 15:05       ` Tom Lendacky
@ 2016-09-12 16:33         ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:33 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Sep 12, 2016 at 10:05:36AM -0500, Tom Lendacky wrote:
> I can look into that.  The reason I put this here is this is all the
> early page fault support that is very specific to this file. I modified
> an existing static function to take advantage of the mapping support.

Yeah, but all this code is SME-specific and doesn't belong there.
AFAICT, it uses global/public symbols so there shouldn't be a problem to
have it in mem_encrypt.c.

> Hmmm, maybe... With the change to the early_memremap() the initrd is now
> identified as BOOT_DATA in relocate_initrd() and so it will be mapped
> and copied as non-encyrpted data. But since it was encrypted before the
> call to relocate_initrd() it will copy encrypted bytes which will later
> be accessed encrypted. That isn't clear though, so I'll rework
> reserve_initrd() to perform the sme_early_mem_enc() once at the end
> whether the initrd is re-located or not.

Makes sense.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-12 16:33         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:33 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Sep 12, 2016 at 10:05:36AM -0500, Tom Lendacky wrote:
> I can look into that.  The reason I put this here is this is all the
> early page fault support that is very specific to this file. I modified
> an existing static function to take advantage of the mapping support.

Yeah, but all this code is SME-specific and doesn't belong there.
AFAICT, it uses global/public symbols so there shouldn't be a problem to
have it in mem_encrypt.c.

> Hmmm, maybe... With the change to the early_memremap() the initrd is now
> identified as BOOT_DATA in relocate_initrd() and so it will be mapped
> and copied as non-encyrpted data. But since it was encrypted before the
> call to relocate_initrd() it will copy encrypted bytes which will later
> be accessed encrypted. That isn't clear though, so I'll rework
> reserve_initrd() to perform the sme_early_mem_enc() once at the end
> whether the initrd is re-located or not.

Makes sense.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 16:35         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:35 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Sep 12, 2016 at 10:14:59AM -0500, Tom Lendacky wrote:
> I did run checkpatch against everything, but was always under the
> assumption that I shouldn't change existing warnings/errors like this.
> If it's considered ok since I'm touching that line of code then I'll
> take care of those situations.

Yeah, normally we fix sensible checkpatch warnings/errors when we touch
the code so please do correct them :-)

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 16:35         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:35 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Sep 12, 2016 at 10:14:59AM -0500, Tom Lendacky wrote:
> I did run checkpatch against everything, but was always under the
> assumption that I shouldn't change existing warnings/errors like this.
> If it's considered ok since I'm touching that line of code then I'll
> take care of those situations.

Yeah, normally we fix sensible checkpatch warnings/errors when we touch
the code so please do correct them :-)

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
  2016-09-12 15:41       ` Tom Lendacky
@ 2016-09-12 16:41         ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:41 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Sep 12, 2016 at 10:41:29AM -0500, Tom Lendacky wrote:
> Looking at __change_page_attr_set_clr() isn't it possible for some of
> the pages to be changed before an error is encountered since it is
> looping?  If so, we may still need to flush. The CPA_FLUSHTLB flag
> should take care of a failing case where no attributes have actually
> been changed.

Ah, yes, ok, then yours is correct.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute
@ 2016-09-12 16:41         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:41 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Sep 12, 2016 at 10:41:29AM -0500, Tom Lendacky wrote:
> Looking at __change_page_attr_set_clr() isn't it possible for some of
> the pages to be changed before an error is encountered since it is
> looping?  If so, we may still need to flush. The CPA_FLUSHTLB flag
> should take care of a failing case where no attributes have actually
> been changed.

Ah, yes, ok, then yours is correct.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-12 16:43     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:43 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
> Add support to check if memory encryption is active in the kernel and that
> it has been enabled on the AP. If memory encryption is active in the kernel

A small nit: let's write out "AP" the first time at least: "... on the
Application Processors (AP)." for more clarity.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-12 16:43     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:43 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
> Add support to check if memory encryption is active in the kernel and that
> it has been enabled on the AP. If memory encryption is active in the kernel

A small nit: let's write out "AP" the first time at least: "... on the
Application Processors (AP)." for more clarity.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
  2016-08-22 22:37   ` Tom Lendacky
  (?)
@ 2016-09-12 16:55     ` Andy Lutomirski
  -1 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-09-12 16:55 UTC (permalink / raw)
  To: Tom Lendacky, Matt Fleming
  Cc: kasan-dev, linux-efi, linux-arch, Thomas Gleixner, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.

What happens when you memremap boot services data outside of early
boot?  Matt just added code that does this.

IMO this API is not so great.  It scatters a specialized consideration
all over the place.  Could early_memremap not look up the PA to figure
out what to do?

--Andy

[leaving the rest here for Matt's benefit]

>                      unsigned long size,
> +                                                   enum memremap_owner owner,
> +                                                   pgprot_t prot)
> +{
> +       return prot;
> +}
> +
>  void __init early_ioremap_reset(void)
>  {
>         early_ioremap_shutdown();
> @@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size,
> -                                              FIXMAP_PAGE_NORMAL);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_NORMAL);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #ifdef FIXMAP_PAGE_RO
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_RO);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #endif
>
> @@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
>
>  #define MAX_MAP_CHUNK  (NR_FIX_BTMAPS << PAGE_SHIFT)
>
> -void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
> +void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
> +                               enum memremap_owner owner)
>  {
>         unsigned long slop, clen;
>         char *p;
> @@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
>                 clen = size;
>                 if (clen > MAX_MAP_CHUNK - slop)
>                         clen = MAX_MAP_CHUNK - slop;
> -               p = early_memremap(src & PAGE_MASK, clen + slop);
> +               p = early_memremap(src & PAGE_MASK, clen + slop, owner);
>                 memcpy(dest, p + slop, clen);
>                 early_memunmap(p, clen + slop);
>                 dest += clen;
> @@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 16:55     ` Andy Lutomirski
  0 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-09-12 16:55 UTC (permalink / raw)
  To: Tom Lendacky, Matt Fleming
  Cc: kasan-dev, linux-efi, linux-arch, Thomas Gleixner, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin

On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.

What happens when you memremap boot services data outside of early
boot?  Matt just added code that does this.

IMO this API is not so great.  It scatters a specialized consideration
all over the place.  Could early_memremap not look up the PA to figure
out what to do?

--Andy

[leaving the rest here for Matt's benefit]

>                      unsigned long size,
> +                                                   enum memremap_owner owner,
> +                                                   pgprot_t prot)
> +{
> +       return prot;
> +}
> +
>  void __init early_ioremap_reset(void)
>  {
>         early_ioremap_shutdown();
> @@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size,
> -                                              FIXMAP_PAGE_NORMAL);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_NORMAL);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #ifdef FIXMAP_PAGE_RO
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_RO);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #endif
>
> @@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
>
>  #define MAX_MAP_CHUNK  (NR_FIX_BTMAPS << PAGE_SHIFT)
>
> -void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
> +void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
> +                               enum memremap_owner owner)
>  {
>         unsigned long slop, clen;
>         char *p;
> @@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
>                 clen = size;
>                 if (clen > MAX_MAP_CHUNK - slop)
>                         clen = MAX_MAP_CHUNK - slop;
> -               p = early_memremap(src & PAGE_MASK, clen + slop);
> +               p = early_memremap(src & PAGE_MASK, clen + slop, owner);
>                 memcpy(dest, p + slop, clen);
>                 early_memunmap(p, clen + slop);
>                 dest += clen;
> @@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-12 16:55     ` Andy Lutomirski
  0 siblings, 0 replies; 229+ messages in thread
From: Andy Lutomirski @ 2016-09-12 16:55 UTC (permalink / raw)
  To: Tom Lendacky, Matt Fleming
  Cc: kasan-dev, linux-efi, linux-arch, Thomas Gleixner, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>
> BOOT data (such as EFI related data) is not encyrpted when the system is
> booted and needs to be accessed as non-encrypted.  Add support to the
> early_memremap API to identify the type of data being accessed so that
> the proper encryption attribute can be applied.  Currently, two types
> of data are defined, KERNEL_DATA and BOOT_DATA.

What happens when you memremap boot services data outside of early
boot?  Matt just added code that does this.

IMO this API is not so great.  It scatters a specialized consideration
all over the place.  Could early_memremap not look up the PA to figure
out what to do?

--Andy

[leaving the rest here for Matt's benefit]

>                      unsigned long size,
> +                                                   enum memremap_owner owner,
> +                                                   pgprot_t prot)
> +{
> +       return prot;
> +}
> +
>  void __init early_ioremap_reset(void)
>  {
>         early_ioremap_shutdown();
> @@ -213,16 +221,23 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size,
> -                                              FIXMAP_PAGE_NORMAL);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_NORMAL);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #ifdef FIXMAP_PAGE_RO
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
> -       return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO);
> +       pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size, owner,
> +                                                    FIXMAP_PAGE_RO);
> +
> +       return (__force void *)__early_ioremap(phys_addr, size, prot);
>  }
>  #endif
>
> @@ -236,7 +251,8 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
>
>  #define MAX_MAP_CHUNK  (NR_FIX_BTMAPS << PAGE_SHIFT)
>
> -void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
> +void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size,
> +                               enum memremap_owner owner)
>  {
>         unsigned long slop, clen;
>         char *p;
> @@ -246,7 +262,7 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
>                 clen = size;
>                 if (clen > MAX_MAP_CHUNK - slop)
>                         clen = MAX_MAP_CHUNK - slop;
> -               p = early_memremap(src & PAGE_MASK, clen + slop);
> +               p = early_memremap(src & PAGE_MASK, clen + slop, owner);
>                 memcpy(dest, p + slop, clen);
>                 early_memunmap(p, clen + slop);
>                 dest += clen;
> @@ -265,12 +281,14 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
>
>  /* Remap memory */
>  void __init *
> -early_memremap(resource_size_t phys_addr, unsigned long size)
> +early_memremap(resource_size_t phys_addr, unsigned long size,
> +              enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>  void __init *
> -early_memremap_ro(resource_size_t phys_addr, unsigned long size)
> +early_memremap_ro(resource_size_t phys_addr, unsigned long size,
> +                 enum memremap_owner owner)
>  {
>         return (void *)phys_addr;
>  }
>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-12 16:59     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:59 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:38:59PM -0500, Tom Lendacky wrote:
> Since the setup data is in memory in the clear, it must be accessed as
> un-encrypted.  Always use ioremap (similar to sysfs setup data support)
> to map the data.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
>  1 file changed, 11 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
> index bdb83e4..a58a82e 100644
> --- a/arch/x86/kernel/kdebugfs.c
> +++ b/arch/x86/kernel/kdebugfs.c
> @@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
>  
>  	pa = node->paddr + sizeof(struct setup_data) + pos;
>  	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
> -	if (PageHighMem(pg)) {

Why is it ok to get rid of the PageHighMem() check?

Btw, we did talk earlier in the thread about making __va() clear the SME
mask and then you won't really need to change stuff here. Or?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-12 16:59     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 16:59 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:38:59PM -0500, Tom Lendacky wrote:
> Since the setup data is in memory in the clear, it must be accessed as
> un-encrypted.  Always use ioremap (similar to sysfs setup data support)
> to map the data.
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
>  1 file changed, 11 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
> index bdb83e4..a58a82e 100644
> --- a/arch/x86/kernel/kdebugfs.c
> +++ b/arch/x86/kernel/kdebugfs.c
> @@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
>  
>  	pa = node->paddr + sizeof(struct setup_data) + pos;
>  	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
> -	if (PageHighMem(pg)) {

Why is it ok to get rid of the PageHighMem() check?

Btw, we did talk earlier in the thread about making __va() clear the SME
mask and then you won't really need to change stuff here. Or?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-09-12 17:08     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 17:08 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Mon, Aug 22, 2016 at 05:39:08PM -0500, Tom Lendacky wrote:
> This patch adds the support to check if SME has been enabled and if the
> mem_encrypt=on command line option is set. If both of these conditions
> are true, then the encryption mask is set and the kernel is encrypted
> "in place."
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
> ---
>  Documentation/kernel-parameters.txt |    3 
>  arch/x86/kernel/asm-offsets.c       |    2 
>  arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
>  arch/x86/mm/mem_encrypt.c           |    2 
>  4 files changed, 309 insertions(+)
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 46c030a..a1986c8 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			memory contents and reserves bad memory
>  			regions that are detected.
>  
> +	mem_encrypt=on	[X86_64] Enable memory encryption on processors
> +			that support this feature.
> +
>  	meye.*=		[HW] Set MotionEye Camera parameters
>  			See Documentation/video4linux/meye.txt.
>  
> diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
> index 2bd5c6f..e485ada 100644
> --- a/arch/x86/kernel/asm-offsets.c
> +++ b/arch/x86/kernel/asm-offsets.c
> @@ -85,6 +85,8 @@ void common(void) {
>  	OFFSET(BP_init_size, boot_params, hdr.init_size);
>  	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
>  	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
> +	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
> +	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
>  
>  	BLANK();
>  	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
> diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
> index f2e0536..bf9f6a9 100644
> --- a/arch/x86/kernel/mem_encrypt.S
> +++ b/arch/x86/kernel/mem_encrypt.S
> @@ -12,13 +12,230 @@
>  
>  #include <linux/linkage.h>
>  
> +#include <asm/processor-flags.h>
> +#include <asm/pgtable.h>
> +#include <asm/page.h>
> +#include <asm/msr.h>
> +#include <asm/asm-offsets.h>
> +
>  	.text
>  	.code64
>  ENTRY(sme_enable)
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> +	/* Check for AMD processor */
> +	xorl	%eax, %eax
> +	cpuid
> +	cmpl    $0x68747541, %ebx	# AuthenticAMD
> +	jne     .Lmem_encrypt_exit
> +	cmpl    $0x69746e65, %edx
> +	jne     .Lmem_encrypt_exit
> +	cmpl    $0x444d4163, %ecx
> +	jne     .Lmem_encrypt_exit
> +
> +	/* Check for memory encryption leaf */
> +	movl	$0x80000000, %eax
> +	cpuid
> +	cmpl	$0x8000001f, %eax
> +	jb	.Lmem_encrypt_exit
> +
> +	/*
> +	 * Check for memory encryption feature:
> +	 *   CPUID Fn8000_001F[EAX] - Bit 0
> +	 *     Secure Memory Encryption support
> +	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
> +	 *     Pagetable bit position used to indicate encryption
> +	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
> +	 *     Reduction in physical address space (in bits) when enabled
> +	 */
> +	movl	$0x8000001f, %eax
> +	cpuid
> +	bt	$0, %eax
> +	jnc	.Lmem_encrypt_exit
> +
> +	/* Check if BIOS/UEFI has allowed memory encryption */
> +	movl	$MSR_K8_SYSCFG, %ecx
> +	rdmsr
> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
> +	jnc	.Lmem_encrypt_exit

Like other people suggested, it would be great if this were in C. Should be
actually readable :)

> +
> +	/* Check for the mem_encrypt=on command line option */
> +	push	%rsi			/* Save RSI (real_mode_data) */
> +	push	%rbx			/* Save CPUID information */
> +	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
> +	shlq	$32, %rcx
> +	movl	BP_cmd_line_ptr(%rsi), %edi
> +	addq	%rcx, %rdi
> +	leaq	mem_encrypt_enable_option(%rip), %rsi
> +	call	cmdline_find_option_bool
> +	pop	%rbx			/* Restore CPUID information */
> +	pop	%rsi			/* Restore RSI (real_mode_data) */
> +	testl	%eax, %eax
> +	jz	.Lno_mem_encrypt

This too.

> +
> +	/* Set memory encryption mask */
> +	movl	%ebx, %ecx
> +	andl	$0x3f, %ecx
> +	bts	%ecx, sme_me_mask(%rip)
> +
> +.Lno_mem_encrypt:
> +	/*
> +	 * BIOS/UEFI has allowed memory encryption so we need to set
> +	 * the amount of physical address space reduction even if
> +	 * the user decides not to use memory encryption.
> +	 */
> +	movl	%ebx, %ecx
> +	shrl	$6, %ecx
> +	andl	$0x3f, %ecx
> +	movb	%cl, sme_me_loss(%rip)
> +
> +.Lmem_encrypt_exit:
> +#endif	/* CONFIG_AMD_MEM_ENCRYPT */
> +
>  	ret
>  ENDPROC(sme_enable)
>  
>  ENTRY(sme_encrypt_kernel)

This should be doable too but I guess you'll have to try it to see.

...

> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 2f28d87..1154353 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
>  
>  	/* Make SWIOTLB use an unencrypted DMA area */
>  	swiotlb_clear_encryption();
> +
> +	pr_info("memory encryption active\n");

Let's make it more official with nice caps and so on...

	pr_info("AMD Secure Memory Encryption active.\n");

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-09-12 17:08     ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-12 17:08 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Mon, Aug 22, 2016 at 05:39:08PM -0500, Tom Lendacky wrote:
> This patch adds the support to check if SME has been enabled and if the
> mem_encrypt=on command line option is set. If both of these conditions
> are true, then the encryption mask is set and the kernel is encrypted
> "in place."
> 
> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
> ---
>  Documentation/kernel-parameters.txt |    3 
>  arch/x86/kernel/asm-offsets.c       |    2 
>  arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
>  arch/x86/mm/mem_encrypt.c           |    2 
>  4 files changed, 309 insertions(+)
> 
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 46c030a..a1986c8 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			memory contents and reserves bad memory
>  			regions that are detected.
>  
> +	mem_encrypt=on	[X86_64] Enable memory encryption on processors
> +			that support this feature.
> +
>  	meye.*=		[HW] Set MotionEye Camera parameters
>  			See Documentation/video4linux/meye.txt.
>  
> diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
> index 2bd5c6f..e485ada 100644
> --- a/arch/x86/kernel/asm-offsets.c
> +++ b/arch/x86/kernel/asm-offsets.c
> @@ -85,6 +85,8 @@ void common(void) {
>  	OFFSET(BP_init_size, boot_params, hdr.init_size);
>  	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
>  	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
> +	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
> +	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
>  
>  	BLANK();
>  	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
> diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
> index f2e0536..bf9f6a9 100644
> --- a/arch/x86/kernel/mem_encrypt.S
> +++ b/arch/x86/kernel/mem_encrypt.S
> @@ -12,13 +12,230 @@
>  
>  #include <linux/linkage.h>
>  
> +#include <asm/processor-flags.h>
> +#include <asm/pgtable.h>
> +#include <asm/page.h>
> +#include <asm/msr.h>
> +#include <asm/asm-offsets.h>
> +
>  	.text
>  	.code64
>  ENTRY(sme_enable)
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> +	/* Check for AMD processor */
> +	xorl	%eax, %eax
> +	cpuid
> +	cmpl    $0x68747541, %ebx	# AuthenticAMD
> +	jne     .Lmem_encrypt_exit
> +	cmpl    $0x69746e65, %edx
> +	jne     .Lmem_encrypt_exit
> +	cmpl    $0x444d4163, %ecx
> +	jne     .Lmem_encrypt_exit
> +
> +	/* Check for memory encryption leaf */
> +	movl	$0x80000000, %eax
> +	cpuid
> +	cmpl	$0x8000001f, %eax
> +	jb	.Lmem_encrypt_exit
> +
> +	/*
> +	 * Check for memory encryption feature:
> +	 *   CPUID Fn8000_001F[EAX] - Bit 0
> +	 *     Secure Memory Encryption support
> +	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
> +	 *     Pagetable bit position used to indicate encryption
> +	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
> +	 *     Reduction in physical address space (in bits) when enabled
> +	 */
> +	movl	$0x8000001f, %eax
> +	cpuid
> +	bt	$0, %eax
> +	jnc	.Lmem_encrypt_exit
> +
> +	/* Check if BIOS/UEFI has allowed memory encryption */
> +	movl	$MSR_K8_SYSCFG, %ecx
> +	rdmsr
> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
> +	jnc	.Lmem_encrypt_exit

Like other people suggested, it would be great if this were in C. Should be
actually readable :)

> +
> +	/* Check for the mem_encrypt=on command line option */
> +	push	%rsi			/* Save RSI (real_mode_data) */
> +	push	%rbx			/* Save CPUID information */
> +	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
> +	shlq	$32, %rcx
> +	movl	BP_cmd_line_ptr(%rsi), %edi
> +	addq	%rcx, %rdi
> +	leaq	mem_encrypt_enable_option(%rip), %rsi
> +	call	cmdline_find_option_bool
> +	pop	%rbx			/* Restore CPUID information */
> +	pop	%rsi			/* Restore RSI (real_mode_data) */
> +	testl	%eax, %eax
> +	jz	.Lno_mem_encrypt

This too.

> +
> +	/* Set memory encryption mask */
> +	movl	%ebx, %ecx
> +	andl	$0x3f, %ecx
> +	bts	%ecx, sme_me_mask(%rip)
> +
> +.Lno_mem_encrypt:
> +	/*
> +	 * BIOS/UEFI has allowed memory encryption so we need to set
> +	 * the amount of physical address space reduction even if
> +	 * the user decides not to use memory encryption.
> +	 */
> +	movl	%ebx, %ecx
> +	shrl	$6, %ecx
> +	andl	$0x3f, %ecx
> +	movb	%cl, sme_me_loss(%rip)
> +
> +.Lmem_encrypt_exit:
> +#endif	/* CONFIG_AMD_MEM_ENCRYPT */
> +
>  	ret
>  ENDPROC(sme_enable)
>  
>  ENTRY(sme_encrypt_kernel)

This should be doable too but I guess you'll have to try it to see.

...

> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 2f28d87..1154353 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
>  
>  	/* Make SWIOTLB use an unencrypted DMA area */
>  	swiotlb_clear_encryption();
> +
> +	pr_info("memory encryption active\n");

Let's make it more official with nice caps and so on...

	pr_info("AMD Secure Memory Encryption active.\n");

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 14/20] x86: DMA support for memory encryption
  2016-09-12 10:58     ` Borislav Petkov
  (?)
@ 2016-09-14 13:36       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:36 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 05:58 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:07PM -0500, Tom Lendacky wrote:
>> Since DMA addresses will effectively look like 48-bit addresses when the
>> memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
>> device performing the DMA does not support 48-bits. SWIOTLB will be
>> initialized to create un-encrypted bounce buffers for use by these devices.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/dma-mapping.h |    5 ++-
>>  arch/x86/include/asm/mem_encrypt.h |    6 +++
>>  arch/x86/kernel/pci-dma.c          |   11 ++++--
>>  arch/x86/kernel/pci-nommu.c        |    2 +
>>  arch/x86/kernel/pci-swiotlb.c      |    8 +++--
>>  arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
>>  include/linux/swiotlb.h            |    1 +
>>  init/main.c                        |   13 +++++++
>>  lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
>>  9 files changed, 115 insertions(+), 17 deletions(-)
> 
> ...
> 
>> @@ -172,3 +174,23 @@ void __init sme_early_init(void)
>>  	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
>>  		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
>>  }
>> +
>> +/* Architecture __weak replacement functions */
>> +void __init mem_encrypt_init(void)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Make SWIOTLB use an unencrypted DMA area */
>> +	swiotlb_clear_encryption();
>> +}
>> +
>> +unsigned long swiotlb_get_me_mask(void)
> 
> This could just as well be named to something more generic:
> 
> swiotlb_get_clear_dma_mask() or so which basically means the mask of
> bits which get cleared before returning DMA addresses...

Ok.

> 
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>> +void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +	sme_set_mem_dec(vaddr, size);
>> +}
>> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
>> index 5f81f8a..5c909fc 100644
>> --- a/include/linux/swiotlb.h
>> +++ b/include/linux/swiotlb.h
>> @@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>>  extern unsigned long swiotlb_nr_tbl(void);
>>  unsigned long swiotlb_size_or_default(void);
>>  extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
>> +extern void __init swiotlb_clear_encryption(void);
>>  
>>  /*
>>   * Enumeration for sync targets
>> diff --git a/init/main.c b/init/main.c
>> index a8a58e2..82c7cd9 100644
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
>>  }
>>  #endif
>>  
>> +void __init __weak mem_encrypt_init(void)
>> +{
>> +}
>> +
>>  /*
>>   * Set up kernel memory allocators
>>   */
>> @@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
>>  	 */
>>  	locking_selftest();
>>  
>> +	/*
>> +	 * This needs to be called before any devices perform DMA
>> +	 * operations that might use the swiotlb bounce buffers.
>> +	 * This call will mark the bounce buffers as un-encrypted so
>> +	 * that the usage of them will not cause "plain-text" data
> 
> 	...that their usage will not cause ...

Ok.

> 
>> +	 * to be decrypted when accessed.
>> +	 */
>> +	mem_encrypt_init();
>> +
>>  #ifdef CONFIG_BLK_DEV_INITRD
>>  	if (initrd_start && !initrd_below_start_ok &&
>>  	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
>> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
>> index 22e13a0..15d5741 100644
>> --- a/lib/swiotlb.c
>> +++ b/lib/swiotlb.c
>> @@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
>>  	return size ? size : (IO_TLB_DEFAULT_SIZE);
>>  }
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to these functions will be provided.
>> + */
> 
> No need for that comment.

Ok.

> 
>> +unsigned long __weak swiotlb_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
>> +
>> +void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +}
>> +
>> +/* For swiotlb, clear memory encryption mask from dma addresses */
>> +static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
>> +				      phys_addr_t address)
>> +{
>> +	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
>> +}
>> +
>>  /* Note that this doesn't work with highmem page */
>>  static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
>>  				      volatile void *address)
>> @@ -159,6 +179,30 @@ void swiotlb_print_info(void)
>>  	       bytes >> 20, vstart, vend - 1);
>>  }
>>  
>> +/*
>> + * If memory encryption is active, the DMA address for an encrypted page may
>> + * be beyond the range of the device. If bounce buffers are required be sure
>> + * that they are not on an encrypted page. This should be called before the
>> + * iotlb area is used.
>> + */
>> +void __init swiotlb_clear_encryption(void)
>> +{
>> +	void *vaddr;
>> +	unsigned long bytes;
>> +
>> +	if (no_iotlb_memory || !io_tlb_start || late_alloc)
>> +		return;
>> +
>> +	vaddr = phys_to_virt(io_tlb_start);
>> +	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
>> +	memset(vaddr, 0, bytes);
> 
> io_tlb_start is cleared...
> 
>> +
>> +	vaddr = phys_to_virt(io_tlb_overflow_buffer);
>> +	bytes = PAGE_ALIGN(io_tlb_overflow);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
> 
> ... but io_tlb_overflow_buffer isn't? I don't see the difference here.

Yup, I missed that one.  Will memset this as well.

Thanks,
Tom

> 
>> +}
>> +
>>  int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
>>  {
>>  	void *v_overflow_buffer;

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-09-14 13:36       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:36 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/12/2016 05:58 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:07PM -0500, Tom Lendacky wrote:
>> Since DMA addresses will effectively look like 48-bit addresses when the
>> memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
>> device performing the DMA does not support 48-bits. SWIOTLB will be
>> initialized to create un-encrypted bounce buffers for use by these devices.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/dma-mapping.h |    5 ++-
>>  arch/x86/include/asm/mem_encrypt.h |    6 +++
>>  arch/x86/kernel/pci-dma.c          |   11 ++++--
>>  arch/x86/kernel/pci-nommu.c        |    2 +
>>  arch/x86/kernel/pci-swiotlb.c      |    8 +++--
>>  arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
>>  include/linux/swiotlb.h            |    1 +
>>  init/main.c                        |   13 +++++++
>>  lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
>>  9 files changed, 115 insertions(+), 17 deletions(-)
> 
> ...
> 
>> @@ -172,3 +174,23 @@ void __init sme_early_init(void)
>>  	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
>>  		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
>>  }
>> +
>> +/* Architecture __weak replacement functions */
>> +void __init mem_encrypt_init(void)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Make SWIOTLB use an unencrypted DMA area */
>> +	swiotlb_clear_encryption();
>> +}
>> +
>> +unsigned long swiotlb_get_me_mask(void)
> 
> This could just as well be named to something more generic:
> 
> swiotlb_get_clear_dma_mask() or so which basically means the mask of
> bits which get cleared before returning DMA addresses...

Ok.

> 
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>> +void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +	sme_set_mem_dec(vaddr, size);
>> +}
>> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
>> index 5f81f8a..5c909fc 100644
>> --- a/include/linux/swiotlb.h
>> +++ b/include/linux/swiotlb.h
>> @@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>>  extern unsigned long swiotlb_nr_tbl(void);
>>  unsigned long swiotlb_size_or_default(void);
>>  extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
>> +extern void __init swiotlb_clear_encryption(void);
>>  
>>  /*
>>   * Enumeration for sync targets
>> diff --git a/init/main.c b/init/main.c
>> index a8a58e2..82c7cd9 100644
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
>>  }
>>  #endif
>>  
>> +void __init __weak mem_encrypt_init(void)
>> +{
>> +}
>> +
>>  /*
>>   * Set up kernel memory allocators
>>   */
>> @@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
>>  	 */
>>  	locking_selftest();
>>  
>> +	/*
>> +	 * This needs to be called before any devices perform DMA
>> +	 * operations that might use the swiotlb bounce buffers.
>> +	 * This call will mark the bounce buffers as un-encrypted so
>> +	 * that the usage of them will not cause "plain-text" data
> 
> 	...that their usage will not cause ...

Ok.

> 
>> +	 * to be decrypted when accessed.
>> +	 */
>> +	mem_encrypt_init();
>> +
>>  #ifdef CONFIG_BLK_DEV_INITRD
>>  	if (initrd_start && !initrd_below_start_ok &&
>>  	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
>> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
>> index 22e13a0..15d5741 100644
>> --- a/lib/swiotlb.c
>> +++ b/lib/swiotlb.c
>> @@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
>>  	return size ? size : (IO_TLB_DEFAULT_SIZE);
>>  }
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to these functions will be provided.
>> + */
> 
> No need for that comment.

Ok.

> 
>> +unsigned long __weak swiotlb_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
>> +
>> +void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +}
>> +
>> +/* For swiotlb, clear memory encryption mask from dma addresses */
>> +static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
>> +				      phys_addr_t address)
>> +{
>> +	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
>> +}
>> +
>>  /* Note that this doesn't work with highmem page */
>>  static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
>>  				      volatile void *address)
>> @@ -159,6 +179,30 @@ void swiotlb_print_info(void)
>>  	       bytes >> 20, vstart, vend - 1);
>>  }
>>  
>> +/*
>> + * If memory encryption is active, the DMA address for an encrypted page may
>> + * be beyond the range of the device. If bounce buffers are required be sure
>> + * that they are not on an encrypted page. This should be called before the
>> + * iotlb area is used.
>> + */
>> +void __init swiotlb_clear_encryption(void)
>> +{
>> +	void *vaddr;
>> +	unsigned long bytes;
>> +
>> +	if (no_iotlb_memory || !io_tlb_start || late_alloc)
>> +		return;
>> +
>> +	vaddr = phys_to_virt(io_tlb_start);
>> +	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
>> +	memset(vaddr, 0, bytes);
> 
> io_tlb_start is cleared...
> 
>> +
>> +	vaddr = phys_to_virt(io_tlb_overflow_buffer);
>> +	bytes = PAGE_ALIGN(io_tlb_overflow);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
> 
> ... but io_tlb_overflow_buffer isn't? I don't see the difference here.

Yup, I missed that one.  Will memset this as well.

Thanks,
Tom

> 
>> +}
>> +
>>  int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
>>  {
>>  	void *v_overflow_buffer;

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 14/20] x86: DMA support for memory encryption
@ 2016-09-14 13:36       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:36 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 05:58 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:07PM -0500, Tom Lendacky wrote:
>> Since DMA addresses will effectively look like 48-bit addresses when the
>> memory encryption mask is set, SWIOTLB is needed if the DMA mask of the
>> device performing the DMA does not support 48-bits. SWIOTLB will be
>> initialized to create un-encrypted bounce buffers for use by these devices.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/dma-mapping.h |    5 ++-
>>  arch/x86/include/asm/mem_encrypt.h |    6 +++
>>  arch/x86/kernel/pci-dma.c          |   11 ++++--
>>  arch/x86/kernel/pci-nommu.c        |    2 +
>>  arch/x86/kernel/pci-swiotlb.c      |    8 +++--
>>  arch/x86/mm/mem_encrypt.c          |   22 ++++++++++++
>>  include/linux/swiotlb.h            |    1 +
>>  init/main.c                        |   13 +++++++
>>  lib/swiotlb.c                      |   64 ++++++++++++++++++++++++++++++++----
>>  9 files changed, 115 insertions(+), 17 deletions(-)
> 
> ...
> 
>> @@ -172,3 +174,23 @@ void __init sme_early_init(void)
>>  	for (i = 0; i < ARRAY_SIZE(protection_map); i++)
>>  		protection_map[i] = __pgprot(pgprot_val(protection_map[i]) | sme_me_mask);
>>  }
>> +
>> +/* Architecture __weak replacement functions */
>> +void __init mem_encrypt_init(void)
>> +{
>> +	if (!sme_me_mask)
>> +		return;
>> +
>> +	/* Make SWIOTLB use an unencrypted DMA area */
>> +	swiotlb_clear_encryption();
>> +}
>> +
>> +unsigned long swiotlb_get_me_mask(void)
> 
> This could just as well be named to something more generic:
> 
> swiotlb_get_clear_dma_mask() or so which basically means the mask of
> bits which get cleared before returning DMA addresses...

Ok.

> 
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>> +void swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +	sme_set_mem_dec(vaddr, size);
>> +}
>> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
>> index 5f81f8a..5c909fc 100644
>> --- a/include/linux/swiotlb.h
>> +++ b/include/linux/swiotlb.h
>> @@ -29,6 +29,7 @@ int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
>>  extern unsigned long swiotlb_nr_tbl(void);
>>  unsigned long swiotlb_size_or_default(void);
>>  extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
>> +extern void __init swiotlb_clear_encryption(void);
>>  
>>  /*
>>   * Enumeration for sync targets
>> diff --git a/init/main.c b/init/main.c
>> index a8a58e2..82c7cd9 100644
>> --- a/init/main.c
>> +++ b/init/main.c
>> @@ -458,6 +458,10 @@ void __init __weak thread_stack_cache_init(void)
>>  }
>>  #endif
>>  
>> +void __init __weak mem_encrypt_init(void)
>> +{
>> +}
>> +
>>  /*
>>   * Set up kernel memory allocators
>>   */
>> @@ -598,6 +602,15 @@ asmlinkage __visible void __init start_kernel(void)
>>  	 */
>>  	locking_selftest();
>>  
>> +	/*
>> +	 * This needs to be called before any devices perform DMA
>> +	 * operations that might use the swiotlb bounce buffers.
>> +	 * This call will mark the bounce buffers as un-encrypted so
>> +	 * that the usage of them will not cause "plain-text" data
> 
> 	...that their usage will not cause ...

Ok.

> 
>> +	 * to be decrypted when accessed.
>> +	 */
>> +	mem_encrypt_init();
>> +
>>  #ifdef CONFIG_BLK_DEV_INITRD
>>  	if (initrd_start && !initrd_below_start_ok &&
>>  	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
>> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
>> index 22e13a0..15d5741 100644
>> --- a/lib/swiotlb.c
>> +++ b/lib/swiotlb.c
>> @@ -131,6 +131,26 @@ unsigned long swiotlb_size_or_default(void)
>>  	return size ? size : (IO_TLB_DEFAULT_SIZE);
>>  }
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to these functions will be provided.
>> + */
> 
> No need for that comment.

Ok.

> 
>> +unsigned long __weak swiotlb_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
>> +
>> +void __weak swiotlb_set_mem_dec(void *vaddr, unsigned long size)
>> +{
>> +}
>> +
>> +/* For swiotlb, clear memory encryption mask from dma addresses */
>> +static dma_addr_t swiotlb_phys_to_dma(struct device *hwdev,
>> +				      phys_addr_t address)
>> +{
>> +	return phys_to_dma(hwdev, address) & ~swiotlb_get_me_mask();
>> +}
>> +
>>  /* Note that this doesn't work with highmem page */
>>  static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
>>  				      volatile void *address)
>> @@ -159,6 +179,30 @@ void swiotlb_print_info(void)
>>  	       bytes >> 20, vstart, vend - 1);
>>  }
>>  
>> +/*
>> + * If memory encryption is active, the DMA address for an encrypted page may
>> + * be beyond the range of the device. If bounce buffers are required be sure
>> + * that they are not on an encrypted page. This should be called before the
>> + * iotlb area is used.
>> + */
>> +void __init swiotlb_clear_encryption(void)
>> +{
>> +	void *vaddr;
>> +	unsigned long bytes;
>> +
>> +	if (no_iotlb_memory || !io_tlb_start || late_alloc)
>> +		return;
>> +
>> +	vaddr = phys_to_virt(io_tlb_start);
>> +	bytes = PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
>> +	memset(vaddr, 0, bytes);
> 
> io_tlb_start is cleared...
> 
>> +
>> +	vaddr = phys_to_virt(io_tlb_overflow_buffer);
>> +	bytes = PAGE_ALIGN(io_tlb_overflow);
>> +	swiotlb_set_mem_dec(vaddr, bytes);
> 
> ... but io_tlb_overflow_buffer isn't? I don't see the difference here.

Yup, I missed that one.  Will memset this as well.

Thanks,
Tom

> 
>> +}
>> +
>>  int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
>>  {
>>  	void *v_overflow_buffer;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-14 13:45       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:45 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 06:45 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:20PM -0500, Tom Lendacky wrote:
>> Add support to the AMD IOMMU driver to set the memory encryption mask if
>> memory encryption is enabled.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/mem_encrypt.h |    2 ++
>>  arch/x86/mm/mem_encrypt.c          |    5 +++++
>>  drivers/iommu/amd_iommu.c          |   10 ++++++++++
>>  3 files changed, 17 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
>> index 384fdfb..e395729 100644
>> --- a/arch/x86/include/asm/mem_encrypt.h
>> +++ b/arch/x86/include/asm/mem_encrypt.h
>> @@ -36,6 +36,8 @@ void __init sme_early_init(void);
>>  /* Architecture __weak replacement functions */
>>  void __init mem_encrypt_init(void);
>>  
>> +unsigned long amd_iommu_get_me_mask(void);
>> +
>>  unsigned long swiotlb_get_me_mask(void);
>>  void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
>>  
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 6b2e8bf..2f28d87 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
>>  	swiotlb_clear_encryption();
>>  }
>>  
>> +unsigned long amd_iommu_get_me_mask(void)
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>>  unsigned long swiotlb_get_me_mask(void)
>>  {
>>  	return sme_me_mask;
>> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
>> index 96de97a..63995e3 100644
>> --- a/drivers/iommu/amd_iommu.c
>> +++ b/drivers/iommu/amd_iommu.c
>> @@ -166,6 +166,15 @@ struct dma_ops_domain {
>>  static struct iova_domain reserved_iova_ranges;
>>  static struct lock_class_key reserved_rbtree_key;
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to this function will be provided.
>> + */
>> +unsigned long __weak amd_iommu_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
> 
> So instead of adding a function each time which returns sme_me_mask
> for each user it has, why don't you add a single function which
> returns sme_me_mask in mem_encrypt.c and add an inline in the header
> mem_encrypt.h which returns 0 for the !CONFIG_AMD_MEM_ENCRYPT case.

Currently, mem_encrypt.h only lives in the arch/x86 directory so it
wouldn't be able to be included here without breaking other archs.

> 
> This all is still funny because we access sme_me_mask directly for the
> different KERNEL_* masks but then you're adding an accessor function.

Because this lives outside of the arch/x86 I need to use the weak
function.

> 
> So what you should do instead, IMHO, is either hide sme_me_mask
> altogether and use the accessor functions only (not sure if that would
> work in all cases) or expose sme_me_mask unconditionally and have it be
> 0 if CONFIG_AMD_MEM_ENCRYPT is not enabled so that it just works.
> 
> Or is there a third, more graceful variant?

Is there a better way to do this given the support is only in x86?

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-14 13:45       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:45 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/12/2016 06:45 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:20PM -0500, Tom Lendacky wrote:
>> Add support to the AMD IOMMU driver to set the memory encryption mask if
>> memory encryption is enabled.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
>> ---
>>  arch/x86/include/asm/mem_encrypt.h |    2 ++
>>  arch/x86/mm/mem_encrypt.c          |    5 +++++
>>  drivers/iommu/amd_iommu.c          |   10 ++++++++++
>>  3 files changed, 17 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
>> index 384fdfb..e395729 100644
>> --- a/arch/x86/include/asm/mem_encrypt.h
>> +++ b/arch/x86/include/asm/mem_encrypt.h
>> @@ -36,6 +36,8 @@ void __init sme_early_init(void);
>>  /* Architecture __weak replacement functions */
>>  void __init mem_encrypt_init(void);
>>  
>> +unsigned long amd_iommu_get_me_mask(void);
>> +
>>  unsigned long swiotlb_get_me_mask(void);
>>  void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
>>  
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 6b2e8bf..2f28d87 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
>>  	swiotlb_clear_encryption();
>>  }
>>  
>> +unsigned long amd_iommu_get_me_mask(void)
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>>  unsigned long swiotlb_get_me_mask(void)
>>  {
>>  	return sme_me_mask;
>> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
>> index 96de97a..63995e3 100644
>> --- a/drivers/iommu/amd_iommu.c
>> +++ b/drivers/iommu/amd_iommu.c
>> @@ -166,6 +166,15 @@ struct dma_ops_domain {
>>  static struct iova_domain reserved_iova_ranges;
>>  static struct lock_class_key reserved_rbtree_key;
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to this function will be provided.
>> + */
>> +unsigned long __weak amd_iommu_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
> 
> So instead of adding a function each time which returns sme_me_mask
> for each user it has, why don't you add a single function which
> returns sme_me_mask in mem_encrypt.c and add an inline in the header
> mem_encrypt.h which returns 0 for the !CONFIG_AMD_MEM_ENCRYPT case.

Currently, mem_encrypt.h only lives in the arch/x86 directory so it
wouldn't be able to be included here without breaking other archs.

> 
> This all is still funny because we access sme_me_mask directly for the
> different KERNEL_* masks but then you're adding an accessor function.

Because this lives outside of the arch/x86 I need to use the weak
function.

> 
> So what you should do instead, IMHO, is either hide sme_me_mask
> altogether and use the accessor functions only (not sure if that would
> work in all cases) or expose sme_me_mask unconditionally and have it be
> 0 if CONFIG_AMD_MEM_ENCRYPT is not enabled so that it just works.
> 
> Or is there a third, more graceful variant?

Is there a better way to do this given the support is only in x86?

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-14 13:45       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:45 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 06:45 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:20PM -0500, Tom Lendacky wrote:
>> Add support to the AMD IOMMU driver to set the memory encryption mask if
>> memory encryption is enabled.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/mem_encrypt.h |    2 ++
>>  arch/x86/mm/mem_encrypt.c          |    5 +++++
>>  drivers/iommu/amd_iommu.c          |   10 ++++++++++
>>  3 files changed, 17 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
>> index 384fdfb..e395729 100644
>> --- a/arch/x86/include/asm/mem_encrypt.h
>> +++ b/arch/x86/include/asm/mem_encrypt.h
>> @@ -36,6 +36,8 @@ void __init sme_early_init(void);
>>  /* Architecture __weak replacement functions */
>>  void __init mem_encrypt_init(void);
>>  
>> +unsigned long amd_iommu_get_me_mask(void);
>> +
>>  unsigned long swiotlb_get_me_mask(void);
>>  void swiotlb_set_mem_dec(void *vaddr, unsigned long size);
>>  
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 6b2e8bf..2f28d87 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -185,6 +185,11 @@ void __init mem_encrypt_init(void)
>>  	swiotlb_clear_encryption();
>>  }
>>  
>> +unsigned long amd_iommu_get_me_mask(void)
>> +{
>> +	return sme_me_mask;
>> +}
>> +
>>  unsigned long swiotlb_get_me_mask(void)
>>  {
>>  	return sme_me_mask;
>> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
>> index 96de97a..63995e3 100644
>> --- a/drivers/iommu/amd_iommu.c
>> +++ b/drivers/iommu/amd_iommu.c
>> @@ -166,6 +166,15 @@ struct dma_ops_domain {
>>  static struct iova_domain reserved_iova_ranges;
>>  static struct lock_class_key reserved_rbtree_key;
>>  
>> +/*
>> + * Support for memory encryption. If memory encryption is supported, then an
>> + * override to this function will be provided.
>> + */
>> +unsigned long __weak amd_iommu_get_me_mask(void)
>> +{
>> +	return 0;
>> +}
> 
> So instead of adding a function each time which returns sme_me_mask
> for each user it has, why don't you add a single function which
> returns sme_me_mask in mem_encrypt.c and add an inline in the header
> mem_encrypt.h which returns 0 for the !CONFIG_AMD_MEM_ENCRYPT case.

Currently, mem_encrypt.h only lives in the arch/x86 directory so it
wouldn't be able to be included here without breaking other archs.

> 
> This all is still funny because we access sme_me_mask directly for the
> different KERNEL_* masks but then you're adding an accessor function.

Because this lives outside of the arch/x86 I need to use the weak
function.

> 
> So what you should do instead, IMHO, is either hide sme_me_mask
> altogether and use the accessor functions only (not sure if that would
> work in all cases) or expose sme_me_mask unconditionally and have it be
> 0 if CONFIG_AMD_MEM_ENCRYPT is not enabled so that it just works.
> 
> Or is there a third, more graceful variant?

Is there a better way to do this given the support is only in x86?

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
  2016-09-12 12:17     ` Borislav Petkov
@ 2016-09-14 13:50       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:50 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 07:17 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
>> Add support to check if memory encryption is active in the kernel and that
>> it has been enabled on the AP. If memory encryption is active in the kernel
>> but has not been enabled on the AP then do not allow the AP to continue
>> start up.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/msr-index.h     |    2 ++
>>  arch/x86/include/asm/realmode.h      |   12 ++++++++++++
>>  arch/x86/realmode/init.c             |    4 ++++
>>  arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
>>  4 files changed, 37 insertions(+)
> 
> ...
> 
>> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
>> index dac7b20..94e29f4 100644
>> --- a/arch/x86/realmode/rm/trampoline_64.S
>> +++ b/arch/x86/realmode/rm/trampoline_64.S
>> @@ -30,6 +30,7 @@
>>  #include <asm/msr.h>
>>  #include <asm/segment.h>
>>  #include <asm/processor-flags.h>
>> +#include <asm/realmode.h>
>>  #include "realmode.h"
>>  
>>  	.text
>> @@ -92,6 +93,23 @@ ENTRY(startup_32)
>>  	movl	%edx, %fs
>>  	movl	%edx, %gs
>>  
>> +	/* Check for memory encryption support */
>> +	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
>> +	jnc	.Ldone
>> +	movl	$MSR_K8_SYSCFG, %ecx
>> +	rdmsr
>> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
>> +	jc	.Ldone
>> +
>> +	/*
>> +	 * Memory encryption is enabled but the MSR has not been set on this
>> +	 * CPU so we can't continue
> 
> Hmm, let me try to parse this correctly: BSP has SME enabled but the
> BIOS might not've set this on the AP? Really? Is that even possible?

Anything is possible, although it's highly unlikely.

> 
> Because if SME is enabled, that means that MSR_K8_SYSCFG[23] on the BSP
> is set, right?

Correct.

> 
> Also, I want to rule out here simple BIOS idiocy: if the only problem
> with the bit not being set in the AP is because some BIOS monkey forgot
> to do so, then we should try to set it ourselves and not die for no real
> reason.

Yes, we can do that.  I was debating on which way to go with this. Most
likely this would never happen, but if it did...  I can change this to
set the MSR bit and continue.

Thanks,
Tom

> 
> Or is there another issue?
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-14 13:50       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 13:50 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 07:17 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
>> Add support to check if memory encryption is active in the kernel and that
>> it has been enabled on the AP. If memory encryption is active in the kernel
>> but has not been enabled on the AP then do not allow the AP to continue
>> start up.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/msr-index.h     |    2 ++
>>  arch/x86/include/asm/realmode.h      |   12 ++++++++++++
>>  arch/x86/realmode/init.c             |    4 ++++
>>  arch/x86/realmode/rm/trampoline_64.S |   19 +++++++++++++++++++
>>  4 files changed, 37 insertions(+)
> 
> ...
> 
>> diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
>> index dac7b20..94e29f4 100644
>> --- a/arch/x86/realmode/rm/trampoline_64.S
>> +++ b/arch/x86/realmode/rm/trampoline_64.S
>> @@ -30,6 +30,7 @@
>>  #include <asm/msr.h>
>>  #include <asm/segment.h>
>>  #include <asm/processor-flags.h>
>> +#include <asm/realmode.h>
>>  #include "realmode.h"
>>  
>>  	.text
>> @@ -92,6 +93,23 @@ ENTRY(startup_32)
>>  	movl	%edx, %fs
>>  	movl	%edx, %gs
>>  
>> +	/* Check for memory encryption support */
>> +	bt	$TH_FLAGS_SME_ENABLE_BIT, pa_tr_flags
>> +	jnc	.Ldone
>> +	movl	$MSR_K8_SYSCFG, %ecx
>> +	rdmsr
>> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
>> +	jc	.Ldone
>> +
>> +	/*
>> +	 * Memory encryption is enabled but the MSR has not been set on this
>> +	 * CPU so we can't continue
> 
> Hmm, let me try to parse this correctly: BSP has SME enabled but the
> BIOS might not've set this on the AP? Really? Is that even possible?

Anything is possible, although it's highly unlikely.

> 
> Because if SME is enabled, that means that MSR_K8_SYSCFG[23] on the BSP
> is set, right?

Correct.

> 
> Also, I want to rule out here simple BIOS idiocy: if the only problem
> with the bit not being set in the AP is because some BIOS monkey forgot
> to do so, then we should try to set it ourselves and not die for no real
> reason.

Yes, we can do that.  I was debating on which way to go with this. Most
likely this would never happen, but if it did...  I can change this to
set the MSR bit and continue.

Thanks,
Tom

> 
> Or is there another issue?
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
  2016-09-12 14:35     ` Borislav Petkov
@ 2016-09-14 14:02       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:02 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 09:35 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:49PM -0500, Tom Lendacky wrote:
>> Update the KVM support to include the memory encryption mask when creating
>> and using nested page tables.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/kvm_host.h |    3 ++-
>>  arch/x86/kvm/mmu.c              |    8 ++++++--
>>  arch/x86/kvm/vmx.c              |    3 ++-
>>  arch/x86/kvm/x86.c              |    3 ++-
>>  4 files changed, 12 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
>> index 33ae3a4..c51c1cb 100644
>> --- a/arch/x86/include/asm/kvm_host.h
>> +++ b/arch/x86/include/asm/kvm_host.h
>> @@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
>>  void kvm_mmu_init_vm(struct kvm *kvm);
>>  void kvm_mmu_uninit_vm(struct kvm *kvm);
>>  void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
>> -		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
>> +		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
>> +		u64 me_mask);
> 
> Why do you need a separate mask?
> 
> arch/x86/kvm/mmu.c::set_spte() ORs in shadow_present_mask
> unconditionally. So you can simply do:
> 
> 
> 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
> 			      PT_DIRTY_MASK, PT64_NX_MASK, 0,
> 			      PT_PRESENT_MASK | sme_me_mask);
> 
> and have this change much simpler.

Just keeping in step with the way this is done for the other masks.
They each have a specific meaning so I was trying not to combine
them in case they may be used differently in the future.

> 
>>  void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
>>  void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>> index 3d4cc8cc..a7040f4 100644
>> --- a/arch/x86/kvm/mmu.c
>> +++ b/arch/x86/kvm/mmu.c
>> @@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
>>  					    * PT32_LEVEL_BITS))) - 1))
>>  
>>  #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
>> -			| shadow_x_mask | shadow_nx_mask)
>> +			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
> 
> This would be sme_me_mask, of course, like with the baremetal masks.
> 
> Or am I missing something?

Given the current patch, this would be shadow_me_mask since that value
is set by the call to kvm_mmu_set_mask_ptes.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables
@ 2016-09-14 14:02       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:02 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 09:35 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:49PM -0500, Tom Lendacky wrote:
>> Update the KVM support to include the memory encryption mask when creating
>> and using nested page tables.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/include/asm/kvm_host.h |    3 ++-
>>  arch/x86/kvm/mmu.c              |    8 ++++++--
>>  arch/x86/kvm/vmx.c              |    3 ++-
>>  arch/x86/kvm/x86.c              |    3 ++-
>>  4 files changed, 12 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
>> index 33ae3a4..c51c1cb 100644
>> --- a/arch/x86/include/asm/kvm_host.h
>> +++ b/arch/x86/include/asm/kvm_host.h
>> @@ -1039,7 +1039,8 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu);
>>  void kvm_mmu_init_vm(struct kvm *kvm);
>>  void kvm_mmu_uninit_vm(struct kvm *kvm);
>>  void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
>> -		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask);
>> +		u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 p_mask,
>> +		u64 me_mask);
> 
> Why do you need a separate mask?
> 
> arch/x86/kvm/mmu.c::set_spte() ORs in shadow_present_mask
> unconditionally. So you can simply do:
> 
> 
> 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
> 			      PT_DIRTY_MASK, PT64_NX_MASK, 0,
> 			      PT_PRESENT_MASK | sme_me_mask);
> 
> and have this change much simpler.

Just keeping in step with the way this is done for the other masks.
They each have a specific meaning so I was trying not to combine
them in case they may be used differently in the future.

> 
>>  void kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
>>  void kvm_mmu_slot_remove_write_access(struct kvm *kvm,
>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>> index 3d4cc8cc..a7040f4 100644
>> --- a/arch/x86/kvm/mmu.c
>> +++ b/arch/x86/kvm/mmu.c
>> @@ -122,7 +122,7 @@ module_param(dbg, bool, 0644);
>>  					    * PT32_LEVEL_BITS))) - 1))
>>  
>>  #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \
>> -			| shadow_x_mask | shadow_nx_mask)
>> +			| shadow_x_mask | shadow_nx_mask | shadow_me_mask)
> 
> This would be sme_me_mask, of course, like with the baremetal masks.
> 
> Or am I missing something?

Given the current patch, this would be shadow_me_mask since that value
is set by the call to kvm_mmu_set_mask_ptes.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-14 14:11           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 11:33 AM, Borislav Petkov wrote:
> On Mon, Sep 12, 2016 at 10:05:36AM -0500, Tom Lendacky wrote:
>> I can look into that.  The reason I put this here is this is all the
>> early page fault support that is very specific to this file. I modified
>> an existing static function to take advantage of the mapping support.
> 
> Yeah, but all this code is SME-specific and doesn't belong there.
> AFAICT, it uses global/public symbols so there shouldn't be a problem to
> have it in mem_encrypt.c.

Ok, I'll look into moving this into mem_encrypt.c. I'd like to avoid
duplicating code so I may have to make that static function external
unless I find a better way.

Thanks,
Tom

> 
>> Hmmm, maybe... With the change to the early_memremap() the initrd is now
>> identified as BOOT_DATA in relocate_initrd() and so it will be mapped
>> and copied as non-encyrpted data. But since it was encrypted before the
>> call to relocate_initrd() it will copy encrypted bytes which will later
>> be accessed encrypted. That isn't clear though, so I'll rework
>> reserve_initrd() to perform the sme_early_mem_enc() once at the end
>> whether the initrd is re-located or not.
> 
> Makes sense.
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-14 14:11           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/12/2016 11:33 AM, Borislav Petkov wrote:
> On Mon, Sep 12, 2016 at 10:05:36AM -0500, Tom Lendacky wrote:
>> I can look into that.  The reason I put this here is this is all the
>> early page fault support that is very specific to this file. I modified
>> an existing static function to take advantage of the mapping support.
> 
> Yeah, but all this code is SME-specific and doesn't belong there.
> AFAICT, it uses global/public symbols so there shouldn't be a problem to
> have it in mem_encrypt.c.

Ok, I'll look into moving this into mem_encrypt.c. I'd like to avoid
duplicating code so I may have to make that static function external
unless I find a better way.

Thanks,
Tom

> 
>> Hmmm, maybe... With the change to the early_memremap() the initrd is now
>> identified as BOOT_DATA in relocate_initrd() and so it will be mapped
>> and copied as non-encyrpted data. But since it was encrypted before the
>> call to relocate_initrd() it will copy encrypted bytes which will later
>> be accessed encrypted. That isn't clear though, so I'll rework
>> reserve_initrd() to perform the sme_early_mem_enc() once at the end
>> whether the initrd is re-located or not.
> 
> Makes sense.
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible
@ 2016-09-14 14:11           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 11:33 AM, Borislav Petkov wrote:
> On Mon, Sep 12, 2016 at 10:05:36AM -0500, Tom Lendacky wrote:
>> I can look into that.  The reason I put this here is this is all the
>> early page fault support that is very specific to this file. I modified
>> an existing static function to take advantage of the mapping support.
> 
> Yeah, but all this code is SME-specific and doesn't belong there.
> AFAICT, it uses global/public symbols so there shouldn't be a problem to
> have it in mem_encrypt.c.

Ok, I'll look into moving this into mem_encrypt.c. I'd like to avoid
duplicating code so I may have to make that static function external
unless I find a better way.

Thanks,
Tom

> 
>> Hmmm, maybe... With the change to the early_memremap() the initrd is now
>> identified as BOOT_DATA in relocate_initrd() and so it will be mapped
>> and copied as non-encyrpted data. But since it was encrypted before the
>> call to relocate_initrd() it will copy encrypted bytes which will later
>> be accessed encrypted. That isn't clear though, so I'll rework
>> reserve_initrd() to perform the sme_early_mem_enc() once at the end
>> whether the initrd is re-located or not.
> 
> Makes sense.
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-14 14:12       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:12 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov



On 09/12/2016 11:43 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
>> Add support to check if memory encryption is active in the kernel and that
>> it has been enabled on the AP. If memory encryption is active in the kernel
> 
> A small nit: let's write out "AP" the first time at least: "... on the
> Application Processors (AP)." for more clarity.

Will do.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-14 14:12       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:12 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini



On 09/12/2016 11:43 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
>> Add support to check if memory encryption is active in the kernel and that
>> it has been enabled on the AP. If memory encryption is active in the kernel
> 
> A small nit: let's write out "AP" the first time at least: "... on the
> Application Processors (AP)." for more clarity.

Will do.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs
@ 2016-09-14 14:12       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:12 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov



On 09/12/2016 11:43 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:29PM -0500, Tom Lendacky wrote:
>> Add support to check if memory encryption is active in the kernel and that
>> it has been enabled on the AP. If memory encryption is active in the kernel
> 
> A small nit: let's write out "AP" the first time at least: "... on the
> Application Processors (AP)." for more clarity.

Will do.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-14 14:20       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:20 UTC (permalink / raw)
  To: Andy Lutomirski, Matt Fleming
  Cc: kasan-dev, linux-efi, linux-arch, Thomas Gleixner, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> What happens when you memremap boot services data outside of early
> boot?  Matt just added code that does this.
> 
> IMO this API is not so great.  It scatters a specialized consideration
> all over the place.  Could early_memremap not look up the PA to figure
> out what to do?

Yes, I could see if the PA falls outside of the kernel usable area and,
if so, remove the memory encryption attribute from the mapping (for both
early_memremap and memremap).

Let me look into that, I would prefer something along that line over
this change.

Thanks,
Tom

> 
> --Andy
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-14 14:20       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:20 UTC (permalink / raw)
  To: Andy Lutomirski, Matt Fleming
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm list,
	Radim Krčmář,
	Matt Fleming, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	Alexander Potapenko, H. Peter Anvin, linux-arch, Jonathan Corbet,
	X86 ML, kasan-dev, Ingo Molnar, Andrey Ryabinin, Arnd Bergmann,
	Borislav Petkov, Thomas Gleixner, Dmitry Vyukov,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky-5C7GfCeVMHo@public.gmane.org> wrote:
>>
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> What happens when you memremap boot services data outside of early
> boot?  Matt just added code that does this.
> 
> IMO this API is not so great.  It scatters a specialized consideration
> all over the place.  Could early_memremap not look up the PA to figure
> out what to do?

Yes, I could see if the PA falls outside of the kernel usable area and,
if so, remove the memory encryption attribute from the mapping (for both
early_memremap and memremap).

Let me look into that, I would prefer something along that line over
this change.

Thanks,
Tom

> 
> --Andy
> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-14 14:20       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:20 UTC (permalink / raw)
  To: Andy Lutomirski, Matt Fleming
  Cc: kasan-dev, linux-efi, linux-arch, Thomas Gleixner, Paolo Bonzini,
	Ingo Molnar, Borislav Petkov, iommu, linux-doc, Jonathan Corbet,
	Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Matt Fleming,
	Alexander Potapenko, linux-kernel, Dmitry Vyukov, Arnd Bergmann,
	Joerg Roedel, Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list

On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>
>> BOOT data (such as EFI related data) is not encyrpted when the system is
>> booted and needs to be accessed as non-encrypted.  Add support to the
>> early_memremap API to identify the type of data being accessed so that
>> the proper encryption attribute can be applied.  Currently, two types
>> of data are defined, KERNEL_DATA and BOOT_DATA.
> 
> What happens when you memremap boot services data outside of early
> boot?  Matt just added code that does this.
> 
> IMO this API is not so great.  It scatters a specialized consideration
> all over the place.  Could early_memremap not look up the PA to figure
> out what to do?

Yes, I could see if the PA falls outside of the kernel usable area and,
if so, remove the memory encryption attribute from the mapping (for both
early_memremap and memremap).

Let me look into that, I would prefer something along that line over
this change.

Thanks,
Tom

> 
> --Andy
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-14 14:29       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:29 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 11:59 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:59PM -0500, Tom Lendacky wrote:
>> Since the setup data is in memory in the clear, it must be accessed as
>> un-encrypted.  Always use ioremap (similar to sysfs setup data support)
>> to map the data.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
>>  1 file changed, 11 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
>> index bdb83e4..a58a82e 100644
>> --- a/arch/x86/kernel/kdebugfs.c
>> +++ b/arch/x86/kernel/kdebugfs.c
>> @@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
>>  
>>  	pa = node->paddr + sizeof(struct setup_data) + pos;
>>  	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
>> -	if (PageHighMem(pg)) {
> 
> Why is it ok to get rid of the PageHighMem() check?

Since the change is to perform the ioremap call no matter what the check
for PageHighMem() wasn't needed anymore.

> 
> Btw, we did talk earlier in the thread about making __va() clear the SME
> mask and then you won't really need to change stuff here. Or?

This is still required because just using the __va() would still cause
the mapping created to have the encryption bit set. The ioremap call
will result in the mapping not having the encryption bit set.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-14 14:29       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:29 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner

On 09/12/2016 11:59 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:59PM -0500, Tom Lendacky wrote:
>> Since the setup data is in memory in the clear, it must be accessed as
>> un-encrypted.  Always use ioremap (similar to sysfs setup data support)
>> to map the data.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky-5C7GfCeVMHo@public.gmane.org>
>> ---
>>  arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
>>  1 file changed, 11 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
>> index bdb83e4..a58a82e 100644
>> --- a/arch/x86/kernel/kdebugfs.c
>> +++ b/arch/x86/kernel/kdebugfs.c
>> @@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
>>  
>>  	pa = node->paddr + sizeof(struct setup_data) + pos;
>>  	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
>> -	if (PageHighMem(pg)) {
> 
> Why is it ok to get rid of the PageHighMem() check?

Since the change is to perform the ioremap call no matter what the check
for PageHighMem() wasn't needed anymore.

> 
> Btw, we did talk earlier in the thread about making __va() clear the SME
> mask and then you won't really need to change stuff here. Or?

This is still required because just using the __va() would still cause
the mapping created to have the encryption bit set. The ioremap call
will result in the mapping not having the encryption bit set.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-14 14:29       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:29 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 11:59 AM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:38:59PM -0500, Tom Lendacky wrote:
>> Since the setup data is in memory in the clear, it must be accessed as
>> un-encrypted.  Always use ioremap (similar to sysfs setup data support)
>> to map the data.
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  arch/x86/kernel/kdebugfs.c |   30 +++++++++++-------------------
>>  1 file changed, 11 insertions(+), 19 deletions(-)
>>
>> diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
>> index bdb83e4..a58a82e 100644
>> --- a/arch/x86/kernel/kdebugfs.c
>> +++ b/arch/x86/kernel/kdebugfs.c
>> @@ -48,17 +48,13 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
>>  
>>  	pa = node->paddr + sizeof(struct setup_data) + pos;
>>  	pg = pfn_to_page((pa + count - 1) >> PAGE_SHIFT);
>> -	if (PageHighMem(pg)) {
> 
> Why is it ok to get rid of the PageHighMem() check?

Since the change is to perform the ioremap call no matter what the check
for PageHighMem() wasn't needed anymore.

> 
> Btw, we did talk earlier in the thread about making __va() clear the SME
> mask and then you won't really need to change stuff here. Or?

This is still required because just using the __va() would still cause
the mapping created to have the encryption bit set. The ioremap call
will result in the mapping not having the encryption bit set.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
  2016-09-12 17:08     ` Borislav Petkov
@ 2016-09-14 14:31       ` Tom Lendacky
  -1 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:31 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 12:08 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:39:08PM -0500, Tom Lendacky wrote:
>> This patch adds the support to check if SME has been enabled and if the
>> mem_encrypt=on command line option is set. If both of these conditions
>> are true, then the encryption mask is set and the kernel is encrypted
>> "in place."
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  Documentation/kernel-parameters.txt |    3 
>>  arch/x86/kernel/asm-offsets.c       |    2 
>>  arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
>>  arch/x86/mm/mem_encrypt.c           |    2 
>>  4 files changed, 309 insertions(+)
>>
>> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
>> index 46c030a..a1986c8 100644
>> --- a/Documentation/kernel-parameters.txt
>> +++ b/Documentation/kernel-parameters.txt
>> @@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>>  			memory contents and reserves bad memory
>>  			regions that are detected.
>>  
>> +	mem_encrypt=on	[X86_64] Enable memory encryption on processors
>> +			that support this feature.
>> +
>>  	meye.*=		[HW] Set MotionEye Camera parameters
>>  			See Documentation/video4linux/meye.txt.
>>  
>> diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
>> index 2bd5c6f..e485ada 100644
>> --- a/arch/x86/kernel/asm-offsets.c
>> +++ b/arch/x86/kernel/asm-offsets.c
>> @@ -85,6 +85,8 @@ void common(void) {
>>  	OFFSET(BP_init_size, boot_params, hdr.init_size);
>>  	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
>>  	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
>> +	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
>> +	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
>>  
>>  	BLANK();
>>  	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
>> diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
>> index f2e0536..bf9f6a9 100644
>> --- a/arch/x86/kernel/mem_encrypt.S
>> +++ b/arch/x86/kernel/mem_encrypt.S
>> @@ -12,13 +12,230 @@
>>  
>>  #include <linux/linkage.h>
>>  
>> +#include <asm/processor-flags.h>
>> +#include <asm/pgtable.h>
>> +#include <asm/page.h>
>> +#include <asm/msr.h>
>> +#include <asm/asm-offsets.h>
>> +
>>  	.text
>>  	.code64
>>  ENTRY(sme_enable)
>> +#ifdef CONFIG_AMD_MEM_ENCRYPT
>> +	/* Check for AMD processor */
>> +	xorl	%eax, %eax
>> +	cpuid
>> +	cmpl    $0x68747541, %ebx	# AuthenticAMD
>> +	jne     .Lmem_encrypt_exit
>> +	cmpl    $0x69746e65, %edx
>> +	jne     .Lmem_encrypt_exit
>> +	cmpl    $0x444d4163, %ecx
>> +	jne     .Lmem_encrypt_exit
>> +
>> +	/* Check for memory encryption leaf */
>> +	movl	$0x80000000, %eax
>> +	cpuid
>> +	cmpl	$0x8000001f, %eax
>> +	jb	.Lmem_encrypt_exit
>> +
>> +	/*
>> +	 * Check for memory encryption feature:
>> +	 *   CPUID Fn8000_001F[EAX] - Bit 0
>> +	 *     Secure Memory Encryption support
>> +	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
>> +	 *     Pagetable bit position used to indicate encryption
>> +	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
>> +	 *     Reduction in physical address space (in bits) when enabled
>> +	 */
>> +	movl	$0x8000001f, %eax
>> +	cpuid
>> +	bt	$0, %eax
>> +	jnc	.Lmem_encrypt_exit
>> +
>> +	/* Check if BIOS/UEFI has allowed memory encryption */
>> +	movl	$MSR_K8_SYSCFG, %ecx
>> +	rdmsr
>> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
>> +	jnc	.Lmem_encrypt_exit
> 
> Like other people suggested, it would be great if this were in C. Should be
> actually readable :)

Yup, working on that.  I'll try and make it all completely C.

> 
>> +
>> +	/* Check for the mem_encrypt=on command line option */
>> +	push	%rsi			/* Save RSI (real_mode_data) */
>> +	push	%rbx			/* Save CPUID information */
>> +	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
>> +	shlq	$32, %rcx
>> +	movl	BP_cmd_line_ptr(%rsi), %edi
>> +	addq	%rcx, %rdi
>> +	leaq	mem_encrypt_enable_option(%rip), %rsi
>> +	call	cmdline_find_option_bool
>> +	pop	%rbx			/* Restore CPUID information */
>> +	pop	%rsi			/* Restore RSI (real_mode_data) */
>> +	testl	%eax, %eax
>> +	jz	.Lno_mem_encrypt
> 
> This too.
> 
>> +
>> +	/* Set memory encryption mask */
>> +	movl	%ebx, %ecx
>> +	andl	$0x3f, %ecx
>> +	bts	%ecx, sme_me_mask(%rip)
>> +
>> +.Lno_mem_encrypt:
>> +	/*
>> +	 * BIOS/UEFI has allowed memory encryption so we need to set
>> +	 * the amount of physical address space reduction even if
>> +	 * the user decides not to use memory encryption.
>> +	 */
>> +	movl	%ebx, %ecx
>> +	shrl	$6, %ecx
>> +	andl	$0x3f, %ecx
>> +	movb	%cl, sme_me_loss(%rip)
>> +
>> +.Lmem_encrypt_exit:
>> +#endif	/* CONFIG_AMD_MEM_ENCRYPT */
>> +
>>  	ret
>>  ENDPROC(sme_enable)
>>  
>>  ENTRY(sme_encrypt_kernel)
> 
> This should be doable too but I guess you'll have to try it to see.
> 
> ...
> 
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 2f28d87..1154353 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
>>  
>>  	/* Make SWIOTLB use an unencrypted DMA area */
>>  	swiotlb_clear_encryption();
>> +
>> +	pr_info("memory encryption active\n");
> 
> Let's make it more official with nice caps and so on...
> 
> 	pr_info("AMD Secure Memory Encryption active.\n");

Will do.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption
@ 2016-09-14 14:31       ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-14 14:31 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/12/2016 12:08 PM, Borislav Petkov wrote:
> On Mon, Aug 22, 2016 at 05:39:08PM -0500, Tom Lendacky wrote:
>> This patch adds the support to check if SME has been enabled and if the
>> mem_encrypt=on command line option is set. If both of these conditions
>> are true, then the encryption mask is set and the kernel is encrypted
>> "in place."
>>
>> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
>> ---
>>  Documentation/kernel-parameters.txt |    3 
>>  arch/x86/kernel/asm-offsets.c       |    2 
>>  arch/x86/kernel/mem_encrypt.S       |  302 +++++++++++++++++++++++++++++++++++
>>  arch/x86/mm/mem_encrypt.c           |    2 
>>  4 files changed, 309 insertions(+)
>>
>> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
>> index 46c030a..a1986c8 100644
>> --- a/Documentation/kernel-parameters.txt
>> +++ b/Documentation/kernel-parameters.txt
>> @@ -2268,6 +2268,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>>  			memory contents and reserves bad memory
>>  			regions that are detected.
>>  
>> +	mem_encrypt=on	[X86_64] Enable memory encryption on processors
>> +			that support this feature.
>> +
>>  	meye.*=		[HW] Set MotionEye Camera parameters
>>  			See Documentation/video4linux/meye.txt.
>>  
>> diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
>> index 2bd5c6f..e485ada 100644
>> --- a/arch/x86/kernel/asm-offsets.c
>> +++ b/arch/x86/kernel/asm-offsets.c
>> @@ -85,6 +85,8 @@ void common(void) {
>>  	OFFSET(BP_init_size, boot_params, hdr.init_size);
>>  	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
>>  	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
>> +	OFFSET(BP_cmd_line_ptr, boot_params, hdr.cmd_line_ptr);
>> +	OFFSET(BP_ext_cmd_line_ptr, boot_params, ext_cmd_line_ptr);
>>  
>>  	BLANK();
>>  	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
>> diff --git a/arch/x86/kernel/mem_encrypt.S b/arch/x86/kernel/mem_encrypt.S
>> index f2e0536..bf9f6a9 100644
>> --- a/arch/x86/kernel/mem_encrypt.S
>> +++ b/arch/x86/kernel/mem_encrypt.S
>> @@ -12,13 +12,230 @@
>>  
>>  #include <linux/linkage.h>
>>  
>> +#include <asm/processor-flags.h>
>> +#include <asm/pgtable.h>
>> +#include <asm/page.h>
>> +#include <asm/msr.h>
>> +#include <asm/asm-offsets.h>
>> +
>>  	.text
>>  	.code64
>>  ENTRY(sme_enable)
>> +#ifdef CONFIG_AMD_MEM_ENCRYPT
>> +	/* Check for AMD processor */
>> +	xorl	%eax, %eax
>> +	cpuid
>> +	cmpl    $0x68747541, %ebx	# AuthenticAMD
>> +	jne     .Lmem_encrypt_exit
>> +	cmpl    $0x69746e65, %edx
>> +	jne     .Lmem_encrypt_exit
>> +	cmpl    $0x444d4163, %ecx
>> +	jne     .Lmem_encrypt_exit
>> +
>> +	/* Check for memory encryption leaf */
>> +	movl	$0x80000000, %eax
>> +	cpuid
>> +	cmpl	$0x8000001f, %eax
>> +	jb	.Lmem_encrypt_exit
>> +
>> +	/*
>> +	 * Check for memory encryption feature:
>> +	 *   CPUID Fn8000_001F[EAX] - Bit 0
>> +	 *     Secure Memory Encryption support
>> +	 *   CPUID Fn8000_001F[EBX] - Bits 5:0
>> +	 *     Pagetable bit position used to indicate encryption
>> +	 *   CPUID Fn8000_001F[EBX] - Bits 11:6
>> +	 *     Reduction in physical address space (in bits) when enabled
>> +	 */
>> +	movl	$0x8000001f, %eax
>> +	cpuid
>> +	bt	$0, %eax
>> +	jnc	.Lmem_encrypt_exit
>> +
>> +	/* Check if BIOS/UEFI has allowed memory encryption */
>> +	movl	$MSR_K8_SYSCFG, %ecx
>> +	rdmsr
>> +	bt	$MSR_K8_SYSCFG_MEM_ENCRYPT_BIT, %eax
>> +	jnc	.Lmem_encrypt_exit
> 
> Like other people suggested, it would be great if this were in C. Should be
> actually readable :)

Yup, working on that.  I'll try and make it all completely C.

> 
>> +
>> +	/* Check for the mem_encrypt=on command line option */
>> +	push	%rsi			/* Save RSI (real_mode_data) */
>> +	push	%rbx			/* Save CPUID information */
>> +	movl	BP_ext_cmd_line_ptr(%rsi), %ecx
>> +	shlq	$32, %rcx
>> +	movl	BP_cmd_line_ptr(%rsi), %edi
>> +	addq	%rcx, %rdi
>> +	leaq	mem_encrypt_enable_option(%rip), %rsi
>> +	call	cmdline_find_option_bool
>> +	pop	%rbx			/* Restore CPUID information */
>> +	pop	%rsi			/* Restore RSI (real_mode_data) */
>> +	testl	%eax, %eax
>> +	jz	.Lno_mem_encrypt
> 
> This too.
> 
>> +
>> +	/* Set memory encryption mask */
>> +	movl	%ebx, %ecx
>> +	andl	$0x3f, %ecx
>> +	bts	%ecx, sme_me_mask(%rip)
>> +
>> +.Lno_mem_encrypt:
>> +	/*
>> +	 * BIOS/UEFI has allowed memory encryption so we need to set
>> +	 * the amount of physical address space reduction even if
>> +	 * the user decides not to use memory encryption.
>> +	 */
>> +	movl	%ebx, %ecx
>> +	shrl	$6, %ecx
>> +	andl	$0x3f, %ecx
>> +	movb	%cl, sme_me_loss(%rip)
>> +
>> +.Lmem_encrypt_exit:
>> +#endif	/* CONFIG_AMD_MEM_ENCRYPT */
>> +
>>  	ret
>>  ENDPROC(sme_enable)
>>  
>>  ENTRY(sme_encrypt_kernel)
> 
> This should be doable too but I guess you'll have to try it to see.
> 
> ...
> 
>> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
>> index 2f28d87..1154353 100644
>> --- a/arch/x86/mm/mem_encrypt.c
>> +++ b/arch/x86/mm/mem_encrypt.c
>> @@ -183,6 +183,8 @@ void __init mem_encrypt_init(void)
>>  
>>  	/* Make SWIOTLB use an unencrypted DMA area */
>>  	swiotlb_clear_encryption();
>> +
>> +	pr_info("memory encryption active\n");
> 
> Let's make it more official with nice caps and so on...
> 
> 	pr_info("AMD Secure Memory Encryption active.\n");

Will do.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
  2016-09-14 13:45       ` Tom Lendacky
@ 2016-09-14 14:41         ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-14 14:41 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 14, 2016 at 08:45:44AM -0500, Tom Lendacky wrote:
> Currently, mem_encrypt.h only lives in the arch/x86 directory so it
> wouldn't be able to be included here without breaking other archs.

I'm wondering if it would be simpler to move only sme_me_mask to an
arch-agnostic header just so that we save us all the code duplication.

Hmmm.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-14 14:41         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-14 14:41 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 14, 2016 at 08:45:44AM -0500, Tom Lendacky wrote:
> Currently, mem_encrypt.h only lives in the arch/x86 directory so it
> wouldn't be able to be included here without breaking other archs.

I'm wondering if it would be simpler to move only sme_me_mask to an
arch-agnostic header just so that we save us all the code duplication.

Hmmm.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
  2016-09-14 14:29       ` Tom Lendacky
@ 2016-09-14 14:51         ` Borislav Petkov
  -1 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-14 14:51 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 14, 2016 at 09:29:41AM -0500, Tom Lendacky wrote:
> This is still required because just using the __va() would still cause
> the mapping created to have the encryption bit set. The ioremap call
> will result in the mapping not having the encryption bit set.

I meant this: https://lkml.kernel.org/r/20160902181447.GA25328@nazgul.tnic

Wouldn't simply clearing the SME mask work?

#define __va(x)			((void *)(((unsigned long)(x)+PAGE_OFFSET) & ~sme_me_mask))

Or are you saying, one needs the whole noodling through ioremap_cache()
because the data is already encrypted and accessing it with sme_me_mask
cleared would simply give you the encrypted garbage?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-14 14:51         ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-14 14:51 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Wed, Sep 14, 2016 at 09:29:41AM -0500, Tom Lendacky wrote:
> This is still required because just using the __va() would still cause
> the mapping created to have the encryption bit set. The ioremap call
> will result in the mapping not having the encryption bit set.

I meant this: https://lkml.kernel.org/r/20160902181447.GA25328@nazgul.tnic

Wouldn't simply clearing the SME mask work?

#define __va(x)			((void *)(((unsigned long)(x)+PAGE_OFFSET) & ~sme_me_mask))

Or are you saying, one needs the whole noodling through ioremap_cache()
because the data is already encrypted and accessing it with sme_me_mask
cleared would simply give you the encrypted garbage?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15  9:57         ` Matt Fleming
  0 siblings, 0 replies; 229+ messages in thread
From: Matt Fleming @ 2016-09-15  9:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: Andy Lutomirski, kasan-dev, linux-efi, linux-arch,
	Thomas Gleixner, Paolo Bonzini, Ingo Molnar, Borislav Petkov,
	iommu, linux-doc, Jonathan Corbet, Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Alexander Potapenko,
	linux-kernel, Dmitry Vyukov, Arnd Bergmann, Joerg Roedel,
	Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list, Dave Young

On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> > On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
> >>
> >> BOOT data (such as EFI related data) is not encyrpted when the system is
> >> booted and needs to be accessed as non-encrypted.  Add support to the
> >> early_memremap API to identify the type of data being accessed so that
> >> the proper encryption attribute can be applied.  Currently, two types
> >> of data are defined, KERNEL_DATA and BOOT_DATA.
> > 
> > What happens when you memremap boot services data outside of early
> > boot?  Matt just added code that does this.
> > 
> > IMO this API is not so great.  It scatters a specialized consideration
> > all over the place.  Could early_memremap not look up the PA to figure
> > out what to do?
> 
> Yes, I could see if the PA falls outside of the kernel usable area and,
> if so, remove the memory encryption attribute from the mapping (for both
> early_memremap and memremap).
> 
> Let me look into that, I would prefer something along that line over
> this change.

So, the last time we talked about using the address to figure out
whether to encrypt/decrypt you said,

 "I looked into this and this would be a large change also to parse
  tables and build lists."

Has something changed that makes this approach easier?

And again, you need to be careful with the EFI kexec code paths, since
you've got a mixture of boot and kernel data being passed. In
particular the EFI memory map is allocated by the firmware on first
boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).

That's one of the reasons I suggested requiring the caller to decide
on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
distinction isn't easily made.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15  9:57         ` Matt Fleming
  0 siblings, 0 replies; 229+ messages in thread
From: Matt Fleming @ 2016-09-15  9:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm list,
	Radim Krčmář,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch, Jonathan Corbet, X86 ML, kasan-dev,
	Ingo Molnar, Andrey Ryabinin, Dave Young, Arnd Bergmann,
	Borislav Petkov, Thomas Gleixner, Dmitry Vyukov,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andy Lutomirski,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> > On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky-5C7GfCeVMHo@public.gmane.org> wrote:
> >>
> >> BOOT data (such as EFI related data) is not encyrpted when the system is
> >> booted and needs to be accessed as non-encrypted.  Add support to the
> >> early_memremap API to identify the type of data being accessed so that
> >> the proper encryption attribute can be applied.  Currently, two types
> >> of data are defined, KERNEL_DATA and BOOT_DATA.
> > 
> > What happens when you memremap boot services data outside of early
> > boot?  Matt just added code that does this.
> > 
> > IMO this API is not so great.  It scatters a specialized consideration
> > all over the place.  Could early_memremap not look up the PA to figure
> > out what to do?
> 
> Yes, I could see if the PA falls outside of the kernel usable area and,
> if so, remove the memory encryption attribute from the mapping (for both
> early_memremap and memremap).
> 
> Let me look into that, I would prefer something along that line over
> this change.

So, the last time we talked about using the address to figure out
whether to encrypt/decrypt you said,

 "I looked into this and this would be a large change also to parse
  tables and build lists."

Has something changed that makes this approach easier?

And again, you need to be careful with the EFI kexec code paths, since
you've got a mixture of boot and kernel data being passed. In
particular the EFI memory map is allocated by the firmware on first
boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).

That's one of the reasons I suggested requiring the caller to decide
on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
distinction isn't easily made.

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15  9:57         ` Matt Fleming
  0 siblings, 0 replies; 229+ messages in thread
From: Matt Fleming @ 2016-09-15  9:57 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: Andy Lutomirski, kasan-dev, linux-efi, linux-arch,
	Thomas Gleixner, Paolo Bonzini, Ingo Molnar, Borislav Petkov,
	iommu, linux-doc, Jonathan Corbet, Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Alexander Potapenko,
	linux-kernel, Dmitry Vyukov, Arnd Bergmann, Joerg Roedel,
	Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list, Dave Young

On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
> > On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
> >>
> >> BOOT data (such as EFI related data) is not encyrpted when the system is
> >> booted and needs to be accessed as non-encrypted.  Add support to the
> >> early_memremap API to identify the type of data being accessed so that
> >> the proper encryption attribute can be applied.  Currently, two types
> >> of data are defined, KERNEL_DATA and BOOT_DATA.
> > 
> > What happens when you memremap boot services data outside of early
> > boot?  Matt just added code that does this.
> > 
> > IMO this API is not so great.  It scatters a specialized consideration
> > all over the place.  Could early_memremap not look up the PA to figure
> > out what to do?
> 
> Yes, I could see if the PA falls outside of the kernel usable area and,
> if so, remove the memory encryption attribute from the mapping (for both
> early_memremap and memremap).
> 
> Let me look into that, I would prefer something along that line over
> this change.

So, the last time we talked about using the address to figure out
whether to encrypt/decrypt you said,

 "I looked into this and this would be a large change also to parse
  tables and build lists."

Has something changed that makes this approach easier?

And again, you need to be careful with the EFI kexec code paths, since
you've got a mixture of boot and kernel data being passed. In
particular the EFI memory map is allocated by the firmware on first
boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).

That's one of the reasons I suggested requiring the caller to decide
on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
distinction isn't easily made.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15 16:52           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:52 UTC (permalink / raw)
  To: Matt Fleming
  Cc: Andy Lutomirski, kasan-dev, linux-efi, linux-arch,
	Thomas Gleixner, Paolo Bonzini, Ingo Molnar, Borislav Petkov,
	iommu, linux-doc, Jonathan Corbet, Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Alexander Potapenko,
	linux-kernel, Dmitry Vyukov, Arnd Bergmann, Joerg Roedel,
	Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list, Dave Young

On 09/15/2016 04:57 AM, Matt Fleming wrote:
> On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
>> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
>>> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>>>
>>>> BOOT data (such as EFI related data) is not encyrpted when the system is
>>>> booted and needs to be accessed as non-encrypted.  Add support to the
>>>> early_memremap API to identify the type of data being accessed so that
>>>> the proper encryption attribute can be applied.  Currently, two types
>>>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>>
>>> What happens when you memremap boot services data outside of early
>>> boot?  Matt just added code that does this.
>>>
>>> IMO this API is not so great.  It scatters a specialized consideration
>>> all over the place.  Could early_memremap not look up the PA to figure
>>> out what to do?
>>
>> Yes, I could see if the PA falls outside of the kernel usable area and,
>> if so, remove the memory encryption attribute from the mapping (for both
>> early_memremap and memremap).
>>
>> Let me look into that, I would prefer something along that line over
>> this change.
> 
> So, the last time we talked about using the address to figure out
> whether to encrypt/decrypt you said,
> 
>  "I looked into this and this would be a large change also to parse
>   tables and build lists."
> 
> Has something changed that makes this approach easier?

The original idea of parsing the tables and building a list was
a large change.  This approach would be simpler by just checking if
the PA is outside the kernel usable area, and if so, removing the
encryption bit.

> 
> And again, you need to be careful with the EFI kexec code paths, since
> you've got a mixture of boot and kernel data being passed. In
> particular the EFI memory map is allocated by the firmware on first
> boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).
> 
> That's one of the reasons I suggested requiring the caller to decide
> on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
> distinction isn't easily made.

Yeah, for kexec I think I'll need to make sure that everything looks
like it came from the BIOS/UEFI/bootloader.  If all of the kexec
pieces are allocated with un-encrypted memory, then the boot path
should remain the same.  That's the piece I need to investigate
further.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15 16:52           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:52 UTC (permalink / raw)
  To: Matt Fleming
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm list,
	Radim Krčmář,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch, Jonathan Corbet, X86 ML, kasan-dev,
	Ingo Molnar, Andrey Ryabinin, Dave Young, Arnd Bergmann,
	Borislav Petkov, Thomas Gleixner, Dmitry Vyukov,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andy Lutomirski,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/15/2016 04:57 AM, Matt Fleming wrote:
> On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
>> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
>>> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky-5C7GfCeVMHo@public.gmane.org> wrote:
>>>>
>>>> BOOT data (such as EFI related data) is not encyrpted when the system is
>>>> booted and needs to be accessed as non-encrypted.  Add support to the
>>>> early_memremap API to identify the type of data being accessed so that
>>>> the proper encryption attribute can be applied.  Currently, two types
>>>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>>
>>> What happens when you memremap boot services data outside of early
>>> boot?  Matt just added code that does this.
>>>
>>> IMO this API is not so great.  It scatters a specialized consideration
>>> all over the place.  Could early_memremap not look up the PA to figure
>>> out what to do?
>>
>> Yes, I could see if the PA falls outside of the kernel usable area and,
>> if so, remove the memory encryption attribute from the mapping (for both
>> early_memremap and memremap).
>>
>> Let me look into that, I would prefer something along that line over
>> this change.
> 
> So, the last time we talked about using the address to figure out
> whether to encrypt/decrypt you said,
> 
>  "I looked into this and this would be a large change also to parse
>   tables and build lists."
> 
> Has something changed that makes this approach easier?

The original idea of parsing the tables and building a list was
a large change.  This approach would be simpler by just checking if
the PA is outside the kernel usable area, and if so, removing the
encryption bit.

> 
> And again, you need to be careful with the EFI kexec code paths, since
> you've got a mixture of boot and kernel data being passed. In
> particular the EFI memory map is allocated by the firmware on first
> boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).
> 
> That's one of the reasons I suggested requiring the caller to decide
> on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
> distinction isn't easily made.

Yeah, for kexec I think I'll need to make sure that everything looks
like it came from the BIOS/UEFI/bootloader.  If all of the kexec
pieces are allocated with un-encrypted memory, then the boot path
should remain the same.  That's the piece I need to investigate
further.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear
@ 2016-09-15 16:52           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:52 UTC (permalink / raw)
  To: Matt Fleming
  Cc: Andy Lutomirski, kasan-dev, linux-efi, linux-arch,
	Thomas Gleixner, Paolo Bonzini, Ingo Molnar, Borislav Petkov,
	iommu, linux-doc, Jonathan Corbet, Radim Krčmář,
	Konrad Rzeszutek Wilk, linux-mm, Alexander Potapenko,
	linux-kernel, Dmitry Vyukov, Arnd Bergmann, Joerg Roedel,
	Andrey Ryabinin, H. Peter Anvin, X86 ML, kvm list, Dave Young

On 09/15/2016 04:57 AM, Matt Fleming wrote:
> On Wed, 14 Sep, at 09:20:44AM, Tom Lendacky wrote:
>> On 09/12/2016 11:55 AM, Andy Lutomirski wrote:
>>> On Aug 22, 2016 6:53 PM, "Tom Lendacky" <thomas.lendacky@amd.com> wrote:
>>>>
>>>> BOOT data (such as EFI related data) is not encyrpted when the system is
>>>> booted and needs to be accessed as non-encrypted.  Add support to the
>>>> early_memremap API to identify the type of data being accessed so that
>>>> the proper encryption attribute can be applied.  Currently, two types
>>>> of data are defined, KERNEL_DATA and BOOT_DATA.
>>>
>>> What happens when you memremap boot services data outside of early
>>> boot?  Matt just added code that does this.
>>>
>>> IMO this API is not so great.  It scatters a specialized consideration
>>> all over the place.  Could early_memremap not look up the PA to figure
>>> out what to do?
>>
>> Yes, I could see if the PA falls outside of the kernel usable area and,
>> if so, remove the memory encryption attribute from the mapping (for both
>> early_memremap and memremap).
>>
>> Let me look into that, I would prefer something along that line over
>> this change.
> 
> So, the last time we talked about using the address to figure out
> whether to encrypt/decrypt you said,
> 
>  "I looked into this and this would be a large change also to parse
>   tables and build lists."
> 
> Has something changed that makes this approach easier?

The original idea of parsing the tables and building a list was
a large change.  This approach would be simpler by just checking if
the PA is outside the kernel usable area, and if so, removing the
encryption bit.

> 
> And again, you need to be careful with the EFI kexec code paths, since
> you've got a mixture of boot and kernel data being passed. In
> particular the EFI memory map is allocated by the firmware on first
> boot (BOOT_DATA) but by the kernel on kexec (KERNEL_DATA).
> 
> That's one of the reasons I suggested requiring the caller to decide
> on BOOT_DATA vs KERNEL_DATA - when you start looking at kexec the
> distinction isn't easily made.

Yeah, for kexec I think I'll need to make sure that everything looks
like it came from the BIOS/UEFI/bootloader.  If all of the kexec
pieces are allocated with un-encrypted memory, then the boot path
should remain the same.  That's the piece I need to investigate
further.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-15 16:57           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:57 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/14/2016 09:41 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 08:45:44AM -0500, Tom Lendacky wrote:
>> Currently, mem_encrypt.h only lives in the arch/x86 directory so it
>> wouldn't be able to be included here without breaking other archs.
> 
> I'm wondering if it would be simpler to move only sme_me_mask to an
> arch-agnostic header just so that we save us all the code duplication.
> 
> Hmmm.

If I do that, then I could put an #ifdef in the header to include the
asm/mem_encrypt.h if the memory encryption is configured, else set the
value to zero.  I'll look into this.  One immediate question becomes do
we keep the name very specific vs. making it more generic, sme_me_mask
vs me_mask, etc.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-15 16:57           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:57 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/14/2016 09:41 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 08:45:44AM -0500, Tom Lendacky wrote:
>> Currently, mem_encrypt.h only lives in the arch/x86 directory so it
>> wouldn't be able to be included here without breaking other archs.
> 
> I'm wondering if it would be simpler to move only sme_me_mask to an
> arch-agnostic header just so that we save us all the code duplication.
> 
> Hmmm.

If I do that, then I could put an #ifdef in the header to include the
asm/mem_encrypt.h if the memory encryption is configured, else set the
value to zero.  I'll look into this.  One immediate question becomes do
we keep the name very specific vs. making it more generic, sme_me_mask
vs me_mask, etc.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-15 16:57           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 16:57 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/14/2016 09:41 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 08:45:44AM -0500, Tom Lendacky wrote:
>> Currently, mem_encrypt.h only lives in the arch/x86 directory so it
>> wouldn't be able to be included here without breaking other archs.
> 
> I'm wondering if it would be simpler to move only sme_me_mask to an
> arch-agnostic header just so that we save us all the code duplication.
> 
> Hmmm.

If I do that, then I could put an #ifdef in the header to include the
asm/mem_encrypt.h if the memory encryption is configured, else set the
value to zero.  I'll look into this.  One immediate question becomes do
we keep the name very specific vs. making it more generic, sme_me_mask
vs me_mask, etc.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-15 17:08           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 17:08 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/14/2016 09:51 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 09:29:41AM -0500, Tom Lendacky wrote:
>> This is still required because just using the __va() would still cause
>> the mapping created to have the encryption bit set. The ioremap call
>> will result in the mapping not having the encryption bit set.
> 
> I meant this: https://lkml.kernel.org/r/20160902181447.GA25328@nazgul.tnic
> 
> Wouldn't simply clearing the SME mask work?
> 
> #define __va(x)			((void *)(((unsigned long)(x)+PAGE_OFFSET) & ~sme_me_mask))
> 
> Or are you saying, one needs the whole noodling through ioremap_cache()
> because the data is already encrypted and accessing it with sme_me_mask
> cleared would simply give you the encrypted garbage?

The problem is that this physical address does not contain the
encryption bit, and even if it did, it wouldn't matter.  The __va()
define creates a virtual address that will be mapped as encrypted given
the current approach (which is how I found this).  It's only ioremap()
that would create a mapping without the encryption attribute and since
this is unencrypted data it needs to be access accordingly.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-15 17:08           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 17:08 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On 09/14/2016 09:51 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 09:29:41AM -0500, Tom Lendacky wrote:
>> This is still required because just using the __va() would still cause
>> the mapping created to have the encryption bit set. The ioremap call
>> will result in the mapping not having the encryption bit set.
> 
> I meant this: https://lkml.kernel.org/r/20160902181447.GA25328-K5JNixvcfoxupOikMc4+xw@public.gmane.org
> 
> Wouldn't simply clearing the SME mask work?
> 
> #define __va(x)			((void *)(((unsigned long)(x)+PAGE_OFFSET) & ~sme_me_mask))
> 
> Or are you saying, one needs the whole noodling through ioremap_cache()
> because the data is already encrypted and accessing it with sme_me_mask
> cleared would simply give you the encrypted garbage?

The problem is that this physical address does not contain the
encryption bit, and even if it did, it wouldn't matter.  The __va()
define creates a virtual address that will be mapped as encrypted given
the current approach (which is how I found this).  It's only ioremap()
that would create a mapping without the encryption attribute and since
this is unencrypted data it needs to be access accordingly.

Thanks,
Tom

> 

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-15 17:08           ` Tom Lendacky
  0 siblings, 0 replies; 229+ messages in thread
From: Tom Lendacky @ 2016-09-15 17:08 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On 09/14/2016 09:51 AM, Borislav Petkov wrote:
> On Wed, Sep 14, 2016 at 09:29:41AM -0500, Tom Lendacky wrote:
>> This is still required because just using the __va() would still cause
>> the mapping created to have the encryption bit set. The ioremap call
>> will result in the mapping not having the encryption bit set.
> 
> I meant this: https://lkml.kernel.org/r/20160902181447.GA25328@nazgul.tnic
> 
> Wouldn't simply clearing the SME mask work?
> 
> #define __va(x)			((void *)(((unsigned long)(x)+PAGE_OFFSET) & ~sme_me_mask))
> 
> Or are you saying, one needs the whole noodling through ioremap_cache()
> because the data is already encrypted and accessing it with sme_me_mask
> cleared would simply give you the encrypted garbage?

The problem is that this physical address does not contain the
encryption bit, and even if it did, it wouldn't matter.  The __va()
define creates a virtual address that will be mapped as encrypted given
the current approach (which is how I found this).  It's only ioremap()
that would create a mapping without the encryption attribute and since
this is unencrypted data it needs to be access accordingly.

Thanks,
Tom

> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-16  7:08             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-16  7:08 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Thu, Sep 15, 2016 at 11:57:41AM -0500, Tom Lendacky wrote:
> If I do that, then I could put an #ifdef in the header to include the
> asm/mem_encrypt.h if the memory encryption is configured, else set the
> value to zero.

Yeah, something along those lines...

> I'll look into this. One immediate question becomes do we keep the
> name very specific vs. making it more generic, sme_me_mask vs me_mask,
> etc.

No strong opinion either way from me. My angle is that whatever it is,
we can always rename it later if we decide to.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU support for memory encryption
@ 2016-09-16  7:08             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-16  7:08 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Thu, Sep 15, 2016 at 11:57:41AM -0500, Tom Lendacky wrote:
> If I do that, then I could put an #ifdef in the header to include the
> asm/mem_encrypt.h if the memory encryption is configured, else set the
> value to zero.

Yeah, something along those lines...

> I'll look into this. One immediate question becomes do we keep the
> name very specific vs. making it more generic, sme_me_mask vs me_mask,
> etc.

No strong opinion either way from me. My angle is that whatever it is,
we can always rename it later if we decide to.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-16  7:11             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-16  7:11 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
	kasan-dev, linux-mm, iommu, Radim Krčmář,
	Arnd Bergmann, Jonathan Corbet, Matt Fleming, Joerg Roedel,
	Konrad Rzeszutek Wilk, Andrey Ryabinin, Ingo Molnar,
	Andy Lutomirski, H. Peter Anvin, Paolo Bonzini,
	Alexander Potapenko, Thomas Gleixner, Dmitry Vyukov

On Thu, Sep 15, 2016 at 12:08:04PM -0500, Tom Lendacky wrote:
> The problem is that this physical address does not contain the
> encryption bit, and even if it did, it wouldn't matter.  The __va()
> define creates a virtual address that will be mapped as encrypted given
> the current approach (which is how I found this).  It's only ioremap()
> that would create a mapping without the encryption attribute and since
> this is unencrypted data it needs to be access accordingly.

I see. So since this is not obvious, please add this explanation to maybe

Documentation/x86/amd-memory-encryption.txt

and point in there to an example or so so.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

* Re: [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted
@ 2016-09-16  7:11             ` Borislav Petkov
  0 siblings, 0 replies; 229+ messages in thread
From: Borislav Petkov @ 2016-09-16  7:11 UTC (permalink / raw)
  To: Tom Lendacky
  Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, kvm-u79uwXL29TY76Z2rM5mHXA,
	Radim Krčmář,
	Matt Fleming, x86-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg, Alexander Potapenko,
	H. Peter Anvin, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Jonathan Corbet, linux-doc-u79uwXL29TY76Z2rM5mHXA,
	kasan-dev-/JYPxA39Uh5TLH3MbocFFw, Ingo Molnar, Andrey Ryabinin,
	Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Dmitry Vyukov,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Paolo Bonzini

On Thu, Sep 15, 2016 at 12:08:04PM -0500, Tom Lendacky wrote:
> The problem is that this physical address does not contain the
> encryption bit, and even if it did, it wouldn't matter.  The __va()
> define creates a virtual address that will be mapped as encrypted given
> the current approach (which is how I found this).  It's only ioremap()
> that would create a mapping without the encryption attribute and since
> this is unencrypted data it needs to be access accordingly.

I see. So since this is not obvious, please add this explanation to maybe

Documentation/x86/amd-memory-encryption.txt

and point in there to an example or so so.

Thanks.

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 229+ messages in thread

end of thread, other threads:[~2016-09-16  7:12 UTC | newest]

Thread overview: 229+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-22 22:35 [RFC PATCH v2 00/20] x86: Secure Memory Encryption (AMD) Tom Lendacky
2016-08-22 22:35 ` Tom Lendacky
2016-08-22 22:35 ` Tom Lendacky
2016-08-22 22:35 ` Tom Lendacky
2016-08-22 22:35 ` [RFC PATCH v2 01/20] x86: Documentation for AMD Secure Memory Encryption (SME) Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-09-02  8:50   ` Borislav Petkov
2016-09-02  8:50     ` Borislav Petkov
2016-09-07 14:02     ` Tom Lendacky
2016-09-07 14:02       ` Tom Lendacky
2016-09-07 14:02       ` Tom Lendacky
2016-09-07 15:23       ` Borislav Petkov
2016-09-07 15:23         ` Borislav Petkov
2016-08-22 22:35 ` [RFC PATCH v2 02/20] x86: Set the write-protect cache mode for full PAT support Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-25  3:58   ` Borislav Petkov
2016-08-25  3:58     ` Borislav Petkov
2016-08-22 22:35 ` [RFC PATCH v2 03/20] x86: Secure Memory Encryption (SME) build enablement Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-08-22 22:35   ` Tom Lendacky
2016-09-02 11:03   ` Borislav Petkov
2016-09-02 11:03     ` Borislav Petkov
2016-09-07 14:03     ` Tom Lendacky
2016-09-07 14:03       ` Tom Lendacky
2016-08-22 22:36 ` [RFC PATCH v2 04/20] x86: Secure Memory Encryption (SME) support Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-25 13:04   ` Thomas Gleixner
2016-08-25 13:04     ` Thomas Gleixner
2016-08-30 13:19     ` Tom Lendacky
2016-08-30 13:19       ` Tom Lendacky
2016-08-30 14:57       ` Andy Lutomirski
2016-08-30 14:57         ` Andy Lutomirski
2016-08-30 14:57         ` Andy Lutomirski
2016-08-31 13:26         ` Tom Lendacky
2016-08-31 13:26           ` Tom Lendacky
2016-08-31 13:26           ` Tom Lendacky
2016-08-22 22:36 ` [RFC PATCH v2 05/20] x86: Add the Secure Memory Encryption cpu feature Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-09-02 14:09   ` Borislav Petkov
2016-09-02 14:09     ` Borislav Petkov
2016-09-07 14:07     ` Tom Lendacky
2016-09-07 14:07       ` Tom Lendacky
2016-08-22 22:36 ` [RFC PATCH v2 06/20] x86: Handle reduction in physical address size with SME Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36 ` [RFC PATCH v2 07/20] x86: Provide general kernel support for memory encryption Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-08-22 22:36   ` Tom Lendacky
2016-09-02 18:14   ` Borislav Petkov
2016-09-02 18:14     ` Borislav Petkov
2016-09-07 14:11     ` Tom Lendacky
2016-09-07 14:11       ` Tom Lendacky
2016-09-05  8:48   ` Borislav Petkov
2016-09-05  8:48     ` Borislav Petkov
2016-09-07 14:16     ` Tom Lendacky
2016-09-07 14:16       ` Tom Lendacky
2016-09-05 15:22   ` Borislav Petkov
2016-09-05 15:22     ` Borislav Petkov
2016-09-07 14:19     ` Tom Lendacky
2016-09-07 14:19       ` Tom Lendacky
2016-09-07 14:19       ` Tom Lendacky
2016-09-06  9:31   ` Borislav Petkov
2016-09-06  9:31     ` Borislav Petkov
2016-09-07 14:30     ` Tom Lendacky
2016-09-07 14:30       ` Tom Lendacky
2016-09-07 14:30       ` Tom Lendacky
2016-09-07 15:55       ` Borislav Petkov
2016-09-07 15:55         ` Borislav Petkov
2016-09-08 13:26         ` Tom Lendacky
2016-09-08 13:26           ` Tom Lendacky
2016-09-08 13:26           ` Tom Lendacky
2016-09-08 13:55           ` Borislav Petkov
2016-09-08 13:55             ` Borislav Petkov
2016-09-12 13:43             ` Tom Lendacky
2016-09-12 13:43               ` Tom Lendacky
2016-08-22 22:37 ` [RFC PATCH v2 08/20] x86: Extend the early_memmap support with additional attrs Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37 ` [RFC PATCH v2 09/20] x86: Add support for early encryption/decryption of memory Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-09-06 16:12   ` Borislav Petkov
2016-09-06 16:12     ` Borislav Petkov
2016-08-22 22:37 ` [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-09-09 15:53   ` Borislav Petkov
2016-09-09 15:53     ` Borislav Petkov
2016-09-12 15:05     ` Tom Lendacky
2016-09-12 15:05       ` Tom Lendacky
2016-09-12 15:05       ` Tom Lendacky
2016-09-12 16:33       ` Borislav Petkov
2016-09-12 16:33         ` Borislav Petkov
2016-09-14 14:11         ` Tom Lendacky
2016-09-14 14:11           ` Tom Lendacky
2016-09-14 14:11           ` Tom Lendacky
2016-08-22 22:37 ` [RFC PATCH v2 11/20] mm: Access BOOT related data in the clear Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-09-09 16:38   ` Borislav Petkov
2016-09-09 16:38     ` Borislav Petkov
2016-09-12 15:14     ` Tom Lendacky
2016-09-12 15:14       ` Tom Lendacky
2016-09-12 15:14       ` Tom Lendacky
2016-09-12 16:35       ` Borislav Petkov
2016-09-12 16:35         ` Borislav Petkov
2016-09-12 16:55   ` Andy Lutomirski
2016-09-12 16:55     ` Andy Lutomirski
2016-09-12 16:55     ` Andy Lutomirski
2016-09-14 14:20     ` Tom Lendacky
2016-09-14 14:20       ` Tom Lendacky
2016-09-14 14:20       ` Tom Lendacky
2016-09-15  9:57       ` Matt Fleming
2016-09-15  9:57         ` Matt Fleming
2016-09-15  9:57         ` Matt Fleming
2016-09-15 16:52         ` Tom Lendacky
2016-09-15 16:52           ` Tom Lendacky
2016-09-15 16:52           ` Tom Lendacky
2016-08-22 22:37 ` [RFC PATCH v2 12/20] x86: Add support for changing memory encryption attribute Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-09-09 17:23   ` Borislav Petkov
2016-09-09 17:23     ` Borislav Petkov
2016-09-12 15:41     ` Tom Lendacky
2016-09-12 15:41       ` Tom Lendacky
2016-09-12 15:41       ` Tom Lendacky
2016-09-12 16:41       ` Borislav Petkov
2016-09-12 16:41         ` Borislav Petkov
2016-08-22 22:37 ` [RFC PATCH v2 13/20] x86: Decrypt trampoline area if memory encryption is active Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-08-22 22:37   ` Tom Lendacky
2016-09-09 17:34   ` Borislav Petkov
2016-09-09 17:34     ` Borislav Petkov
2016-09-12 15:43     ` Tom Lendacky
2016-09-12 15:43       ` Tom Lendacky
2016-08-22 22:38 ` [RFC PATCH v2 14/20] x86: DMA support for memory encryption Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-09-12 10:58   ` Borislav Petkov
2016-09-12 10:58     ` Borislav Petkov
2016-09-14 13:36     ` Tom Lendacky
2016-09-14 13:36       ` Tom Lendacky
2016-09-14 13:36       ` Tom Lendacky
2016-08-22 22:38 ` [RFC PATCH v2 15/20] iommu/amd: AMD IOMMU " Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-09-12 11:45   ` Borislav Petkov
2016-09-12 11:45     ` Borislav Petkov
2016-09-14 13:45     ` Tom Lendacky
2016-09-14 13:45       ` Tom Lendacky
2016-09-14 13:45       ` Tom Lendacky
2016-09-14 14:41       ` Borislav Petkov
2016-09-14 14:41         ` Borislav Petkov
2016-09-15 16:57         ` Tom Lendacky
2016-09-15 16:57           ` Tom Lendacky
2016-09-15 16:57           ` Tom Lendacky
2016-09-16  7:08           ` Borislav Petkov
2016-09-16  7:08             ` Borislav Petkov
2016-08-22 22:38 ` [RFC PATCH v2 16/20] x86: Check for memory encryption on the APs Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-09-12 12:17   ` Borislav Petkov
2016-09-12 12:17     ` Borislav Petkov
2016-09-14 13:50     ` Tom Lendacky
2016-09-14 13:50       ` Tom Lendacky
2016-09-12 16:43   ` Borislav Petkov
2016-09-12 16:43     ` Borislav Petkov
2016-09-14 14:12     ` Tom Lendacky
2016-09-14 14:12       ` Tom Lendacky
2016-09-14 14:12       ` Tom Lendacky
2016-08-22 22:38 ` [RFC PATCH v2 17/20] x86: Do not specify encrypted memory for VGA mapping Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38 ` [RFC PATCH v2 18/20] x86/kvm: Enable Secure Memory Encryption of nested page tables Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-09-12 14:35   ` Borislav Petkov
2016-09-12 14:35     ` Borislav Petkov
2016-09-14 14:02     ` Tom Lendacky
2016-09-14 14:02       ` Tom Lendacky
2016-08-22 22:38 ` [RFC PATCH v2 19/20] x86: Access the setup data through debugfs un-encrypted Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-08-22 22:38   ` Tom Lendacky
2016-09-12 16:59   ` Borislav Petkov
2016-09-12 16:59     ` Borislav Petkov
2016-09-14 14:29     ` Tom Lendacky
2016-09-14 14:29       ` Tom Lendacky
2016-09-14 14:29       ` Tom Lendacky
2016-09-14 14:51       ` Borislav Petkov
2016-09-14 14:51         ` Borislav Petkov
2016-09-15 17:08         ` Tom Lendacky
2016-09-15 17:08           ` Tom Lendacky
2016-09-15 17:08           ` Tom Lendacky
2016-09-16  7:11           ` Borislav Petkov
2016-09-16  7:11             ` Borislav Petkov
2016-08-22 22:39 ` [RFC PATCH v2 20/20] x86: Add support to make use of Secure Memory Encryption Tom Lendacky
2016-08-22 22:39   ` Tom Lendacky
2016-08-22 22:39   ` Tom Lendacky
2016-08-22 22:39   ` Tom Lendacky
2016-09-12 17:08   ` Borislav Petkov
2016-09-12 17:08     ` Borislav Petkov
2016-09-14 14:31     ` Tom Lendacky
2016-09-14 14:31       ` Tom Lendacky

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.