optee: add FF-A capability OPTEE_FFA_SEC_CAP_ARG_OFFSET
authorJens Wiklander <jens.wiklander@linaro.org>
Wed, 12 Jan 2022 16:06:32 +0000 (17:06 +0100)
committerJens Wiklander <jens.wiklander@linaro.org>
Wed, 13 Apr 2022 05:37:48 +0000 (07:37 +0200)
Adds the secure capability OPTEE_FFA_SEC_CAP_ARG_OFFSET to indicate that
OP-TEE with FF-A can support an argument struct at a non-zero offset into
a passed shared memory object.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
drivers/tee/optee/ffa_abi.c
drivers/tee/optee/optee_ffa.h

index 7686f7020616a7d10293b4dbdcfb854740c0a985..cc863aaefcd91bd992413913396fadb66c5e40d7 100644 (file)
@@ -615,12 +615,21 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
                .data0 = OPTEE_FFA_YIELDING_CALL_WITH_ARG,
                .data1 = (u32)shm->sec_world_id,
                .data2 = (u32)(shm->sec_world_id >> 32),
-               .data3 = shm->offset,
+               .data3 = 0,
        };
        struct optee_msg_arg *arg;
        unsigned int rpc_arg_offs;
        struct optee_msg_arg *rpc_arg;
 
+       /*
+        * The shared memory object has to start on a page when passed as
+        * an argument struct. This is also what the shm pool allocator
+        * returns, but check this before calling secure world to catch
+        * eventual errors early in case something changes.
+        */
+       if (shm->offset)
+               return -EINVAL;
+
        arg = tee_shm_get_va(shm, 0);
        if (IS_ERR(arg))
                return PTR_ERR(arg);
@@ -678,6 +687,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
 
 static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
                                    const struct ffa_dev_ops *ops,
+                                   u32 *sec_caps,
                                    unsigned int *rpc_param_count)
 {
        struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
@@ -694,6 +704,7 @@ static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
        }
 
        *rpc_param_count = (u8)data.data1;
+       *sec_caps = data.data2;
 
        return true;
 }
@@ -777,6 +788,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
        struct tee_device *teedev;
        struct tee_context *ctx;
        struct optee *optee;
+       u32 sec_caps;
        int rc;
 
        ffa_ops = ffa_dev_ops_get(ffa_dev);
@@ -788,7 +800,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
        if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
                return -EINVAL;
 
-       if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &rpc_param_count))
+       if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps,
+                                    &rpc_param_count))
                return -EINVAL;
 
        optee = kzalloc(sizeof(*optee), GFP_KERNEL);
index ee3a03fc392c5baf3f9c2a756a264bafe4d25cf5..97266243deaa032b13b123373bac4251ff56fc01 100644 (file)
  *                   as the second MSG arg struct for
  *                   OPTEE_FFA_YIELDING_CALL_WITH_ARG.
  *        Bit[31:8]: Reserved (MBZ)
- * w5-w7: Note used (MBZ)
+ * w5:   Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below,
+ *       unused bits MBZ.
+ * w6-w7: Not used (MBZ)
+ */
+/*
+ * Secure world supports giving an offset into the argument shared memory
+ * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG
  */
+#define OPTEE_FFA_SEC_CAP_ARG_OFFSET   BIT(0)
+
 #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
 
 /*
  *       OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg
  *       for RPC, this struct has reserved space for the number of RPC
  *       parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES.
+ *       MBZ unless the bit OPTEE_FFA_SEC_CAP_ARG_OFFSET is received with
+ *       OPTEE_FFA_EXCHANGE_CAPABILITIES.
  * w7:    Not used (MBZ)
  * Resume from RPC. Register usage:
  * w3:    Service ID, OPTEE_FFA_YIELDING_CALL_RESUME