Re: [PATCH v15 13/37] KVM: arm64: CCA: Support timers in realm RECs

From: Steven Price

Date: Thu Jul 30 2026 - 04:52:00 EST


On 29/07/2026 11:58, Marc Zyngier wrote:
> On Wed, 29 Jul 2026 11:47:03 +0100,
> Steven Price <steven.price@xxxxxxx> wrote:
>>
>> On 27/07/2026 10:21, Marc Zyngier wrote:
>>> On Wed, 15 Jul 2026 15:28:15 +0100,
>>> Steven Price <steven.price@xxxxxxx> wrote:
>>>>
>>>> The RMM keeps track of the timer while the realm REC is running, but on
>>>> exit to the normal world KVM is responsible for handling the timers.
>>>>
>>>> A later patch adds the support for propagating the timer values from the
>>>> exit data structure and calling kvm_realm_timers_update().
>>>>
>>>> Signed-off-by: Steven Price <steven.price@xxxxxxx>
>>>> ---
>>>> Changes since v14:
>>>> * Special case in kvm_timer_vcpu_load()/kvm_timer_vcpu_put() the timer
>>>> handling.
>>>> Changes since v12:
>>>> * Adapt to upstream changes.
>>>> Changes since v11:
>>>> * Drop the kvm_is_realm() check from timer_set_offset(). We already
>>>> ensure that the offset is 0 when calling the function.
>>>> Changes since v10:
>>>> * KVM_CAP_COUNTER_OFFSET is now already hidden by a previous patch.
>>>> Changes since v9:
>>>> * No need to move the call to kvm_timer_unblocking() in
>>>> kvm_timer_vcpu_load().
>>>> Changes since v7:
>>>> * Hide KVM_CAP_COUNTER_OFFSET for realm guests.
>>>> ---
>>>> arch/arm64/kvm/arch_timer.c | 38 +++++++++++++++++++++++++++++++++---
>>>> include/kvm/arm_arch_timer.h | 2 ++
>>>> 2 files changed, 37 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
>>>> index 4155fe89b58a..fdd68f1f5b7b 100644
>>>> --- a/arch/arm64/kvm/arch_timer.c
>>>> +++ b/arch/arm64/kvm/arch_timer.c
>>>> @@ -482,6 +482,20 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
>>>> timer_ctx);
>>>> }
>>>>
>>>> +void kvm_realm_timers_update(struct kvm_vcpu *vcpu)
>>>> +{
>>>> + struct arch_timer_cpu *arch_timer = &vcpu->arch.timer_cpu;
>>>> + int i;
>>>> +
>>>> + for (i = 0; i < NR_KVM_EL0_TIMERS; i++) {
>>>> + struct arch_timer_context *timer = &arch_timer->timers[i];
>>>> + bool status = timer_get_ctl(timer) & ARCH_TIMER_CTRL_IT_STAT;
>>>> + bool level = kvm_timer_enabled(timer) && status;
>>>> +
>>>> + kvm_timer_update_irq(vcpu, level, timer);
>>>> + }
>>>> +}
>>>> +
>>>
>>> Why do we need this? What is so special about CCA that it cannot use
>>> the existing timer flow?
>>
>> CCA is a little special because the timer context is owned by the RMM
>> while the realm is executing. It's the RMM which actually loads/saves
>> the timer registers not KVM.
>>
>> The RMM returns some of the timer state on every exit, and the host is
>> responsible for updating the interrupt status (as the host controls the
>> GIC emulation).
>
> But KVM relies on the timers being live when the vcpu is loaded. So
> the first port of call should be for CCA to adapt to KVM, and not the
> other way around.
>
> You can always make sure that the timers are in the registers at the
> point where you reach the KVM code.

Indeed if you'd prefer that I can modify the code to load the timer
state into the registers in the Linux CCA code before reaching the
generic KVM code. It's a little weird from an overall point of view (the
RMM saves the state into memory, and then Linux reloads it just to save
it again), but I don't see any implementation issues.

But a quick go at implementing this does indeed seem to save us a bit of
code, so I'll include this in the next posting.

Thanks,
Steve