| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /** |
| 3 | * Copyright(c) 2016-20 Intel Corporation. |
| 4 | * |
| 5 | * Contains the software defined data structures for enclaves. |
| 6 | */ |
| 7 | #ifndef _X86_ENCL_H |
| 8 | #define _X86_ENCL_H |
| 9 | |
| 10 | #include <linux/cpumask.h> |
| 11 | #include <linux/kref.h> |
| 12 | #include <linux/list.h> |
| 13 | #include <linux/mm_types.h> |
| 14 | #include <linux/mmu_notifier.h> |
| 15 | #include <linux/mutex.h> |
| 16 | #include <linux/notifier.h> |
| 17 | #include <linux/srcu.h> |
| 18 | #include <linux/workqueue.h> |
| 19 | #include <linux/xarray.h> |
| 20 | #include "sgx.h" |
| 21 | |
| 22 | /* 'desc' bits holding the offset in the VA (version array) page. */ |
| 23 | #define SGX_ENCL_PAGE_VA_OFFSET_MASK GENMASK_ULL(11, 3) |
| 24 | |
| 25 | /* 'desc' bit marking that the page is being reclaimed. */ |
| 26 | #define SGX_ENCL_PAGE_BEING_RECLAIMED BIT(3) |
| 27 | |
| 28 | struct sgx_encl_page { |
| 29 | unsigned long desc; |
| 30 | unsigned long vm_max_prot_bits:8; |
| 31 | enum sgx_page_type type:16; |
| 32 | struct sgx_epc_page *epc_page; |
| 33 | struct sgx_encl *encl; |
| 34 | struct sgx_va_page *va_page; |
| 35 | }; |
| 36 | |
| 37 | enum sgx_encl_flags { |
| 38 | SGX_ENCL_IOCTL = BIT(0), |
| 39 | SGX_ENCL_DEBUG = BIT(1), |
| 40 | SGX_ENCL_CREATED = BIT(2), |
| 41 | SGX_ENCL_INITIALIZED = BIT(3), |
| 42 | }; |
| 43 | |
| 44 | struct sgx_encl_mm { |
| 45 | struct sgx_encl *encl; |
| 46 | struct mm_struct *mm; |
| 47 | struct list_head list; |
| 48 | struct mmu_notifier mmu_notifier; |
| 49 | }; |
| 50 | |
| 51 | struct sgx_encl { |
| 52 | unsigned long base; |
| 53 | unsigned long size; |
| 54 | unsigned long flags; |
| 55 | unsigned int page_cnt; |
| 56 | unsigned int secs_child_cnt; |
| 57 | struct mutex lock; |
| 58 | struct xarray page_array; |
| 59 | struct sgx_encl_page secs; |
| 60 | unsigned long attributes; |
| 61 | unsigned long attributes_mask; |
| 62 | |
| 63 | cpumask_t cpumask; |
| 64 | struct file *backing; |
| 65 | struct kref refcount; |
| 66 | struct list_head va_pages; |
| 67 | unsigned long mm_list_version; |
| 68 | struct list_head mm_list; |
| 69 | spinlock_t mm_lock; |
| 70 | struct srcu_struct srcu; |
| 71 | }; |
| 72 | |
| 73 | #define SGX_VA_SLOT_COUNT 512 |
| 74 | |
| 75 | struct sgx_va_page { |
| 76 | struct sgx_epc_page *epc_page; |
| 77 | DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT); |
| 78 | struct list_head list; |
| 79 | }; |
| 80 | |
| 81 | struct sgx_backing { |
| 82 | struct page *contents; |
| 83 | struct page *pcmd; |
| 84 | unsigned long pcmd_offset; |
| 85 | }; |
| 86 | |
| 87 | extern const struct vm_operations_struct sgx_vm_ops; |
| 88 | |
| 89 | static inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr, |
| 90 | struct vm_area_struct **vma) |
| 91 | { |
| 92 | struct vm_area_struct *result; |
| 93 | |
| 94 | result = vma_lookup(mm, addr); |
| 95 | if (!result || result->vm_ops != &sgx_vm_ops) |
| 96 | return -EINVAL; |
| 97 | |
| 98 | *vma = result; |
| 99 | |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start, |
| 104 | unsigned long end, vm_flags_t vm_flags); |
| 105 | |
| 106 | bool current_is_ksgxd(void); |
| 107 | void sgx_encl_release(struct kref *ref); |
| 108 | int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm); |
| 109 | const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl); |
| 110 | int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index, |
| 111 | struct sgx_backing *backing); |
| 112 | void sgx_encl_put_backing(struct sgx_backing *backing); |
| 113 | int sgx_encl_test_and_clear_young(struct mm_struct *mm, |
| 114 | struct sgx_encl_page *page); |
| 115 | struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl, |
| 116 | unsigned long offset, |
| 117 | u64 secinfo_flags); |
| 118 | void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr); |
| 119 | struct sgx_epc_page *sgx_alloc_va_page(bool reclaim); |
| 120 | unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page); |
| 121 | void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset); |
| 122 | bool sgx_va_page_full(struct sgx_va_page *va_page); |
| 123 | void sgx_encl_free_epc_page(struct sgx_epc_page *page); |
| 124 | struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl, |
| 125 | unsigned long addr); |
| 126 | struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim); |
| 127 | void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page); |
| 128 | |
| 129 | #endif /* _X86_ENCL_H */ |
| 130 | |