On 3/26/25 4:13 PM, Jan Beulich wrote:
On 25.03.2025 18:36, Oleksii Kurochko wrote:
preinit_xen_time() does two things:
1. Parse timebase-frequency properpy of /cpus node to initialize
    cpu_khz variable.
2. Initialize xen_start_clock_cycles with the current time counter
    value.

Signed-off-by: Oleksii Kurochko<oleksii.kuroc...@gmail.com>
---
Changes in v2:
  - Update SPDX tag for time.c
  - s/read_mostly/__ro_after_init for boot_count variable.
  - Add declaration of boot_count to asm/time.h.
  - Rename boot_count to xen_start_clock_cycles.
I'm not going to insist on another name change, but I'm having a hard time
seeing why almost any global variable in Xen would need to have a xen_
prefix. "start" also can be ambiguous, so imo boot_clock_cycles would have
been best.

I can change that during the work on the version of this patch.


--- /dev/null
+++ b/xen/arch/riscv/time.c
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <xen/device_tree.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/sections.h>
+
+unsigned long __ro_after_init cpu_khz; /* CPU clock frequency in kHz. */
+unsigned long __ro_after_init xen_start_clock_cycles;
For the theoretical at this point case of support RV32, will unsigned long
be wide enough? I.e. is the counter only 32 bits wide when XLEN=32?

No, it will be really an issue and the type should be uint64_t for this variable
because on RV32I the timeh CSR is a read-only shadow of the upper 32 bits of the
memory-mapped mtime register, while time shadows only the lower 32 bits of 
mtime.
So on RV32 it is still 64-bit long and requires two reads to get cycle value.


+static __initdata struct dt_device_node *timer;
Please can __initdata (and alike) live at its canonical place, between
type and identifier?

It's also unclear at this point why this needs to be a file scope variable.

Because this variable is used and will be used only in preinit_dt_xen_time().
But I think we could move the declaration of this variable to 
preinit_dt_xen_time()
as it is used only during preinit_dt_xen_time().


+/* Set up the timer on the boot CPU (early init function) */
+static void __init preinit_dt_xen_time(void)
+{
+    static const struct dt_device_match __initconstrel timer_ids[] =
+    {
+        DT_MATCH_PATH("/cpus"),
+        { /* sentinel */ },
+    };
+    uint32_t rate;
+
+    timer = dt_find_matching_node(NULL, timer_ids);
+    if ( !timer )
+        panic("Unable to find a compatible timer in the device tree\n");
+
+    dt_device_set_used_by(timer, DOMID_XEN);
+
+    if ( !dt_property_read_u32(timer, "timebase-frequency", &rate) )
+        panic("Unable to find clock frequency\n");
+
+    cpu_khz = rate / 1000;
"rate" being only 32 bits wide, what about clock rates above 4GHz? Or is
this some external clock running at a much lower rate than the CPU would?

It is the frequency of the hardware timer that drives the |mtime|register, it defines the frequency (in Hz) at which the timer increments.



+}
+
+void __init preinit_xen_time(void)
+{
+    preinit_dt_xen_time();
+
+    xen_start_clock_cycles = get_cycles();
+}
I take it that more stuff is going to be added to this function? Else I
wouldn't see why preinit_dt_xen_time() needed to be a separate function.

Actually, I checked my latest downstream branch and I haven't added nothing
extra to this function.
Only one thing that I want to add is ACPI case:
    if ( acpi_disabled )
        preinit_dt_xen_time();
    else
        panic("TBD\n"); /* preinit_acpi_xen_time(); */

~ Oleksii

Reply via email to