Closed bstandaert-wustl closed 3 weeks ago
Hello @bstandaert-wustl,
Issue https://github.com/OP-TEE/optee_os/issues/4781 is rather about ability to cancel a TA execution, not about whether or not it can be preempted.
- Are TAs intended to be preemptible?
TAs are interruptible and preemptible. When a TA executes, it can be interrupted by secure interrupts and by non-secure interrupts.
When a secure interrupt occurs, the TA is interrupted for the secure interrupt to be served then the TA execution resumes.
When a non-secure interrupts occurs, the TA is interrupted and secure monitor switches to non-secure world for the interrupt to be served. When interrupt is served in non-secure world, the non-secure scheduler may decide to schedule another thread. In this case, the TA execution will resume only when the non-secure scheduler decides to schedule back the non-secure thread related to the TA invocation (that is the non-secure thread that initially invoked the TA, e.g. through a call to TEE_InvokeTACommand()
).
Non-secure interrupt management and scheduling impacts are described in documentation section Deliver non-secure interrupts to Normal World and section Scheduling considerations in Trusted thread scheduling.
- If I want to control/limit the amount of preemption that can occur during TA execution (ideally without having to disable all foreign interrupts), how can I do that?
You need to act on the Linux thread that invokes the TA. OP-TEE core has no impact on non-secure scheduler (aside masking non-secure interrupts when a TA executes).
OK, thanks, I think that clarifies some things!
Hello, as part of a research project I’m doing into scheduling of TAs, I’m trying to understand when OP-TEE allows long-running TAs to be preempted.
From the discussion in #4781, I understood that TAs could only be interrupted if they called Wait(); otherwise they would execute in a single non-preemptive chunk. However, I put together a testcase, where that seems to not be the case: https://gist.github.com/bstandaert-wustl/6f2c7a7f53c4c48363d1831246745887
In my testcase, I create one subthread that I pin to core 1, which invokes a TA that spins for 20 seconds using the TA persistent time APIs. Meanwhile, I repeatedly create other child threads at a 100ms interval, each of which I also pin to core 1; these threads print a message and increment a counter when they execute. Both types of threads are set to use the FIFO scheduler; I give the thread running the TA the lowest priority of the group, so that if the scheduler is picking a new task, it will always pick one of the message-printing threads.
If my TA was nonpreemptible, I would expect it to block other tasks from starting on the core while it executed, but what I actually see happen is that the other tasks, on the same CPU core as the TA thread, continuously launch and execute at the same time as the TA, as shown in the collapsed log below:
If I turn off foreign interrupts here, then execution of my other tasks are deferred until the TA returns: https://github.com/OP-TEE/optee_os/blob/master/core/tee/entry_std.c#L538, which produces the following log:
I thought that perhaps the scheduling tick from the kernel was being treated as an FIQ and causing preemptions, but even after enabling nohz_full on CPU 1, I’m still seeing this behavior, both in QEMU and on a Raspberry Pi.
Therefore, I have the following questions: