you don't. */
#undef HAVE_DECL_FDT_NEXT_SUBNODE
+/* Define to 1 if you have the declaration of `fdt_property_u32', and to 0 if
+ you don't. */
+#undef HAVE_DECL_FDT_PROPERTY_U32
+
/* Define to 1 if you have the `fdt_first_subnode' function. */
#undef HAVE_FDT_FIRST_SUBNODE
#define HAVE_DECL_FDT_NEXT_SUBNODE $ac_have_decl
_ACEOF
+
+# 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_fn_c_check_decl "$LINENO" "fdt_property_u32" "ac_cv_have_decl_fdt_property_u32" "#include <libfdt.h>
+"
+if test "x$ac_cv_have_decl_fdt_property_u32" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_FDT_PROPERTY_U32 $ac_have_decl
+_ACEOF
+
esac
# Checks for header files.
# * 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.
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];
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;
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)
#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);
_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
/*
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;
/*
* 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)
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;
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) )
{
#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);
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);
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__ */