Re: [PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-28 Thread Brijesh Singh




On 08/27/2018 05:11 PM, Tom Lendacky wrote:

On 08/27/2018 06:24 AM, Brijesh Singh wrote:

kvmclock defines few static variables which are shared with hypervisor
during the kvmclock initialization.

When SEV is active, memory is encrypted with a guest-specific key, and
if guest OS wants to share the memory region with hypervisor then it must
clear the C-bit before sharing it.

The '__decrypted' can be used to define a shared variables; the variables
will be put in the .data.decryption section. This section is mapped with
C=0 early in the boot, we also ensure that the initialized values are
updated to match with C=0 (i.e peform an in-place decryption). The
.data..decrypted section is PMD aligned and sized so that we avoid the
need for spliting the pages when map with C=0.


This should probably be broken into a few smaller patches.  Maybe a
patch that adds the section and the attribute, a patch that re-arranges
the mapping setup and then the in-place decryption and clearing of the
encryption bit for the area.




OK, I will break the patch. Probably will create a separate patch which
just re-arranges the mapping setup without making any logical changes.




Signed-off-by: Brijesh Singh 
Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
Cc: sta...@vger.kernel.org
Cc: Tom Lendacky 
Cc: k...@vger.kernel.org
Cc: Thomas Gleixner 
Cc: Borislav Petkov 
Cc: "H. Peter Anvin" 
Cc: linux-kernel@vger.kernel.org
Cc: Paolo Bonzini 
Cc: Sean Christopherson 
Cc: "Radim Krčmář" 
---
  arch/x86/include/asm/mem_encrypt.h |   4 +
  arch/x86/kernel/head64.c   |  12 ++
  arch/x86/kernel/vmlinux.lds.S  |  18 +++
  arch/x86/mm/mem_encrypt_identity.c | 220 +++--
  4 files changed, 197 insertions(+), 57 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h 
b/arch/x86/include/asm/mem_encrypt.h
index c064383..3f7d9d3 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
  bool sme_active(void);
  bool sev_active(void);
  
+#define __decrypted __attribute__((__section__(".data..decrypted")))

+
  #else /* !CONFIG_AMD_MEM_ENCRYPT */
  
  #define sme_me_mask	0ULL

@@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned long 
size) { return 0;
  static inline int __init
  early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
0; }
  
+#define __decrypted

+
  #endif/* CONFIG_AMD_MEM_ENCRYPT */
  
  /*

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 8047379..6a18297 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -43,6 +43,9 @@ extern pmd_t 
early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
  static unsigned int __initdata next_early_pgt;
  pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
  
+/* To clear memory encryption mask from the decrypted section */

+extern char __start_data_decrypted[], __end_data_decrypted[];
+


Should find a header for these rather than defining them here.



OK, will move then in mem_encrypt.h. Will that work ?



  #ifdef CONFIG_X86_5LEVEL
  unsigned int __pgtable_l5_enabled __ro_after_init;
  unsigned int pgdir_shift __ro_after_init = 39;
@@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
physaddr)
  unsigned long __head __startup_64(unsigned long physaddr,
  struct boot_params *bp)
  {
+   unsigned long vaddr, vaddr_end;
unsigned long load_delta, *p;
unsigned long pgtable_flags;
pgdval_t *pgd;
@@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Encrypt the kernel and related (if SME is active) */
sme_encrypt_kernel(bp);
  
+	/* Clear the memory encryption mask from the decrypted section */

+   vaddr = (unsigned long)__start_data_decrypted;
+   vaddr_end = (unsigned long)__end_data_decrypted;
+   for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
+   i = pmd_index(vaddr);
+   pmd[i] -= sme_get_me_mask();
+   }
+
/*
 * Return the SME encryption mask (if SME is active) to be used as a
 * modifier for the initial pgdir entry programmed into CR3.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 8bde0a4..511b875 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -89,6 +89,22 @@ PHDRS {
note PT_NOTE FLAGS(0);  /* ___ */
  }
  
+/*

+ * This section contains data which will be mapped as decrypted. Memory
+ * encryption operates on a page basis. But we make this section a pmd
+ * aligned to avoid spliting the pages while mapping the section early.
+ *
+ * Note: We use a separate section so that only this section gets
+ * decrypted to avoid exposing more than we wish.
+ */
+#define DATA_DECRYPTED_SECTION \
+   . = 

Re: [PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-28 Thread Brijesh Singh




On 08/27/2018 05:11 PM, Tom Lendacky wrote:

On 08/27/2018 06:24 AM, Brijesh Singh wrote:

kvmclock defines few static variables which are shared with hypervisor
during the kvmclock initialization.

When SEV is active, memory is encrypted with a guest-specific key, and
if guest OS wants to share the memory region with hypervisor then it must
clear the C-bit before sharing it.

The '__decrypted' can be used to define a shared variables; the variables
will be put in the .data.decryption section. This section is mapped with
C=0 early in the boot, we also ensure that the initialized values are
updated to match with C=0 (i.e peform an in-place decryption). The
.data..decrypted section is PMD aligned and sized so that we avoid the
need for spliting the pages when map with C=0.


This should probably be broken into a few smaller patches.  Maybe a
patch that adds the section and the attribute, a patch that re-arranges
the mapping setup and then the in-place decryption and clearing of the
encryption bit for the area.




OK, I will break the patch. Probably will create a separate patch which
just re-arranges the mapping setup without making any logical changes.




Signed-off-by: Brijesh Singh 
Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
Cc: sta...@vger.kernel.org
Cc: Tom Lendacky 
Cc: k...@vger.kernel.org
Cc: Thomas Gleixner 
Cc: Borislav Petkov 
Cc: "H. Peter Anvin" 
Cc: linux-kernel@vger.kernel.org
Cc: Paolo Bonzini 
Cc: Sean Christopherson 
Cc: "Radim Krčmář" 
---
  arch/x86/include/asm/mem_encrypt.h |   4 +
  arch/x86/kernel/head64.c   |  12 ++
  arch/x86/kernel/vmlinux.lds.S  |  18 +++
  arch/x86/mm/mem_encrypt_identity.c | 220 +++--
  4 files changed, 197 insertions(+), 57 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h 
b/arch/x86/include/asm/mem_encrypt.h
index c064383..3f7d9d3 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
  bool sme_active(void);
  bool sev_active(void);
  
+#define __decrypted __attribute__((__section__(".data..decrypted")))

+
  #else /* !CONFIG_AMD_MEM_ENCRYPT */
  
  #define sme_me_mask	0ULL

@@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned long 
size) { return 0;
  static inline int __init
  early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
0; }
  
+#define __decrypted

+
  #endif/* CONFIG_AMD_MEM_ENCRYPT */
  
  /*

diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 8047379..6a18297 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -43,6 +43,9 @@ extern pmd_t 
early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
  static unsigned int __initdata next_early_pgt;
  pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
  
+/* To clear memory encryption mask from the decrypted section */

+extern char __start_data_decrypted[], __end_data_decrypted[];
+


Should find a header for these rather than defining them here.



OK, will move then in mem_encrypt.h. Will that work ?



  #ifdef CONFIG_X86_5LEVEL
  unsigned int __pgtable_l5_enabled __ro_after_init;
  unsigned int pgdir_shift __ro_after_init = 39;
@@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
physaddr)
  unsigned long __head __startup_64(unsigned long physaddr,
  struct boot_params *bp)
  {
+   unsigned long vaddr, vaddr_end;
unsigned long load_delta, *p;
unsigned long pgtable_flags;
pgdval_t *pgd;
@@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Encrypt the kernel and related (if SME is active) */
sme_encrypt_kernel(bp);
  
+	/* Clear the memory encryption mask from the decrypted section */

+   vaddr = (unsigned long)__start_data_decrypted;
+   vaddr_end = (unsigned long)__end_data_decrypted;
+   for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
+   i = pmd_index(vaddr);
+   pmd[i] -= sme_get_me_mask();
+   }
+
/*
 * Return the SME encryption mask (if SME is active) to be used as a
 * modifier for the initial pgdir entry programmed into CR3.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 8bde0a4..511b875 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -89,6 +89,22 @@ PHDRS {
note PT_NOTE FLAGS(0);  /* ___ */
  }
  
+/*

+ * This section contains data which will be mapped as decrypted. Memory
+ * encryption operates on a page basis. But we make this section a pmd
+ * aligned to avoid spliting the pages while mapping the section early.
+ *
+ * Note: We use a separate section so that only this section gets
+ * decrypted to avoid exposing more than we wish.
+ */
+#define DATA_DECRYPTED_SECTION \
+   . = 

Re: [PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-27 Thread Tom Lendacky
On 08/27/2018 06:24 AM, Brijesh Singh wrote:
> kvmclock defines few static variables which are shared with hypervisor
> during the kvmclock initialization.
> 
> When SEV is active, memory is encrypted with a guest-specific key, and
> if guest OS wants to share the memory region with hypervisor then it must
> clear the C-bit before sharing it.
> 
> The '__decrypted' can be used to define a shared variables; the variables
> will be put in the .data.decryption section. This section is mapped with
> C=0 early in the boot, we also ensure that the initialized values are
> updated to match with C=0 (i.e peform an in-place decryption). The
> .data..decrypted section is PMD aligned and sized so that we avoid the
> need for spliting the pages when map with C=0.

This should probably be broken into a few smaller patches.  Maybe a
patch that adds the section and the attribute, a patch that re-arranges
the mapping setup and then the in-place decryption and clearing of the
encryption bit for the area.

> 
> Signed-off-by: Brijesh Singh 
> Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
> Cc: sta...@vger.kernel.org
> Cc: Tom Lendacky 
> Cc: k...@vger.kernel.org
> Cc: Thomas Gleixner 
> Cc: Borislav Petkov 
> Cc: "H. Peter Anvin" 
> Cc: linux-kernel@vger.kernel.org
> Cc: Paolo Bonzini 
> Cc: Sean Christopherson 
> Cc: "Radim Krčmář" 
> ---
>  arch/x86/include/asm/mem_encrypt.h |   4 +
>  arch/x86/kernel/head64.c   |  12 ++
>  arch/x86/kernel/vmlinux.lds.S  |  18 +++
>  arch/x86/mm/mem_encrypt_identity.c | 220 
> +++--
>  4 files changed, 197 insertions(+), 57 deletions(-)
> 
> diff --git a/arch/x86/include/asm/mem_encrypt.h 
> b/arch/x86/include/asm/mem_encrypt.h
> index c064383..3f7d9d3 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
>  bool sme_active(void);
>  bool sev_active(void);
>  
> +#define __decrypted __attribute__((__section__(".data..decrypted")))
> +
>  #else/* !CONFIG_AMD_MEM_ENCRYPT */
>  
>  #define sme_me_mask  0ULL
> @@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned 
> long size) { return 0;
>  static inline int __init
>  early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
> 0; }
>  
> +#define __decrypted
> +
>  #endif   /* CONFIG_AMD_MEM_ENCRYPT */
>  
>  /*
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 8047379..6a18297 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -43,6 +43,9 @@ extern pmd_t 
> early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
>  static unsigned int __initdata next_early_pgt;
>  pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
>  
> +/* To clear memory encryption mask from the decrypted section */
> +extern char __start_data_decrypted[], __end_data_decrypted[];
> +

Should find a header for these rather than defining them here.

>  #ifdef CONFIG_X86_5LEVEL
>  unsigned int __pgtable_l5_enabled __ro_after_init;
>  unsigned int pgdir_shift __ro_after_init = 39;
> @@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
> physaddr)
>  unsigned long __head __startup_64(unsigned long physaddr,
> struct boot_params *bp)
>  {
> + unsigned long vaddr, vaddr_end;
>   unsigned long load_delta, *p;
>   unsigned long pgtable_flags;
>   pgdval_t *pgd;
> @@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
>   /* Encrypt the kernel and related (if SME is active) */
>   sme_encrypt_kernel(bp);
>  
> + /* Clear the memory encryption mask from the decrypted section */
> + vaddr = (unsigned long)__start_data_decrypted;
> + vaddr_end = (unsigned long)__end_data_decrypted;
> + for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
> + i = pmd_index(vaddr);
> + pmd[i] -= sme_get_me_mask();
> + }
> +
>   /*
>* Return the SME encryption mask (if SME is active) to be used as a
>* modifier for the initial pgdir entry programmed into CR3.
> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> index 8bde0a4..511b875 100644
> --- a/arch/x86/kernel/vmlinux.lds.S
> +++ b/arch/x86/kernel/vmlinux.lds.S
> @@ -89,6 +89,22 @@ PHDRS {
>   note PT_NOTE FLAGS(0);  /* ___ */
>  }
>  
> +/*
> + * This section contains data which will be mapped as decrypted. Memory
> + * encryption operates on a page basis. But we make this section a pmd
> + * aligned to avoid spliting the pages while mapping the section early.
> + *
> + * Note: We use a separate section so that only this section gets
> + * decrypted to avoid exposing more than we wish.
> + */
> +#define DATA_DECRYPTED_SECTION   
> \
> + . = ALIGN(PMD_SIZE);\
> + 

Re: [PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-27 Thread Tom Lendacky
On 08/27/2018 06:24 AM, Brijesh Singh wrote:
> kvmclock defines few static variables which are shared with hypervisor
> during the kvmclock initialization.
> 
> When SEV is active, memory is encrypted with a guest-specific key, and
> if guest OS wants to share the memory region with hypervisor then it must
> clear the C-bit before sharing it.
> 
> The '__decrypted' can be used to define a shared variables; the variables
> will be put in the .data.decryption section. This section is mapped with
> C=0 early in the boot, we also ensure that the initialized values are
> updated to match with C=0 (i.e peform an in-place decryption). The
> .data..decrypted section is PMD aligned and sized so that we avoid the
> need for spliting the pages when map with C=0.

This should probably be broken into a few smaller patches.  Maybe a
patch that adds the section and the attribute, a patch that re-arranges
the mapping setup and then the in-place decryption and clearing of the
encryption bit for the area.

> 
> Signed-off-by: Brijesh Singh 
> Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
> Cc: sta...@vger.kernel.org
> Cc: Tom Lendacky 
> Cc: k...@vger.kernel.org
> Cc: Thomas Gleixner 
> Cc: Borislav Petkov 
> Cc: "H. Peter Anvin" 
> Cc: linux-kernel@vger.kernel.org
> Cc: Paolo Bonzini 
> Cc: Sean Christopherson 
> Cc: "Radim Krčmář" 
> ---
>  arch/x86/include/asm/mem_encrypt.h |   4 +
>  arch/x86/kernel/head64.c   |  12 ++
>  arch/x86/kernel/vmlinux.lds.S  |  18 +++
>  arch/x86/mm/mem_encrypt_identity.c | 220 
> +++--
>  4 files changed, 197 insertions(+), 57 deletions(-)
> 
> diff --git a/arch/x86/include/asm/mem_encrypt.h 
> b/arch/x86/include/asm/mem_encrypt.h
> index c064383..3f7d9d3 100644
> --- a/arch/x86/include/asm/mem_encrypt.h
> +++ b/arch/x86/include/asm/mem_encrypt.h
> @@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
>  bool sme_active(void);
>  bool sev_active(void);
>  
> +#define __decrypted __attribute__((__section__(".data..decrypted")))
> +
>  #else/* !CONFIG_AMD_MEM_ENCRYPT */
>  
>  #define sme_me_mask  0ULL
> @@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned 
> long size) { return 0;
>  static inline int __init
>  early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
> 0; }
>  
> +#define __decrypted
> +
>  #endif   /* CONFIG_AMD_MEM_ENCRYPT */
>  
>  /*
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 8047379..6a18297 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -43,6 +43,9 @@ extern pmd_t 
> early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
>  static unsigned int __initdata next_early_pgt;
>  pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
>  
> +/* To clear memory encryption mask from the decrypted section */
> +extern char __start_data_decrypted[], __end_data_decrypted[];
> +

Should find a header for these rather than defining them here.

>  #ifdef CONFIG_X86_5LEVEL
>  unsigned int __pgtable_l5_enabled __ro_after_init;
>  unsigned int pgdir_shift __ro_after_init = 39;
> @@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
> physaddr)
>  unsigned long __head __startup_64(unsigned long physaddr,
> struct boot_params *bp)
>  {
> + unsigned long vaddr, vaddr_end;
>   unsigned long load_delta, *p;
>   unsigned long pgtable_flags;
>   pgdval_t *pgd;
> @@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
>   /* Encrypt the kernel and related (if SME is active) */
>   sme_encrypt_kernel(bp);
>  
> + /* Clear the memory encryption mask from the decrypted section */
> + vaddr = (unsigned long)__start_data_decrypted;
> + vaddr_end = (unsigned long)__end_data_decrypted;
> + for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
> + i = pmd_index(vaddr);
> + pmd[i] -= sme_get_me_mask();
> + }
> +
>   /*
>* Return the SME encryption mask (if SME is active) to be used as a
>* modifier for the initial pgdir entry programmed into CR3.
> diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
> index 8bde0a4..511b875 100644
> --- a/arch/x86/kernel/vmlinux.lds.S
> +++ b/arch/x86/kernel/vmlinux.lds.S
> @@ -89,6 +89,22 @@ PHDRS {
>   note PT_NOTE FLAGS(0);  /* ___ */
>  }
>  
> +/*
> + * This section contains data which will be mapped as decrypted. Memory
> + * encryption operates on a page basis. But we make this section a pmd
> + * aligned to avoid spliting the pages while mapping the section early.
> + *
> + * Note: We use a separate section so that only this section gets
> + * decrypted to avoid exposing more than we wish.
> + */
> +#define DATA_DECRYPTED_SECTION   
> \
> + . = ALIGN(PMD_SIZE);\
> + 

[PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-27 Thread Brijesh Singh
kvmclock defines few static variables which are shared with hypervisor
during the kvmclock initialization.

When SEV is active, memory is encrypted with a guest-specific key, and
if guest OS wants to share the memory region with hypervisor then it must
clear the C-bit before sharing it.

The '__decrypted' can be used to define a shared variables; the variables
will be put in the .data.decryption section. This section is mapped with
C=0 early in the boot, we also ensure that the initialized values are
updated to match with C=0 (i.e peform an in-place decryption). The
.data..decrypted section is PMD aligned and sized so that we avoid the
need for spliting the pages when map with C=0.

Signed-off-by: Brijesh Singh 
Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
Cc: sta...@vger.kernel.org
Cc: Tom Lendacky 
Cc: k...@vger.kernel.org
Cc: Thomas Gleixner 
Cc: Borislav Petkov 
Cc: "H. Peter Anvin" 
Cc: linux-kernel@vger.kernel.org
Cc: Paolo Bonzini 
Cc: Sean Christopherson 
Cc: "Radim Krčmář" 
---
 arch/x86/include/asm/mem_encrypt.h |   4 +
 arch/x86/kernel/head64.c   |  12 ++
 arch/x86/kernel/vmlinux.lds.S  |  18 +++
 arch/x86/mm/mem_encrypt_identity.c | 220 +++--
 4 files changed, 197 insertions(+), 57 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h 
b/arch/x86/include/asm/mem_encrypt.h
index c064383..3f7d9d3 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
 bool sme_active(void);
 bool sev_active(void);
 
+#define __decrypted __attribute__((__section__(".data..decrypted")))
+
 #else  /* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask0ULL
@@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned long 
size) { return 0;
 static inline int __init
 early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
0; }
 
+#define __decrypted
+
 #endif /* CONFIG_AMD_MEM_ENCRYPT */
 
 /*
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 8047379..6a18297 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -43,6 +43,9 @@ extern pmd_t 
early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
 static unsigned int __initdata next_early_pgt;
 pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
 
+/* To clear memory encryption mask from the decrypted section */
+extern char __start_data_decrypted[], __end_data_decrypted[];
+
 #ifdef CONFIG_X86_5LEVEL
 unsigned int __pgtable_l5_enabled __ro_after_init;
 unsigned int pgdir_shift __ro_after_init = 39;
@@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
physaddr)
 unsigned long __head __startup_64(unsigned long physaddr,
  struct boot_params *bp)
 {
+   unsigned long vaddr, vaddr_end;
unsigned long load_delta, *p;
unsigned long pgtable_flags;
pgdval_t *pgd;
@@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Encrypt the kernel and related (if SME is active) */
sme_encrypt_kernel(bp);
 
+   /* Clear the memory encryption mask from the decrypted section */
+   vaddr = (unsigned long)__start_data_decrypted;
+   vaddr_end = (unsigned long)__end_data_decrypted;
+   for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
+   i = pmd_index(vaddr);
+   pmd[i] -= sme_get_me_mask();
+   }
+
/*
 * Return the SME encryption mask (if SME is active) to be used as a
 * modifier for the initial pgdir entry programmed into CR3.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 8bde0a4..511b875 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -89,6 +89,22 @@ PHDRS {
note PT_NOTE FLAGS(0);  /* ___ */
 }
 
+/*
+ * This section contains data which will be mapped as decrypted. Memory
+ * encryption operates on a page basis. But we make this section a pmd
+ * aligned to avoid spliting the pages while mapping the section early.
+ *
+ * Note: We use a separate section so that only this section gets
+ * decrypted to avoid exposing more than we wish.
+ */
+#define DATA_DECRYPTED_SECTION \
+   . = ALIGN(PMD_SIZE);\
+   __start_data_decrypted = .; \
+   *(.data..decrypted);\
+   __end_data_decrypted = .;   \
+   . = ALIGN(PMD_SIZE);\
+
+
 SECTIONS
 {
 #ifdef CONFIG_X86_32
@@ -171,6 +187,8 @@ SECTIONS
/* rarely changed data like cpu maps */
READ_MOSTLY_DATA(INTERNODE_CACHE_BYTES)
 
+   DATA_DECRYPTED_SECTION
+
/* End of data section */
_edata = 

[PATCH 1/2] x86/mm: add .data..decrypted section to hold shared variables

2018-08-27 Thread Brijesh Singh
kvmclock defines few static variables which are shared with hypervisor
during the kvmclock initialization.

When SEV is active, memory is encrypted with a guest-specific key, and
if guest OS wants to share the memory region with hypervisor then it must
clear the C-bit before sharing it.

The '__decrypted' can be used to define a shared variables; the variables
will be put in the .data.decryption section. This section is mapped with
C=0 early in the boot, we also ensure that the initialized values are
updated to match with C=0 (i.e peform an in-place decryption). The
.data..decrypted section is PMD aligned and sized so that we avoid the
need for spliting the pages when map with C=0.

Signed-off-by: Brijesh Singh 
Fixes: 368a540e0232 ("x86/kvmclock: Remove memblock dependency")
Cc: sta...@vger.kernel.org
Cc: Tom Lendacky 
Cc: k...@vger.kernel.org
Cc: Thomas Gleixner 
Cc: Borislav Petkov 
Cc: "H. Peter Anvin" 
Cc: linux-kernel@vger.kernel.org
Cc: Paolo Bonzini 
Cc: Sean Christopherson 
Cc: "Radim Krčmář" 
---
 arch/x86/include/asm/mem_encrypt.h |   4 +
 arch/x86/kernel/head64.c   |  12 ++
 arch/x86/kernel/vmlinux.lds.S  |  18 +++
 arch/x86/mm/mem_encrypt_identity.c | 220 +++--
 4 files changed, 197 insertions(+), 57 deletions(-)

diff --git a/arch/x86/include/asm/mem_encrypt.h 
b/arch/x86/include/asm/mem_encrypt.h
index c064383..3f7d9d3 100644
--- a/arch/x86/include/asm/mem_encrypt.h
+++ b/arch/x86/include/asm/mem_encrypt.h
@@ -52,6 +52,8 @@ void __init mem_encrypt_init(void);
 bool sme_active(void);
 bool sev_active(void);
 
+#define __decrypted __attribute__((__section__(".data..decrypted")))
+
 #else  /* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask0ULL
@@ -77,6 +79,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned long 
size) { return 0;
 static inline int __init
 early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 
0; }
 
+#define __decrypted
+
 #endif /* CONFIG_AMD_MEM_ENCRYPT */
 
 /*
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 8047379..6a18297 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -43,6 +43,9 @@ extern pmd_t 
early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
 static unsigned int __initdata next_early_pgt;
 pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
 
+/* To clear memory encryption mask from the decrypted section */
+extern char __start_data_decrypted[], __end_data_decrypted[];
+
 #ifdef CONFIG_X86_5LEVEL
 unsigned int __pgtable_l5_enabled __ro_after_init;
 unsigned int pgdir_shift __ro_after_init = 39;
@@ -112,6 +115,7 @@ static bool __head check_la57_support(unsigned long 
physaddr)
 unsigned long __head __startup_64(unsigned long physaddr,
  struct boot_params *bp)
 {
+   unsigned long vaddr, vaddr_end;
unsigned long load_delta, *p;
unsigned long pgtable_flags;
pgdval_t *pgd;
@@ -234,6 +238,14 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Encrypt the kernel and related (if SME is active) */
sme_encrypt_kernel(bp);
 
+   /* Clear the memory encryption mask from the decrypted section */
+   vaddr = (unsigned long)__start_data_decrypted;
+   vaddr_end = (unsigned long)__end_data_decrypted;
+   for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
+   i = pmd_index(vaddr);
+   pmd[i] -= sme_get_me_mask();
+   }
+
/*
 * Return the SME encryption mask (if SME is active) to be used as a
 * modifier for the initial pgdir entry programmed into CR3.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 8bde0a4..511b875 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -89,6 +89,22 @@ PHDRS {
note PT_NOTE FLAGS(0);  /* ___ */
 }
 
+/*
+ * This section contains data which will be mapped as decrypted. Memory
+ * encryption operates on a page basis. But we make this section a pmd
+ * aligned to avoid spliting the pages while mapping the section early.
+ *
+ * Note: We use a separate section so that only this section gets
+ * decrypted to avoid exposing more than we wish.
+ */
+#define DATA_DECRYPTED_SECTION \
+   . = ALIGN(PMD_SIZE);\
+   __start_data_decrypted = .; \
+   *(.data..decrypted);\
+   __end_data_decrypted = .;   \
+   . = ALIGN(PMD_SIZE);\
+
+
 SECTIONS
 {
 #ifdef CONFIG_X86_32
@@ -171,6 +187,8 @@ SECTIONS
/* rarely changed data like cpu maps */
READ_MOSTLY_DATA(INTERNODE_CACHE_BYTES)
 
+   DATA_DECRYPTED_SECTION
+
/* End of data section */
_edata =