As the issue #1132 explains, in order for the timer interrupts to "work",
many dots need to be connected.

Firstly, when the timer condition is met (CVAL <= global system counter)
on a specific CPU, the interrupt signal is asserted to the interrupt controller
(GIC - Generic Interrupt Controller) ONLY if both timer is enabled (ENABLE bit)
and interrupt unmasked (IMASK bit) per the CPU timer CTL register.

Secondly, once the signal is asserted on the GIC side, other settings on GIC 
side
dictate if the corresponding timer interrupt (PPI - Private Peripheral 
Interrupt)
is to be delivered back to the corresponding CPU. One of these settings is
the GICD_ISENABLER register which in essence dictates if the corresponding 
interrupt
is forwarded to specific CPU (see 
https://developer.arm.com/documentation/ihi0048/b/Programmers--Model/Distributor-register-descriptions/Interrupt-Set-Enable-Registers--GICD-ISENABLERn?lang=en).

So this patch in essence enhances the gic_driver::init_cpu() method,
which is called on each cpu, to unmask timer PPI interrupt for
that CPU if it is a secondary one (please note that this interrupt
is unmasked on primary CPU when the interrupt handler is registered).

Fixes #1132

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 arch/aarch64/arm-clock.cc | 24 +++++++++++-------------
 arch/aarch64/arm-clock.hh | 10 ++++++++++
 arch/aarch64/gic.cc       |  6 ++++++
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/aarch64/arm-clock.cc b/arch/aarch64/arm-clock.cc
index 534726ad..027c05ed 100644
--- a/arch/aarch64/arm-clock.cc
+++ b/arch/aarch64/arm-clock.cc
@@ -14,14 +14,12 @@
 
 #include <osv/debug.hh>
 #include <osv/prio.hh>
+#include <osv/sched.hh>
 
 #include "arch-dtb.hh"
 
 using namespace processor;
 
-#define NANO_PER_SEC 1000000000
-#define MHZ 1000000
-
 class arm_clock : public clock {
 public:
     arm_clock();
@@ -102,10 +100,6 @@ u64 arm_clock::processor_to_nano(u64 ticks)
     return cntvct;
 }
 
-#define TIMER_CTL_ISTATUS_BIT 4
-#define TIMER_CTL_IMASK_BIT   2
-#define TIMER_CTL_ENABLE_BIT  1
-
 class arm_clock_events : public clock_event_driver {
 public:
     arm_clock_events();
@@ -117,17 +111,21 @@ public:
     void write_ctl(unsigned int cntv_ctl);
     unsigned int read_tval();
     void write_tval(unsigned int cntv_tval);
-
     std::unique_ptr<ppi_interrupt> _irq;
 };
 
-arm_clock_events::arm_clock_events()
+int get_timer_irq_id()
 {
-    int res = dtb_get_timer_irq();
-    if (!res) {
-        res = 16 + 11; /* default PPI 11 */
+    auto _irq_id = dtb_get_timer_irq();
+    if (!_irq_id) {
+        _irq_id = DEFAULT_TIMER_IRQ_ID;
     }
-    _irq.reset(new ppi_interrupt(gic::irq_type::IRQ_TYPE_EDGE, res,
+    return _irq_id;
+}
+
+arm_clock_events::arm_clock_events()
+{
+    _irq.reset(new ppi_interrupt(gic::irq_type::IRQ_TYPE_EDGE, 
get_timer_irq_id(),
                                  [this] {
         /* From AArch64 Programmer's Guides Generic Timer (chapter 3.4, page 
10):
          * The interrupts generated by the timer behave in a level-sensitive 
manner.
diff --git a/arch/aarch64/arm-clock.hh b/arch/aarch64/arm-clock.hh
index 60cc5d0a..9796391f 100644
--- a/arch/aarch64/arm-clock.hh
+++ b/arch/aarch64/arm-clock.hh
@@ -11,5 +11,15 @@
 namespace processor {
 }
 
+#define NANO_PER_SEC 1000000000
+#define MHZ 1000000
+
+#define TIMER_CTL_ISTATUS_BIT 4
+#define TIMER_CTL_IMASK_BIT   2
+#define TIMER_CTL_ENABLE_BIT  1
+
+#define DEFAULT_TIMER_IRQ_ID  (16 + 11)
+
+int get_timer_irq_id();
 
 #endif /* ARCH_ARM_CLOCK_HH */
diff --git a/arch/aarch64/gic.cc b/arch/aarch64/gic.cc
index 9aba2c9f..95bd9827 100644
--- a/arch/aarch64/gic.cc
+++ b/arch/aarch64/gic.cc
@@ -13,6 +13,7 @@
 #include "processor.hh"
 
 #include "gic.hh"
+#include "arm-clock.hh"
 
 namespace gic {
 
@@ -58,6 +59,11 @@ void gic_driver::init_cpu(int smp_idx)
     gicc_ctlr |= 1;
     this->gicc.write_reg(gicc_reg::GICC_CTLR, gicc_ctlr);
 
+    /* enable CPU clock timer PPI interrupt on non-primary CPUs */
+    if (smp_idx) {
+        this->gicd.write_reg_grp(gicd_reg_irq1::GICD_ISENABLER, 
get_timer_irq_id(), 1);
+    }
+
 #if CONF_logger_debug
     debug_early("CPU interface enabled.\n");
 #endif
-- 
2.27.0

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20210429030010.794075-1-jwkozaczuk%40gmail.com.

Reply via email to