@@ -28,6 +28,15 @@ extern int mktme_map_get_free_keyid(void);
extern void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid,
unsigned long start, unsigned long end);
+/* Manage the MTKME encrypt_count references */
+extern int mktme_alloc_encrypt_array(void);
+extern void mktme_free_encrypt_array(void);
+extern int mktme_read_encrypt_ref(int keyid);
+extern void vma_get_encrypt_ref(struct vm_area_struct *vma);
+extern void vma_put_encrypt_ref(struct vm_area_struct *vma);
+extern void key_get_encrypt_ref(int keyid);
+extern void key_put_encrypt_ref(int keyid);
+
DECLARE_STATIC_KEY_FALSE(mktme_enabled_key);
static inline bool mktme_enabled(void)
{
@@ -157,6 +157,64 @@ void mprotect_set_encrypt(struct vm_area_struct *vma, int newkeyid,
unlink_anon_vmas(vma);
}
+/*
+ * Helper functions manage the encrypt_count[] array that counts
+ * references on each MKTME hardware keyid. The gets & puts are
+ * used in core mm code that allocates and free's VMA's. The alloc,
+ * free, and read functions are used by the MKTME key service to
+ * manage key allocation and programming.
+ */
+refcount_t *encrypt_count;
+
+int mktme_alloc_encrypt_array(void)
+{
+ encrypt_count = kvcalloc(mktme_nr_keyids, sizeof(refcount_t),
+ GFP_KERNEL);
+ if (!encrypt_count)
+ return -ENOMEM;
+ return 0;
+}
+
+void mktme_free_encrypt_array(void)
+{
+ kvfree(encrypt_count);
+}
+
+int mktme_read_encrypt_ref(int keyid)
+{
+ return refcount_read(&encrypt_count[keyid]);
+}
+
+void vma_get_encrypt_ref(struct vm_area_struct *vma)
+{
+ if (vma_keyid(vma))
+ refcount_inc(&encrypt_count[vma_keyid(vma)]);
+}
+
+void vma_put_encrypt_ref(struct vm_area_struct *vma)
+{
+ if (vma_keyid(vma))
+ if (refcount_dec_and_test(&encrypt_count[vma_keyid(vma)])) {
+ mktme_map_lock();
+ mktme_map_free_keyid(vma_keyid(vma));
+ mktme_map_unlock();
+ }
+}
+
+void key_get_encrypt_ref(int keyid)
+{
+ refcount_inc(&encrypt_count[keyid]);
+}
+
+void key_put_encrypt_ref(int keyid)
+{
+ if (refcount_dec_and_test(&encrypt_count[keyid])) {
+ mktme_map_lock();
+ mktme_map_free_keyid(keyid);
+ mktme_map_unlock();
+ }
+}
+
/* Prepare page to be used for encryption. Called from page allocator. */
void __prep_encrypted_page(struct page *page, int order, int keyid, bool zero)
{
@@ -2812,6 +2812,8 @@ static inline void mprotect_set_encrypt(struct vm_area_struct *vma,
int newkeyid,
unsigned long start,
unsigned long end) {}
+static inline void vma_get_encrypt_ref(struct vm_area_struct *vma) {}
+static inline void vma_put_encrypt_ref(struct vm_area_struct *vma) {}
#endif /* CONFIG_X86_INTEL_MKTME */
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */