Hi Edison,

If it is a bug, I will upsteam a patch to fix it later.

Thanks,
Matt

At 2019-12-19 16:43:18, "Edison Ai via TF-M" <tf-m@lists.trustedfirmware.org> wrote:

Hi Matt,

 

Sorry not got your point in the first time.

 

Yes, you are right. It is indeed a bug here. And thanks for your detail explaining and good example.

 

Can you upstream a patch to fix it?

 

Thanks,

Edison

 

From: TF-M <tf-m-bounces@lists.trustedfirmware.org> On Behalf Of lg via TF-M
Sent: Wednesday, December 18, 2019 9:54 PM
To: tf-m@lists.trustedfirmware.org
Cc: nd <nd@arm.com>
Subject: Re: [TF-M] irq handling in library mode

 

Hi Edison,

 

Thanks for your reply.

 

In file tfm_secure_irq_handling.rst, we can know every SP have a continuous irq related stack as follows,

 

interrupted_ctx_stack_frame_t  

handler_ctx_stack_frame_t

interrupted_ctx_stack_frame_t   

...

handler_ctx_stack_frame_t

interrupted_ctx_stack_frame_t 

     

And this stack pointer is saved in the field ctx_stack_ptr of structure  spm_partition_runtime_data_t  for each partition.

 

If partition  A is interrupted for the first time by a lower priority interrupt, as current code shown bellow, the interrupted_ctx_stack_frame_t will be pushed at the beginning of the irq stack.

 

void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx)

{

    struct spm_partition_runtime_data_t *runtime_data =

        &g_spm_partition_db.partitions[partition_idx].runtime_data;

    struct interrupted_ctx_stack_frame_t *stack_frame =

        (struct interrupted_ctx_stack_frame_t *)runtime_data->ctx_stack_ptr;

    stack_frame->partition_state = runtime_data->partition_state;

}

Now the stack is show as below,

interrupted_ctx_stack_frame_t (used) 

handler_ctx_stack_frame_t

interrupted_ctx_stack_frame_t   

...

handler_ctx_stack_frame_t

interrupted_ctx_stack_frame_t 

But the stack pointer is not moved upper after pushing interrupted_ctx_stack_frame_t, so the ctx_stack_ptr is still point to the beginning of the stack.

At this time,if a higher priority interrupt of partition A is coming, partition A becomes handler partition, so the structure handler_ctx_stack_frame_t should be pushed in

the stack of partition A, as current code shown below,

void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx)

{

    struct spm_partition_runtime_data_t *runtime_data =

        &g_spm_partition_db.partitions[partition_idx].runtime_data;

    struct handler_ctx_stack_frame_t *stack_frame =

        (struct handler_ctx_stack_frame_t *)

            runtime_data->ctx_stack_ptr;

    stack_frame->partition_state = runtime_data->partition_state;

    stack_frame->caller_partition_idx = runtime_data->caller_partition_idx;

    runtime_data->ctx_stack_ptr +=

        sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);

}

As it shown above, the content of  handler_ctx_stack_frame_t will be overlapped with already pushed content of interrupted_ctx_stack_frame_t.

 

My question is exactly about the above scenario. 

If the stack pointer is also moved upper after pushing the interrupted_ctx_stack_frame_t, handler_ctx_stack_frame_t will be pushed at different location in the stack as follows,

 

interrupted_ctx_stack_frame_t (used

handler_ctx_stack_frame_t (used)

interrupted_ctx_stack_frame_t   

...

handler_ctx_stack_frame_t

interrupted_ctx_stack_frame_t 

 

Please read the file tfm_secure_irq_handling.rst again , and help to check about this question.

 

Thanks,

Matt

 

At 2019-12-17 14:22:13, "Edison Ai \\(Arm Technology China\\) via TF-M" <tf-m@lists.trustedfirmware.org> wrote:

Hi Matt,

 

Thanks for your email.

 

Let me try to answer your question because of the designer of the TF-M interrupt handling is on leave now.

 

First, you are right about this: ¡°If the interrupted partition is the same as the handler partition, interrupted_ctx_stack_frame_t  and handler_ctx_stack_frame_t should be pushed at different location.¡±

 

Let¡¯s start from an example, there are 3 SPs with different interrupt priority, SP1 < SP2 < SP3. And there is one scenario like this:

  • SP1 is running, SP2 interrupt SP1. Current, the interrupted partition is SP1, and the handler partition is SP2.

As the below code show in tfm_spm_partition_push_handler_ctx(), the stack pointer will be moved upper as below:

 

SP2 stack pointer -¨¤

 

 

Caller_partition_indx(handler)

 

Partition_sate(handler)


  • SP2 starts to run, and it is interrupted by SP3. Current, the interrupted partition is SP2, and the handler partition is SP3.

As the code shown in tfm_spm_partition_push_interrupted_ctx(),  it uses the current stack member directly without moving its pointer.

 

SP2 stack pointer -¨¤

Partition_state(interrupted)

 

Caller_partition_indx(handler)

 

Partition_sate(handler)

                And after SP2 is interrupted by SP3, its partition status will be changed to ¡°SPM_PARTITION_STATE_SUSPENDED¡±.  So that this partition will not be interrupted by others anymore unless it comes back to running state. Which means it does not need more stack anymore.

 

We can consider that after one SP is interrupted by others, there is no more stack is needed for it before it comes back to running status.

 

So I think it should be ok in the current design for the interrupt in the library model.

 

I am not sure if this can solve your confuse. Please feel free to give feedback. We can discuss more about it.

 

Thanks,

Edison

 

From: TF-M <tf-m-bounces@lists.trustedfirmware.org> On Behalf Of lg via TF-M
Sent: Monday, December 16, 2019 1:08 PM
To:
tf-m@lists.trustedfirmware.org
Subject: [TF-M] irq handling in library mode

 

Hi TFM experts,

 

I have a question about the code logic of irq handling in library mode, code blocks in spm_api_func.c are as follows:

 

void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx)

{

    struct spm_partition_runtime_data_t *runtime_data =

        &g_spm_partition_db.partitions[partition_idx].runtime_data;

    struct interrupted_ctx_stack_frame_t *stack_frame =

        (struct interrupted_ctx_stack_frame_t *)runtime_data->ctx_stack_ptr;

 

    stack_frame->partition_state = runtime_data->partition_state;

}

 

void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx)

{

    struct spm_partition_runtime_data_t *runtime_data =

        &g_spm_partition_db.partitions[partition_idx].runtime_data;

    struct handler_ctx_stack_frame_t *stack_frame =

        (struct handler_ctx_stack_frame_t *)

            runtime_data->ctx_stack_ptr;

 

    stack_frame->partition_state = runtime_data->partition_state;

    stack_frame->caller_partition_idx = runtime_data->caller_partition_idx;

 

    runtime_data->ctx_stack_ptr +=

        sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);

}

 

My question is why there is not the following such code logic  at the end of function tfm_spm_partition_push_interrupted_ctx.

runtime_data->ctx_stack_ptr +=

        sizeof(struct interrupted_ctx_stack_frame_t ) / sizeof(uint32_t);

 

If the interrupted partition is the same as the handler partition, interrupted_ctx_stack_frame_t  and handler_ctx_stack_frame_t should be pushed at different location.

 

And when pop the stack frame after handling irq, there is the following code logic in tfm_spm_partition_pop_handler_ctx

    runtime_data->ctx_stack_ptr -=

        sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);

 

I think the same logic of changing ctx_stack_ptr should be added the begining of the function tfm_spm_partition_pop_interrupted_ctx like the above code logic in tfm_spm_partition_pop_handler_ctx.

    runtime_data->ctx_stack_ptr -=

        sizeof(struct interrupted_ctx_stack_frame_t ) / sizeof(uint32_t);

 

Please help to check.

 

Thanks,

Matt