blob: 9b28e01f9b0238a16ce49b515f9ba638377790fb [file]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2022 The Regents of the University of California (Regents).
* Copyright (c) 2023 Univrsity of Tampere.
*
* Authors:
* Dayeol Lee <dayeol@berkeley.edu>
* Evgeny Pobachienko <evgenyp@berkeley.edu>
* Jarkko Sakkinen <jarkko.sakkinen@tuni.fi>
*/
#include <linux/dma-mapping.h>
#include "keystone.h"
/* database for enclave ID's (EID's) of active enclaves: */
DEFINE_IDR(idr_enclave);
/* lock for idr_enclave: */
DEFINE_MUTEX(idr_enclave_lock);
#define ENCLAVE_IDR_MIN 0x1000
#define ENCLAVE_IDR_MAX 0xffff
void keystone_enclave_destroy(struct enclave *enclave)
{
struct epm *epm;
struct utm *utm;
WARN_ON_ONCE(!enclave);
if (!enclave)
return;
epm = enclave->epm;
utm = enclave->utm;
if (epm) {
#ifdef CONFIG_CMA
dma_free_coherent(keystone_dev.this_device, epm->size, epm->ptr, epm->pa);
#else
free_pages(epm->ptr, epm->order);
#endif
kfree(epm);
}
if (utm) {
if (utm->ptr)
free_pages((vaddr_t)utm->ptr, utm->order);
kfree(utm);
}
kfree(enclave);
}
struct enclave *keystone_enclave_create(unsigned long min_pages)
{
struct enclave *enclave;
enclave = kzalloc(sizeof(*enclave), GFP_KERNEL);
if (!enclave)
return NULL;
enclave->eid = -1; /* invalid */
enclave->utm = NULL;
enclave->close_on_pexit = 1;
enclave->is_init = true;
enclave->epm = kzalloc(sizeof(*enclave->epm), GFP_KERNEL);
if (!enclave->epm)
goto err;
if (epm_init(enclave->epm, min_pages))
goto err;
return enclave;
err:
keystone_enclave_destroy(enclave);
return NULL;
}
int keystone_alloc_eid(struct enclave *enclave)
{
int ret;
mutex_lock(&idr_enclave_lock);
ret = idr_alloc(&idr_enclave, enclave, ENCLAVE_IDR_MIN, ENCLAVE_IDR_MAX, GFP_KERNEL);
mutex_unlock(&idr_enclave_lock);
return ret;
}
struct enclave *keystone_free_eid(unsigned int ueid)
{
struct enclave *enclave;
mutex_lock(&idr_enclave_lock);
enclave = idr_remove(&idr_enclave, ueid);
mutex_unlock(&idr_enclave_lock);
return enclave;
}