Unverified Commit c6e5bdae authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'optee-async-notif-for-v5.17' of...

Merge tag 'optee-async-notif-for-v5.17' of https://git.linaro.org/people/jens.wiklander/linux-tee into arm/drivers

OP-TEE Asynchronous notifications from secure world

Adds support in the SMC based OP-TEE driver to receive asynchronous
notifications from secure world using an edge-triggered interrupt as
delivery mechanism.

* tag 'optee-async-notif-for-v5.17' of https://git.linaro.org/people/jens.wiklander/linux-tee:
  optee: Fix NULL but dereferenced coccicheck error
  optee: add asynchronous notifications
  optee: separate notification functions
  tee: export teedev_open() and teedev_close_context()
  tee: fix put order in teedev_close_context()
  dt-bindings: arm: optee: add interrupt property
  docs: staging/tee.rst: add a section on OP-TEE notifications

Link: https://lore.kernel.org/r/20211213102359.GA1638682@jade


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 5213313b b98aee46
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@ properties:
  compatible:
    const: linaro,optee-tz

  interrupts:
    maxItems: 1
    description: |
      This interrupt which is used to signal an event by the secure world
      software is expected to be edge-triggered.

  method:
    enum: [smc, hvc]
    description: |
@@ -42,10 +48,12 @@ additionalProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    firmware  {
        optee  {
            compatible = "linaro,optee-tz";
            method = "smc";
            interrupts = <GIC_SPI 187 IRQ_TYPE_EDGE_RISING>;
        };
    };

+30 −0
Original line number Diff line number Diff line
@@ -184,6 +184,36 @@ order to support device enumeration. In other words, OP-TEE driver invokes this
application to retrieve a list of Trusted Applications which can be registered
as devices on the TEE bus.

OP-TEE notifications
--------------------

There are two kinds of notifications that secure world can use to make
normal world aware of some event.

1. Synchronous notifications delivered with ``OPTEE_RPC_CMD_NOTIFICATION``
   using the ``OPTEE_RPC_NOTIFICATION_SEND`` parameter.
2. Asynchronous notifications delivered with a combination of a non-secure
   edge-triggered interrupt and a fast call from the non-secure interrupt
   handler.

Synchronous notifications are limited by depending on RPC for delivery,
this is only usable when secure world is entered with a yielding call via
``OPTEE_SMC_CALL_WITH_ARG``. This excludes such notifications from secure
world interrupt handlers.

An asynchronous notification is delivered via a non-secure edge-triggered
interrupt to an interrupt handler registered in the OP-TEE driver. The
actual notification value are retrieved with the fast call
``OPTEE_SMC_GET_ASYNC_NOTIF_VALUE``. Note that one interrupt can represent
multiple notifications.

One notification value ``OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF`` has a
special meaning. When this value is received it means that normal world is
supposed to make a yielding call ``OPTEE_MSG_CMD_DO_BOTTOM_HALF``. This
call is done from the thread assisting the interrupt handler. This is a
building block for OP-TEE OS in secure world to implement the top half and
bottom half style of device drivers.

AMD-TEE driver
==============

+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
obj-$(CONFIG_OPTEE) += optee.o
optee-objs += core.o
optee-objs += call.o
optee-objs += notif.o
optee-objs += rpc.o
optee-objs += supp.o
optee-objs += device.o
+1 −1
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ void optee_remove_common(struct optee *optee)
	/* Unregister OP-TEE specific client devices on TEE bus */
	optee_unregister_devices();

	optee_notif_uninit(optee);
	/*
	 * The two devices have to be unregistered before we can free the
	 * other resources.
@@ -167,7 +168,6 @@ void optee_remove_common(struct optee *optee)
	tee_device_unregister(optee->teedev);

	tee_shm_pool_free(optee->pool);
	optee_wait_queue_exit(&optee->wait_queue);
	optee_supp_uninit(&optee->supp);
	mutex_destroy(&optee->call_queue.mutex);
}
+5 −1
Original line number Diff line number Diff line
@@ -856,9 +856,13 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
	mutex_init(&optee->ffa.mutex);
	mutex_init(&optee->call_queue.mutex);
	INIT_LIST_HEAD(&optee->call_queue.waiters);
	optee_wait_queue_init(&optee->wait_queue);
	optee_supp_init(&optee->supp);
	ffa_dev_set_drvdata(ffa_dev, optee);
	rc = optee_notif_init(optee, OPTEE_DEFAULT_MAX_NOTIF_VALUE);
	if (rc) {
		optee_ffa_remove(ffa_dev);
		return rc;
	}

	rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
	if (rc) {
Loading