[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v6 01/13] xen/arm: Add suspend and resume timer helpers
Hi Mykola, On 01/09/2025 23:10, Mykola Kvach wrote: From: Mirela Simonovic <mirela.simonovic@xxxxxxxxxx> Timer interrupts must be disabled while the system is suspended to prevent spurious wake-ups. Yet, you don't seem to disable the virtual interrupt. Can you explain why? I know this is what Arm is naming the timers. But I would rather s/EL1// and s/EL2// because the physical timer is also accessible from EL0.Suspending the timers involves disabling both the EL1 physical timer and the EL2 hypervisor timer. Note that Xen doesn't use or expose the physical timer. So it should always be disabled at the point "time_suspend()" is called. I am still ok to disable it just in case though. Resuming consists of raising the TIMER_SOFTIRQ, which prompts the generic timer code to reprogram the EL2 timer as needed. Re-enabling of the EL1 timer is left to the entity that uses it. Introduce a new helper, disable_physical_timers, to encapsulate disabling of the physical timers. Signed-off-by: Mirela Simonovic <mirela.simonovic@xxxxxxxxxx> Signed-off-by: Saeed Nowshadi <saeed.nowshadi@xxxxxxxxxx> Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx> --- Changes in V4: - Rephrased comment and commit message for better clarity - Created separate function for disabling physical timers Changes in V3: - time_suspend and time_resume are now conditionally compiled under CONFIG_SYSTEM_SUSPEND --- xen/arch/arm/include/asm/time.h | 5 +++++ xen/arch/arm/time.c | 38 +++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/xen/arch/arm/include/asm/time.h b/xen/arch/arm/include/asm/time.h index 49ad8c1a6d..f4fd0c6af5 100644 --- a/xen/arch/arm/include/asm/time.h +++ b/xen/arch/arm/include/asm/time.h @@ -108,6 +108,11 @@ void preinit_xen_time(void);void force_update_vcpu_system_time(struct vcpu *v); +#ifdef CONFIG_SYSTEM_SUSPEND+void time_suspend(void); +void time_resume(void); +#endif /* CONFIG_SYSTEM_SUSPEND */ + #endif /* __ARM_TIME_H__ */ /* * Local variables: diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index e74d30d258..ad984fdfdd 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -303,6 +303,14 @@ static void check_timer_irq_cfg(unsigned int irq, const char *which) "WARNING: %s-timer IRQ%u is not level triggered.\n", which, irq); }+/* Disable physical timers for EL1 and EL2 on the current CPU */ The name of the times are "physical timer" and "hypervisor timer". +static inline void disable_physical_timers(void) "Physical is a bit misleading" in this context. All the 3 timers (virtual, physical, hypervisor) are physical timers. My preference would be to name this function disable_timers() (assuming you also need to disable the virtual timer). +{ + WRITE_SYSREG(0, CNTP_CTL_EL0); /* Physical timer disabled */ + WRITE_SYSREG(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */ + isb(); +} + /* Set up the timer interrupt on this CPU */ void init_timer_interrupt(void) { @@ -310,9 +318,7 @@ void init_timer_interrupt(void) WRITE_SYSREG64(0, CNTVOFF_EL2); /* No VM-specific offset */ /* Do not let the VMs program the physical timer, only read the physical counter */ WRITE_SYSREG(CNTHCTL_EL2_EL1PCTEN, CNTHCTL_EL2); - WRITE_SYSREG(0, CNTP_CTL_EL0); /* Physical timer disabled */ - WRITE_SYSREG(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */ - isb(); + disable_physical_timers();request_irq(timer_irq[TIMER_HYP_PPI], 0, htimer_interrupt,"hyptimer", NULL); @@ -330,9 +336,7 @@ void init_timer_interrupt(void) */ static void deinit_timer_interrupt(void) { - WRITE_SYSREG(0, CNTP_CTL_EL0); /* Disable physical timer */ - WRITE_SYSREG(0, CNTHP_CTL_EL2); /* Disable hypervisor's timer */ - isb(); + disable_physical_timers();release_irq(timer_irq[TIMER_HYP_PPI], NULL);release_irq(timer_irq[TIMER_VIRT_PPI], NULL); @@ -372,6 +376,28 @@ void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds) /* XXX update guest visible wallclock time */ }+#ifdef CONFIG_SYSTEM_SUSPEND+ +void time_suspend(void) +{ + disable_physical_timers(); +} + +void time_resume(void) +{ + /* + * Raising the timer softirq triggers generic code to call reprogram_timer + * with the correct timeout (not known here). + * + * No further action is needed to restore timekeeping after power down, + * since the system counter is unaffected. See ARM DDI 0487 L.a, D12.1.2 + * "The system counter must be implemented in an always-on power domain." + */ + raise_softirq(TIMER_SOFTIRQ); I think we should add a comment about the physical timer. +} + +#endif /* CONFIG_SYSTEM_SUSPEND */ + static int cpu_time_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)Cheers, -- Julien Grall
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |