[PATCH v3 5/6] xen/arm: report clock_frequency via sysctl physinfo, not createdomain

Julian Vetter <[email protected]>
Newsgroups org.xenproject.lists.xen-devel
Message-ID <1784211106.8631fc262581453bbf619ec5b2062170.19f6b44e953000edb5@vates.tech>
The xen_arch_domainconfig.clock_frequency value is populated in
domain_vtimer_init() during XEN_DOMCTL_createdomain from the global
timer_dt_clock_frequency, which comes from the host's DT timer node and
has nothing to do with the domain being created. Like now removed
GIC_NATIVE resolution, this is a host-wide system property being
smuggled out through a domain-creation IN struct.

Expose it instead as a new arch_clock_frequency_hz field in
XEN_SYSCTL_physinfo, populated via arch_do_physinfo(), and mirroring how
the GIC capability bits were already moved there. The field is only set
when booting via Device Tree. Systems booting via ACPI get the frequency
from firmware/CNTFRQ directly and leave it 0, same as 'property not
present'.

Although the CNTFRQ_EL0 register is 64 bits wide, and some current timer
implementations run at 1GHz, a 32bit value is sufficient to store the
timer value, because it only mirrors the DT 'clock-frequency' property,
which the bindins define as a single 32-bit cell. The
XEN_DOMCTL_INTERFACE_VERSION doesn't need to be bumped, because only a
previously zero'ed / ignored field is now used.

The xen_arch_domainconfig parameter passed to domain_vtimer_init() is no
longer needed, so drop that parameter entirely. libxl now fetches the
frequency via libxl_get_physinfo() in libxl__arch_domain_save_config()
instead of reading it back out of the createdomain reply. The OCaml
xen_arch_domainconfig mirror drops the field too.

Signed-off-by: Julian Vetter <[email protected]>
---
Changes in v3:
- Replaced arch_clock_frequency by arch_clock_frequency_hz to clearly
  specify which granularity the value has
- Updated commit message and comments in the code to...
  - ...mention why a 32bit value is "enough" for now
  - ...mention behaviour when a guest boots via ACPI
---
 tools/libs/light/libxl.c          |  1 +
 tools/libs/light/libxl_arm.c      | 13 ++++++++++++-
 tools/libs/light/libxl_types.idl  |  1 +
 tools/ocaml/libs/xc/xenctrl.ml    |  1 -
 tools/ocaml/libs/xc/xenctrl.mli   |  1 -
 xen/arch/arm/domain.c             |  2 +-
 xen/arch/arm/include/asm/vtimer.h |  3 +--
 xen/arch/arm/sysctl.c             |  3 +++
 xen/arch/arm/vtimer.c             |  4 +---
 xen/include/public/arch-arm.h     | 16 +---------------
 xen/include/public/sysctl.h       | 21 ++++++++++++++++++++-
 11 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/tools/libs/light/libxl.c b/tools/libs/light/libxl.c
index a1fe16274d..ec7e6d3f65 100644
--- a/tools/libs/light/libxl.c
+++ b/tools/libs/light/libxl.c
@@ -410,6 +410,7 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
     physinfo->cap_gnttab_v2 =
         !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_gnttab_v2);
     physinfo->arch_capabilities = xcphysinfo.arch_capabilities;
+    physinfo->arch_clock_frequency_hz = xcphysinfo.arch_clock_frequency_hz;
 
     GC_FREE;
     return 0;
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index 926d651857..cf441f0737 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -252,6 +252,9 @@ int libxl__arch_domain_save_config(libxl__gc *gc,
                                    libxl__domain_build_state *state,
                                    const struct xen_domctl_createdomain *config)
 {
+    libxl_physinfo info;
+    int rc;
+
     switch (config->arch.gic_version) {
     case XEN_DOMCTL_CONFIG_GIC_V2:
         d_config->b_info.arch_arm.gic_version = LIBXL_GIC_VERSION_V2;
@@ -264,7 +267,15 @@ int libxl__arch_domain_save_config(libxl__gc *gc,
         return ERROR_FAIL;
     }
 
-    state->clock_frequency = config->arch.clock_frequency;
+    libxl_physinfo_init(&info);
+    rc = libxl_get_physinfo(CTX, &info);
+    if (rc) {
+        LOG(ERROR, "failed to get physinfo");
+        libxl_physinfo_dispose(&info);
+        return ERROR_FAIL;
+    }
+    state->clock_frequency = info.arch_clock_frequency_hz;
+    libxl_physinfo_dispose(&info);
 
     return 0;
 }
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index a7893460f0..e24a3253f8 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -1201,6 +1201,7 @@ libxl_physinfo = Struct("physinfo", [
     ("cap_gnttab_v1", bool),
     ("cap_gnttab_v2", bool),
     ("arch_capabilities", uint32),
+    ("arch_clock_frequency_hz", uint32), # ARM only
     ], dir=DIR_OUT)
 
 libxl_connectorinfo = Struct("connectorinfo", [
diff --git a/tools/ocaml/libs/xc/xenctrl.ml b/tools/ocaml/libs/xc/xenctrl.ml
index 147afa62c2..582897af6d 100644
--- a/tools/ocaml/libs/xc/xenctrl.ml
+++ b/tools/ocaml/libs/xc/xenctrl.ml
@@ -32,7 +32,6 @@ type xen_arm_arch_domainconfig =
   {
     gic_version: int;
     nr_spis: int;
-    clock_frequency: int32;
   }
 
 type x86_arch_emulation_flags =
diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli
index 9fccb2c2c2..9414b87164 100644
--- a/tools/ocaml/libs/xc/xenctrl.mli
+++ b/tools/ocaml/libs/xc/xenctrl.mli
@@ -26,7 +26,6 @@ type vcpuinfo = {
 type xen_arm_arch_domainconfig = {
   gic_version: int;
   nr_spis: int;
-  clock_frequency: int32;
 }
 
 type x86_arch_emulation_flags =
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index b396d5e615..d6d80ac55d 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -711,7 +711,7 @@ int arch_domain_create(struct domain *d,
     if ( (rc = domain_vgic_init(d, config->arch.nr_spis)) != 0 )
         goto fail;
 
-    if ( (rc = domain_vtimer_init(d, &config->arch)) != 0 )
+    if ( (rc = domain_vtimer_init(d)) != 0 )
         goto fail;
 
     if ( (rc = tee_domain_init(d, config->arch.tee_type)) != 0 )
diff --git a/xen/arch/arm/include/asm/vtimer.h b/xen/arch/arm/include/asm/vtimer.h
index 9d4fb4c6e8..6bbfcf4e69 100644
--- a/xen/arch/arm/include/asm/vtimer.h
+++ b/xen/arch/arm/include/asm/vtimer.h
@@ -20,8 +20,7 @@
 #ifndef __ARCH_ARM_VTIMER_H__
 #define __ARCH_ARM_VTIMER_H__
 
-extern int domain_vtimer_init(struct domain *d,
-                              struct xen_arch_domainconfig *config);
+extern int domain_vtimer_init(struct domain *d);
 extern int vcpu_vtimer_init(struct vcpu *v);
 extern bool vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr);
 extern void virt_timer_save(struct vcpu *v);
diff --git a/xen/arch/arm/sysctl.c b/xen/arch/arm/sysctl.c
index 3b0edf4cec..060132dabb 100644
--- a/xen/arch/arm/sysctl.c
+++ b/xen/arch/arm/sysctl.c
@@ -15,6 +15,7 @@
 
 #include <asm/arm64/sve.h>
 #include <asm/gic.h>
+#include <asm/time.h>
 
 #include <public/sysctl.h>
 
@@ -25,6 +26,8 @@ void arch_do_physinfo(struct xen_sysctl_physinfo *pi)
     pi->arch_capabilities |= MASK_INSR(sve_encode_vl(get_sys_vl_len()),
                                        XEN_SYSCTL_PHYSCAP_ARM_SVE_MASK);
 
+    pi->arch_clock_frequency_hz = timer_dt_clock_frequency;
+
     /*
      * The GIC version(s) we're happy creating guests with.  Right now for
      * simplicity it is tied to the active hardware version, but this will
diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
index 2e85ff2b6e..18f5676158 100644
--- a/xen/arch/arm/vtimer.c
+++ b/xen/arch/arm/vtimer.c
@@ -52,7 +52,7 @@ static void virt_timer_expired(void *data)
     perfc_incr(vtimer_virt_inject);
 }
 
-int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config)
+int domain_vtimer_init(struct domain *d)
 {
     d->arch.virt_timer_base.offset = get_cycles();
     d->arch.virt_timer_base.nanoseconds =
@@ -60,8 +60,6 @@ int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config)
     d->time_offset.seconds = d->arch.virt_timer_base.nanoseconds;
     do_div(d->time_offset.seconds, 1000000000);
 
-    config->clock_frequency = timer_dt_clock_frequency;
-
     /*
      * Per the ACPI specification, providing a secure EL1 timer
      * interrupt is optional and will be ignored by non-secure OS.
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 6987f5bdf4..b88c61c8ff 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -334,7 +334,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_VMSA    2
 
 struct xen_arch_domainconfig {
-    /* IN/OUT */
+    /* IN */
     uint8_t gic_version;
     /* IN - Contains SVE vector length divided by 128 */
     uint8_t sve_vl;
@@ -342,20 +342,6 @@ struct xen_arch_domainconfig {
     uint16_t tee_type;
     /* IN */
     uint32_t nr_spis;
-    /*
-     * OUT
-     * Based on the property clock-frequency in the DT timer node.
-     * The property may be present when the bootloader/firmware doesn't
-     * set correctly CNTFRQ which hold the timer frequency.
-     *
-     * As it's not possible to trap this register, we have to replicate
-     * the value in the guest DT.
-     *
-     * = 0 => property not present
-     * > 0 => Value of the property
-     *
-     */
-    uint32_t clock_frequency;
     /* IN */
     uint8_t arm_sci_type;
     /* IN */
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index d20ebf3644..7d051bf14f 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -120,7 +120,26 @@ struct xen_sysctl_physinfo {
     uint32_t cpu_khz;
     uint32_t capabilities;/* XEN_SYSCTL_PHYSCAP_??? */
     uint32_t arch_capabilities;/* XEN_SYSCTL_PHYSCAP_{X86,ARM,...}_??? */
-    uint32_t pad;
+    /*
+     * ARM only, and only set when booting via Device Tree. Value, in Hz, of
+     * the "clock-frequency" property in the DT timer node. The property may
+     * be present when the bootloader/firmware doesn't correctly set CNTFRQ
+     * to hold the timer frequency.
+     *
+     * As it's not possible to trap this register, we have to replicate the
+     * value in the guest DT.
+     *
+     * This field mirrors the DT property (a single <u32> cell), independent of
+     * CNTFRQ_EL0's own width or any given implementation's actual frequency.
+     * Should the DT binding ever grow a wider encoding, this field would need
+     * to grow (or gain a companion) to match, same as any other ABI change.
+     *
+     * = 0 => property not present, non-ARM, or booting via ACPI (ACPI
+     *        guests get the frequency from firmware/CNTFRQ instead, so
+     *        there is nothing to replicate).
+     * > 0 => Value of the property, in Hz.
+     */
+    uint32_t arch_clock_frequency_hz;
     uint64_aligned_t total_pages;
     uint64_aligned_t free_pages;
     uint64_aligned_t scrub_pages;
-- 
2.53.0



-- 
Julian Vetter | Vates Hypervisor & Kernel Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.