Index: sys/amd64/include/cpufunc.h =================================================================== --- sys/amd64/include/cpufunc.h +++ sys/amd64/include/cpufunc.h @@ -802,6 +802,110 @@ write_rflags(rflags); } +enum { + ECREATE = 0x0, + EADD = 0x1, + EINIT = 0x2, + EREMOVE = 0x3, + EDGBRD = 0x4, + EDGBWR = 0x5, + EEXTEND = 0x6, + ELDU = 0x8, + EBLOCK = 0x9, + EPA = 0xA, + EWB = 0xB, + ETRACK = 0xC, +}; + +enum { + PT_SECS = 0x00, + PT_TCS = 0x01, + PT_REG = 0x02, + PT_VA = 0x03, + PT_TRIM = 0x04, +}; + +struct sgx_out_regs { + uint32_t oeax; + uint64_t orbx; +}; + +#define encls_ret(rax, rbx, rcx, rdx, tmp) \ + __asm __volatile( \ + ".byte 0x0f, 0x01, 0xcf" \ + :"=a"(tmp.oeax), \ + "=b"(tmp.orbx) \ + :"a"((uint32_t)rax), \ + "b"(rbx), \ + "c"(rcx), \ + "d"(rdx) \ + :"memory"); + +#define encls(rax, rbx, rcx, rdx) \ + __asm __volatile( \ + ".byte 0x0f, 0x01, 0xcf" \ + ::"a"((uint32_t)rax), \ + "b"(rbx), \ + "c"(rcx), \ + "d"(rdx) \ + :"memory"); + +static __inline void +sgx_ecreate(void *pginfo, void *secs) +{ + + encls(ECREATE, pginfo, secs, 0); +} + +static __inline void +sgx_eadd(void *pginfo, void *epc) +{ + + encls(EADD, pginfo, epc, 0); +} + +static __inline int +sgx_einit(void *sigstruct, void *secs, void *einittoken) +{ + struct sgx_out_regs tmp; + + encls_ret(EINIT, sigstruct, secs, einittoken, tmp); + + return (tmp.oeax); +} + +static __inline void +sgx_eextend(void *secs, void *epc) +{ + + encls(EEXTEND, secs, epc, 0); +} + +static __inline void +sgx_epa(void *epc) +{ + + encls(EPA, PT_VA, epc, 0); +} + +static __inline int +sgx_eldu(uint64_t rbx, uint64_t rcx, + uint64_t rdx) +{ + struct sgx_out_regs tmp; + + encls_ret(ELDU, rbx, rcx, rdx, tmp); + + return (tmp.oeax); +} + +static __inline void +sgx_eremove(void *epc) +{ + + encls(EREMOVE, 0, epc, 0); +} + #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ int breakpoint(void); Index: sys/amd64/include/sgx.h =================================================================== --- /dev/null +++ sys/amd64/include/sgx.h @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2017 Ruslan Bukin + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* User-visible header. */ + +#ifndef _MACHINE_SGX_H_ +#define _MACHINE_SGX_H_ + +/* Error codes. */ +#define SGX_SUCCESS 0 +#define SGX_INVALID_SIG_STRUCT 1 /* EINIT */ +#define SGX_INVALID_ATTRIBUTE 2 /* EINIT, EGETKEY */ +#define SGX_BLSTATE 3 /* EBLOCK */ +#define SGX_INVALID_MEASUREMENT 4 /* EINIT */ +#define SGX_NOTBLOCKABLE 5 /* EBLOCK */ +#define SGX_PG_INVLD 6 /* EBLOCK */ +#define SGX_LOCKFAIL 7 /* EBLOCK, EMODPR, EMODT */ +#define SGX_INVALID_SIGNATURE 8 /* EINIT */ +#define SGX_MAC_COMPARE_FAIL 9 /* ELDB, ELDU */ +#define SGX_PAGE_NOT_BLOCKED 10 /* EWB */ +#define SGX_NOT_TRACKED 11 /* EWB, EACCEPT */ +#define SGX_VA_SLOT_OCCUPIED 12 /* EWB */ +#define SGX_CHILD_PRESENT 13 /* EWB, EREMOVE */ +#define SGX_ENCLAVE_ACT 14 /* EREMOVE */ +#define SGX_ENTRYEPOCH_LOCKED 15 /* EBLOCK */ +#define SGX_INVALID_EINIT_TOKEN 16 /* EINIT */ +#define SGX_PREV_TRK_INCMPL 17 /* ETRACK */ +#define SGX_PG_IS_SECS 18 /* EBLOCK */ +#define SGX_PAGE_ATTRIBUTES_MISMATCH 19 /* EACCEPT, EACCEPTCOPY */ +#define SGX_PAGE_NOT_MODIFIABLE 20 /* EMODPR, EMODT */ +#define SGX_INVALID_CPUSVN 32 /* EINIT, EGETKEY */ +#define SGX_INVALID_ISVSVN 64 /* EGETKEY */ +#define SGX_UNMASKED_EVENT 128 /* EINIT */ +#define SGX_INVALID_KEYNAME 256 /* EGETKEY */ + +#define SGX_MAGIC 0xA4 +#define SGX_IOC_ENCLAVE_CREATE \ + _IOR(SGX_MAGIC, 0x00, struct sgx_enclave_create) +#define SGX_IOC_ENCLAVE_ADD_PAGE \ + _IOR(SGX_MAGIC, 0x01, struct sgx_enclave_add_page) +#define SGX_IOC_ENCLAVE_INIT \ + _IOR(SGX_MAGIC, 0x02, struct sgx_enclave_init) + +struct sgx_enclave_create { + uint64_t src; +} __packed; + +struct sgx_enclave_add_page { + uint64_t addr; + uint64_t src; + uint64_t secinfo; + uint16_t mrmask; +} __packed; + +struct sgx_enclave_init { + uint64_t addr; + uint64_t sigstruct; + uint64_t einittoken; +} __packed; + +/* + * 2.11 Security Information (SECINFO) + * The SECINFO data structure holds meta-data about an enclave page. + */ +struct secinfo { + uint64_t flags; +#define SECINFO_FLAGS_PT_S 8 /* Page type shift */ +#define SECINFO_FLAGS_PT_M (0xff << SECINFO_FLAGS_PT_S) + uint64_t reserved[7]; +} __aligned(128); + +/* + * 2.7.1 ATTRIBUTES + * The ATTRIBUTES data structure is comprised of bit-granular fields that + * are used in the SECS, CPUID enumeration, the REPORT and the KEYREQUEST + * structures. + */ +struct secs_attr { + uint8_t reserved1: 1; + uint8_t debug: 1; + uint8_t mode64bit: 1; + uint8_t reserved2: 1; + uint8_t provisionkey: 1; + uint8_t einittokenkey: 1; + uint8_t reserved3: 2; + uint8_t reserved4[7]; + uint64_t xfrm; /* X-Feature Request Mask */ +}; + +/* + * 2.7 SGX Enclave Control Structure (SECS) + * The SECS data structure requires 4K-Bytes alignment. + */ +struct secs { + uint64_t size; + uint64_t base; + uint32_t ssa_frame_size; + uint32_t misc_select; + uint8_t reserved1[24]; + struct secs_attr attributes; + uint8_t mr_enclave[32]; + uint8_t reserved2[32]; + uint8_t mr_signer[32]; + uint8_t reserved3[96]; + uint16_t isv_prod_id; + uint16_t isv_svn; + uint8_t reserved4[3836]; +}; + +/* + * 2.8 Thread Control Structure (TCS) + * Each executing thread in the enclave is associated with a + * Thread Control Structure. It requires 4K-Bytes alignment. + */ +struct tcs { + uint64_t reserved1; + uint64_t flags; + uint64_t ossa; + uint32_t cssa; + uint32_t nssa; + uint64_t oentry; + uint64_t reserved2; + uint64_t ofsbasgx; + uint64_t ogsbasgx; + uint32_t fslimit; + uint32_t gslimit; + uint64_t reserved3[503]; +}; + +#endif /* !_MACHINE_SGX_H_ */ Index: sys/amd64/include/sgxvar.h =================================================================== --- /dev/null +++ sys/amd64/include/sgxvar.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2017 Ruslan Bukin + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SGXVAR_H_ +#define _MACHINE_SGXVAR_H_ + +/* + * 2.10 Page Information (PAGEINFO) + * PAGEINFO is an architectural data structure that is used as a parameter + * to the EPC-management instructions. It requires 32-Byte alignment. + */ +struct page_info { + uint64_t linaddr; + uint64_t srcpge; + union { + struct secinfo *secinfo; + uint64_t pcmd; + }; + uint64_t secs; +} __aligned(32); + +#endif /* !_MACHINE_SGXVAR_H_ */ Index: sys/amd64/sgx/sgx.h =================================================================== --- /dev/null +++ sys/amd64/sgx/sgx.h @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2017 Ruslan Bukin + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _AMD64_SGX_SGX_H_ +#define _AMD64_SGX_SGX_H_ + +#define SGX_CPUID 0x12 +#define SGX_PAGE_SIZE 4096 +#define SGX_VA_PAGE_SLOTS 512 +#define SIGSTRUCT_SIZE 1808 +#define EINITTOKEN_SIZE 304 +#define IOCTL_MAX_DATA_LEN 26 + +static MALLOC_DEFINE(M_SGX, "sgx", "SGX driver"); + +struct sgx_vm_handle { + struct sgx_softc *sc; + vm_object_t mem; + uint64_t base; + vm_size_t size; + struct sgx_enclave *enclave; +}; + +/* EPC (Enclave Page Cache) page. */ +struct epc_page { + uint64_t base; + uint64_t phys; + uint8_t used; +}; + +/* Version Array page. */ +struct va_page { + struct epc_page *epc_page; + TAILQ_ENTRY(va_page) va_next; + bool slots[SGX_VA_PAGE_SLOTS]; +}; + +struct sgx_enclave_page { + struct epc_page *epc_page; + struct va_page *va_page; + int va_slot; + uint64_t addr; + TAILQ_ENTRY(sgx_enclave_page) next; +}; + +struct sgx_enclave { + uint64_t base; + uint64_t size; + struct sgx_enclave_page secs_page; + struct sgx_vm_handle *vmh; + struct mtx mtx; + TAILQ_ENTRY(sgx_enclave) next; + TAILQ_HEAD(, sgx_enclave_page) pages; + TAILQ_HEAD(, va_page) va_pages; +}; + +struct sgx_softc { + struct cdev *sgx_cdev; + device_t dev; + struct mtx mtx_epc; + struct mtx mtx; + uint64_t epc_base; + uint64_t epc_size; + struct epc_page *epc_pages; + uint32_t npages; + TAILQ_HEAD(, sgx_enclave) enclaves; +}; + +#endif /* !_AMD64_SGX_SGX_H_ */ Index: sys/amd64/sgx/sgx.c =================================================================== --- /dev/null +++ sys/amd64/sgx/sgx.c @@ -0,0 +1,1060 @@ +/*- + * Copyright (c) 2017 Ruslan Bukin + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif + +struct sgx_softc sgx_sc; + +#ifdef DEBUG +static int +sgx_count_epc_pages(struct sgx_softc *sc) +{ + struct epc_page *epc; + int cnt; + int i; + + cnt = 0; + + for (i = 0; i < sc->npages; i++) { + epc = &sc->epc_pages[i]; + if (epc->used == 0) + cnt++; + } + + return (cnt); +} +#endif + +static int +sgx_get_epc_page(struct sgx_softc *sc, struct epc_page **epc0) +{ + struct epc_page *epc; + int i; + + mtx_lock(&sc->mtx_epc); + + for (i = 0; i < sc->npages; i++) { + epc = &sc->epc_pages[i]; + if (epc->used == 0) { + epc->used = 1; + mtx_unlock(&sc->mtx_epc); + *epc0 = epc; + return (0); + } + } + + mtx_unlock(&sc->mtx_epc); + + return (ENOMEM); +} + +static void +sgx_put_epc_page(struct sgx_softc *sc, struct epc_page *epc) +{ + + if (epc == NULL) + return; + + KASSERT(epc->used == 1, ("Freeing unused page.")); + epc->used = 0; +} + +static int +sgx_va_slot_alloc(struct sgx_enclave *enclave, + struct va_page *va_page) +{ + int i; + + mtx_assert(&enclave->mtx, MA_OWNED); + + for (i = 0; i < SGX_VA_PAGE_SLOTS; i++) + if (va_page->slots[i] == 0) { + va_page->slots[i] = 1; + return (i); + } + + return (-1); +} + +static void +sgx_va_slot_free(struct sgx_softc *sc, + struct sgx_enclave *enclave, + struct sgx_enclave_page *enclave_page) +{ + struct va_page *va_page; + struct epc_page *epc; + int va_slot; + int i; + + va_page = enclave_page->va_page; + va_slot = enclave_page->va_slot; + + KASSERT(va_page->slots[va_slot] == 1, + ("Freeing unused slot.")); + + va_page->slots[va_slot] = 0; + + /* Now check if we need to remove va_page. */ + mtx_lock(&enclave->mtx); + for (i = 0; i < SGX_VA_PAGE_SLOTS; i++) + if (va_page->slots[i] == 1) { + mtx_unlock(&enclave->mtx); + return; + } + + TAILQ_REMOVE(&enclave->va_pages, va_page, va_next); + mtx_unlock(&enclave->mtx); + + epc = va_page->epc_page; + mtx_lock(&sc->mtx); + sgx_eremove((void *)epc->base); + mtx_unlock(&sc->mtx); + sgx_put_epc_page(sc, epc); + free(enclave_page->va_page, M_SGX); +} + +static void +sgx_enclave_page_remove(struct sgx_softc *sc, + struct sgx_enclave *enclave, + struct sgx_enclave_page *enclave_page) +{ + struct epc_page *epc; + + sgx_va_slot_free(sc, enclave, enclave_page); + + epc = enclave_page->epc_page; + mtx_lock(&sc->mtx); + sgx_eremove((void *)epc->base); + mtx_unlock(&sc->mtx); + sgx_put_epc_page(sc, epc); +} + +static int +sgx_enclave_page_construct(struct sgx_softc *sc, + struct sgx_enclave *enclave, + struct sgx_enclave_page *enclave_page) +{ + struct va_page *va_page; + struct va_page *va_page_tmp; + struct epc_page *epc; + int va_slot; + int ret; + + va_slot = -1; + + mtx_lock(&enclave->mtx); + TAILQ_FOREACH_SAFE(va_page, &enclave->va_pages, va_next, + va_page_tmp) { + va_slot = sgx_va_slot_alloc(enclave, va_page); + if (va_slot >= 0) + break; + } + mtx_unlock(&enclave->mtx); + + if (va_slot < 0) { + ret = sgx_get_epc_page(sc, &epc); + if (ret) { + dprintf("%s: No free EPC pages available.\n", + __func__); + return (ret); + } + + va_page = malloc(sizeof(struct va_page), + M_SGX, M_WAITOK | M_ZERO); + if (va_page == NULL) { + dprintf("%s: Can't alloc va_page.\n", __func__); + sgx_put_epc_page(sc, epc); + return (ENOMEM); + } + + mtx_lock(&enclave->mtx); + va_slot = sgx_va_slot_alloc(enclave, va_page); + mtx_unlock(&enclave->mtx); + + va_page->epc_page = epc; + mtx_lock(&sc->mtx); + sgx_epa((void *)epc->base); + mtx_unlock(&sc->mtx); + + mtx_lock(&enclave->mtx); + TAILQ_INSERT_TAIL(&enclave->va_pages, va_page, va_next); + mtx_unlock(&enclave->mtx); + } + + enclave_page->va_page = va_page; + enclave_page->va_slot = va_slot; + + return (0); +} + +static int +sgx_mem_find(struct sgx_softc *sc, uint64_t addr, + vm_map_entry_t *entry0, vm_object_t *mem0) +{ + struct proc *proc; + vm_map_t map; + vm_map_entry_t entry; + + proc = curthread->td_proc; + map = &proc->p_vmspace->vm_map; + + vm_map_lock_read(map); + if (!vm_map_lookup_entry(map, addr, &entry)) { + vm_map_unlock_read(map); + dprintf("%s: Can't find enclave.\n", __func__); + return (EINVAL); + } + vm_map_unlock_read(map); + + *mem0 = entry->object.vm_object; + *entry0 = entry; + + return (0); +} + +static int +sgx_enclave_find(struct sgx_softc *sc, uint64_t addr, + struct sgx_enclave **encl) +{ + struct sgx_vm_handle *vmh; + vm_map_entry_t entry; + vm_object_t mem; + int ret; + + ret = sgx_mem_find(sc, addr, &entry, &mem); + if (ret) + return (ret); + + vmh = mem->handle; + if (vmh == NULL) + return (ENXIO); + + *encl = vmh->enclave; + + return (0); +} + +static int +sgx_enclave_alloc(struct sgx_softc *sc, struct secs *secs, + struct sgx_enclave **enclave0) +{ + struct sgx_enclave *enclave; + + enclave = malloc(sizeof(struct sgx_enclave), + M_SGX, M_WAITOK | M_ZERO); + if (enclave == NULL) { + dprintf("%s: Can't alloc memory for enclave.\n", + __func__); + return (ENOMEM); + } + + TAILQ_INIT(&enclave->pages); + TAILQ_INIT(&enclave->va_pages); + + mtx_init(&enclave->mtx, "SGX enclave", NULL, MTX_DEF); + + enclave->base = secs->base; + enclave->size = secs->size; + + *enclave0 = enclave; + + return (0); +} + +static void +sgx_enclave_remove(struct sgx_softc *sc, + struct sgx_enclave *enclave) +{ + struct sgx_enclave_page *enclave_page_tmp; + struct sgx_enclave_page *enclave_page; + + mtx_lock(&sc->mtx); + TAILQ_REMOVE(&sc->enclaves, enclave, next); + mtx_unlock(&sc->mtx); + + /* Remove all the enclave pages */ + TAILQ_FOREACH_SAFE(enclave_page, &enclave->pages, next, + enclave_page_tmp) { + TAILQ_REMOVE(&enclave->pages, enclave_page, next); + sgx_enclave_page_remove(sc, enclave, enclave_page); + free(enclave_page, M_SGX); + } + + /* Remove SECS page */ + enclave_page = &enclave->secs_page; + sgx_enclave_page_remove(sc, enclave, enclave_page); + + KASSERT(TAILQ_EMPTY(&enclave->va_pages), + ("Enclave version-array pages tailq is not empty.")); + KASSERT(TAILQ_EMPTY(&enclave->pages), + ("Enclave pages is not empty.")); + + mtx_destroy(&enclave->mtx); + free(enclave, M_SGX); +} + +static void +sgx_measure_page(struct sgx_softc *sc, struct epc_page *secs, + struct epc_page *epc, uint16_t mrmask) +{ + int i, j; + + mtx_lock(&sc->mtx); + + for (i = 0, j = 1; i < PAGE_SIZE; i += 0x100, j <<= 1) { + if (!(j & mrmask)) + continue; + + sgx_eextend((void *)secs->base, + (void *)((uint64_t)epc->base + i)); + } + + mtx_unlock(&sc->mtx); +} + +static int +sgx_tcs_validate(struct tcs *tcs) +{ + int i; + + if ((tcs->flags) || + (tcs->ossa & (PAGE_SIZE - 1)) || + (tcs->ofsbasgx & (PAGE_SIZE - 1)) || + (tcs->ogsbasgx & (PAGE_SIZE - 1)) || + ((tcs->fslimit & 0xfff) != 0xfff) || + ((tcs->gslimit & 0xfff) != 0xfff)) + return (EINVAL); + + for (i = 0; i < nitems(tcs->reserved3); i++) + if (tcs->reserved3[i]) + return (EINVAL); + + return (0); +} + +static void +sgx_tcs_dump(struct sgx_softc *sc, struct tcs *t) +{ + + dprintf("t->flags %lx\n", t->flags); + dprintf("t->ossa %lx\n", t->ossa); + dprintf("t->cssa %x\n", t->cssa); + dprintf("t->nssa %x\n", t->nssa); + dprintf("t->oentry %lx\n", t->oentry); + dprintf("t->ofsbasgx %lx\n", t->ofsbasgx); + dprintf("t->ogsbasgx %lx\n", t->ogsbasgx); + dprintf("t->fslimit %x\n", t->fslimit); + dprintf("t->gslimit %x\n", t->gslimit); +} + +static int +sgx_pg_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) +{ + struct sgx_vm_handle *vmh; + + vmh = handle; + if (vmh == NULL) { + dprintf("%s: vmh not found.\n", __func__); + return (0); + } + + dprintf("%s: vmh->base %lx foff 0x%lx size 0x%lx\n", + __func__, vmh->base, foff, size); + + return (0); +} + +static void +sgx_pg_dtor(void *handle) +{ + struct sgx_vm_handle *vmh; + struct sgx_softc *sc; + + vmh = handle; + if (vmh == NULL) { + dprintf("%s: vmh not found.\n", __func__); + return; + } + + sc = vmh->sc; + if (sc == NULL) { + dprintf("%s: sc is NULL\n", __func__); + return; + } + + if (vmh->enclave == NULL) { + dprintf("%s: Enclave not found.\n", __func__); + return; + } + + sgx_enclave_remove(sc, vmh->enclave); + free(vmh, M_SGX); + + dprintf("%s: Free epc pages: %d\n", + __func__, sgx_count_epc_pages(sc)); +} + +static int +sgx_pg_fault(vm_object_t object, vm_ooffset_t offset, + int prot, vm_page_t *mres) +{ + struct sgx_enclave *enclave; + struct sgx_vm_handle *vmh; + vm_page_t page; + vm_memattr_t memattr; + vm_pindex_t pidx; + struct sgx_enclave_page *enclave_page_tmp; + struct sgx_enclave_page *enclave_page; + struct epc_page *epc; + bool found; + + vmh = object->handle; + if (vmh == NULL) + return (VM_PAGER_FAIL); + + enclave = vmh->enclave; + if (enclave == NULL) + return (VM_PAGER_FAIL); + + dprintf("%s: offset 0x%lx\n", __func__, offset); + + memattr = object->memattr; + pidx = OFF_TO_IDX(offset); + + found = false; + mtx_lock(&enclave->mtx); + TAILQ_FOREACH_SAFE(enclave_page, &enclave->pages, next, + enclave_page_tmp) { + if ((vmh->base + offset) == enclave_page->addr) { + found = true; + break; + } + } + mtx_unlock(&enclave->mtx); + if (!found) { + dprintf("%s: Page not found.\n", __func__); + return (VM_PAGER_FAIL); + } + + epc = enclave_page->epc_page; + + page = PHYS_TO_VM_PAGE(epc->phys); + if (page == NULL) + return (VM_PAGER_FAIL); + + KASSERT(page->flags & PG_FICTITIOUS, + ("Not fictitious page %p", page)); + KASSERT(page->wire_count == 1, ("wire_count is not 1 %p", page)); + KASSERT(vm_page_busied(page) == 0, ("page %p is busy", page)); + + if (*mres != NULL) { + vm_page_lock(*mres); + vm_page_free(*mres); + vm_page_unlock(*mres); + *mres = NULL; + } + + vm_page_insert(page, object, pidx); + page->valid = VM_PAGE_BITS_ALL; + vm_page_xbusy(page); + + *mres = page; + + return (VM_PAGER_OK); +} + +static struct cdev_pager_ops sgx_pg_ops = { + .cdev_pg_ctor = sgx_pg_ctor, + .cdev_pg_dtor = sgx_pg_dtor, + .cdev_pg_fault = sgx_pg_fault, +}; + +static int +sgx_ioctl_create(struct sgx_softc *sc, struct sgx_enclave_create *param) +{ + struct sgx_vm_handle *vmh; + vm_map_entry_t entry; + vm_object_t mem; + struct sgx_enclave_page *secs_page; + struct page_info pginfo; + struct secinfo secinfo; + struct sgx_enclave *enclave; + struct epc_page *epc; + struct secs *secs; + int ret; + + epc = NULL; + secs = NULL; + enclave = NULL; + + /* SGX Enclave Control Structure (SECS) */ + secs = (struct secs *)kmem_alloc_contig(kmem_arena, PAGE_SIZE, + M_WAITOK | M_ZERO, 0, BUS_SPACE_MAXADDR_32BIT, + PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); + if (secs == NULL) { + dprintf("%s: Can't allocate memory.\n", __func__); + ret = ENOMEM; + goto error; + } + + ret = copyin((void *)param->src, secs, sizeof(struct secs)); + if (ret) { + dprintf("%s: Can't copy SECS.\n", __func__); + goto error; + } + + ret = sgx_mem_find(sc, secs->base, &entry, &mem); + if (ret) { + dprintf("%s: Can't find vm_map.\n", __func__); + goto error; + } + + vmh = mem->handle; + if (!vmh) { + dprintf("%s: Can't find vmh.\n", __func__); + ret = ENXIO; + goto error; + } + vmh->base = (entry->start - entry->offset); + + ret = sgx_enclave_alloc(sc, secs, &enclave); + if (ret) { + dprintf("%s: Can't alloc enclave.\n", __func__); + goto error; + } + + memset(&secinfo, 0, sizeof(struct secinfo)); + memset(&pginfo, 0, sizeof(struct page_info)); + pginfo.linaddr = 0; + pginfo.srcpge = (uint64_t)secs; + pginfo.secinfo = &secinfo; + pginfo.secs = 0; + + ret = sgx_get_epc_page(sc, &epc); + if (ret) { + dprintf("%s: Failed to get free epc page.\n", __func__); + goto error; + } + + ret = sgx_enclave_page_construct(sc, enclave, &enclave->secs_page); + if (ret) { + dprintf("%s: Can't construct page.\n", __func__); + goto error; + } + + secs_page = &enclave->secs_page; + secs_page->epc_page = epc; + + mtx_lock(&sc->mtx); + sgx_ecreate(&pginfo, (void *)epc->base); + TAILQ_INSERT_TAIL(&sc->enclaves, enclave, next); + mtx_unlock(&sc->mtx); + + kmem_free(kmem_arena, (vm_offset_t)secs, PAGE_SIZE); + + enclave->vmh = vmh; + vmh->enclave = enclave; + + return (0); + +error: + if (secs != NULL) + kmem_free(kmem_arena, (vm_offset_t)secs, PAGE_SIZE); + sgx_put_epc_page(sc, epc); + free(enclave, M_SGX); + + return (ret); +} + +static int +sgx_ioctl_add_page(struct sgx_softc *sc, + struct sgx_enclave_add_page *addp) +{ + struct sgx_enclave_page *enclave_page; + struct epc_page *secs_epc_page; + struct sgx_enclave *enclave; + struct epc_page *epc; + struct page_info pginfo; + struct secinfo secinfo; + void *tmp_vaddr; + uint64_t page_type; + struct proc *proc; + struct tcs *t; + pmap_t pmap; + int ret; + + tmp_vaddr = NULL; + enclave_page = NULL; + epc = NULL; + + ret = sgx_enclave_find(sc, addp->addr, &enclave); + if (ret) { + dprintf("%s: Failed to find enclave.\n", __func__); + goto error; + } + + ret = sgx_get_epc_page(sc, &epc); + if (ret) { + dprintf("%s: Failed to get free epc page.\n", __func__); + goto error; + } + + proc = curthread->td_proc; + pmap = vm_map_pmap(&proc->p_vmspace->vm_map); + + memset(&secinfo, 0, sizeof(struct secinfo)); + ret = copyin((void *)addp->secinfo, &secinfo, + sizeof(struct secinfo)); + if (ret) { + dprintf("%s: Failed to copy secinfo.\n", __func__); + goto error; + } + + tmp_vaddr = (void *)kmem_alloc_contig(kmem_arena, PAGE_SIZE, + M_WAITOK | M_ZERO, 0, BUS_SPACE_MAXADDR_32BIT, + PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); + if (tmp_vaddr == NULL) { + dprintf("%s: Failed to alloc memory.\n", __func__); + ret = ENOMEM; + goto error; + } + + ret = copyin((void *)addp->src, tmp_vaddr, PAGE_SIZE); + if (ret) { + dprintf("%s: Failed to copy page.\n", __func__); + goto error; + } + + page_type = (secinfo.flags & SECINFO_FLAGS_PT_M) >> \ + SECINFO_FLAGS_PT_S; + if (page_type == PT_TCS) { + t = (struct tcs *)tmp_vaddr; + ret = sgx_tcs_validate(t); + if (ret) { + dprintf("%s: TCS page validation failed.\n", + __func__); + goto error; + } + sgx_tcs_dump(sc, t); + } + + enclave_page = malloc(sizeof(struct sgx_enclave_page), + M_SGX, M_WAITOK | M_ZERO); + if (enclave_page == NULL) { + dprintf("%s: Can't allocate enclave page.\n", __func__); + ret = ENOMEM; + goto error; + } + + ret = sgx_enclave_page_construct(sc, enclave, enclave_page); + if (ret) { + dprintf("%s: Can't construct page.\n", __func__); + goto error; + } + + enclave_page->epc_page = epc; + enclave_page->addr = addp->addr; + secs_epc_page = enclave->secs_page.epc_page; + + memset(&pginfo, 0, sizeof(struct page_info)); + pginfo.linaddr = (uint64_t)addp->addr; + pginfo.srcpge = (uint64_t)tmp_vaddr; + pginfo.secinfo = &secinfo; + pginfo.secs = (uint64_t)secs_epc_page->base; + + mtx_lock(&sc->mtx); + sgx_eadd(&pginfo, (void *)epc->base); + mtx_unlock(&sc->mtx); + + kmem_free(kmem_arena, (vm_offset_t)tmp_vaddr, PAGE_SIZE); + + sgx_measure_page(sc, enclave->secs_page.epc_page, epc, addp->mrmask); + + mtx_lock(&enclave->mtx); + TAILQ_INSERT_TAIL(&enclave->pages, enclave_page, next); + mtx_unlock(&enclave->mtx); + + return (0); + +error: + if (tmp_vaddr != NULL) + kmem_free(kmem_arena, (vm_offset_t)tmp_vaddr, PAGE_SIZE); + + sgx_put_epc_page(sc, epc); + free(enclave_page, M_SGX); + + return (ret); +} + +static int +sgx_ioctl_init(struct sgx_softc *sc, struct sgx_enclave_init *initp) +{ + struct epc_page *secs_epc_page; + struct sgx_enclave *enclave; + struct thread *td; + void *tmp_vaddr; + void *einittoken; + void *sigstruct; + int retry; + int ret; + + td = curthread; + tmp_vaddr = NULL; + + dprintf("%s: addr %lx, sigstruct %lx, einittoken %lx\n", + __func__, initp->addr, initp->sigstruct, initp->einittoken); + + ret = sgx_enclave_find(sc, initp->addr, &enclave); + if (ret) { + dprintf("%s: Failed to get enclave.\n", __func__); + goto error; + } + + tmp_vaddr = (void *)kmem_alloc_contig(kmem_arena, PAGE_SIZE, + M_WAITOK | M_ZERO, 0, BUS_SPACE_MAXADDR_32BIT, + PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); + if (tmp_vaddr == NULL) { + dprintf("%s: Failed to alloc memory.\n", __func__); + ret = ENOMEM; + goto error; + } + + sigstruct = tmp_vaddr; + einittoken = (void *)((uint64_t)sigstruct + PAGE_SIZE / 2); + + ret = copyin((void *)initp->sigstruct, sigstruct, + SIGSTRUCT_SIZE); + if (ret) { + dprintf("%s: Failed to copy SIGSTRUCT page.\n", __func__); + goto error; + } + + ret = copyin((void *)initp->einittoken, einittoken, + EINITTOKEN_SIZE); + if (ret) { + dprintf("%s: Failed to copy EINITTOKEN page.\n", __func__); + goto error; + } + + secs_epc_page = enclave->secs_page.epc_page; + retry = 16; + do { + mtx_lock(&sc->mtx); + ret = sgx_einit(sigstruct, (void *)secs_epc_page->base, + einittoken); + mtx_unlock(&sc->mtx); + dprintf("%s: sgx_einit returned %d\n", __func__, ret); + } while (ret == SGX_UNMASKED_EVENT && retry--); + + if (ret) { + dprintf("%s: Failed init enclave: %d\n", __func__, ret); + td->td_retval[0] = ret; + ret = 0; + } + +error: + if (tmp_vaddr != NULL) + kmem_free(kmem_arena, (vm_offset_t)tmp_vaddr, PAGE_SIZE); + + return (ret); +} + +static int +sgx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, + struct thread *td) +{ + struct sgx_enclave_add_page *addp; + struct sgx_enclave_create *param; + struct sgx_enclave_init *initp; + struct sgx_softc *sc; + uint8_t data[IOCTL_MAX_DATA_LEN]; + int ret; + int len; + + sc = dev->si_drv1; + + len = IOCPARM_LEN(cmd); + + dprintf("%s: cmd %lx, len %d\n", __func__, cmd, len); + + if (len > IOCTL_MAX_DATA_LEN) + return (EINVAL); + + ret = copyin(addr, data, len); + if (ret) { + dprintf("%s: Can't copy data.\n", __func__); + return (EINVAL); + } + + switch (cmd) { + case SGX_IOC_ENCLAVE_CREATE: + param = (struct sgx_enclave_create *)data; + ret = sgx_ioctl_create(sc, param); + break; + case SGX_IOC_ENCLAVE_ADD_PAGE: + addp = (struct sgx_enclave_add_page *)data; + ret = sgx_ioctl_add_page(sc, addp); + break; + case SGX_IOC_ENCLAVE_INIT: + initp = (struct sgx_enclave_init *)data; + ret = sgx_ioctl_init(sc, initp); + break; + default: + return (EINVAL); + } + + return (ret); +} + +static int +sgx_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, + vm_size_t mapsize, struct vm_object **objp, int nprot) +{ + struct sgx_vm_handle *vmh; + struct sgx_softc *sc; + + sc = cdev->si_drv1; + + dprintf("%s: mapsize 0x%lx, offset %lx\n", + __func__, mapsize, *offset); + + vmh = malloc(sizeof(struct sgx_vm_handle), + M_SGX, M_WAITOK | M_ZERO); + if (vmh == NULL) { + dprintf("%s: Can't alloc memory.\n", __func__); + return (ENOMEM); + } + + vmh->sc = sc; + vmh->size = mapsize; + vmh->mem = cdev_pager_allocate(vmh, OBJT_MGTDEVICE, &sgx_pg_ops, + mapsize, nprot, *offset, NULL); + if (vmh->mem == NULL) { + free(vmh, M_SGX); + return (ENOMEM); + } + + *objp = vmh->mem; + + return (0); +} + +static struct cdevsw sgx_cdevsw = { + .d_version = D_VERSION, + .d_ioctl = sgx_ioctl, + .d_mmap_single = sgx_mmap_single, + .d_name = "Intel SGX", +}; + +static int +sgx_get_epc_area(struct sgx_softc *sc) +{ + vm_offset_t epc_base_vaddr; + u_int cp[4]; + int error; + int i; + + cpuid_count(SGX_CPUID, 0x2, cp); + + sc->epc_base = ((uint64_t)(cp[1] & 0xfffff) << 32) + \ + (cp[0] & 0xfffff000); + sc->epc_size = ((uint64_t)(cp[3] & 0xfffff) << 32) + \ + (cp[2] & 0xfffff000); + sc->npages = sc->epc_size / SGX_PAGE_SIZE; + + epc_base_vaddr = (vm_offset_t)pmap_mapdev_attr(sc->epc_base, + sc->epc_size, VM_MEMATTR_DEFAULT); + + sc->epc_pages = malloc(sizeof(struct epc_page) * sc->npages, + M_DEVBUF, M_WAITOK | M_ZERO); + if (sc->epc_pages == NULL) { + dprintf("%s: Can't alloc memory.\n", __func__); + return (ENOMEM); + } + + for (i = 0; i < sc->npages; i++) { + sc->epc_pages[i].base = epc_base_vaddr + SGX_PAGE_SIZE * i; + sc->epc_pages[i].phys = sc->epc_base + SGX_PAGE_SIZE * i; + sc->epc_pages[i].used = 0; + } + + error = vm_phys_fictitious_reg_range(sc->epc_base, + sc->epc_base + sc->epc_size, VM_MEMATTR_DEFAULT); + if (error) { + printf("%s: Can't register fictitious space.\n", __func__); + free(sc->epc_pages, M_SGX); + return (EINVAL); + } + + return (0); +} + +static void +sgx_put_epc_area(struct sgx_softc *sc) +{ + + vm_phys_fictitious_unreg_range(sc->epc_base, + sc->epc_base + sc->epc_size); + + free(sc->epc_pages, M_SGX); +} + +static int +sgx_load(void) +{ + struct sgx_softc *sc; + int error; + + sc = &sgx_sc; + + if ((cpu_stdext_feature & CPUID_STDEXT_SGX) == 0) + return (ENXIO); + + mtx_init(&sc->mtx, "SGX", NULL, MTX_DEF); + mtx_init(&sc->mtx_epc, "SGX EPC area", NULL, MTX_DEF); + + error = sgx_get_epc_area(sc); + if (error) { + printf("%s: Failed to get Processor Reserved Memory area.\n", + __func__); + return (ENXIO); + } + + TAILQ_INIT(&sc->enclaves); + + sc->sgx_cdev = make_dev(&sgx_cdevsw, 0, UID_ROOT, GID_WHEEL, + 0600, "isgx"); + if (sc->sgx_cdev == NULL) { + printf("%s: Failed to create character device.\n", + __func__); + sgx_put_epc_area(sc); + return (ENXIO); + } + sc->sgx_cdev->si_drv1 = sc; + + printf("SGX initialized: EPC base 0x%lx size %ld (%d pages)\n", + sc->epc_base, sc->epc_size, sc->npages); + + return (0); +} + +static int +sgx_unload(void) +{ + struct sgx_softc *sc; + + sc = &sgx_sc; + + if (!TAILQ_EMPTY(&sc->enclaves)) + return (EBUSY); + + destroy_dev(sc->sgx_cdev); + + sgx_put_epc_area(sc); + + mtx_destroy(&sc->mtx); + mtx_destroy(&sc->mtx_epc); + + return (0); +} + +static int +sgx_handler(module_t mod, int what, void *arg) +{ + int error; + + switch (what) { + case MOD_LOAD: + error = sgx_load(); + break; + case MOD_UNLOAD: + error = sgx_unload(); + break; + default: + error = 0; + break; + } + + return (error); +} + +static moduledata_t sgx_kmod = { + "sgx", + sgx_handler, + NULL +}; + +DECLARE_MODULE(sgx, sgx_kmod, SI_SUB_LAST, SI_ORDER_ANY); +MODULE_VERSION(sgx, 1); Index: sys/amd64/sgx/sgx_linux.c =================================================================== --- /dev/null +++ sys/amd64/sgx/sgx_linux.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2017 Ruslan Bukin + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define SGX_LINUX_IOCTL_MIN (SGX_IOC_ENCLAVE_CREATE & 0xffff) +#define SGX_LINUX_IOCTL_MAX (SGX_IOC_ENCLAVE_INIT & 0xffff) + +static int +sgx_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) +{ + cap_rights_t rights; + struct file *fp; + u_long cmd; + int error; + + error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + if (error != 0) + return (error); + + cmd = args->cmd; + + error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td)); + fdrop(fp, td); + + return (error); +} + +static struct linux_ioctl_handler sgx_linux_handler = { + sgx_linux_ioctl, + SGX_LINUX_IOCTL_MIN, + SGX_LINUX_IOCTL_MAX, +}; + +SYSINIT(sgx_linux_register, SI_SUB_KLD, SI_ORDER_MIDDLE, + linux_ioctl_register_handler, &sgx_linux_handler); +SYSUNINIT(sgx_linux_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, + linux_ioctl_unregister_handler, &sgx_linux_handler); + +static int +sgx_linux_modevent(module_t mod, int type, void *data) +{ + + return (0); +} + +DEV_MODULE(sgx_linux, sgx_linux_modevent, NULL); +MODULE_DEPEND(sgx_linux, linux64, 1, 1, 1); Index: sys/modules/Makefile =================================================================== --- sys/modules/Makefile +++ sys/modules/Makefile @@ -346,6 +346,8 @@ ${_sf} \ ${_sfxge} \ sge \ + ${_sgx} \ + ${_sgx_linux} \ siba_bwn \ siftr \ siis \ @@ -709,6 +711,8 @@ _qlxgbe= qlxgbe _qlnx= qlnx _sfxge= sfxge +_sgx= sgx +_sgx_linux= sgx_linux .if ${MK_BHYVE} != "no" || defined(ALL_MODULES) _vmm= vmm Index: sys/modules/sgx/Makefile =================================================================== --- /dev/null +++ sys/modules/sgx/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/amd64/sgx + +KMOD= sgx +SRCS= sgx.c sgx.h + +.include Index: sys/modules/sgx_linux/Makefile =================================================================== --- /dev/null +++ sys/modules/sgx_linux/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/amd64/sgx + +KMOD= sgx_linux +SRCS= sgx_linux.c + +.include