/* SPDX-License-Identifier: GPL-2.0 */ /** * Copyright(c) 2016-20 Intel Corporation. * * Contains the software defined data structures for enclaves. */ #ifndef _X86_ENCL_H #define _X86_ENCL_H #include #include #include #include #include #include #include #include #include #include #include "sgx.h" /* 'desc' bits holding the offset in the VA (version array) page. */ #define SGX_ENCL_PAGE_VA_OFFSET_MASK GENMASK_ULL(11, 3) /* 'desc' bit marking that the page is being reclaimed. */ #define SGX_ENCL_PAGE_BEING_RECLAIMED BIT(3) struct sgx_encl_page { unsigned long desc; unsigned long vm_max_prot_bits; struct sgx_epc_page *epc_page; struct sgx_encl *encl; struct sgx_va_page *va_page; }; enum sgx_encl_flags { SGX_ENCL_IOCTL = BIT(0), SGX_ENCL_DEBUG = BIT(1), SGX_ENCL_CREATED = BIT(2), SGX_ENCL_INITIALIZED = BIT(3), }; struct sgx_encl_mm { struct sgx_encl *encl; struct mm_struct *mm; struct list_head list; struct mmu_notifier mmu_notifier; }; struct sgx_encl { unsigned long base; unsigned long size; unsigned long flags; unsigned int page_cnt; unsigned int secs_child_cnt; struct mutex lock; struct xarray page_array; struct sgx_encl_page secs; unsigned long attributes; unsigned long attributes_mask; cpumask_t cpumask; struct file *backing; struct kref refcount; struct list_head va_pages; unsigned long mm_list_version; struct list_head mm_list; spinlock_t mm_lock; struct srcu_struct srcu; }; #define SGX_VA_SLOT_COUNT 512 struct sgx_va_page { struct sgx_epc_page *epc_page; DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT); struct list_head list; }; struct sgx_backing { pgoff_t page_index; struct page *contents; struct page *pcmd; unsigned long pcmd_offset; }; extern const struct vm_operations_struct sgx_vm_ops; static inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr, struct vm_area_struct **vma) { struct vm_area_struct *result; result = vma_lookup(mm, addr); if (!result || result->vm_ops != &sgx_vm_ops) return -EINVAL; *vma = result; return 0; } int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start, unsigned long end, unsigned long vm_flags); void sgx_encl_release(struct kref *ref); int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm); int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index, struct sgx_backing *backing); void sgx_encl_put_backing(struct sgx_backing *backing, bool do_write); int sgx_encl_test_and_clear_young(struct mm_struct *mm, struct sgx_encl_page *page); struct sgx_epc_page *sgx_alloc_va_page(void); unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page); void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset); bool sgx_va_page_full(struct sgx_va_page *va_page); void sgx_encl_free_epc_page(struct sgx_epc_page *page); #endif /* _X86_ENCL_H */