summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/tlk_driver/Makefile14
-rw-r--r--security/tlk_driver/ote_asm.S74
-rw-r--r--security/tlk_driver/ote_comms.c52
-rw-r--r--security/tlk_driver/ote_device.c13
-rw-r--r--security/tlk_driver/ote_fs.c207
-rw-r--r--security/tlk_driver/ote_irq.S23
-rw-r--r--security/tlk_driver/ote_log.c4
-rw-r--r--security/tlk_driver/ote_protocol.h34
8 files changed, 97 insertions, 324 deletions
diff --git a/security/tlk_driver/Makefile b/security/tlk_driver/Makefile
index 86a293d2f009..9ab4168f7e11 100644
--- a/security/tlk_driver/Makefile
+++ b/security/tlk_driver/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
+# Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,15 +16,15 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
-plus_sec := $(call as-instr,.arch_extension sec,+sec)
-AFLAGS_ote_irq.o :=-Wa,-march=armv7-a$(plus_sec)
-CFLAGS_ote_comms.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
-CFLAGS_ote_fs.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
-
tlk_driver-objs += ote_device.o
tlk_driver-objs += ote_comms.o
tlk_driver-objs += ote_fs.o
-tlk_driver-objs += ote_irq.o
+tlk_driver-objs += ote_asm.o
tlk_driver-objs += ote_log.o
+ifeq ($(CONFIG_ARM),y)
+plus_sec := $(call as-instr,.arch_extension sec,+sec)
+AFLAGS_ote_asm.o :=-Wa,-march=armv7-a$(plus_sec)
+endif
+
obj-$(CONFIG_TRUSTED_LITTLE_KERNEL) += tlk_driver.o
diff --git a/security/tlk_driver/ote_asm.S b/security/tlk_driver/ote_asm.S
new file mode 100644
index 000000000000..2c5563ba7ed8
--- /dev/null
+++ b/security/tlk_driver/ote_asm.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_ARM64
+
+ENTRY(tlk_irq_handler)
+ mov x0, #0x5
+ movk x0, #0x3200, lsl #16 // TE_SMC_NS_IRQ_DONE
+ smc #0
+ ret
+ENDPROC(tlk_irq_handler)
+
+/* uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2) */
+ENTRY(_tlk_generic_smc)
+ smc #0
+ ret
+ENDPROC(_tlk_generic_smc)
+
+ /* allows MAX_EXT_SMC_ARGS (r0-r11) to be passed in registers */
+
+/* uint32_t tlk_extended_smc(uint32_t *regs) */
+ENTRY(_tlk_extended_smc)
+ /*
+ * Allows MAX_EXT_SMC_ARGS (r0-r11) to be passed in registers
+ * (for aarch64, these are scratch, so no need to save them)
+ */
+ mov x12, x0
+ ldp x0, x1, [x12], #16
+ ldp x2, x3, [x12], #16
+ ldp x4, x5, [x12], #16
+ ldp x6, x7, [x12], #16
+ ldp x8, x9, [x12], #16
+ ldp x10, x11, [x12], #16
+ smc #0
+ ret
+ENDPROC(_tlk_extended_smc)
+
+#else
+
+ENTRY(tlk_irq_handler)
+ movw r0, #0x5
+ movt r0, #0x3200 @ TE_SMC_NS_IRQ_DONE
+ mov r1, #0
+ mov r2, #0
+ smc #0
+ENDPROC(tlk_irq_handler)
+
+ENTRY(_tlk_generic_smc)
+ smc #0
+ mov pc, lr
+ENDPROC(_tlk_generic_smc)
+
+ENTRY(_tlk_extended_smc)
+ stmfd sp!, {r4-r12} @ save reg state
+ mov r12, r0 @ reg ptr to r12
+ ldmia r12, {r0-r11} @ load arg regs
+ smc #0
+ ldmfd sp!, {r4-r12} @ restore saved regs
+ENDPROC(_tlk_extended_smc)
+
+#endif
diff --git a/security/tlk_driver/ote_comms.c b/security/tlk_driver/ote_comms.c
index 46d7fc679b78..1f380b772499 100644
--- a/security/tlk_driver/ote_comms.c
+++ b/security/tlk_driver/ote_comms.c
@@ -237,29 +237,7 @@ static inline void switch_cpumask_to_cpu0(void) {};
static inline void restore_cpumask(void) {};
#endif
-static uint32_t _tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2)
-{
- register uint32_t r0 asm("r0") = arg0;
- register uint32_t r1 asm("r1") = arg1;
- register uint32_t r2 asm("r2") = arg2;
-
- asm volatile(
- __asmeq("%0", "r0")
- __asmeq("%1", "r0")
- __asmeq("%2", "r1")
- __asmeq("%3", "r2")
-#ifdef REQUIRES_SEC
- ".arch_extension sec \n"
-#endif
- "smc #0 @ switch to secure world\n"
- : "=r" (r0)
- : "r" (r0), "r" (r1), "r" (r2)
- );
-
- return r0;
-}
-
-uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2)
+uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2)
{
uint32_t retval;
@@ -274,29 +252,7 @@ uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2)
return retval;
}
-static uint32_t _tlk_extended_smc(uint32_t *regs)
-{
- register uint32_t r0 asm("r0") = (uint32_t)regs;
-
- /* allows MAX_EXT_SMC_ARGS (r0-r11) to be passed in registers */
- asm volatile(
- __asmeq("%0", "r0")
- "stmfd sp!, {r4-r12} @ save reg state\n"
- "mov r12, r0 @ reg ptr to r12\n"
- "ldmia r12, {r0-r11} @ load arg regs\n"
-#ifdef REQUIRES_SEC
- ".arch_extension sec\n"
-#endif
- "smc #0 @ switch to secure world\n"
- "ldmfd sp!, {r4-r12} @ restore saved regs\n"
- : "=r" (r0)
- : "r" (r0)
- );
-
- return r0;
-}
-
-uint32_t tlk_extended_smc(uint32_t *regs)
+uint32_t tlk_extended_smc(uintptr_t *regs)
{
uint32_t retval;
@@ -373,7 +329,7 @@ int te_set_vpr_params(void *vpr_base, size_t vpr_size)
/* Share the same lock used when request is send from user side */
mutex_lock(&smc_lock);
- retval = tlk_generic_smc(TE_SMC_PROGRAM_VPR, (uint32_t)vpr_base,
+ retval = tlk_generic_smc(TE_SMC_PROGRAM_VPR, (uintptr_t)vpr_base,
vpr_size);
mutex_unlock(&smc_lock);
@@ -535,7 +491,7 @@ void te_launch_operation_compat(struct te_launchop_compat *cmd,
static int __init tlk_register_irq_handler(void)
{
tlk_generic_smc(TE_SMC_REGISTER_IRQ_HANDLER,
- (unsigned int)tlk_irq_handler, 0);
+ (uintptr_t)tlk_irq_handler, 0);
return 0;
}
diff --git a/security/tlk_driver/ote_device.c b/security/tlk_driver/ote_device.c
index 170f46c06e14..bfc59d3cb94c 100644
--- a/security/tlk_driver/ote_device.c
+++ b/security/tlk_driver/ote_device.c
@@ -68,7 +68,7 @@ static int te_create_free_cmd_list(struct tlk_device *dev)
(dev->req_param_buf + PAGE_SIZE);
tlk_generic_smc(TE_SMC_REGISTER_REQ_BUF,
- (uint32_t)dev->req_addr, (2 * PAGE_SIZE));
+ (uintptr_t)dev->req_addr, (2 * PAGE_SIZE));
} else {
dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
&dev->req_addr_phys, GFP_KERNEL);
@@ -712,20 +712,15 @@ static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
mutex_unlock(&smc_lock);
break;
- case TE_IOCTL_FILE_NEW_REQ:
- case TE_IOCTL_FILE_FILL_BUF:
- case TE_IOCTL_FILE_REQ_COMPLETE:
- err = te_handle_fs_ioctl(file, ioctl_num, ioctl_param);
- break;
-
case TE_IOCTL_SS_NEW_REQ:
case TE_IOCTL_SS_REQ_COMPLETE:
err = te_handle_ss_ioctl(file, ioctl_num, ioctl_param);
break;
default:
- pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%x\n", __func__,
- ioctl_num, _IOC_NR(ioctl_num), TE_IOCTL_MAX_NR);
+ pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%lx\n",
+ __func__, ioctl_num, _IOC_NR(ioctl_num),
+ (unsigned long)TE_IOCTL_MAX_NR);
err = -EINVAL;
break;
}
diff --git a/security/tlk_driver/ote_fs.c b/security/tlk_driver/ote_fs.c
index d398bebed9d2..e3d427ae9a2f 100644
--- a/security/tlk_driver/ote_fs.c
+++ b/security/tlk_driver/ote_fs.c
@@ -27,188 +27,17 @@
#include "ote_protocol.h"
-#define TE_SHMEM_FNAME_SZ SZ_64
-#define TE_SHMEM_DATA_SZ SZ_128K
-
-struct te_file_req_shmem {
- char file_name[TE_SHMEM_FNAME_SZ];
- char file_data[TE_SHMEM_DATA_SZ];
-};
-
-struct te_file_req_node {
- struct list_head node;
- struct te_file_req *req;
-};
-
-static struct list_head req_list;
static DECLARE_COMPLETION(req_ready);
static DECLARE_COMPLETION(req_complete);
-static unsigned long secure_error;
static struct te_ss_op *ss_op_shmem;
static uint32_t ss_op_size;
-static void indicate_complete(unsigned long ret)
-{
- tlk_generic_smc(TE_SMC_FS_OP_DONE, ret, 0);
-}
-
static void indicate_ss_op_complete(void)
{
tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0);
}
-int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
- unsigned long ioctl_param)
-{
- struct te_file_req new_req, *ptr_user_req = NULL;
- struct te_file_req_node *req_node;
-
- switch (ioctl_num) {
- case TE_IOCTL_FILE_NEW_REQ: /* new request */
-
- ptr_user_req = (struct te_file_req *)ioctl_param;
-
- /* wait for a new request */
- if (wait_for_completion_interruptible(&req_ready)) {
- return -ENODATA;
- }
-
- /* dequeue new request from the secure world */
- req_node = list_first_entry(&req_list, struct te_file_req_node,
- node);
-
- /* populate request for the non-secure client */
- if (req_node) {
- if (copy_to_user(ptr_user_req, req_node->req,
- sizeof(struct te_file_req))) {
- pr_err("copy_to_user failed for new request\n");
- return -EFAULT;
- }
-
- list_del(&req_node->node);
- kfree(req_node);
- } else {
- pr_err("no request available\n");
- return -ENOMEM;
- }
-
- break;
-
- case TE_IOCTL_FILE_FILL_BUF: /* pass data to be written to the file */
-
- if (copy_from_user(&new_req, (void __user *)ioctl_param,
- sizeof(struct te_file_req))) {
- pr_err("copy_from_user failed for request\n");
- return -EFAULT;
- }
-
- if (new_req.type != OTE_FILE_REQ_WRITE)
- return -EINVAL;
-
- if (!new_req.kern_data_buf || !new_req.user_data_buf)
- return -EINVAL;
-
- if (copy_to_user(new_req.user_data_buf, new_req.kern_data_buf,
- new_req.data_len)) {
- pr_err("copy_to_user failed for fill buffer\n");
- return -EFAULT;
- }
- break;
-
- case TE_IOCTL_FILE_REQ_COMPLETE: /* request complete */
-
- if (copy_from_user(&new_req, (void __user *)ioctl_param,
- sizeof(struct te_file_req))) {
- pr_err("copy_from_user failed for request\n");
- return -EFAULT;
- }
-
- if (new_req.type == OTE_FILE_REQ_READ && !new_req.error) {
- if (copy_from_user(new_req.kern_data_buf,
- (void __user *)new_req.user_data_buf,
- new_req.data_len)) {
- pr_err("copy_from_user failed for request\n");
- return -EFAULT;
- }
- }
-
- /* get error code */
- secure_error = (new_req.error) ? OTE_ERROR_NO_DATA
- : new_req.result;
-
- /* signal the producer */
- complete(&req_complete);
- break;
-
- default:
- pr_err("copy_from_user failed for request\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void _te_fs_file_operation(const char *name, void *buf, int len,
- enum te_file_req_type type)
-{
- struct te_file_req *new_req;
- struct te_file_req_node *req_node;
-
- BUG_ON(!name);
-
- if (type == OTE_FILE_REQ_READ || type == OTE_FILE_REQ_WRITE)
- BUG_ON(!buf);
-
- /* allocate te_file_req structure */
- new_req = kzalloc(sizeof(struct te_file_req), GFP_KERNEL);
- BUG_ON(!new_req);
-
- /* prepare a new request */
- strncpy(new_req->name, name, strlen(name));
- new_req->type = type;
- new_req->data_len = len;
- new_req->result = 0;
- new_req->kern_data_buf = buf;
- new_req->error = 0;
-
- req_node = kzalloc(sizeof(struct te_file_req_node), GFP_KERNEL);
- BUG_ON(!req_node);
-
- req_node->req = new_req;
- INIT_LIST_HEAD(&req_node->node);
-
- /* add it to the pending queue and signal the consumer */
- list_add_tail(&req_list, &req_node->node);
- complete(&req_ready);
-
- /* wait for the consumer's signal */
- wait_for_completion(&req_complete);
-
- kfree(new_req);
-
- /* signal completion to the secure world */
- indicate_complete(secure_error);
-}
-
-void tlk_fread(const char *name, void *buf, int len)
-{
- if (!buf)
- _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_SIZE);
- else
- _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_READ);
-}
-
-void tlk_fwrite(const char *name, void *buf, int len)
-{
- _te_fs_file_operation(name, buf, len, OTE_FILE_REQ_WRITE);
-}
-
-void tlk_fdelete(const char *name)
-{
- _te_fs_file_operation(name, NULL, 0, OTE_FILE_REQ_DELETE);
-}
-
int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param)
{
@@ -256,44 +85,10 @@ void tlk_ss_op(uint32_t size)
indicate_ss_op_complete();
}
-static int tlk_fs_register_handlers(void)
-{
- struct te_file_req_shmem *shmem_ptr;
- uint32_t smc_args[MAX_EXT_SMC_ARGS];
- dma_addr_t shmem_dma;
-
- shmem_ptr = dma_alloc_coherent(NULL, sizeof(struct te_file_req_shmem),
- &shmem_dma, GFP_KERNEL);
- if (!shmem_ptr) {
- pr_err("%s: no memory available for fs operations\n", __func__);
- return -ENOMEM;
- }
-
- memset(shmem_ptr, 0, sizeof(struct te_file_req_shmem));
-
- INIT_LIST_HEAD(&req_list);
- init_completion(&req_ready);
- init_completion(&req_complete);
-
- smc_args[0] = TE_SMC_REGISTER_FS_HANDLERS;
- smc_args[1] = (uint32_t)tlk_fread;
- smc_args[2] = (uint32_t)tlk_fwrite;
- smc_args[3] = (uint32_t)tlk_fdelete;
- smc_args[4] = (uint32_t)shmem_ptr->file_name;
- smc_args[5] = (uint32_t)shmem_ptr->file_data;
-
- tlk_extended_smc(smc_args);
-
- return 0;
-}
-
static int __init tlk_ss_init(void)
{
dma_addr_t ss_op_shmem_dma;
- /* register legacy support */
- tlk_fs_register_handlers();
-
/* allocate shared memory buffer */
ss_op_shmem = dma_alloc_coherent(NULL, sizeof(struct te_ss_op),
&ss_op_shmem_dma, GFP_KERNEL);
@@ -303,7 +98,7 @@ static int __init tlk_ss_init(void)
}
tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER,
- (uint32_t)tlk_ss_op, (uint32_t)ss_op_shmem);
+ (uintptr_t)tlk_ss_op, (uintptr_t)ss_op_shmem);
return 0;
}
diff --git a/security/tlk_driver/ote_irq.S b/security/tlk_driver/ote_irq.S
deleted file mode 100644
index 3a4ca6875801..000000000000
--- a/security/tlk_driver/ote_irq.S
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-ENTRY(tlk_irq_handler)
- movw r0, #0x5
- movt r0, #0x3200 @ TE_SMC_NS_IRQ_DONE
- mov r1, #0
- mov r2, #0
- smc #0
-ENDPROC(tlk_irq_handler)
diff --git a/security/tlk_driver/ote_log.c b/security/tlk_driver/ote_log.c
index 0cd4412d1470..0a1fbd79b617 100644
--- a/security/tlk_driver/ote_log.c
+++ b/security/tlk_driver/ote_log.c
@@ -172,14 +172,14 @@ void ote_print_logs(void) {}
*/
static int __init ote_logger_init(void)
{
- uint32_t smc_args[MAX_EXT_SMC_ARGS];
+ uintptr_t smc_args[MAX_EXT_SMC_ARGS];
#if defined(CONFIG_OTE_ENABLE_LOGGER)
if (circ_buf_init(&cb) != 0)
return -1;
smc_args[0] = TE_SMC_INIT_LOGGER;
- smc_args[1] = (uint32_t)cb;
+ smc_args[1] = (uintptr_t)cb;
tlk_generic_smc(smc_args[0], smc_args[1], 0);
ote_logging_enabled = 1;
diff --git a/security/tlk_driver/ote_protocol.h b/security/tlk_driver/ote_protocol.h
index 66228e4a9eaa..7e10feed5233 100644
--- a/security/tlk_driver/ote_protocol.h
+++ b/security/tlk_driver/ote_protocol.h
@@ -37,12 +37,6 @@
#define TE_IOCTL_LAUNCH_OPERATION_COMPAT \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd_compat)
-#define TE_IOCTL_FILE_NEW_REQ \
- _IOR(TE_IOCTL_MAGIC_NUMBER, 0x16, struct te_file_req)
-#define TE_IOCTL_FILE_FILL_BUF \
- _IOR(TE_IOCTL_MAGIC_NUMBER, 0x17, struct te_file_req)
-#define TE_IOCTL_FILE_REQ_COMPLETE \
- _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x18, struct te_file_req)
#define TE_IOCTL_SS_NEW_REQ \
_IOR(TE_IOCTL_MAGIC_NUMBER, 0x20, struct te_ss_op)
#define TE_IOCTL_SS_REQ_COMPLETE \
@@ -63,9 +57,12 @@
#define MAX_EXT_SMC_ARGS 12
extern struct mutex smc_lock;
+extern struct tlk_device tlk_dev;
-uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2);
-uint32_t tlk_extended_smc(uint32_t *args);
+uint32_t _tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2);
+uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2);
+uint32_t _tlk_extended_smc(uintptr_t *args);
+uint32_t tlk_extended_smc(uintptr_t *args);
void tlk_irq_handler(void);
struct tlk_device {
@@ -114,12 +111,10 @@ enum {
TE_SMC_LAUNCH_OPERATION = 0x30000003,
/* Trusted OS calls */
- TE_SMC_REGISTER_FS_HANDLERS = 0x32000001,
TE_SMC_REGISTER_REQ_BUF = 0x32000002,
TE_SMC_PROGRAM_VPR = 0x32000003,
TE_SMC_REGISTER_IRQ_HANDLER = 0x32000004,
TE_SMC_NS_IRQ_DONE = 0x32000005,
- TE_SMC_FS_OP_DONE = 0x32000006,
TE_SMC_INIT_LOGGER = 0x32000007,
TE_SMC_SS_REGISTER_HANDLER = 0x32000008,
TE_SMC_SS_REQ_COMPLETE = 0x32000009,
@@ -309,25 +304,6 @@ void te_launch_operation_compat(struct te_launchop_compat *cmd,
struct te_request_compat *request,
struct tlk_context *context);
-#define TE_MAX_FILE_NAME_LEN 64
-
-enum te_file_req_type {
- OTE_FILE_REQ_READ = 0,
- OTE_FILE_REQ_WRITE = 1,
- OTE_FILE_REQ_DELETE = 2,
- OTE_FILE_REQ_SIZE = 3,
-};
-
-struct te_file_req {
- char name[TE_MAX_FILE_NAME_LEN];
- enum te_file_req_type type;
- void *user_data_buf;
- void *kern_data_buf;
- unsigned long data_len;
- unsigned long result;
- int error;
-};
-
#define SS_OP_MAX_DATA_SIZE 0x1000
struct te_ss_op {
uint8_t data[SS_OP_MAX_DATA_SIZE];