Skip to content

FP context switch xtest - #828

Open
dave-patel-riscstar wants to merge 3 commits into
OP-TEE:masterfrom
dave-patel-riscstar:rp022-m7-fp
Open

FP context switch xtest#828
dave-patel-riscstar wants to merge 3 commits into
OP-TEE:masterfrom
dave-patel-riscstar:rp022-m7-fp

Conversation

@dave-patel-riscstar

@dave-patel-riscstar dave-patel-riscstar commented Aug 27, 2026

Copy link
Copy Markdown

xtest for FP

A TA runs with the floating-point unit disabled and is handed a context on
the first floating-point instruction it executes, so every sub-test starts
by taking that trap. What they then cover is:

  SYSCALL      a syscall serviced entirely inside the TEE, where the TA
               context is saved on the way in and has to be given back on
               the first floating-point instruction after the return
  RPC          TEE_Wait(), which suspends the thread, runs the normal
               world and resumes through thread_resume_from_rpc()
  CRYPTO       a digest, which the TEE may compute in a secure kernel
               floating-point section of its own and so has to take the
               registers from the TA and hand them back
  TAINT        leaves a pattern in the registers and returns
  CHECK_TAINT  reads the registers before writing any of them and fails
               if an earlier TA's pattern is still there

Introduce riscv_fp_ctx.h, a small assembly-based helper library used by both
xtest and the os_test TA to observe the behaviour of floating‑point registers
across a call. The goal is to verify correct FP context preservation without
interference from compiler optimisations.

Only callee‑saved FP registers (fs0..fs11) and fcsr are covered. Caller‑saved
register (ft0..ft11, fa0..fa7) are intentionally excluded since the ABI allows
a callee to clobber them.

The routines are implemented in assembly to ensure value remain in FP registers
rather than being spilled to the stack by the compiler. They are emitted from a
header instead of a .S file so both xtest and the TA can share the same code
without adding assembler rules to their respective build systems.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
Add TA_OS_TEST_CMD_RISCV_FP_CONTEXT, which runs a set of sub-tests that
each install a known floating-point context, make a different kind of
excursion out of the TA, and check that the context comes back intact.

A TA runs with the floating-point unit disabled and is handed a context on
the first floating-point instruction it executes, so every sub-test starts
by taking that trap. What they then cover is:

  SYSCALL      a syscall serviced entirely inside the TEE, where the TA
               context is saved on the way in and has to be given back on
               the first floating-point instruction after the return
  RPC          TEE_Wait(), which suspends the thread, runs the normal
               world and resumes through thread_resume_from_rpc()
  CRYPTO       a digest, which the TEE may compute in a secure kernel
               floating-point section of its own and so has to take the
               registers from the TA and hand them back
  TAINT        leaves a pattern in the registers and returns
  CHECK_TAINT  reads the registers before writing any of them and fails
               if an earlier TA's pattern is still there

On failure the index of the first field that did not survive is reported
back to the caller so that a failure says which register was lost.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
Drive the os_test sub-tests from xtest and add the checks that can only be
made from the normal world.

Alongside the TA side cases the test holds a pattern in this process'
fs0..fs11 and fcsr across a call into the TEE. That is the normal world
half of the domain switch, and it is run twice: once against a TA command
that uses floating point and once against one that does not, since the TEE
restores the normal world context in the first case and skips the restore
in the second, having never disturbed the registers. Both have to leave
the caller's registers exactly as it left them.

A concurrency case runs the RPC sub-test from several threads at once,
since the floating-point bookkeeping is per OP-TEE thread and one thread's
context must not surface in another.

The test skips itself when the TA reports TEE_ERROR_NOT_SUPPORTED, which
covers both a non-RISC-V target and an OP-TEE built without
CFG_WITH_VFP.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
@dave-patel-riscstar

Copy link
Copy Markdown
Author

Add TA_OS_TEST_CMD_RISCV_FP_CONTEXT, which runs a set of sub-tests that
each install a known floating-point context, which runs different sets of test
out of the TA, and check that the context comes back intact.

A TA runs with the floating-point unit disabled and is handed a context on
the first floating-point instruction it executes, so every sub-test starts
by taking that trap. What they then cover is:

SYSCALL a syscall serviced entirely inside the TEE, where the TA
context is saved on the way in and has to be given back on
the first floating-point instruction after the return
RPC TEE_Wait(), which suspends the thread, runs the normal
world and resumes through thread_resume_from_rpc()
CRYPTO a digest, which the TEE may compute in a secure kernel
floating-point section of its own and so has to take the
registers from the TA and hand them back
TAINT leaves a pattern in the registers and returns
CHECK_TAINT reads the registers before writing any of them and fails
if an earlier TA's pattern is still there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant