@@ -347,8 +347,14 @@ static void test_ptimer(void)
static void test_init(void)
{
assert(TIMER_PTIMER_IRQ != -1 && TIMER_VTIMER_IRQ != -1);
- ptimer_info.irq = TIMER_PTIMER_IRQ;
- vtimer_info.irq = TIMER_VTIMER_IRQ;
+ if (current_level() == CurrentEL_EL1) {
+ ptimer_info.irq = TIMER_PTIMER_IRQ;
+ vtimer_info.irq = TIMER_VTIMER_IRQ;
+ } else {
+ assert(TIMER_HPTIMER_IRQ != -1 && TIMER_HVTIMER_IRQ != -1);
+ ptimer_info.irq = TIMER_HPTIMER_IRQ;
+ vtimer_info.irq = TIMER_HVTIMER_IRQ;
+ }
install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, ptimer_unsupported_handler);
ptimer_info.read_ctl();
@@ -290,6 +290,8 @@ struct acpi_table_gtdt {
u64 counter_read_block_address;
u32 platform_timer_count;
u32 platform_timer_offset;
+ u32 virtual_el2_timer_interrupt;
+ u32 virtual_el2_timer_flags;
};
/* Reset to default packing */
@@ -21,12 +21,23 @@ struct timer_state {
u32 irq;
u32 irq_flags;
} vtimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hptimer;
+ struct {
+ u32 irq;
+ u32 irq_flags;
+ } hvtimer;
};
extern struct timer_state __timer_state;
#define TIMER_PTIMER_IRQ (__timer_state.ptimer.irq)
#define TIMER_VTIMER_IRQ (__timer_state.vtimer.irq)
+#define TIMER_HPTIMER_IRQ (__timer_state.hptimer.irq)
+#define TIMER_HVTIMER_IRQ (__timer_state.hvtimer.irq)
+
void timer_save_state(void);
#endif /* !__ASSEMBLY__ */
@@ -38,10 +38,11 @@ static void timer_save_state_fdt(void)
* secure timer irq
* non-secure timer irq (ptimer)
* virtual timer irq (vtimer)
- * hypervisor timer irq
+ * hypervisor timer irq (hptimer)
+ * hypervisor virtual timer irq (hvtimer)
*/
prop = fdt_get_property(fdt, node, "interrupts", &len);
- assert(prop && len == (4 * 3 * sizeof(u32)));
+ assert(prop && len >= (4 * 3 * sizeof(u32)));
data = (u32 *) prop->data;
assert(fdt32_to_cpu(data[3]) == 1 /* PPI */ );
@@ -50,6 +51,14 @@ static void timer_save_state_fdt(void)
assert(fdt32_to_cpu(data[6]) == 1 /* PPI */ );
__timer_state.vtimer.irq = PPI(fdt32_to_cpu(data[7]));
__timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
+ if (len == (5 * 3 * sizeof(u32))) {
+ assert(fdt32_to_cpu(data[9]) == 1 /* PPI */ );
+ __timer_state.hptimer.irq = PPI(fdt32_to_cpu(data[10]));
+ __timer_state.hptimer.irq_flags = fdt32_to_cpu(data[11]);
+ assert(fdt32_to_cpu(data[12]) == 1 /* PPI */ );
+ __timer_state.hvtimer.irq = PPI(fdt32_to_cpu(data[13]));
+ __timer_state.hvtimer.irq_flags = fdt32_to_cpu(data[14]);
+ }
}
#ifdef CONFIG_EFI
@@ -72,6 +81,12 @@ static void timer_save_state_acpi(void)
__timer_state.vtimer.irq = gtdt->virtual_timer_interrupt;
__timer_state.vtimer.irq_flags = gtdt->virtual_timer_flags;
+
+ __timer_state.hptimer.irq = gtdt->non_secure_el2_interrupt;
+ __timer_state.hptimer.irq_flags = gtdt->non_secure_el2_flags;
+
+ __timer_state.hvtimer.irq = gtdt->virtual_el2_timer_interrupt;
+ __timer_state.hvtimer.irq_flags = gtdt->virtual_el2_timer_flags;
}
#else
At EL2, with VHE: - CNTP_CVAL_EL0 is forwarded to CNTHP_CVAL_EL0 - CNTV_CVAL_EL0 is forwarded to CNTHP_CVAL_EL0 Save the hypervisor physical and virtual timer IRQ numbers from the DT/ACPI. Signed-off-by: Joey Gouly <joey.gouly@arm.com> --- arm/timer.c | 10 ++++++++-- lib/acpi.h | 2 ++ lib/arm/asm/timer.h | 11 +++++++++++ lib/arm/timer.c | 19 +++++++++++++++++-- 4 files changed, 38 insertions(+), 4 deletions(-)