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

Steven Price <[email protected]> Thu, 30 Jul 2026 09:47:27 +0100
Newsgroups dev.linux.lists.linux-coco,dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 29/07/2026 11:58, Marc Zyngier wrote:
> On Wed, 29 Jul 2026 11:47:03 +0100,
> Steven Price <[email protected]> wrote:
>>
>> On 27/07/2026 10:21, Marc Zyngier wrote:
>>> On Wed, 15 Jul 2026 15:28:15 +0100,
>>> Steven Price <[email protected]> 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 <[email protected]>
>>>> ---
>>>> 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