1e7e05452SSean Christopherson /* SPDX-License-Identifier: GPL-2.0 */ 2e7e05452SSean Christopherson #ifndef _X86_SGX_H 3e7e05452SSean Christopherson #define _X86_SGX_H 4e7e05452SSean Christopherson 5e7e05452SSean Christopherson #include <linux/bitops.h> 6e7e05452SSean Christopherson #include <linux/err.h> 7e7e05452SSean Christopherson #include <linux/io.h> 8e7e05452SSean Christopherson #include <linux/rwsem.h> 9e7e05452SSean Christopherson #include <linux/types.h> 10e7e05452SSean Christopherson #include <asm/asm.h> 118ca52cc3SSean Christopherson #include <asm/sgx.h> 12e7e05452SSean Christopherson 13e7e05452SSean Christopherson #undef pr_fmt 14e7e05452SSean Christopherson #define pr_fmt(fmt) "sgx: " fmt 15e7e05452SSean Christopherson 16b0c7459bSKai Huang #define EREMOVE_ERROR_MESSAGE \ 17b0c7459bSKai Huang "EREMOVE returned %d (0x%x) and an EPC page was leaked. SGX may become unusable. " \ 18*ff61f079SJonathan Corbet "Refer to Documentation/arch/x86/sgx.rst for more information." 19b0c7459bSKai Huang 20e7e05452SSean Christopherson #define SGX_MAX_EPC_SECTIONS 8 21c6d26d37SJarkko Sakkinen #define SGX_EEXTEND_BLOCK_SIZE 256 221728ab54SJarkko Sakkinen #define SGX_NR_TO_SCAN 16 231728ab54SJarkko Sakkinen #define SGX_NR_LOW_PAGES 32 241728ab54SJarkko Sakkinen #define SGX_NR_HIGH_PAGES 64 251728ab54SJarkko Sakkinen 261728ab54SJarkko Sakkinen /* Pages, which are being tracked by the page reclaimer. */ 271728ab54SJarkko Sakkinen #define SGX_EPC_PAGE_RECLAIMER_TRACKED BIT(0) 28e7e05452SSean Christopherson 29d6d261bdSTony Luck /* Pages on free list */ 30d6d261bdSTony Luck #define SGX_EPC_PAGE_IS_FREE BIT(1) 31d6d261bdSTony Luck 32e7e05452SSean Christopherson struct sgx_epc_page { 33e7e05452SSean Christopherson unsigned int section; 34992801aeSTony Luck u16 flags; 35992801aeSTony Luck u16 poison; 361728ab54SJarkko Sakkinen struct sgx_encl_page *owner; 37e7e05452SSean Christopherson struct list_head list; 38e7e05452SSean Christopherson }; 39e7e05452SSean Christopherson 40e7e05452SSean Christopherson /* 41901ddbb9SJarkko Sakkinen * Contains the tracking data for NUMA nodes having EPC pages. Most importantly, 42901ddbb9SJarkko Sakkinen * the free page list local to the node is stored here. 43901ddbb9SJarkko Sakkinen */ 44901ddbb9SJarkko Sakkinen struct sgx_numa_node { 45901ddbb9SJarkko Sakkinen struct list_head free_page_list; 46992801aeSTony Luck struct list_head sgx_poison_page_list; 4750468e43SJarkko Sakkinen unsigned long size; 48901ddbb9SJarkko Sakkinen spinlock_t lock; 49901ddbb9SJarkko Sakkinen }; 50901ddbb9SJarkko Sakkinen 51901ddbb9SJarkko Sakkinen /* 52e7e05452SSean Christopherson * The firmware can define multiple chunks of EPC to the different areas of the 53e7e05452SSean Christopherson * physical memory e.g. for memory areas of the each node. This structure is 54e7e05452SSean Christopherson * used to store EPC pages for one EPC section and virtual memory area where 55e7e05452SSean Christopherson * the pages have been mapped. 56e7e05452SSean Christopherson */ 57e7e05452SSean Christopherson struct sgx_epc_section { 58e7e05452SSean Christopherson unsigned long phys_addr; 59e7e05452SSean Christopherson void *virt_addr; 60e7e05452SSean Christopherson struct sgx_epc_page *pages; 61901ddbb9SJarkko Sakkinen struct sgx_numa_node *node; 62e7e05452SSean Christopherson }; 63e7e05452SSean Christopherson 64e7e05452SSean Christopherson extern struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS]; 65e7e05452SSean Christopherson sgx_get_epc_phys_addr(struct sgx_epc_page * page)66e7e05452SSean Christophersonstatic inline unsigned long sgx_get_epc_phys_addr(struct sgx_epc_page *page) 67e7e05452SSean Christopherson { 68e7e05452SSean Christopherson struct sgx_epc_section *section = &sgx_epc_sections[page->section]; 69e7e05452SSean Christopherson unsigned long index; 70e7e05452SSean Christopherson 71e7e05452SSean Christopherson index = ((unsigned long)page - (unsigned long)section->pages) / sizeof(*page); 72e7e05452SSean Christopherson 73e7e05452SSean Christopherson return section->phys_addr + index * PAGE_SIZE; 74e7e05452SSean Christopherson } 75e7e05452SSean Christopherson sgx_get_epc_virt_addr(struct sgx_epc_page * page)76e7e05452SSean Christophersonstatic inline void *sgx_get_epc_virt_addr(struct sgx_epc_page *page) 77e7e05452SSean Christopherson { 78e7e05452SSean Christopherson struct sgx_epc_section *section = &sgx_epc_sections[page->section]; 79e7e05452SSean Christopherson unsigned long index; 80e7e05452SSean Christopherson 81e7e05452SSean Christopherson index = ((unsigned long)page - (unsigned long)section->pages) / sizeof(*page); 82e7e05452SSean Christopherson 83e7e05452SSean Christopherson return section->virt_addr + index * PAGE_SIZE; 84e7e05452SSean Christopherson } 85e7e05452SSean Christopherson 86d2285493SJarkko Sakkinen struct sgx_epc_page *__sgx_alloc_epc_page(void); 87d2285493SJarkko Sakkinen void sgx_free_epc_page(struct sgx_epc_page *page); 88d2285493SJarkko Sakkinen 89a0506b3bSReinette Chatre void sgx_reclaim_direct(void); 901728ab54SJarkko Sakkinen void sgx_mark_page_reclaimable(struct sgx_epc_page *page); 911728ab54SJarkko Sakkinen int sgx_unmark_page_reclaimable(struct sgx_epc_page *page); 921728ab54SJarkko Sakkinen struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim); 931728ab54SJarkko Sakkinen 94c7c6a8a6SReinette Chatre void sgx_ipi_cb(void *info); 95c7c6a8a6SReinette Chatre 96540745ddSSean Christopherson #ifdef CONFIG_X86_SGX_KVM 97540745ddSSean Christopherson int __init sgx_vepc_init(void); 98540745ddSSean Christopherson #else sgx_vepc_init(void)99540745ddSSean Christophersonstatic inline int __init sgx_vepc_init(void) 100540745ddSSean Christopherson { 101540745ddSSean Christopherson return -ENODEV; 102540745ddSSean Christopherson } 103540745ddSSean Christopherson #endif 104540745ddSSean Christopherson 10573916b6aSKai Huang void sgx_update_lepubkeyhash(u64 *lepubkeyhash); 10673916b6aSKai Huang 107e7e05452SSean Christopherson #endif /* _X86_SGX_H */ 108