1105698Srwatson/* SPDX-License-Identifier: GPL-2.0 */
2105698Srwatson/**
3119314Srwatson * Copyright(c) 2016-20 Intel Corporation.
4105698Srwatson *
5105698Srwatson * Contains the software defined data structures for enclaves.
6105698Srwatson */
7105698Srwatson#ifndef _X86_ENCL_H
8106436Srwatson#define _X86_ENCL_H
9106436Srwatson
10106436Srwatson#include <linux/cpumask.h>
11106436Srwatson#include <linux/kref.h>
12105698Srwatson#include <linux/list.h>
13105698Srwatson#include <linux/mm_types.h>
14105698Srwatson#include <linux/mmu_notifier.h>
15105698Srwatson#include <linux/mutex.h>
16105698Srwatson#include <linux/notifier.h>
17105698Srwatson#include <linux/srcu.h>
18105698Srwatson#include <linux/workqueue.h>
19105698Srwatson#include <linux/xarray.h>
20105698Srwatson#include "sgx.h"
21105698Srwatson
22105698Srwatson/* 'desc' bits holding the offset in the VA (version array) page. */
23105698Srwatson#define SGX_ENCL_PAGE_VA_OFFSET_MASK	GENMASK_ULL(11, 3)
24105698Srwatson
25105698Srwatson/* 'desc' bit marking that the page is being reclaimed. */
26105698Srwatson#define SGX_ENCL_PAGE_BEING_RECLAIMED	BIT(3)
27105698Srwatson
28105698Srwatsonstruct sgx_encl_page {
29105698Srwatson	unsigned long desc;
30105698Srwatson	unsigned long vm_max_prot_bits:8;
31105698Srwatson	enum sgx_page_type type:16;
32105698Srwatson	struct sgx_epc_page *epc_page;
33105698Srwatson	struct sgx_encl *encl;
34105698Srwatson	struct sgx_va_page *va_page;
35176901Srwatson};
36176901Srwatson
37176901Srwatsonenum sgx_encl_flags {
38105698Srwatson	SGX_ENCL_IOCTL		= BIT(0),
39105698Srwatson	SGX_ENCL_DEBUG		= BIT(1),
40105698Srwatson	SGX_ENCL_CREATED	= BIT(2),
41105698Srwatson	SGX_ENCL_INITIALIZED	= BIT(3),
42105698Srwatson};
43105698Srwatson
44106053Swollmanstruct sgx_encl_mm {
45105698Srwatson	struct sgx_encl *encl;
46105698Srwatson	struct mm_struct *mm;
47105698Srwatson	struct list_head list;
48124174Snectar	struct mmu_notifier mmu_notifier;
49105698Srwatson};
50105698Srwatson
51105698Srwatsonstruct sgx_encl {
52105698Srwatson	unsigned long base;
53105698Srwatson	unsigned long size;
54119314Srwatson	unsigned long flags;
55119314Srwatson	unsigned int page_cnt;
56119314Srwatson	unsigned int secs_child_cnt;
57119314Srwatson	struct mutex lock;
58119314Srwatson	struct xarray page_array;
59119314Srwatson	struct sgx_encl_page secs;
60122868Srwatson	unsigned long attributes;
61119314Srwatson	unsigned long attributes_mask;
62119314Srwatson
63119314Srwatson	cpumask_t cpumask;
64119314Srwatson	struct file *backing;
65119314Srwatson	struct kref refcount;
66105698Srwatson	struct list_head va_pages;
67105698Srwatson	unsigned long mm_list_version;
68105698Srwatson	struct list_head mm_list;
69105698Srwatson	spinlock_t mm_lock;
70119314Srwatson	struct srcu_struct srcu;
71105698Srwatson};
72119314Srwatson
73119314Srwatson#define SGX_VA_SLOT_COUNT 512
74119314Srwatson
75119314Srwatsonstruct sgx_va_page {
76119314Srwatson	struct sgx_epc_page *epc_page;
77105698Srwatson	DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT);
78105698Srwatson	struct list_head list;
79105698Srwatson};
80105698Srwatson
81105698Srwatsonstruct sgx_backing {
82105698Srwatson	struct page *contents;
83105698Srwatson	struct page *pcmd;
84105698Srwatson	unsigned long pcmd_offset;
85105698Srwatson};
86105698Srwatson
87105698Srwatsonextern const struct vm_operations_struct sgx_vm_ops;
88105698Srwatson
89105698Srwatsonstatic inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr,
90119314Srwatson				struct vm_area_struct **vma)
91105698Srwatson{
92119314Srwatson	struct vm_area_struct *result;
93119314Srwatson
94119314Srwatson	result = vma_lookup(mm, addr);
95119314Srwatson	if (!result || result->vm_ops != &sgx_vm_ops)
96119314Srwatson		return -EINVAL;
97119314Srwatson
98119314Srwatson	*vma = result;
99119314Srwatson
100119314Srwatson	return 0;
101119314Srwatson}
102119314Srwatson
103119314Srwatsonint sgx_encl_may_map(struct sgx_encl *encl, unsigned long start,
104119314Srwatson		     unsigned long end, unsigned long vm_flags);
105119314Srwatson
106119314Srwatsonbool current_is_ksgxd(void);
107119314Srwatsonvoid sgx_encl_release(struct kref *ref);
108119314Srwatsonint sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm);
109119314Srwatsonconst cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl);
110119314Srwatsonint sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
111119314Srwatson			   struct sgx_backing *backing);
112119314Srwatsonvoid sgx_encl_put_backing(struct sgx_backing *backing);
113119314Srwatsonint sgx_encl_test_and_clear_young(struct mm_struct *mm,
114119314Srwatson				  struct sgx_encl_page *page);
115119314Srwatsonstruct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
116119314Srwatson					  unsigned long offset,
117119314Srwatson					  u64 secinfo_flags);
118119314Srwatsonvoid sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr);
119119314Srwatsonstruct sgx_epc_page *sgx_alloc_va_page(bool reclaim);
120119314Srwatsonunsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page);
121119314Srwatsonvoid sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset);
122119314Srwatsonbool sgx_va_page_full(struct sgx_va_page *va_page);
123119314Srwatsonvoid sgx_encl_free_epc_page(struct sgx_epc_page *page);
124119314Srwatsonstruct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl,
125119314Srwatson					 unsigned long addr);
126119314Srwatsonstruct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim);
127119314Srwatsonvoid sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page);
128119314Srwatson
129119314Srwatson#endif /* _X86_ENCL_H */
130119314Srwatson