Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133292879
D11113.id31423.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
43 KB
Referenced Files
None
Subscribers
None
D11113.id31423.diff
View Options
Index: sys/amd64/include/cpufunc.h
===================================================================
--- sys/amd64/include/cpufunc.h
+++ sys/amd64/include/cpufunc.h
@@ -802,6 +802,85 @@
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,
+};
+
+int sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx);
+
+static __inline int
+sgx_ecreate(void *pginfo, void *secs)
+{
+
+ return (sgx_encls(SGX_ECREATE, (uint64_t)pginfo,
+ (uint64_t)secs, 0));
+}
+
+static __inline int
+sgx_eadd(void *pginfo, void *epc)
+{
+
+ return (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 int
+sgx_eextend(void *secs, void *epc)
+{
+
+ return (sgx_encls(SGX_EEXTEND, (uint64_t)secs,
+ (uint64_t)epc, 0));
+}
+
+static __inline int
+sgx_epa(void *epc)
+{
+
+ return (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 int
+sgx_eremove(void *epc)
+{
+
+ return (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 <br@bsdpad.com>
+ * 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 <br@bsdpad.com>
+ * 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(64);
+
+/*
+ * 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,1096 @@
+/*-
+ * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioccom.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/conf.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+#include <vm/vm_phys.h>
+#include <vm/vm_radix.h>
+#include <vm/pmap.h>
+
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+#include <machine/cpufunc.h>
+#include <machine/sgx.h>
+#include <machine/sgxreg.h>
+
+#include <amd64/sgx/sgxvar.h>
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#else
+#define dprintf(fmt, ...)
+#endif
+
+static struct cdev_pager_ops sgx_pg_ops;
+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 object;
+ int va_slot;
+ int ret;
+
+ object = enclave->object;
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+
+ 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(object, 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, object, 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 *object0)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ vm_object_t object;
+
+ 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);
+ }
+
+ object = entry->object.vm_object;
+ if (object == NULL || object->handle == NULL) {
+ vm_map_unlock_read(map);
+ return (EINVAL);
+ }
+
+ if ((object->type != OBJT_MGTDEVICE) ||
+ (object->un_pager.devp.ops != &sgx_pg_ops)) {
+ vm_map_unlock_read(map);
+ return (EINVAL);
+ }
+
+ vm_object_reference(object);
+
+ *object0 = 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 object;
+ int ret;
+
+ ret = sgx_mem_find(sc, addr, &entry, &object);
+ if (ret)
+ return (ret);
+
+ vmh = object->handle;
+ if (vmh == NULL) {
+ vm_object_deallocate(object);
+ return (EINVAL);
+ }
+
+ enclave = vmh->enclave;
+ if (enclave == NULL || enclave->object == NULL) {
+ vm_object_deallocate(object);
+ return (EINVAL);
+ }
+
+ *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);
+}
+
+static void
+sgx_page_remove(struct sgx_softc *sc, vm_page_t p)
+{
+ struct epc_page *epc;
+ vm_paddr_t pa;
+ uint64_t offs;
+
+ vm_page_lock(p);
+ vm_page_remove(p);
+ vm_page_unlock(p);
+
+ 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);
+ sgx_put_epc_page(sc, epc);
+}
+
+static void
+sgx_enclave_remove(struct sgx_softc *sc,
+ struct sgx_enclave *enclave)
+{
+ vm_object_t object;
+ vm_page_t p, p0, p_next;
+
+ mtx_lock(&sc->mtx);
+ TAILQ_REMOVE(&sc->enclaves, enclave, next);
+ mtx_unlock(&sc->mtx);
+
+ object = enclave->object;
+
+ VM_OBJECT_WLOCK(object);
+
+ /*
+ * First remove all the pages except SECS,
+ * then remove SECS page.
+ */
+ p0 = NULL;
+ TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) {
+ if (p->pindex == 0) {
+ p0 = p;
+ continue;
+ }
+ sgx_page_remove(sc, p);
+ }
+ /* Now remove SECS page */
+ if (p0 != NULL)
+ sgx_page_remove(sc, p0);
+
+ KASSERT(TAILQ_EMPTY(&object->memq) == 1, ("not empty"));
+ KASSERT(object->resident_page_count == 0, ("count"));
+
+ VM_OBJECT_WUNLOCK(object);
+}
+
+static int
+sgx_measure_page(struct sgx_softc *sc, struct epc_page *secs,
+ struct epc_page *epc, uint16_t mrmask)
+{
+ int i, j;
+ int ret;
+
+ mtx_lock(&sc->mtx);
+
+ for (i = 0, j = 1; i < PAGE_SIZE; i += 0x100, j <<= 1) {
+ if (!(j & mrmask))
+ continue;
+
+ ret = sgx_eextend((void *)secs->base,
+ (void *)(epc->base + i));
+ if (ret == SGX_EFAULT) {
+ mtx_unlock(&sc->mtx);
+ return (ret);
+ }
+ }
+
+ mtx_unlock(&sc->mtx);
+
+ return (0);
+}
+
+static int
+sgx_secs_validate(struct sgx_softc *sc, struct secs *secs)
+{
+ struct secs_attr *attr;
+ int i;
+
+ if (secs->size == 0)
+ return (EINVAL);
+
+ /* BASEADDR must be naturally aligned on an SECS.SIZE boundary. */
+ if (secs->base & (secs->size - 1))
+ return (EINVAL);
+
+ /* SECS.SIZE must be at least 2 pages. */
+ if (secs->size < 2 * PAGE_SIZE)
+ 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->object);
+
+ pidx = OFF_TO_IDX(addr);
+ page = PHYS_TO_VM_PAGE(epc->phys);
+ vm_page_insert(page, enclave->object, 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_page_t p;
+ struct page_info pginfo;
+ struct secinfo secinfo;
+ struct sgx_enclave *enclave;
+ struct epc_page *epc;
+ struct secs *secs;
+ vm_object_t object;
+ int ret;
+
+ epc = NULL;
+ secs = NULL;
+ enclave = NULL;
+ object = 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, &object);
+ if (ret) {
+ dprintf("%s: Can't find vm_map.\n", __func__);
+ goto error;
+ }
+
+ vmh = object->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->object = object;
+ 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(object);
+ p = vm_page_lookup(object, 0);
+ if (p) {
+ VM_OBJECT_WUNLOCK(object);
+ /* SECS page already added. */
+ ret = ENXIO;
+ goto error;
+ }
+
+ ret = sgx_va_slot_init(sc, enclave, 0);
+ if (ret) {
+ VM_OBJECT_WUNLOCK(object);
+ 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->object, -SGX_VA_PAGES_OFFS);
+ sgx_page_remove(sc, p);
+ VM_OBJECT_WUNLOCK(object);
+ goto error;
+ }
+ ret = sgx_ecreate(&pginfo, (void *)epc->base);
+ if (ret == SGX_EFAULT) {
+ dprintf("%s: gp fault\n", __func__);
+ mtx_unlock(&sc->mtx);
+ /* Remove VA page that was just created for SECS page. */
+ p = vm_page_lookup(enclave->object, -SGX_VA_PAGES_OFFS);
+ sgx_page_remove(sc, p);
+ VM_OBJECT_WUNLOCK(object);
+ goto error;
+ }
+
+ TAILQ_INSERT_TAIL(&sc->enclaves, enclave, next);
+ mtx_unlock(&sc->mtx);
+
+ vmh->enclave = enclave;
+ sgx_insert_epc_page(enclave, epc, 0);
+ VM_OBJECT_WUNLOCK(object);
+
+ /* Release the reference. */
+ vm_object_deallocate(object);
+
+ free(secs, M_SGX);
+
+ return (0);
+
+error:
+ free(secs, M_SGX);
+ sgx_put_epc_page(sc, epc);
+ free(enclave, M_SGX);
+ vm_object_deallocate(object);
+
+ 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 object;
+ 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;
+ object = 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;
+ }
+
+ object = enclave->object;
+ KASSERT(object != NULL, ("vm object is NULL\n"));
+ vmh = object->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(object);
+ p = vm_page_lookup(object, pidx);
+ if (p) {
+ VM_OBJECT_WUNLOCK(object);
+ /* Page already added. */
+ ret = ENXIO;
+ goto error;
+ }
+
+ ret = sgx_va_slot_init(sc, enclave, addr);
+ if (ret) {
+ VM_OBJECT_WUNLOCK(object);
+ 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);
+ ret = sgx_eadd(&pginfo, (void *)epc->base);
+ if (ret == SGX_EFAULT) {
+ dprintf("%s: gp fault on eadd\n", __func__);
+ mtx_unlock(&sc->mtx);
+ VM_OBJECT_WUNLOCK(object);
+ goto error;
+ }
+ mtx_unlock(&sc->mtx);
+
+ ret = sgx_measure_page(sc, enclave->secs_epc_page, epc, addp->mrmask);
+ if (ret == SGX_EFAULT) {
+ dprintf("%s: gp fault on eextend\n", __func__);
+ sgx_epc_page_remove(sc, epc);
+ VM_OBJECT_WUNLOCK(object);
+ goto error;
+ }
+
+ sgx_insert_epc_page(enclave, epc, addr);
+
+ VM_OBJECT_WUNLOCK(object);
+
+ /* Release the reference. */
+ vm_object_deallocate(object);
+
+ free(tmp_vaddr, M_SGX);
+
+ return (0);
+
+error:
+ free(tmp_vaddr, M_SGX);
+ sgx_put_epc_page(sc, epc);
+ vm_object_deallocate(object);
+
+ 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 object;
+ int retry;
+ int ret;
+
+ td = curthread;
+ tmp_vaddr = NULL;
+ object = 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;
+ }
+
+ object = enclave->object;
+
+ 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(object);
+
+ 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;
+
+ 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);
+ }
+
+ VM_OBJECT_WLOCK(vmh->mem);
+ vm_object_set_flag(vmh->mem, OBJ_PG_DTOR);
+ VM_OBJECT_WUNLOCK(vmh->mem);
+
+ *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;
+
+ 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");
+
+ 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 <br@bsdpad.com>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capsicum.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+
+#include <machine/sgx.h>
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_ioctl.h>
+
+#include <amd64/sgx/sgxvar.h>
+
+#include <sys/ioccom.h>
+
+#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/sgx_support.S
===================================================================
--- /dev/null
+++ sys/amd64/sgx/sgx_support.S
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
+ * 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$
+ */
+
+#include <machine/asmacros.h>
+#include <amd64/sgx/sgxvar.h>
+
+#include "assym.s"
+
+ .text
+
+/*
+ * int
+ * sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx);
+ * %edi, %rsi, %rdx, %rcx
+ */
+ENTRY(sgx_encls)
+ PUSH_FRAME_POINTER
+ pushq %rbx
+ movq PCPU(CURPCB),%r8
+ movl %edi,%eax
+ movq %rsi,%rbx
+ xchgq %rdx,%rcx
+ movq $sgx_onfault,PCB_ONFAULT(%r8)
+ .byte 0x0f, 0x01, 0xcf
+ movq $0,PCB_ONFAULT(%r8)
+ popq %rbx
+ POP_FRAME_POINTER
+ ret
+END(sgx_encls)
+
+/*
+ * SGX operations fault handler
+ */
+ ALIGN_TEXT
+sgx_onfault:
+ movq $0,PCB_ONFAULT(%r8)
+ movl $SGX_EFAULT,%eax
+ popq %rbx
+ POP_FRAME_POINTER
+ ret
Index: sys/amd64/sgx/sgxvar.h
===================================================================
--- /dev/null
+++ sys/amd64/sgx/sgxvar.h
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
+ * 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
+#define SGX_EFAULT 99
+
+#ifndef LOCORE
+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 object;
+ 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 /* !LOCORE */
+
+#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,12 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/amd64/sgx
+
+KMOD= sgx
+SRCS= sgx.c sgxvar.h assym.s sgx_support.S
+
+sgx_support.o: assym.s
+ ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \
+ ${.IMPSRC} -o ${.TARGET}
+
+.include <bsd.kmod.mk>
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 <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 25, 4:59 PM (4 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24181626
Default Alt Text
D11113.id31423.diff (43 KB)
Attached To
Mode
D11113: Intel SGX driver
Attached
Detach File
Event Timeline
Log In to Comment