13fe0778eSJarkko Sakkinen /* SPDX-License-Identifier: GPL-2.0 */
23fe0778eSJarkko Sakkinen /**
33fe0778eSJarkko Sakkinen * Copyright(c) 2016-20 Intel Corporation.
43fe0778eSJarkko Sakkinen *
53fe0778eSJarkko Sakkinen * Contains the software defined data structures for enclaves.
63fe0778eSJarkko Sakkinen */
73fe0778eSJarkko Sakkinen #ifndef _X86_ENCL_H
83fe0778eSJarkko Sakkinen #define _X86_ENCL_H
93fe0778eSJarkko Sakkinen
103fe0778eSJarkko Sakkinen #include <linux/cpumask.h>
113fe0778eSJarkko Sakkinen #include <linux/kref.h>
123fe0778eSJarkko Sakkinen #include <linux/list.h>
133fe0778eSJarkko Sakkinen #include <linux/mm_types.h>
143fe0778eSJarkko Sakkinen #include <linux/mmu_notifier.h>
153fe0778eSJarkko Sakkinen #include <linux/mutex.h>
163fe0778eSJarkko Sakkinen #include <linux/notifier.h>
173fe0778eSJarkko Sakkinen #include <linux/srcu.h>
183fe0778eSJarkko Sakkinen #include <linux/workqueue.h>
193fe0778eSJarkko Sakkinen #include <linux/xarray.h>
203fe0778eSJarkko Sakkinen #include "sgx.h"
213fe0778eSJarkko Sakkinen
221728ab54SJarkko Sakkinen /* 'desc' bits holding the offset in the VA (version array) page. */
231728ab54SJarkko Sakkinen #define SGX_ENCL_PAGE_VA_OFFSET_MASK GENMASK_ULL(11, 3)
241728ab54SJarkko Sakkinen
251728ab54SJarkko Sakkinen /* 'desc' bit marking that the page is being reclaimed. */
261728ab54SJarkko Sakkinen #define SGX_ENCL_PAGE_BEING_RECLAIMED BIT(3)
271728ab54SJarkko Sakkinen
283fe0778eSJarkko Sakkinen struct sgx_encl_page {
293fe0778eSJarkko Sakkinen unsigned long desc;
308cb7b502SReinette Chatre unsigned long vm_max_prot_bits:8;
318cb7b502SReinette Chatre enum sgx_page_type type:16;
323fe0778eSJarkko Sakkinen struct sgx_epc_page *epc_page;
333fe0778eSJarkko Sakkinen struct sgx_encl *encl;
341728ab54SJarkko Sakkinen struct sgx_va_page *va_page;
353fe0778eSJarkko Sakkinen };
363fe0778eSJarkko Sakkinen
37888d2491SJarkko Sakkinen enum sgx_encl_flags {
38888d2491SJarkko Sakkinen SGX_ENCL_IOCTL = BIT(0),
39888d2491SJarkko Sakkinen SGX_ENCL_DEBUG = BIT(1),
40888d2491SJarkko Sakkinen SGX_ENCL_CREATED = BIT(2),
419d0c151bSJarkko Sakkinen SGX_ENCL_INITIALIZED = BIT(3),
42888d2491SJarkko Sakkinen };
43888d2491SJarkko Sakkinen
441728ab54SJarkko Sakkinen struct sgx_encl_mm {
451728ab54SJarkko Sakkinen struct sgx_encl *encl;
461728ab54SJarkko Sakkinen struct mm_struct *mm;
471728ab54SJarkko Sakkinen struct list_head list;
481728ab54SJarkko Sakkinen struct mmu_notifier mmu_notifier;
491728ab54SJarkko Sakkinen };
501728ab54SJarkko Sakkinen
513fe0778eSJarkko Sakkinen struct sgx_encl {
523fe0778eSJarkko Sakkinen unsigned long base;
533fe0778eSJarkko Sakkinen unsigned long size;
54888d2491SJarkko Sakkinen unsigned long flags;
553fe0778eSJarkko Sakkinen unsigned int page_cnt;
563fe0778eSJarkko Sakkinen unsigned int secs_child_cnt;
573fe0778eSJarkko Sakkinen struct mutex lock;
583fe0778eSJarkko Sakkinen struct xarray page_array;
593fe0778eSJarkko Sakkinen struct sgx_encl_page secs;
609d0c151bSJarkko Sakkinen unsigned long attributes;
619d0c151bSJarkko Sakkinen unsigned long attributes_mask;
621728ab54SJarkko Sakkinen
631728ab54SJarkko Sakkinen cpumask_t cpumask;
641728ab54SJarkko Sakkinen struct file *backing;
651728ab54SJarkko Sakkinen struct kref refcount;
661728ab54SJarkko Sakkinen struct list_head va_pages;
671728ab54SJarkko Sakkinen unsigned long mm_list_version;
681728ab54SJarkko Sakkinen struct list_head mm_list;
691728ab54SJarkko Sakkinen spinlock_t mm_lock;
701728ab54SJarkko Sakkinen struct srcu_struct srcu;
711728ab54SJarkko Sakkinen };
721728ab54SJarkko Sakkinen
731728ab54SJarkko Sakkinen #define SGX_VA_SLOT_COUNT 512
741728ab54SJarkko Sakkinen
751728ab54SJarkko Sakkinen struct sgx_va_page {
761728ab54SJarkko Sakkinen struct sgx_epc_page *epc_page;
771728ab54SJarkko Sakkinen DECLARE_BITMAP(slots, SGX_VA_SLOT_COUNT);
781728ab54SJarkko Sakkinen struct list_head list;
791728ab54SJarkko Sakkinen };
801728ab54SJarkko Sakkinen
811728ab54SJarkko Sakkinen struct sgx_backing {
821728ab54SJarkko Sakkinen struct page *contents;
831728ab54SJarkko Sakkinen struct page *pcmd;
841728ab54SJarkko Sakkinen unsigned long pcmd_offset;
853fe0778eSJarkko Sakkinen };
863fe0778eSJarkko Sakkinen
873fe0778eSJarkko Sakkinen extern const struct vm_operations_struct sgx_vm_ops;
883fe0778eSJarkko Sakkinen
sgx_encl_find(struct mm_struct * mm,unsigned long addr,struct vm_area_struct ** vma)893fe0778eSJarkko Sakkinen static inline int sgx_encl_find(struct mm_struct *mm, unsigned long addr,
903fe0778eSJarkko Sakkinen struct vm_area_struct **vma)
913fe0778eSJarkko Sakkinen {
923fe0778eSJarkko Sakkinen struct vm_area_struct *result;
933fe0778eSJarkko Sakkinen
949ce2c3fcSLiam Howlett result = vma_lookup(mm, addr);
959ce2c3fcSLiam Howlett if (!result || result->vm_ops != &sgx_vm_ops)
963fe0778eSJarkko Sakkinen return -EINVAL;
973fe0778eSJarkko Sakkinen
983fe0778eSJarkko Sakkinen *vma = result;
993fe0778eSJarkko Sakkinen
1003fe0778eSJarkko Sakkinen return 0;
1013fe0778eSJarkko Sakkinen }
1023fe0778eSJarkko Sakkinen
1033fe0778eSJarkko Sakkinen int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start,
1043fe0778eSJarkko Sakkinen unsigned long end, unsigned long vm_flags);
1053fe0778eSJarkko Sakkinen
1060c9782e2SKristen Carlson Accardi bool current_is_ksgxd(void);
1071728ab54SJarkko Sakkinen void sgx_encl_release(struct kref *ref);
1081728ab54SJarkko Sakkinen int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm);
109bdaa8799SReinette Chatre const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl);
1100c9782e2SKristen Carlson Accardi int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
1111728ab54SJarkko Sakkinen struct sgx_backing *backing);
1126bd42964SReinette Chatre void sgx_encl_put_backing(struct sgx_backing *backing);
1131728ab54SJarkko Sakkinen int sgx_encl_test_and_clear_young(struct mm_struct *mm,
1141728ab54SJarkko Sakkinen struct sgx_encl_page *page);
1158123073cSJarkko Sakkinen struct sgx_encl_page *sgx_encl_page_alloc(struct sgx_encl *encl,
1168123073cSJarkko Sakkinen unsigned long offset,
1178123073cSJarkko Sakkinen u64 secinfo_flags);
118f89c2f9bSReinette Chatre void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr);
119*a76e7f1fSReinette Chatre struct sgx_epc_page *sgx_alloc_va_page(bool reclaim);
1201728ab54SJarkko Sakkinen unsigned int sgx_alloc_va_slot(struct sgx_va_page *va_page);
1211728ab54SJarkko Sakkinen void sgx_free_va_slot(struct sgx_va_page *va_page, unsigned int offset);
1221728ab54SJarkko Sakkinen bool sgx_va_page_full(struct sgx_va_page *va_page);
123b0c7459bSKai Huang void sgx_encl_free_epc_page(struct sgx_epc_page *page);
124b3fb517dSReinette Chatre struct sgx_encl_page *sgx_encl_load_page(struct sgx_encl *encl,
125b3fb517dSReinette Chatre unsigned long addr);
126*a76e7f1fSReinette Chatre struct sgx_va_page *sgx_encl_grow(struct sgx_encl *encl, bool reclaim);
1273a535141SReinette Chatre void sgx_encl_shrink(struct sgx_encl *encl, struct sgx_va_page *va_page);
1281728ab54SJarkko Sakkinen
1293fe0778eSJarkko Sakkinen #endif /* _X86_ENCL_H */
130