Message ID | f0ff967e2015a9dffceef22ac52ecd736a1ddb7e.1543903910.git.alison.schofield@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Multi-Key Total Memory Encryption API (MKTME) | expand |
On Mon, 2018-12-03 at 23:39 -0800, Alison Schofield wrote: > MKTME architecture requires the KeyID to be placed in PTE bits 51:46. > To create an encrypted VMA, place the KeyID in the upper bits of > vm_page_prot that matches the position of those PTE bits. > > When the VMA is assigned a KeyID it is always considered a KeyID > change. The VMA is either going from not encrypted to encrypted, > or from encrypted with any KeyID to encrypted with any other KeyID. > To make the change safely, remove the user pages held by the VMA > and unlink the VMA's anonymous chain. > > Change-Id: I676056525c49c8803898315a10b196ef5a5c5415 Remove. > Signed-off-by: Alison Schofield <alison.schofield@intel.com> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > arch/x86/include/asm/mktme.h | 4 ++++ > arch/x86/mm/mktme.c | 26 ++++++++++++++++++++++++++ > include/linux/mm.h | 6 ++++++ > 3 files changed, 36 insertions(+) > > diff --git a/arch/x86/include/asm/mktme.h b/arch/x86/include/asm/mktme.h > index dbb49909d665..de3e529f3ab0 100644 > --- a/arch/x86/include/asm/mktme.h > +++ b/arch/x86/include/asm/mktme.h > @@ -24,6 +24,10 @@ extern int mktme_map_keyid_from_key(void *key); > extern void *mktme_map_key_from_keyid(int keyid); > extern int mktme_map_get_free_keyid(void); > > +/* Set the encryption keyid bits in a VMA */ > +extern void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid, > + unsigned long start, unsigned long end); > + > DECLARE_STATIC_KEY_FALSE(mktme_enabled_key); > static inline bool mktme_enabled(void) > { > diff --git a/arch/x86/mm/mktme.c b/arch/x86/mm/mktme.c > index 34224d4e3f45..e3fdf7b48173 100644 > --- a/arch/x86/mm/mktme.c > +++ b/arch/x86/mm/mktme.c > @@ -1,5 +1,6 @@ > #include <linux/mm.h> > #include <linux/highmem.h> > +#include <linux/rmap.h> > #include <asm/mktme.h> > #include <asm/set_memory.h> > > @@ -131,6 +132,31 @@ int mktme_map_get_free_keyid(void) > return 0; > } > > +/* Set the encryption keyid bits in a VMA */ Maybe proper kdoc? > +void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid, > + unsigned long start, unsigned long end) > +{ > + int oldkeyid = vma_keyid(vma); > + pgprotval_t newprot; > + > + /* Unmap pages with old KeyID if there's any. */ > + zap_page_range(vma, start, end - start); > + > + if (oldkeyid == newkeyid) > + return; > + > + newprot = pgprot_val(vma->vm_page_prot); > + newprot &= ~mktme_keyid_mask; > + newprot |= (unsigned long)newkeyid << mktme_keyid_shift; > + vma->vm_page_prot = __pgprot(newprot); > + > + /* No empty comment line. > + * The VMA doesn't have any inherited pages. > + * Start anon VMA tree from scratch. > + */ > +} > + > /* Prepare page to be used for encryption. Called from page allocator. */ > void __prep_encrypted_page(struct page *page, int order, int keyid, bool > zero) > { > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 1309761bb6d0..e2d87e92ca74 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2806,5 +2806,11 @@ void __init setup_nr_node_ids(void); > static inline void setup_nr_node_ids(void) {} > #endif > > +#ifndef CONFIG_X86_INTEL_MKTME > +static inline void mprotect_set_encrypt(struct vm_area_struct *vma, > + int newkeyid, > + unsigned long start, > + unsigned long end) {} Add a new line and { } > +#endif /* CONFIG_X86_INTEL_MKTME */ > #endif /* __KERNEL__ */ > #endif /* _LINUX_MM_H */ /Jarkko
diff --git a/arch/x86/include/asm/mktme.h b/arch/x86/include/asm/mktme.h index dbb49909d665..de3e529f3ab0 100644 --- a/arch/x86/include/asm/mktme.h +++ b/arch/x86/include/asm/mktme.h @@ -24,6 +24,10 @@ extern int mktme_map_keyid_from_key(void *key); extern void *mktme_map_key_from_keyid(int keyid); extern int mktme_map_get_free_keyid(void); +/* Set the encryption keyid bits in a VMA */ +extern void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid, + unsigned long start, unsigned long end); + DECLARE_STATIC_KEY_FALSE(mktme_enabled_key); static inline bool mktme_enabled(void) { diff --git a/arch/x86/mm/mktme.c b/arch/x86/mm/mktme.c index 34224d4e3f45..e3fdf7b48173 100644 --- a/arch/x86/mm/mktme.c +++ b/arch/x86/mm/mktme.c @@ -1,5 +1,6 @@ #include <linux/mm.h> #include <linux/highmem.h> +#include <linux/rmap.h> #include <asm/mktme.h> #include <asm/set_memory.h> @@ -131,6 +132,31 @@ int mktme_map_get_free_keyid(void) return 0; } +/* Set the encryption keyid bits in a VMA */ +void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid, + unsigned long start, unsigned long end) +{ + int oldkeyid = vma_keyid(vma); + pgprotval_t newprot; + + /* Unmap pages with old KeyID if there's any. */ + zap_page_range(vma, start, end - start); + + if (oldkeyid == newkeyid) + return; + + newprot = pgprot_val(vma->vm_page_prot); + newprot &= ~mktme_keyid_mask; + newprot |= (unsigned long)newkeyid << mktme_keyid_shift; + vma->vm_page_prot = __pgprot(newprot); + + /* + * The VMA doesn't have any inherited pages. + * Start anon VMA tree from scratch. + */ + unlink_anon_vmas(vma); +} + /* Prepare page to be used for encryption. Called from page allocator. */ void __prep_encrypted_page(struct page *page, int order, int keyid, bool zero) { diff --git a/include/linux/mm.h b/include/linux/mm.h index 1309761bb6d0..e2d87e92ca74 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2806,5 +2806,11 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +#ifndef CONFIG_X86_INTEL_MKTME +static inline void mprotect_set_encrypt(struct vm_area_struct *vma, + int newkeyid, + unsigned long start, + unsigned long end) {} +#endif /* CONFIG_X86_INTEL_MKTME */ #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */