Index: sys/amd64/include/cpufunc.h
===================================================================
--- sys/amd64/include/cpufunc.h
+++ sys/amd64/include/cpufunc.h
@@ -802,6 +802,97 @@
write_rflags(rflags);
}
+enum {
+ SGX_ECREATE = 0x0,
+ SGX_EADD = 0x1,
+ SGX_EINIT = 0x2,
+ SGX_EREMOVE = 0x3,
+ SGX_EDGBRD = 0x4,
+ SGX_EDGBWR = 0x5,
+ SGX_EEXTEND = 0x6,
+ SGX_ELDU = 0x8,
+ SGX_EBLOCK = 0x9,
+ SGX_EPA = 0xA,
+ SGX_EWB = 0xB,
+ SGX_ETRACK = 0xC,
+};
+
+enum {
+ SGX_PT_SECS = 0x00,
+ SGX_PT_TCS = 0x01,
+ SGX_PT_REG = 0x02,
+ SGX_PT_VA = 0x03,
+ SGX_PT_TRIM = 0x04,
+};
+
+static __inline int
+sgx_encls(uint64_t rax, uint64_t rbx, uint64_t rcx, uint64_t rdx)
+{
+ int oeax;
+
+ __asm __volatile(
+ ".byte 0x0f, 0x01, 0xcf"
+ :"=a"(oeax)
+ :"a"((uint32_t)rax),
+ "b"(rbx),
+ "c"(rcx),
+ "d"(rdx)
+ :"memory");
+
+ return (oeax);
+}
+
+static __inline void
+sgx_ecreate(void *pginfo, void *secs)
+{
+
+ sgx_encls(SGX_ECREATE, (uint64_t)pginfo, (uint64_t)secs, 0);
+}
+
+static __inline void
+sgx_eadd(void *pginfo, void *epc)
+{
+
+ sgx_encls(SGX_EADD, (uint64_t)pginfo, (uint64_t)epc, 0);
+}
+
+static __inline int
+sgx_einit(void *sigstruct, void *secs, void *einittoken)
+{
+
+ return (sgx_encls(SGX_EINIT, (uint64_t)sigstruct,
+ (uint64_t)secs, (uint64_t)einittoken));
+}
+
+static __inline void
+sgx_eextend(void *secs, void *epc)
+{
+
+ sgx_encls(SGX_EEXTEND, (uint64_t)secs, (uint64_t)epc, 0);
+}
+
+static __inline void
+sgx_epa(void *epc)
+{
+
+ sgx_encls(SGX_EPA, SGX_PT_VA, (uint64_t)epc, 0);
+}
+
+static __inline int
+sgx_eldu(uint64_t rbx, uint64_t rcx,
+ uint64_t rdx)
+{
+
+ return (sgx_encls(SGX_ELDU, rbx, rcx, rdx));
+}
+
+static __inline void
+sgx_eremove(void *epc)
+{
+
+ sgx_encls(SGX_EREMOVE, 0, (uint64_t)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,64 @@
+/*-
+ * 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_
+
+#define SGX_MAGIC 0xA4
+#define SGX_IOC_ENCLAVE_CREATE \
+ _IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create)
+#define SGX_IOC_ENCLAVE_ADD_PAGE \
+ _IOW(SGX_MAGIC, 0x01, struct sgx_enclave_add_page)
+#define SGX_IOC_ENCLAVE_INIT \
+ _IOW(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;
+
+#endif /* !_MACHINE_SGX_H_ */
Index: sys/amd64/include/sgxreg.h
===================================================================
--- /dev/null
+++ sys/amd64/include/sgxreg.h
@@ -0,0 +1,155 @@
+/*-
+ * 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$
+ */
+
+/* Machine-defined variables. */
+
+#ifndef _MACHINE_SGXREG_H_
+#define _MACHINE_SGXREG_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 */
+
+/*
+ * 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);
+
+/*
+ * 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;
+#define SECS_ATTR_RSV4_SIZE 7
+ uint8_t reserved4[SECS_ATTR_RSV4_SIZE];
+ 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;
+#define SECS_RSV1_SIZE 24
+ uint8_t reserved1[SECS_RSV1_SIZE];
+ struct secs_attr attributes;
+ uint8_t mr_enclave[32];
+#define SECS_RSV2_SIZE 32
+ uint8_t reserved2[SECS_RSV2_SIZE];
+ uint8_t mr_signer[32];
+#define SECS_RSV3_SIZE 96
+ uint8_t reserved3[SECS_RSV3_SIZE];
+ uint16_t isv_prod_id;
+ uint16_t isv_svn;
+#define SECS_RSV4_SIZE 3836
+ uint8_t reserved4[SECS_RSV4_SIZE];
+};
+
+/*
+ * 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_SGXREG_H_ */
Index: sys/amd64/sgx/sgx.c
===================================================================
--- /dev/null
+++ sys/amd64/sgx/sgx.c
@@ -0,0 +1,1055 @@
+/*-
+ * 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_init(struct sgx_softc *sc,
+ struct sgx_enclave *enclave,
+ uint64_t addr)
+{
+ struct epc_page *epc;
+ vm_pindex_t pidx;
+ vm_page_t page;
+ vm_page_t p;
+ uint64_t va_page_idx;
+ uint64_t idx;
+ vm_object_t obj;
+ int va_slot;
+ int ret;
+
+ obj = enclave->obj;
+
+ VM_OBJECT_ASSERT_WLOCKED(obj);
+
+ pidx = OFF_TO_IDX(addr);
+
+ va_slot = pidx % SGX_VA_PAGE_SLOTS;
+ va_page_idx = pidx / SGX_VA_PAGE_SLOTS;
+ idx = - SGX_VA_PAGES_OFFS - va_page_idx;
+
+ p = vm_page_lookup(obj, idx);
+ if (p == NULL) {
+ ret = sgx_get_epc_page(sc, &epc);
+ if (ret) {
+ dprintf("%s: No free EPC pages available.\n",
+ __func__);
+ return (ret);
+ }
+
+ mtx_lock(&sc->mtx);
+ sgx_epa((void *)epc->base);
+ mtx_unlock(&sc->mtx);
+
+ page = PHYS_TO_VM_PAGE(epc->phys);
+
+ vm_page_insert(page, obj, idx);
+ page->valid = VM_PAGE_BITS_ALL;
+ }
+
+ return (0);
+}
+
+static int
+sgx_mem_find(struct sgx_softc *sc, uint64_t addr,
+ vm_map_entry_t *entry0, vm_object_t *mem0)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+
+ map = &curproc->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);
+ }
+
+ if (entry->object.vm_object == NULL) {
+ vm_map_unlock_read(map);
+ return (EINVAL);
+ }
+
+ vm_object_reference(entry->object.vm_object);
+
+ *mem0 = entry->object.vm_object;
+ *entry0 = entry;
+ vm_map_unlock_read(map);
+
+ return (0);
+}
+
+static int
+sgx_enclave_find(struct sgx_softc *sc, uint64_t addr,
+ struct sgx_enclave **encl)
+{
+ struct sgx_vm_handle *vmh;
+ struct sgx_enclave *enclave;
+ vm_map_entry_t entry;
+ vm_object_t mem;
+ int ret;
+
+ ret = sgx_mem_find(sc, addr, &entry, &mem);
+ if (ret)
+ return (ret);
+
+ KASSERT(mem != NULL, ("mem is NULL\n"));
+ KASSERT(mem->handle != NULL, ("mem->handle is NULL\n"));
+
+ vmh = mem->handle;
+
+ enclave = vmh->enclave;
+ enclave->obj = mem;
+
+ *encl = 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);
+
+ enclave->base = secs->base;
+ enclave->size = secs->size;
+
+ *enclave0 = enclave;
+
+ return (0);
+}
+
+static void
+sgx_epc_page_remove(struct sgx_softc *sc,
+ struct epc_page *epc)
+{
+
+ mtx_lock(&sc->mtx);
+ sgx_eremove((void *)epc->base);
+ mtx_unlock(&sc->mtx);
+ sgx_put_epc_page(sc, epc);
+}
+
+static void
+sgx_page_remove(struct sgx_softc *sc, vm_page_t p)
+{
+ struct epc_page *epc;
+ vm_paddr_t pa;
+ uint64_t offs;
+
+ pa = VM_PAGE_TO_PHYS(p);
+ epc = &sc->epc_pages[0];
+ offs = (pa - epc->phys) / PAGE_SIZE;
+ epc = &sc->epc_pages[offs];
+
+ sgx_epc_page_remove(sc, epc);
+}
+
+static void
+sgx_enclave_remove(struct sgx_softc *sc,
+ struct sgx_enclave *enclave)
+{
+ vm_object_t object;
+ vm_page_t p, p0;
+
+ mtx_lock(&sc->mtx);
+ TAILQ_REMOVE(&sc->enclaves, enclave, next);
+ mtx_unlock(&sc->mtx);
+
+ object = enclave->obj;
+
+ VM_OBJECT_WLOCK(enclave->obj);
+
+ /*
+ * First remove all the pages except SECS,
+ * then remove SECS page.
+ */
+ p0 = vm_page_lookup(enclave->obj, 0);
+ p = TAILQ_NEXT(p0, listq);
+
+ while (p) {
+ vm_page_lock(p);
+ vm_page_remove(p);
+ vm_page_unlock(p);
+ sgx_page_remove(sc, p);
+ p = TAILQ_NEXT(p, listq);
+ }
+
+ /* Now remove SECS page */
+ vm_page_lock(p0);
+ vm_page_remove(p0);
+ vm_page_unlock(p0);
+ sgx_page_remove(sc, p0);
+
+ KASSERT(TAILQ_EMPTY(&object->memq) == 1, ("not empty"));
+ KASSERT(object->resident_page_count == 0, ("count"));
+
+ VM_OBJECT_WUNLOCK(enclave->obj);
+}
+
+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 *)(epc->base + i));
+ }
+
+ mtx_unlock(&sc->mtx);
+}
+
+static int
+sgx_secs_validate(struct sgx_softc *sc, struct secs *secs)
+{
+ struct secs_attr *attr;
+ int i;
+
+ if (secs->size == 0)
+ return (EINVAL);
+
+ if ((secs->size & (secs->size - 1)) != 0)
+ return (EINVAL);
+
+ attr = &secs->attributes;
+
+ if (attr->reserved1 != 0 ||
+ attr->reserved2 != 0 ||
+ attr->reserved3 != 0)
+ return (EINVAL);
+
+ for (i = 0; i < SECS_ATTR_RSV4_SIZE; i++)
+ if (attr->reserved4[i])
+ return (EINVAL);
+
+ /*
+ * IntelĀ® Software Guard Extensions Programming Reference
+ * 6.7.2 Relevant Fields in Various Data Structures
+ * 6.7.2.1 SECS.ATTRIBUTES.XFRM
+ * XFRM[1:0] must be set to 0x3.
+ */
+ if ((attr->xfrm & 0x3) != 0x3)
+ return (EINVAL);
+
+ if (!attr->mode64bit)
+ return (EINVAL);
+
+ if (secs->size > sc->enclave_size_max)
+ return (EINVAL);
+
+ for (i = 0; i < SECS_RSV1_SIZE; i++)
+ if (secs->reserved1[i])
+ return (EINVAL);
+
+ for (i = 0; i < SECS_RSV2_SIZE; i++)
+ if (secs->reserved2[i])
+ return (EINVAL);
+
+ for (i = 0; i < SECS_RSV3_SIZE; i++)
+ if (secs->reserved3[i])
+ return (EINVAL);
+
+ for (i = 0; i < SECS_RSV4_SIZE; i++)
+ if (secs->reserved4[i])
+ return (EINVAL);
+
+ return (0);
+}
+
+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->enclave, M_SGX);
+ 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)
+{
+
+ printf("%s: offset 0x%lx\n", __func__, offset);
+
+ return (VM_PAGER_FAIL);
+}
+
+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 void
+sgx_insert_epc_page(struct sgx_enclave *enclave,
+ struct epc_page *epc, uint64_t addr)
+{
+ vm_pindex_t pidx;
+ vm_page_t page;
+
+ VM_OBJECT_ASSERT_WLOCKED(enclave->obj);
+
+ pidx = OFF_TO_IDX(addr);
+ page = PHYS_TO_VM_PAGE(epc->phys);
+ vm_page_insert(page, enclave->obj, pidx);
+ page->valid = VM_PAGE_BITS_ALL;
+}
+
+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;
+ vm_page_t p;
+ struct page_info pginfo;
+ struct secinfo secinfo;
+ struct sgx_enclave *enclave;
+ struct epc_page *epc;
+ struct secs *secs;
+ vm_object_t obj;
+ int ret;
+
+ epc = NULL;
+ secs = NULL;
+ enclave = NULL;
+ obj = NULL;
+
+ /* SGX Enclave Control Structure (SECS) */
+ secs = malloc(PAGE_SIZE, M_SGX, M_WAITOK | M_ZERO);
+ ret = copyin((void *)param->src, secs, sizeof(struct secs));
+ if (ret) {
+ dprintf("%s: Can't copy SECS.\n", __func__);
+ goto error;
+ }
+
+ ret = sgx_secs_validate(sc, secs);
+ if (ret) {
+ dprintf("%s: SECS validation failed.\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;
+ }
+ obj = entry->object.vm_object;
+
+ vmh = mem->handle;
+ if (!vmh) {
+ dprintf("%s: Can't find vmh.\n", __func__);
+ ret = ENXIO;
+ goto error;
+ }
+
+ dprintf("%s: entry start %lx offset %lx\n",
+ __func__, entry->start, entry->offset);
+ 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;
+ }
+ enclave->obj = obj;
+ enclave->vmh = vmh;
+
+ 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;
+ }
+ enclave->secs_epc_page = epc;
+
+ VM_OBJECT_WLOCK(obj);
+ p = vm_page_lookup(obj, 0);
+ if (p) {
+ VM_OBJECT_WUNLOCK(obj);
+ /* SECS page already added. */
+ ret = ENXIO;
+ goto error;
+ }
+
+ ret = sgx_va_slot_init(sc, enclave, 0);
+ if (ret) {
+ VM_OBJECT_WUNLOCK(obj);
+ dprintf("%s: Can't init va slot.\n", __func__);
+ goto error;
+ }
+
+ mtx_lock(&sc->mtx);
+ if ((sc->state & SGX_STATE_RUNNING) == 0) {
+ mtx_unlock(&sc->mtx);
+ /* Remove VA page that was just created for SECS page. */
+ p = vm_page_lookup(enclave->obj, -SGX_VA_PAGES_OFFS);
+ sgx_page_remove(sc, p);
+ VM_OBJECT_WUNLOCK(obj);
+
+ sgx_epc_page_remove(sc, epc);
+ goto error;
+ }
+ sgx_ecreate(&pginfo, (void *)epc->base);
+ TAILQ_INSERT_TAIL(&sc->enclaves, enclave, next);
+ mtx_unlock(&sc->mtx);
+
+ vmh->enclave = enclave;
+ sgx_insert_epc_page(enclave, epc, 0);
+ VM_OBJECT_WUNLOCK(obj);
+
+ /* Release the reference. */
+ vm_object_deallocate(obj);
+
+ free(secs, M_SGX);
+
+ return (0);
+
+error:
+ free(secs, M_SGX);
+ sgx_put_epc_page(sc, epc);
+ free(enclave, M_SGX);
+ vm_object_deallocate(obj);
+
+ return (ret);
+}
+
+static int
+sgx_ioctl_add_page(struct sgx_softc *sc,
+ struct sgx_enclave_add_page *addp)
+{
+ struct epc_page *secs_epc_page;
+ struct sgx_enclave *enclave;
+ struct sgx_vm_handle *vmh;
+ struct epc_page *epc;
+ struct page_info pginfo;
+ struct secinfo secinfo;
+ vm_object_t obj;
+ void *tmp_vaddr;
+ uint64_t page_type;
+ struct tcs *t;
+ uint64_t addr;
+ uint64_t pidx;
+ vm_page_t p;
+ int ret;
+
+ tmp_vaddr = NULL;
+ epc = NULL;
+ obj = NULL;
+
+ /* Find and get reference to VM object. */
+ ret = sgx_enclave_find(sc, addp->addr, &enclave);
+ if (ret) {
+ dprintf("%s: Failed to find enclave.\n", __func__);
+ goto error;
+ }
+
+ obj = enclave->obj;
+ KASSERT(obj != NULL, ("vm object is NULL\n"));
+ vmh = obj->handle;
+
+ ret = sgx_get_epc_page(sc, &epc);
+ if (ret) {
+ dprintf("%s: Failed to get free epc page.\n", __func__);
+ goto error;
+ }
+
+ 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 = malloc(PAGE_SIZE, M_SGX, M_WAITOK | M_ZERO);
+ 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 == SGX_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);
+ }
+
+ addr = (addp->addr - vmh->base);
+ pidx = OFF_TO_IDX(addr);
+
+ VM_OBJECT_WLOCK(obj);
+ p = vm_page_lookup(obj, pidx);
+ if (p) {
+ VM_OBJECT_WUNLOCK(obj);
+ /* Page already added. */
+ ret = ENXIO;
+ goto error;
+ }
+
+ ret = sgx_va_slot_init(sc, enclave, addr);
+ if (ret) {
+ VM_OBJECT_WUNLOCK(obj);
+ dprintf("%s: Can't init va slot.\n", __func__);
+ goto error;
+ }
+
+ secs_epc_page = enclave->secs_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);
+
+ sgx_measure_page(sc, enclave->secs_epc_page, epc, addp->mrmask);
+
+ sgx_insert_epc_page(enclave, epc, addr);
+
+ VM_OBJECT_WUNLOCK(obj);
+
+ /* Release the reference. */
+ vm_object_deallocate(obj);
+
+ free(tmp_vaddr, M_SGX);
+
+ return (0);
+
+error:
+ free(tmp_vaddr, M_SGX);
+ sgx_put_epc_page(sc, epc);
+ vm_object_deallocate(obj);
+
+ 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;
+ vm_object_t obj;
+ int retry;
+ int ret;
+
+ td = curthread;
+ tmp_vaddr = NULL;
+ obj = NULL;
+
+ dprintf("%s: addr %lx, sigstruct %lx, einittoken %lx\n",
+ __func__, initp->addr, initp->sigstruct, initp->einittoken);
+
+ /* Find and get reference to VM object. */
+ ret = sgx_enclave_find(sc, initp->addr, &enclave);
+ if (ret) {
+ dprintf("%s: Failed to find enclave.\n", __func__);
+ goto error;
+ }
+
+ obj = enclave->obj;
+
+ tmp_vaddr = malloc(PAGE_SIZE, M_SGX, M_WAITOK | M_ZERO);
+ sigstruct = tmp_vaddr;
+ einittoken = (void *)((uint64_t)sigstruct + PAGE_SIZE / 2);
+
+ ret = copyin((void *)initp->sigstruct, sigstruct,
+ SGX_SIGSTRUCT_SIZE);
+ if (ret) {
+ dprintf("%s: Failed to copy SIGSTRUCT page.\n", __func__);
+ goto error;
+ }
+
+ ret = copyin((void *)initp->einittoken, einittoken,
+ SGX_EINITTOKEN_SIZE);
+ if (ret) {
+ dprintf("%s: Failed to copy EINITTOKEN page.\n", __func__);
+ goto error;
+ }
+
+ secs_epc_page = enclave->secs_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:
+ free(tmp_vaddr, M_SGX);
+
+ /* Release the reference. */
+ vm_object_deallocate(obj);
+
+ 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;
+ int ret;
+ int len;
+
+ sc = &sgx_sc;
+
+ len = IOCPARM_LEN(cmd);
+
+ dprintf("%s: cmd %lx, addr %lx, len %d\n",
+ __func__, cmd, (uint64_t)addr, len);
+
+ if (len > SGX_IOCTL_MAX_DATA_LEN)
+ return (EINVAL);
+
+ switch (cmd) {
+ case SGX_IOC_ENCLAVE_CREATE:
+ param = (struct sgx_enclave_create *)addr;
+ ret = sgx_ioctl_create(sc, param);
+ break;
+ case SGX_IOC_ENCLAVE_ADD_PAGE:
+ addp = (struct sgx_enclave_add_page *)addr;
+ ret = sgx_ioctl_add_page(sc, addp);
+ break;
+ case SGX_IOC_ENCLAVE_INIT:
+ initp = (struct sgx_enclave_init *)addr;
+ 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;
+ vm_object_t object;
+
+ sc = &sgx_sc;
+
+ dprintf("%s: mapsize 0x%lx, offset %lx\n",
+ __func__, mapsize, *offset);
+
+ vmh = malloc(sizeof(struct sgx_vm_handle),
+ M_SGX, M_WAITOK | M_ZERO);
+ 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);
+ }
+
+ object = vmh->mem;
+ vm_object_set_flag(object, OBJ_PG_DTOR);
+ *objp = object;
+
+ 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;
+
+ if (cp[3] & 0xffff) {
+ sc->enclave_size_max = (1 << ((cp[3] >> 8) & 0xff));
+ } else {
+ sc->enclave_size_max = SGX_ENCL_SIZE_MAX_DEF;
+ }
+
+ 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);
+
+ 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->state |= SGX_STATE_RUNNING;
+
+ 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;
+
+ mtx_lock(&sc->mtx);
+ if (!TAILQ_EMPTY(&sc->enclaves)) {
+ mtx_unlock(&sc->mtx);
+ return (EBUSY);
+ }
+ sc->state &= ~SGX_STATE_RUNNING;
+ mtx_unlock(&sc->mtx);
+
+ 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,119 @@
+/*-
+ * 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
+
+#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)
+{
+ uint8_t data[SGX_IOCTL_MAX_DATA_LEN];
+ cap_rights_t rights;
+ struct file *fp;
+ u_long cmd;
+ int error;
+ int len;
+
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
+ return (error);
+
+ cmd = args->cmd;
+
+ args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT);
+ if (cmd & LINUX_IOC_IN)
+ args->cmd |= IOC_IN;
+ if (cmd & LINUX_IOC_OUT)
+ args->cmd |= IOC_OUT;
+
+ len = IOCPARM_LEN(cmd);
+ if (len > SGX_IOCTL_MAX_DATA_LEN) {
+ printf("%s: Can't copy data: cmd len is too big %d\n",
+ __func__, len);
+ return (EINVAL);
+ }
+
+ if (cmd & LINUX_IOC_IN) {
+ error = copyin((void *)args->arg, data, len);
+ if (error) {
+ printf("%s: Can't copy data, error %d\n",
+ __func__, error);
+ return (EINVAL);
+ }
+ }
+
+ error = (fo_ioctl(fp, args->cmd, (caddr_t)data, 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/amd64/sgx/sgxvar.h
===================================================================
--- /dev/null
+++ sys/amd64/sgx/sgxvar.h
@@ -0,0 +1,87 @@
+/*-
+ * 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_SGXVAR_H_
+#define _AMD64_SGX_SGXVAR_H_
+
+#define SGX_CPUID 0x12
+#define SGX_PAGE_SIZE 4096
+#define SGX_VA_PAGE_SLOTS 512
+#define SGX_VA_PAGES_OFFS 512
+#define SGX_SIGSTRUCT_SIZE 1808
+#define SGX_EINITTOKEN_SIZE 304
+#define SGX_IOCTL_MAX_DATA_LEN 26
+#define SGX_ENCL_SIZE_MAX_DEF 0x1000000000ULL
+
+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;
+};
+
+struct sgx_enclave {
+ uint64_t base;
+ uint64_t size;
+ struct sgx_vm_handle *vmh;
+ struct mtx mtx;
+ TAILQ_ENTRY(sgx_enclave) next;
+ vm_object_t obj;
+ struct epc_page *secs_epc_page;
+};
+
+struct sgx_softc {
+ struct cdev *sgx_cdev;
+ 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;
+ uint64_t enclave_size_max;
+ uint8_t state;
+#define SGX_STATE_RUNNING (1 << 0)
+};
+
+#endif /* !_AMD64_SGX_SGXVAR_H_ */
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 sgxvar.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