Re: [PATCH] KVM: arm64: Disable TRBE Trace Buffer Unit when running in guest context

Leo Yan
2026-02-19T18:58:03Z

On Thu, Feb 19, 2026 at 01:54:19PM +0000, Will Deacon wrote:

[...]

> > > > > In which case, the host->guest something hideous like:
> > > > >
> > > > > isb();
> > > > > tsb_csync(); // Executes twice if ARM64_WORKAROUND_TSB_FLUSH_FAILURE!
> > > > > dsb(nsh); // I missed this in my patch
> > > > > write_sysreg_s(0, SYS_TRBLIMITR_EL1);
> > > > > if (2064142) {
> > > > > tsb_csync();
> > > > > dsb(nsh);
> > > > > }
> > > > > isb();
> > > >
> > > > As I_QXJZX suggests, the section K10.5.10 "Context switching" gives
> > > > the flow. I'd suggest the VM context switch is also aligned to the
> > > > description in S_VKHHY.
> > >
> > > I honestly have a hard time believing the sequence in S_VKHHY as the DSB
> > > seems to be in the wrong place which means the TSB CSYNC can float. It
> > > also isn't aligned with what the EL1 driver does...
> >
> > Sorry for confusion. I am checking internally for the flow suggested
> > in S_VKHHY.

After internal review, we conclude that S_VKHHY is valid. The intent of
S_VKHHY is to use the minimal number of barriers during a context switch.

Given the mentioned "DSB seems to be in the wrong place which means the
TSB CSYNC can float", this would be fine due to the two considerations:

1) As described in B2.6.8:

| The following situations are synchronized using a TSB operation:
|
| * A direct write B to a System register is ordered after an indirect
| read or indirect write of the same register by atrace operation of
| a traced instruction A, if all of the following are true:
| - A is executed in program order before a Context synchronization event C.
| - C appears in program order before a TSB operation T.
| - B is executed in program order after T.

If trace operations indirectly read or write system registers, the TSB
ensures that these indirect accesses are complete before any direct
writes to the same register are performed in program order after the TSB.

So in S_VKHHY, we don't expect clearing TRCPRGCTLR.EN (step 4) and
clearing TRBLIMITR_EL1.E (step 5) to take effect prior to the TSB.

2) A DSB executed after the TSB ensures the data writes are complete,
then it is safe to read trace data from memory. However, in the context
switch case, we don't need to read trace data, so a DSB for "publishing"
data is not required.

Based on these conclusions, let me summarize the flow:

// Prohibit trace
TRFCR_EL1 = 0;

// No new program-flow trace
isb();

// Trace operation and trace unit are flushed
tsb_csync(); // Executes twice if ARM64_WORKAROUND_TSB_FLUSH_FAILURE!

// Disable trace unit
TRCPRGCTLR.EN = 0b0

// Disable trace buffer unit
TRBLIMITR_EL1.E = 0b0

if (2064142) {
tsb_csync();
dsb(nsh);
}

// Ensure trace disable takes effect and indirect writes are visible;
// Ensure 2064142 is done before affected sysreg write.
isb();

> > > > When switching from host to guest, we need to clear TRCPRGCTLR.EN to
> > > > zero. As the doc states "ETE trace compression logic is stateful,
> > > > and disabling the ETE resets this compression state".
> > > >
> > > > > and then the guest->host part is:
> > > > >
> > > > > write_sysreg_s(trblimitr_el1, SYS_TRBLIMITR_EL1);
> > > > > isb();
> > > > > if (2038923)
> > > > > isb();
> > > > >
> > > > > Does that look right to you?
> > > >
> > > > S_PKLXF gives the flow for switching in.
> > >
> > > Well, modulo errata, sure. I don't have access to the errata document so
> > > I was more interested in whether I got that right...
> >
> > Please see the doc:
> > https://developer.arm.com/documentation/SDEN-1873351/1900/?lang=en
>
> Aha, thank you, Leo!

You are welcome!

> I swear you used to be able to google the erratum number and get the doc,
> but that doesn't seem to be the case any more. In fact, if you type the
> erratum number into the search box on developer.arm.com it doesn't even
> work, so cheers for pointing me to the right place.

I also cannot search the doc via google, seems this is a known issue for
developer.arm.com when I checked this internally. Thanks a lot for
reporting it.

The flow for guest->host might be easy one, anyway, I try to summary for
review:

Restore TRFCR_EL1;

// Ensure restored sysreg is visible
isb();

// Enable trace buffer
TRBLIMITR_EL1.E = 0b1

// Enable trace unit
TRCPRGCTLR.EN = 0b1

if (2038923)
isb();

// eret works as an extra context synchronization

Thanks,
Leo