| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef _X86_SGX_H | |
| #define _X86_SGX_H | |
| #include <linux/bitops.h> | |
| #include <linux/err.h> | |
| #include <linux/io.h> | |
| #include <linux/rwsem.h> | |
| #include <linux/types.h> | |
| #include <asm/asm.h> | |
| #include <asm/sgx.h> | |
| #undef pr_fmt | |
| #define pr_fmt(fmt) "sgx: " fmt | |
| #define EREMOVE_ERROR_MESSAGE \ | |
| "EREMOVE returned %d (0x%x) and an EPC page was leaked. SGX may become unusable. " \ | |
| "Refer to Documentation/arch/x86/sgx.rst for more information." | |
| #define SGX_MAX_EPC_SECTIONS 8 | |
| #define SGX_EEXTEND_BLOCK_SIZE 256 | |
| #define SGX_NR_TO_SCAN 16 | |
| #define SGX_NR_LOW_PAGES 32 | |
| #define SGX_NR_HIGH_PAGES 64 | |
| /* Pages, which are being tracked by the page reclaimer. */ | |
| #define SGX_EPC_PAGE_RECLAIMER_TRACKED BIT(0) | |
| /* Pages on free list */ | |
| #define SGX_EPC_PAGE_IS_FREE BIT(1) | |
| struct sgx_epc_page { | |
| unsigned int section; | |
| u16 flags; | |
| u16 poison; | |
| struct sgx_encl_page *owner; | |
| struct list_head list; | |
| }; | |
| /* | |
| * Contains the tracking data for NUMA nodes having EPC pages. Most importantly, | |
| * the free page list local to the node is stored here. | |
| */ | |
| struct sgx_numa_node { | |
| struct list_head free_page_list; | |
| struct list_head sgx_poison_page_list; | |
| unsigned long size; | |
| spinlock_t lock; | |
| }; | |
| /* | |
| * The firmware can define multiple chunks of EPC to the different areas of the | |
| * physical memory e.g. for memory areas of the each node. This structure is | |
| * used to store EPC pages for one EPC section and virtual memory area where | |
| * the pages have been mapped. | |
| */ | |
| struct sgx_epc_section { | |
| unsigned long phys_addr; | |
| void *virt_addr; | |
| struct sgx_epc_page *pages; | |
| struct sgx_numa_node *node; | |
| }; | |
| extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; | |
| static inline unsigned long sgx_get_epc_phys_addr(struct sgx_epc_page *page) | |
| { | |
| struct sgx_epc_section *section = &sgx_epc_sections[page->section]; | |
| unsigned long index; | |
| index = ((unsigned long)page - (unsigned long)section->pages) / sizeof(*page); | |
| return section->phys_addr + index * PAGE_SIZE; | |
| } | |
| static inline void *sgx_get_epc_virt_addr(struct sgx_epc_page *page) | |
| { | |
| struct sgx_epc_section *section = &sgx_epc_sections[page->section]; | |
| unsigned long index; | |
| index = ((unsigned long)page - (unsigned long)section->pages) / sizeof(*page); | |
| return section->virt_addr + index * PAGE_SIZE; | |
| } | |
| struct sgx_epc_page *__sgx_alloc_epc_page(void); | |
| void sgx_free_epc_page(struct sgx_epc_page *page); | |
| void sgx_reclaim_direct(void); | |
| void sgx_mark_page_reclaimable(struct sgx_epc_page *page); | |
| int sgx_unmark_page_reclaimable(struct sgx_epc_page *page); | |
| struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim); | |
| void sgx_ipi_cb(void *info); | |
| #ifdef CONFIG_X86_SGX_KVM | |
| int __init sgx_vepc_init(void); | |
| #else | |
| static inline int __init sgx_vepc_init(void) | |
| { | |
| return -ENODEV; | |
| } | |
| #endif | |
| int sgx_inc_usage_count(void); | |
| void sgx_dec_usage_count(void); | |
| void sgx_update_lepubkeyhash(u64 *lepubkeyhash); | |
| #endif /* _X86_SGX_H */ |