|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] xen/arm: Propagate clock-frequency to DOMU if present in the DT timer node
On Fri, 2015-06-19 at 13:41 +0100, Julien Grall wrote:
> When the property "clock-frequency" is present in the DT timer node, it
> means that the bootloader/firmware didn't correctly configure the
> CNTFRQ/CNTFRQ_EL0 on each processor.
>
> The best solution would be to fix the offending firmware/bootloader,
> although it may not always be possible to modify and re-flash it.
>
> As it's not possible to trap the register CNTFRQ/CNTFRQ_EL0, we have
> to extend xen_arch_domainconfig to provide the timer frequency to the
> toolstack when the property "clock-frequency" is present to the host DT
> timer node. Then, a property "clock-frequency" will be created in the
> guest
> DT timer node if the value is not 0.
>
> We could have set the property in the guest DT no matter if the property
> is present in the host DT. Although, we still want to let the guest
> using CNTFRQ in normal case. After all, the property "clock-frequency"
> is just a workaround for buggy firmware.
>
> Also add a stub for fdt_property_u32 which is not present in libfdt <
> 1.4.0 used by distribution such as Debian Wheezy.
>
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> Tested-by: Chris Brand <chris.brand@xxxxxxxxxxxx>
I had this on my list to backport to 4.5 but it didn't apply at all cleanly
in a variety of ways.
I don't think this one is particularly worth the effort, so I've dropped it
from the list. If someone is keen to have it then please provide a
backport.
Ian.
>
> ---
> This patch requires to regenerate tools/configure.
>
> Changes in v2:
> - Typo in commit message
> - Make the patch compiling on wheezy where fdt_property_u32 is
> not present
> ---
> tools/configure.ac | 4 ++++
> tools/libxl/libxl_arm.c | 9 +++++++--
> tools/libxl/libxl_libfdt_compat.h | 9 +++++++++
> xen/arch/arm/domain.c | 2 +-
> xen/arch/arm/time.c | 5 +++++
> xen/arch/arm/vtimer.c | 4 +++-
> xen/arch/arm/vtimer.h | 3 ++-
> xen/include/asm-arm/time.h | 6 ++++++
> xen/include/public/arch-arm.h | 14 ++++++++++++++
> 9 files changed, 51 insertions(+), 5 deletions(-)
>
> diff --git a/tools/configure.ac b/tools/configure.ac
> index 1a06ddf..2886cb5 100644
> --- a/tools/configure.ac
> +++ b/tools/configure.ac
> @@ -379,6 +379,10 @@ AS_IF([test "x$partial_dt" = "xy" ],
> # * The prototype exists but the functions are not exposed. Don't ask
> why...
> AC_CHECK_FUNCS([fdt_first_subnode fdt_next_subnode])
> AC_CHECK_DECLS([fdt_first_subnode, fdt_next_subnode],,,[#include
> <libfdt.h>])
> +
> +# The helper fdt_property_u32 is only present in libfdt >= 1.4.0
> +# It's an inline function, so only check if the declaration is present
> +AC_CHECK_DECLS([fdt_property_u32],,,[#include <libfdt.h>])
> esac
>
> # Checks for header files.
> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
> index 4fb5e26..f09c860 100644
> --- a/tools/libxl/libxl_arm.c
> +++ b/tools/libxl/libxl_arm.c
> @@ -444,7 +444,9 @@ static int make_gicv3_node(libxl__gc *gc, void *fdt)
> return 0;
> }
>
> -static int make_timer_node(libxl__gc *gc, void *fdt, const struct
> arch_info *ainfo)
> +static int make_timer_node(libxl__gc *gc, void *fdt,
> + const struct arch_info *ainfo,
> + uint32_t frequency)
> {
> int res;
> gic_interrupt ints[3];
> @@ -462,6 +464,9 @@ static int make_timer_node(libxl__gc *gc, void *fdt,
> const struct arch_info *ain
> res = fdt_property_interrupts(gc, fdt, ints, 3);
> if (res) return res;
>
> + if ( frequency )
> + fdt_property_u32(fdt, "clock-frequency", frequency);
> +
> res = fdt_end_node(fdt);
> if (res) return res;
>
> @@ -805,7 +810,7 @@ next_resize:
> goto out;
> }
>
> - FDT( make_timer_node(gc, fdt, ainfo) );
> + FDT( make_timer_node(gc, fdt, ainfo, xc_config->clock_frequency)
> );
> FDT( make_hypervisor_node(gc, fdt, vers) );
>
> if (pfdt)
> diff --git a/tools/libxl/libxl_libfdt_compat.h
> b/tools/libxl/libxl_libfdt_compat.h
> index 53a5076..23230b5 100644
> --- a/tools/libxl/libxl_libfdt_compat.h
> +++ b/tools/libxl/libxl_libfdt_compat.h
> @@ -61,6 +61,7 @@
> #define LIBXL_LIBFDT_COMPAT_H
>
> #include "libxl_internal.h"
> +#include <libfdt.h>
>
> #if !HAVE_DECL_FDT_FIRST_SUBNODE
> _hidden int fdt_first_subnode(const void *fdt, int offset);
> @@ -70,6 +71,14 @@ _hidden int fdt_first_subnode(const void *fdt, int
> offset);
> _hidden int fdt_next_subnode(const void *fdt, int offset);
> #endif
>
> +#if !HAVE_DECL_FDT_PROPERTY_U32
> +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t
> val)
> +{
> + uint32_t tmp = cpu_to_fdt32(val);
> + return fdt_property(fdt, name, &tmp, sizeof(tmp));
> +}
> +#endif
> +
> #endif
>
> /*
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 24b8938..8b1bf5a 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -593,7 +593,7 @@ int arch_domain_create(struct domain *d, unsigned int
> domcr_flags,
> if ( (rc = domain_vgic_init(d, config->nr_spis)) != 0 )
> goto fail;
>
> - if ( (rc = domain_vtimer_init(d)) != 0 )
> + if ( (rc = domain_vtimer_init(d, config)) != 0 )
> goto fail;
>
> /*
> diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
> index ce6d3fd..5ded30c 100644
> --- a/xen/arch/arm/time.c
> +++ b/xen/arch/arm/time.c
> @@ -42,6 +42,8 @@ uint64_t __read_mostly boot_count;
> * register-mapped time source in the SoC. */
> unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
>
> +uint32_t __read_mostly timer_dt_clock_frequency;
> +
> static unsigned int timer_irq[MAX_TIMER_PPI];
>
> unsigned int timer_get_irq(enum timer_ppi ppi)
> @@ -86,7 +88,10 @@ void __init preinit_xen_time(void)
>
> res = dt_property_read_u32(timer, "clock-frequency", &rate);
> if ( res )
> + {
> cpu_khz = rate / 1000;
> + timer_dt_clock_frequency = rate;
> + }
> else
> cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
>
> diff --git a/xen/arch/arm/vtimer.c b/xen/arch/arm/vtimer.c
> index 685bfea..1418092 100644
> --- a/xen/arch/arm/vtimer.c
> +++ b/xen/arch/arm/vtimer.c
> @@ -60,11 +60,13 @@ static void virt_timer_expired(void *data)
> perfc_incr(vtimer_virt_inject);
> }
>
> -int domain_vtimer_init(struct domain *d)
> +int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig
> *config)
> {
> d->arch.phys_timer_base.offset = NOW();
> d->arch.virt_timer_base.offset = READ_SYSREG64(CNTPCT_EL0);
>
> + config->clock_frequency = timer_dt_clock_frequency;
> +
> /* At this stage vgic_reserve_virq can't fail */
> if ( is_hardware_domain(d) )
> {
> diff --git a/xen/arch/arm/vtimer.h b/xen/arch/arm/vtimer.h
> index 6d2e46e..99e8145 100644
> --- a/xen/arch/arm/vtimer.h
> +++ b/xen/arch/arm/vtimer.h
> @@ -20,7 +20,8 @@
> #ifndef __ARCH_ARM_VTIMER_H__
> #define __ARCH_ARM_VTIMER_H__
>
> -extern int domain_vtimer_init(struct domain *d);
> +extern int domain_vtimer_init(struct domain *d,
> + struct xen_arch_domainconfig *config);
> extern int vcpu_vtimer_init(struct vcpu *v);
> extern int vtimer_emulate(struct cpu_user_regs *regs, union hsr hsr);
> extern int virt_timer_save(struct vcpu *v);
> diff --git a/xen/include/asm-arm/time.h b/xen/include/asm-arm/time.h
> index 039039a..d755f36 100644
> --- a/xen/include/asm-arm/time.h
> +++ b/xen/include/asm-arm/time.h
> @@ -22,6 +22,12 @@ enum timer_ppi
> MAX_TIMER_PPI = 4,
> };
>
> +/*
> + * Value of "clock-frequency" in the DT timer node if present.
> + * 0 means the property doesn't exist.
> + */
> +extern uint32_t timer_dt_clock_frequency;
> +
> /* Get one of the timer IRQ number */
> unsigned int timer_get_irq(enum timer_ppi ppi);
>
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch
> -arm.h
> index a320851..a819196 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -311,6 +311,20 @@ struct xen_arch_domainconfig {
> uint8_t gic_version;
> /* 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;
> };
> #endif /* __XEN__ || __XEN_TOOLS__ */
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |