summaryrefslogtreecommitdiff
path: root/security/tlk_driver
diff options
context:
space:
mode:
authorChris Johnson <cwj@nvidia.com>2013-09-03 17:48:59 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-16 17:41:31 -0700
commitbb3eca7dbb30c11bb077544bf47498fb0e5530f6 (patch)
tree1f3308f74c45d22783230b0160d758f1cf35168a /security/tlk_driver
parent53d6652fef440052aad8941f4c5652b441ca28ed (diff)
security: tlk_driver: shared req/param reg SMC
Add support for attempting to register the req/param buffers with TLK. If it fails, we know we're on an older TLK and have to use phys address to indicate where the buffers are. If the SMC succeeds, we pass the virtual pointers to the buffers knowing TLK will map them in and use them directly. This takes care of the coherency and reduces our dependence on phys addrs. Once both TLK and kernel changes have been synced up, we'll remove the legacy support. Bug 1353314 Change-Id: I1a73ddc66f002f966e80579ac49bbbd3e64a1f72 Signed-off-by: Chris Johnson <cwj@nvidia.com> Reviewed-on: http://git-master/r/269802 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'security/tlk_driver')
-rw-r--r--security/tlk_driver/ote_comms.c36
-rw-r--r--security/tlk_driver/ote_device.c45
-rw-r--r--security/tlk_driver/ote_fs.c7
-rw-r--r--security/tlk_driver/ote_irq.S2
-rw-r--r--security/tlk_driver/ote_protocol.h34
5 files changed, 86 insertions, 38 deletions
diff --git a/security/tlk_driver/ote_comms.c b/security/tlk_driver/ote_comms.c
index d31cd2425621..6e3eb0abbd82 100644
--- a/security/tlk_driver/ote_comms.c
+++ b/security/tlk_driver/ote_comms.c
@@ -36,13 +36,6 @@ static unsigned long saved_regs[16];
#define SET_RESULT(req, r, ro) { req->result = r; req->result_origin = ro; }
-#define TLK_GENERIC_SMC(arg0, arg1, arg2) \
- do { \
- switch_cpumask_to_cpu0(); \
- tlk_generic_smc(arg0, arg1, arg2); \
- restore_cpumask(); \
- } while (0)
-
static int te_pin_user_pages(void *buffer, size_t size,
unsigned long *pages_ptr)
{
@@ -278,13 +271,21 @@ uint32_t tlk_extended_smc(uint32_t *regs)
/*
* Do an SMC call
*/
-static void do_smc(struct te_request *request)
+static void do_smc(struct te_request *request, struct tlk_device *dev)
{
- phys_addr_t smc_args = virt_to_phys(request);
- phys_addr_t smc_params = 0;
-
- if (request->params)
- smc_params = virt_to_phys(request->params);
+ uint32_t smc_args;
+ uint32_t smc_params = 0;
+
+ if (dev->req_param_buf) {
+ smc_args = (char *)request - dev->req_param_buf;
+ if (request->params)
+ smc_params = (char *)request->params -
+ dev->req_param_buf;
+ } else {
+ smc_args = (uint32_t)virt_to_phys(request);
+ if (request->params)
+ smc_params = (uint32_t)virt_to_phys(request->params);
+ }
TLK_GENERIC_SMC(request->type, smc_args, smc_params);
}
@@ -317,7 +318,7 @@ void te_open_session(struct te_opensession *cmd,
request->type = TE_SMC_OPEN_SESSION;
- do_smc(request);
+ do_smc(request, context->dev);
te_unpin_temp_buffers(request, context);
}
@@ -326,12 +327,13 @@ void te_open_session(struct te_opensession *cmd,
* Close session SMC (supporting client-based te_close_session() calls)
*/
void te_close_session(struct te_closesession *cmd,
- struct te_request *request)
+ struct te_request *request,
+ struct tlk_context *context)
{
request->session_id = cmd->session_id;
request->type = TE_SMC_CLOSE_SESSION;
- do_smc(request);
+ do_smc(request, context->dev);
if (request->result)
pr_info("Error closing session: %08x\n", request->result);
}
@@ -356,7 +358,7 @@ void te_launch_operation(struct te_launchop *cmd,
request->command_id = cmd->operation.command;
request->type = TE_SMC_LAUNCH_OPERATION;
- do_smc(request);
+ do_smc(request, context->dev);
te_unpin_temp_buffers(request, context);
}
diff --git a/security/tlk_driver/ote_device.c b/security/tlk_driver/ote_device.c
index f9b0e5647efd..629243297bfb 100644
--- a/security/tlk_driver/ote_device.c
+++ b/security/tlk_driver/ote_device.c
@@ -48,22 +48,44 @@ u32 notrace tegra_read_cycle(void)
return cycle_count;
}
-/*
- * The maximum number of outstanding command requests.
- */
-#define TE_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct te_request))
-#define TE_PARAM_MAX (PAGE_SIZE / sizeof(struct te_oper_param))
-
static int te_create_free_cmd_list(struct tlk_device *dev)
{
int cmd_desc_count, ret = 0;
struct te_cmd_req_desc *req_desc;
int bitmap_size;
+ bool use_reqbuf;
+
+ /*
+ * Check if new shared req/param register SMC is supported.
+ *
+ * If it is, TLK can map in the shared req/param buffers and do_smc
+ * only needs to send the offsets within each (with cache coherency
+ * being maintained by HW through an NS mapping).
+ *
+ * If the SMC support is not yet present, then fallback to the old
+ * mode of writing to an uncached buffer to maintain coherency (and
+ * phys addresses are passed in do_smc).
+ */
+ dev->req_param_buf = NULL;
+ use_reqbuf = !TLK_GENERIC_SMC(TE_SMC_REGISTER_REQ_BUF, 0, 0);
+
+ if (use_reqbuf) {
+ dev->req_param_buf = kmalloc((2 * PAGE_SIZE), GFP_KERNEL);
+
+ /* requests in the first page, params in the second */
+ dev->req_addr = (struct te_request *) dev->req_param_buf;
+ dev->param_addr = (struct te_oper_param *)
+ (dev->req_param_buf + PAGE_SIZE);
+
+ TLK_GENERIC_SMC(TE_SMC_REGISTER_REQ_BUF,
+ (uint32_t)dev->req_addr, (2 * PAGE_SIZE));
+ } else {
+ dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
+ &dev->req_addr_phys, GFP_KERNEL);
+ dev->param_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
+ &dev->param_addr_phys, GFP_KERNEL);
+ }
- dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
- &dev->req_addr_phys, GFP_KERNEL);
- dev->param_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
- &dev->param_addr_phys, GFP_KERNEL);
if ((dev->req_addr == NULL) || (dev->param_addr == NULL)) {
ret = -ENOMEM;
goto error;
@@ -90,7 +112,6 @@ static int te_create_free_cmd_list(struct tlk_device *dev)
}
error:
return ret;
-
}
static struct te_oper_param *te_get_free_params(struct tlk_device *dev,
@@ -331,7 +352,7 @@ static long te_handle_trustedapp_ioctl(struct file *file,
memset(request, 0, sizeof(struct te_request));
/* close session cannot fail */
- te_close_session(&cmd.closesession, request);
+ te_close_session(&cmd.closesession, request, context);
break;
case TE_IOCTL_LAUNCH_OPERATION:
diff --git a/security/tlk_driver/ote_fs.c b/security/tlk_driver/ote_fs.c
index b3524bd37476..cf02e8cb4ac4 100644
--- a/security/tlk_driver/ote_fs.c
+++ b/security/tlk_driver/ote_fs.c
@@ -44,13 +44,6 @@ static DECLARE_COMPLETION(req_ready);
static DECLARE_COMPLETION(req_complete);
static unsigned long secure_error;
-#define TLK_EXTENDED_SMC(arg0) \
- do { \
- switch_cpumask_to_cpu0(); \
- tlk_extended_smc(arg0); \
- restore_cpumask(); \
- } while (0)
-
static void indicate_complete(unsigned long ret)
{
tlk_generic_smc(TE_SMC_FS_OP_DONE, ret, 0);
diff --git a/security/tlk_driver/ote_irq.S b/security/tlk_driver/ote_irq.S
index 7bfda8861108..6305e0799440 100644
--- a/security/tlk_driver/ote_irq.S
+++ b/security/tlk_driver/ote_irq.S
@@ -16,6 +16,6 @@
ENTRY(tlk_irq_handler)
movw r0, #0x1FF1
- movt r0, #0xFFFF
+ movt r0, #0xFFFF @ TE_SMC_NS_IRQ_DONE
smc #0
ENDPROC(tlk_irq_handler)
diff --git a/security/tlk_driver/ote_protocol.h b/security/tlk_driver/ote_protocol.h
index d3b4dd4b0112..4efade0be3f3 100644
--- a/security/tlk_driver/ote_protocol.h
+++ b/security/tlk_driver/ote_protocol.h
@@ -38,6 +38,10 @@
#define TE_IOCTL_MIN_NR _IOC_NR(TE_IOCTL_OPEN_CLIENT_SESSION)
#define TE_IOCTL_MAX_NR _IOC_NR(TE_IOCTL_FILE_REQ_COMPLETE)
+/* shared buffer is 2 pages: 1st are requests, 2nd are params */
+#define TE_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct te_request))
+#define TE_PARAM_MAX (PAGE_SIZE / sizeof(struct te_oper_param))
+
#define MAX_EXT_SMC_ARGS 12
uint32_t tlk_generic_smc(uint32_t arg0, uint32_t arg1, uint32_t arg2);
@@ -52,12 +56,38 @@ static inline void switch_cpumask_to_cpu0(void) {};
static inline void restore_cpumask(void) {};
#endif
+static inline uint32_t
+TLK_GENERIC_SMC(uint32_t arg0, uint32_t arg1, uint32_t arg2)
+{
+ uint32_t retval;
+
+ switch_cpumask_to_cpu0();
+ retval = tlk_generic_smc(arg0, arg1, arg2);
+ restore_cpumask();
+
+ return retval;
+}
+
+static inline uint32_t
+TLK_EXTENDED_SMC(uint32_t *args)
+{
+ uint32_t retval;
+
+ switch_cpumask_to_cpu0();
+ retval = tlk_extended_smc(args);
+ restore_cpumask();
+
+ return retval;
+}
+
struct tlk_device {
struct te_request *req_addr;
dma_addr_t req_addr_phys;
struct te_oper_param *param_addr;
dma_addr_t param_addr_phys;
+ char *req_param_buf;
+
unsigned long *param_bitmap;
struct list_head used_cmd_list;
@@ -90,6 +120,7 @@ enum {
TE_SMC_REGISTER_IRQ_HANDLER = 0xFFFF1FF0,
TE_SMC_NS_IRQ_DONE = 0xFFFF1FF1,
TE_SMC_REGISTER_FS_HANDLERS = 0xFFFF1FF2,
+ TE_SMC_REGISTER_REQ_BUF = 0xFFFF1FF3,
TE_SMC_FS_OP_DONE = 0xFFFF1FFF,
};
@@ -187,7 +218,8 @@ void te_open_session(struct te_opensession *cmd,
struct tlk_context *context);
void te_close_session(struct te_closesession *cmd,
- struct te_request *request);
+ struct te_request *request,
+ struct tlk_context *context);
void te_launch_operation(struct te_launchop *cmd,
struct te_request *request,