@@ -16,6 +16,10 @@ extern int __mktme_nr_keyids;
extern int mktme_nr_keyids(void);
extern unsigned int mktme_algs;
+/* 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)
{
@@ -1,5 +1,6 @@
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/rmap.h>
#include <asm/mktme.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -71,6 +72,31 @@ int __vma_keyid(struct vm_area_struct *vma)
return (prot & mktme_keyid_mask()) >> mktme_keyid_shift();
}
+/* 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)
{
@@ -2905,5 +2905,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 */