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, unsigned long 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 | |