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
28struct 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
37enum 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
44struct 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
51struct 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
75struct 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
81struct sgx_backing {
82	struct page *contents;
83	struct page *pcmd;
84	unsigned long pcmd_offset;
85};
86
87extern const struct vm_operations_struct sgx_vm_ops;
88
89static 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
103int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start,
104		     unsigned long end, unsigned long vm_flags);
105
106bool current_is_ksgxd(void);
107void sgx_encl_release(struct kref *ref);
108int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm);
109const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl);
110int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
111			   struct sgx_backing *backing);
112void sgx_encl_put_backing(struct sgx_backing *backing);
113int sgx_encl_test_and_clear_young(struct mm_struct *mm,
114				  struct sgx_encl_page *page);
115struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
116					  unsigned long offset,
117					  u64 secinfo_flags);
118void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr);
119struct sgx_epc_page *sgx_alloc_va_page(bool reclaim);
120unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page);
121void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset);
122bool sgx_va_page_full(struct sgx_va_page *va_page);
123void sgx_encl_free_epc_page(struct sgx_epc_page *page);
124struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl,
125					 unsigned long addr);
126struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim);
127void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page);
128
129#endif /* _X86_ENCL_H */
130