| /* 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 <linux/cpumask.h> | |
| #include <linux/kref.h> | |
| #include <linux/list.h> | |
| #include <linux/mm_types.h> | |
| #include <linux/mmu_notifier.h> | |
| #include <linux/mutex.h> | |
| #include <linux/notifier.h> | |
| #include <linux/srcu.h> | |
| #include <linux/workqueue.h> | |
| #include <linux/xarray.h> | |
| #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:8; | |
| enum sgx_page_type type:16; | |
| 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 { | |
| 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, vm_flags_t vm_flags); | |
| bool current_is_ksgxd(void); | |
| void sgx_encl_release(struct kref *ref); | |
| int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm); | |
| const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl); | |
| int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index, | |
| struct sgx_backing *backing); | |
| void sgx_encl_put_backing(struct sgx_backing *backing); | |
| int sgx_encl_test_and_clear_young(struct mm_struct *mm, | |
| struct sgx_encl_page *page); | |
| struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl, | |
| unsigned long offset, | |
| u64 secinfo_flags); | |
| void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr); | |
| struct sgx_epc_page *sgx_alloc_va_page(bool reclaim); | |
| 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); | |
| struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl, | |
| unsigned long addr); | |
| struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim); | |
| void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page); | |
| #endif /* _X86_ENCL_H */ |