]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
security: tlk_driver: modify secure storage glue
authorVarun Wadekar <vwadekar@nvidia.com>
Wed, 23 Apr 2014 05:04:00 +0000 (10:34 +0530)
committerKevin Kranzusch <kevink@nvidia.com>
Wed, 3 Sep 2014 01:11:18 +0000 (18:11 -0700)
The secure world now sends a PREEMPT_BY_FS error code as a result
of OpenSession/LaunchOp call. This indicates a pending FS request
from the secure world which we need to handle and send the
FS_COMPLETION SMC on completion.

Until the secure firmware and the linux driver get in sync, we keep
legacy SS handling alive to avoid incomaptibility issues. Once the
secure firmware switches to the new handling, we would remove the
legacy support from the linux driver as well.

Bug 1500621

Change-Id: I9e84cd5a87d820107b1c2279c9d89dcd5c31b44b
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/375994
(cherry picked from commit 433d8d1687725ab7db23eef27e5a073e8d88e862)
Reviewed-on: http://git-master/r/488950
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Hyung Taek Ryoo <hryoo@nvidia.com>
Tested-by: Hyung Taek Ryoo <hryoo@nvidia.com>
Reviewed-by: Kevin Kranzusch <kevink@nvidia.com>
security/tlk_driver/ote_comms.c
security/tlk_driver/ote_device.c
security/tlk_driver/ote_fs.c
security/tlk_driver/ote_protocol.h

index e96c9f30a49f9217e7caf75b559a2cb255984d9a..fe9388bc641a80cf2af43a45af7c596cace1438b 100644 (file)
@@ -245,8 +245,15 @@ uint32_t tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2)
        switch_cpumask_to_cpu0();
 
        retval = _tlk_generic_smc(arg0, arg1, arg2);
-       while (retval == 0xFFFFFFFD)
-               retval = _tlk_generic_smc((60 << 24), 0, 0);
+       while (retval == TE_ERROR_PREEMPT_BY_IRQ ||
+              retval == TE_ERROR_PREEMPT_BY_FS) {
+               if (retval == TE_ERROR_PREEMPT_BY_IRQ) {
+                       retval = _tlk_generic_smc((60 << 24), 0, 0);
+               } else {
+                       tlk_ss_op();
+                       retval = _tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0);
+               }
+       }
 
        restore_cpumask();
 
index bfc59d3cb94c45c61c4cd6de48ef447a0db5a1dd..a1529d676ddbbfd01c53f9911ab5fe2fd4d543e3 100644 (file)
@@ -712,6 +712,11 @@ static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
                mutex_unlock(&smc_lock);
                break;
 
+       case TE_IOCTL_SS_NEW_REQ_LEGACY:
+       case TE_IOCTL_SS_REQ_COMPLETE_LEGACY:
+               err = te_handle_ss_ioctl_legacy(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);
index e3d427ae9a2ff1bb7a38a3e9e3c02ef20ff94348..f58bdd64aecb0cc5957dd90068cbbf713ab0025a 100644 (file)
@@ -30,6 +30,7 @@
 static DECLARE_COMPLETION(req_ready);
 static DECLARE_COMPLETION(req_complete);
 
+static struct te_ss_op_legacy *ss_op_shmem_legacy;
 static struct te_ss_op *ss_op_shmem;
 static uint32_t ss_op_size;
 
@@ -38,26 +39,26 @@ static void indicate_ss_op_complete(void)
        tlk_generic_smc(TE_SMC_SS_REQ_COMPLETE, 0, 0);
 }
 
-int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
+int te_handle_ss_ioctl_legacy(struct file *file, unsigned int ioctl_num,
        unsigned long ioctl_param)
 {
        switch (ioctl_num) {
-       case TE_IOCTL_SS_NEW_REQ:
+       case TE_IOCTL_SS_NEW_REQ_LEGACY:
                /* wait for a new request */
                if (wait_for_completion_interruptible(&req_ready))
                        return -ENODATA;
 
                /* transfer pending request to daemon's buffer */
-               if (copy_to_user((void __user *)ioctl_param, ss_op_shmem,
+               if (copy_to_user((void __user *)ioctl_param, ss_op_shmem_legacy,
                                        ss_op_size)) {
                        pr_err("copy_to_user failed for new request\n");
                        return -EFAULT;
                }
                break;
 
-       case TE_IOCTL_SS_REQ_COMPLETE: /* request complete */
-               if (copy_from_user(ss_op_shmem, (void __user *)ioctl_param,
-                                       ss_op_size)) {
+       case TE_IOCTL_SS_REQ_COMPLETE_LEGACY: /* request complete */
+               if (copy_from_user(ss_op_shmem_legacy,
+                       (void __user *)ioctl_param, ss_op_size)) {
                        pr_err("copy_from_user failed for request\n");
                        return -EFAULT;
                }
@@ -70,7 +71,7 @@ int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
        return 0;
 }
 
-void tlk_ss_op(uint32_t size)
+void tlk_ss_op_legacy(uint32_t size)
 {
        /* store size of request */
        ss_op_size = size;
@@ -85,9 +86,71 @@ void tlk_ss_op(uint32_t size)
        indicate_ss_op_complete();
 }
 
+static int __init tlk_ss_init_legacy(void)
+{
+       dma_addr_t ss_op_shmem_dma;
+
+       /* allocate shared memory buffer */
+       ss_op_shmem_legacy = dma_alloc_coherent(NULL,
+               sizeof(struct te_ss_op_legacy), &ss_op_shmem_dma, GFP_KERNEL);
+       if (!ss_op_shmem_legacy) {
+               pr_err("%s: no memory available for fs operations\n", __func__);
+               return -ENOMEM;
+       }
+
+       tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER_LEGACY,
+               (uintptr_t)tlk_ss_op_legacy, (uintptr_t)ss_op_shmem_legacy);
+
+       return 0;
+}
+
+arch_initcall(tlk_ss_init_legacy);
+
+int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
+       unsigned long ioctl_param)
+{
+       switch (ioctl_num) {
+       case TE_IOCTL_SS_NEW_REQ:
+               /* wait for a new request */
+               if (wait_for_completion_interruptible(&req_ready))
+                       return -ENODATA;
+
+               /* transfer pending request to daemon's buffer */
+               if (copy_to_user((void __user *)ioctl_param, ss_op_shmem->data,
+                                       ss_op_shmem->req_size)) {
+                       pr_err("copy_to_user failed for new request\n");
+                       return -EFAULT;
+               }
+               break;
+
+       case TE_IOCTL_SS_REQ_COMPLETE: /* request complete */
+               if (copy_from_user(ss_op_shmem->data,
+                       (void __user *)ioctl_param, ss_op_shmem->req_size)) {
+                       pr_err("copy_from_user failed for request\n");
+                       return -EFAULT;
+               }
+
+               /* signal the producer */
+               complete(&req_complete);
+               break;
+       }
+
+       return 0;
+}
+
+void tlk_ss_op(void)
+{
+       /* signal consumer */
+       complete(&req_ready);
+
+       /* wait for the consumer's signal */
+       wait_for_completion(&req_complete);
+}
+
 static int __init tlk_ss_init(void)
 {
        dma_addr_t ss_op_shmem_dma;
+       int32_t ret;
 
        /* allocate shared memory buffer */
        ss_op_shmem = dma_alloc_coherent(NULL, sizeof(struct te_ss_op),
@@ -97,8 +160,14 @@ static int __init tlk_ss_init(void)
                return -ENOMEM;
        }
 
-       tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER,
-                       (uintptr_t)tlk_ss_op, (uintptr_t)ss_op_shmem);
+       ret = tlk_generic_smc(TE_SMC_SS_REGISTER_HANDLER,
+                       (uintptr_t)ss_op_shmem, 0);
+       if (ret != 0) {
+               dma_free_coherent(NULL, sizeof(struct te_ss_op),
+                       (void *)ss_op_shmem, ss_op_shmem_dma);
+               ss_op_shmem = NULL;
+               return -ENOTSUPP;
+       }
 
        return 0;
 }
index c5aea3d234e3d1b7e55a50d90b903c561fd6122e..608ee8981e7c72af8bda6e71a87734de01f7eb20 100644 (file)
 #define TE_IOCTL_LAUNCH_OPERATION_COMPAT \
        _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd_compat)
 
+#define TE_IOCTL_SS_NEW_REQ_LEGACY \
+       _IOR(TE_IOCTL_MAGIC_NUMBER,  0x20, struct te_ss_op_legacy)
+#define TE_IOCTL_SS_REQ_COMPLETE_LEGACY \
+       _IOWR(TE_IOCTL_MAGIC_NUMBER, 0x21, struct te_ss_op_legacy)
+
+/* ioctls using new SS structs (eventually to replace current SS ioctls) */
 #define TE_IOCTL_SS_NEW_REQ \
        _IOR(TE_IOCTL_MAGIC_NUMBER,  0x20, struct te_ss_op)
 #define TE_IOCTL_SS_REQ_COMPLETE \
@@ -65,6 +71,12 @@ uint32_t _tlk_extended_smc(uintptr_t *args);
 uint32_t tlk_extended_smc(uintptr_t *args);
 void tlk_irq_handler(void);
 
+/* errors returned by secure world in reponse to SMC calls */
+enum {
+       TE_ERROR_PREEMPT_BY_IRQ = 0xFFFFFFFD,
+       TE_ERROR_PREEMPT_BY_FS = 0xFFFFFFFE,
+};
+
 struct tlk_device {
        struct te_request *req_addr;
        dma_addr_t req_addr_phys;
@@ -115,8 +127,9 @@ enum {
        TE_SMC_REGISTER_IRQ_HANDLER     = 0x32000004,
        TE_SMC_NS_IRQ_DONE              = 0x32000005,
        TE_SMC_INIT_LOGGER              = 0x32000007,
-       TE_SMC_SS_REGISTER_HANDLER      = 0x32000008,
+       TE_SMC_SS_REGISTER_HANDLER_LEGACY       = 0x32000008,
        TE_SMC_SS_REQ_COMPLETE          = 0x32000009,
+       TE_SMC_SS_REGISTER_HANDLER      = 0x32000010,
 
        /* SIP (SOC specific) calls.  */
        TE_SMC_PROGRAM_VPR              = 0x82000003,
@@ -308,13 +321,21 @@ void te_launch_operation_compat(struct te_launchop_compat *cmd,
 
 #define SS_OP_MAX_DATA_SIZE    0x1000
 struct te_ss_op {
+       uint32_t        req_size;
        uint8_t         data[SS_OP_MAX_DATA_SIZE];
 };
 
+struct te_ss_op_legacy {
+       uint8_t         data[SS_OP_MAX_DATA_SIZE];
+};
+
+int te_handle_ss_ioctl_legacy(struct file *file, unsigned int ioctl_num,
+               unsigned long ioctl_param);
 int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
                unsigned long ioctl_param);
 int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
                unsigned long ioctl_param);
 void ote_print_logs(void);
+void tlk_ss_op(void);
 
 #endif