Skip to content

Riscv vector context - #7961

Open
dave-patel-riscstar wants to merge 6 commits into
OP-TEE:masterfrom
dave-patel-riscstar:riscv-vector-context
Open

Riscv vector context#7961
dave-patel-riscstar wants to merge 6 commits into
OP-TEE:masterfrom
dave-patel-riscstar:riscv-vector-context

Conversation

@dave-patel-riscstar

Copy link
Copy Markdown

OP-TEE's architecture-specific trusted-application context management must preserve floating-point and vector registers in addition to the associated control state. Lazy switching is unsuitable because supervisor mode can modify the FS and VS status bits without reliably revealing actual register use across privilege levels. Hidden state changes can cause correctness failures, data leakage, or side-channel exposure. Frequent floating-point and vector use also reduces the expected performance benefit of trapping lazily, making eager save and restore the preferred approach.

The changes has been tested on xtest and there is a separate PR
OP-TEE/optee_test#827

@github-actions

Copy link
Copy Markdown

FYI @maroueneboubakri

Add the macro for a RISC-V vector context and the two routines that
move it between memory and the vector registers.

struct riscv_vector_state declaration for vector registers and CSR.
All four CSRs are needed: vtype and vl describe the shape the
registers are being used. Both vl and vtype are not directly writable,
so the pair is put back by re-running the vsetvl that produced it.

The width of a vector register is discovered at run time from vlenb, so a
context cannot be sized from the ISA the core was built for. The register
file is therefore a flexible array and riscv_vector_state_size() reports
what one context costs on this hart, and is allocate per hart.

The registers are moved with the whole-register forms vs8r.v and vl8r.v,
eight at a time. The vector ISA is enabled for those blocks alone with
.option arch.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit 77ce5faab9f63ee6918bc585f5e296aa250f931b)
Add accessors to drive the vector unit via xstatus.VS.

These mirror the existing FS accessors used for floating-point state:
- Functions accepting an 'xstatus' value modify a saved context (required
  by trap paths, as xstatus is part of frame restored upon exception return).
- All other accessors operate directly on the live CSR of the current hart.

Add the accessors used to drive the vector unit through xstatus.VS. They
mirror the FS accessors used for floating point: those taking an xstatus
value edit a saved context, which is what the trap paths need since
xstatus is part of the frame written back when returning to a trapped
context, while the rest act on the live CSR of the current hart.

riscv_vector_vlenb() is here too because reading vlenb needs the unit
enabled, so the read has to be wrapped the same way the save and restore
routines wrap theirs.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit cd1df4368d050190dbe0445ebb306783efb3b2d0)
Save and restore the normal world vector registers when a thread crosses
into OP-TEE and back.

NS and S used Eager context switch, On the way in the registers are
saved and on the way out the ns context is put back.

Nothing in OP-TEE core uses vector, so there is no secure kernel vector
section to go with thread_kernel_enable_vfp(). Adding an interface with
no caller would be speculative; the ownership tracking has room for one
should core code ever want it.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit 28bfb85f0e555d76e9864276e2a82cc2474d4c47)
Add the per-TA vector context and the routines that hand the vector unit
to a TA and take it back.

Lazy context switch support, TA enters user mode with xstatus.VS == Off
and is given the unit only once it executes a vector instruction and traps.
The eager switching used at the REE/TEE boundary is not the right default here:
within the TEE, OP-TEE alone owns VS, no other context can reach the vector
registers behind, and most TAs never touch vector. Enabling on first use
keeps those TAs from paying for a context switch they have no use for,
which for vector is a good deal larger than it is for floating point,
being 32 registers of vlenb bytes each rather than 32 doublewords.

VS lives in xstatus, which is restored from the register frame on
the way back to user mode, releasing a TA's context means clearing VS in
the saved context as well as in the live CSR. That is what
user_status_disable_vector() does on the scall path, on suspend and on
entry to user mode; without it a TA would resume with VS still set and use
registers that no longer hold its values.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit 6eab1c1197667ebf3ca9aadbb9cd173abe9c86ab)
Decode the illegal instruction trap a TA takes on its first vector
instruction and hand it a context instead of killing it.

A hart traps a vector instruction executed with xstatus.VS == Off as an
illegal instruction, which is the same trap a TA gets for a genuinely
illegal instruction, so the two are told apart by decoding the faulting
instruction reported in xtval. Three groups have to be recognised:

  - the OP-V major opcode, which covers the arithmetic and the vsetvl
    family
  - the vector loads and stores, which share their major opcodes with the
    floating-point ones and are told apart by the width field holding one
    of the four encodings reserved for vector
  - reads and writes of the vector CSRs, which trap with VS == Off just
    as the instructions do, so a TA asking for vlenb or setting a
    rounding mode before it issues any vector instruction is asking for a
    context too

Anything else still panics the TA rather than being resumed on the
instruction that trapped. Vector instructions are always 32 bits wide, so
unlike the floating-point case there are no compressed forms to decode.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit f36545ec73f4be4dcc8edd0c2f3fc9d82a99a0b3)
Hook the vector context switching added by the preceding patches up to
CFG_WITH_VFP, the generic flag that asks OP-TEE to preserve the extended
register state across a context switch.

Which register files that covers follows the extensions the platform says
the hart has, rather than needing a knob of its own: the vector registers
are switched when CFG_RISCV_VEC=y and are left alone otherwise, the same
way CFG_RISCV_FPU already decides whether the floating-point registers are
part of the ISA at all.

plat-virt declares the vector extension since QEMU virt provides it.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
(cherry picked from commit 51d7442e89a764bad8241be4d021c2b4f46335cf)
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