diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
| -rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 83 | 
1 files changed, 69 insertions, 14 deletions
| diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index d0177824c518..fe1a82627d57 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -16,6 +16,7 @@  #include <linux/cpu_pm.h>  #include <linux/clockchips.h>  #include <linux/clocksource.h> +#include <linux/clocksource_ids.h>  #include <linux/interrupt.h>  #include <linux/of_irq.h>  #include <linux/of_address.h> @@ -24,6 +25,8 @@  #include <linux/sched/clock.h>  #include <linux/sched_clock.h>  #include <linux/acpi.h> +#include <linux/arm-smccc.h> +#include <linux/ptp_kvm.h>  #include <asm/arch_timer.h>  #include <asm/virt.h> @@ -51,7 +54,7 @@  static unsigned arch_timers_present __initdata; -static void __iomem *arch_counter_base; +static void __iomem *arch_counter_base __ro_after_init;  struct arch_timer {  	void __iomem *base; @@ -60,15 +63,24 @@ struct arch_timer {  #define to_arch_timer(e) container_of(e, struct arch_timer, evt) -static u32 arch_timer_rate; -static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI]; +static u32 arch_timer_rate __ro_after_init; +u32 arch_timer_rate1 __ro_after_init; +static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI] __ro_after_init; + +static const char *arch_timer_ppi_names[ARCH_TIMER_MAX_TIMER_PPI] = { +	[ARCH_TIMER_PHYS_SECURE_PPI]	= "sec-phys", +	[ARCH_TIMER_PHYS_NONSECURE_PPI]	= "phys", +	[ARCH_TIMER_VIRT_PPI]		= "virt", +	[ARCH_TIMER_HYP_PPI]		= "hyp-phys", +	[ARCH_TIMER_HYP_VIRT_PPI]	= "hyp-virt", +};  static struct clock_event_device __percpu *arch_timer_evt; -static enum arch_timer_ppi_nr arch_timer_uses_ppi = ARCH_TIMER_VIRT_PPI; -static bool arch_timer_c3stop; -static bool arch_timer_mem_use_virtual; -static bool arch_counter_suspend_stop; +static enum arch_timer_ppi_nr arch_timer_uses_ppi __ro_after_init = ARCH_TIMER_VIRT_PPI; +static bool arch_timer_c3stop __ro_after_init; +static bool arch_timer_mem_use_virtual __ro_after_init; +static bool arch_counter_suspend_stop __ro_after_init;  #ifdef CONFIG_GENERIC_GETTIMEOFDAY  static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;  #else @@ -76,7 +88,7 @@ static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_NONE;  #endif /* CONFIG_GENERIC_GETTIMEOFDAY */  static cpumask_t evtstrm_available = CPU_MASK_NONE; -static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); +static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);  static int __init early_evtstrm_cfg(char *buf)  { @@ -176,7 +188,7 @@ static notrace u64 arch_counter_get_cntvct(void)   * to exist on arm64. arm doesn't use this before DT is probed so even   * if we don't have the cp15 accessors we won't have a problem.   */ -u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; +u64 (*arch_timer_read_counter)(void) __ro_after_init = arch_counter_get_cntvct;  EXPORT_SYMBOL_GPL(arch_timer_read_counter);  static u64 arch_counter_read(struct clocksource *cs) @@ -191,6 +203,7 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc)  static struct clocksource clocksource_counter = {  	.name	= "arch_sys_counter", +	.id	= CSID_ARM_ARCH_COUNTER,  	.rating	= 400,  	.read	= arch_counter_read,  	.mask	= CLOCKSOURCE_MASK(56), @@ -925,7 +938,7 @@ static int validate_timer_rate(void)   * rate was probed first, and don't verify that others match. If the first node   * probed has a clock-frequency property, this overrides the HW register.   */ -static void arch_timer_of_configure_rate(u32 rate, struct device_node *np) +static void __init arch_timer_of_configure_rate(u32 rate, struct device_node *np)  {  	/* Who has more than one independent system counter? */  	if (arch_timer_rate) @@ -939,7 +952,7 @@ static void arch_timer_of_configure_rate(u32 rate, struct device_node *np)  		pr_warn("frequency not available\n");  } -static void arch_timer_banner(unsigned type) +static void __init arch_timer_banner(unsigned type)  {  	pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",  		type & ARCH_TIMER_TYPE_CP15 ? "cp15" : "", @@ -1280,8 +1293,9 @@ static void __init arch_timer_populate_kvm_info(void)  static int __init arch_timer_of_init(struct device_node *np)  { -	int i, ret; +	int i, irq, ret;  	u32 rate; +	bool has_names;  	if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {  		pr_warn("multiple nodes in dt, skipping\n"); @@ -1289,8 +1303,17 @@ static int __init arch_timer_of_init(struct device_node *np)  	}  	arch_timers_present |= ARCH_TIMER_TYPE_CP15; -	for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) -		arch_timer_ppi[i] = irq_of_parse_and_map(np, i); + +	has_names = of_property_read_bool(np, "interrupt-names"); + +	for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) { +		if (has_names) +			irq = of_irq_get_byname(np, arch_timer_ppi_names[i]); +		else +			irq = of_irq_get(np, i); +		if (irq > 0) +			arch_timer_ppi[i] = irq; +	}  	arch_timer_populate_kvm_info(); @@ -1657,3 +1680,35 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)  }  TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);  #endif + +int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *ts, +				 struct clocksource **cs) +{ +	struct arm_smccc_res hvc_res; +	u32 ptp_counter; +	ktime_t ktime; + +	if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)) +		return -EOPNOTSUPP; + +	if (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) +		ptp_counter = KVM_PTP_VIRT_COUNTER; +	else +		ptp_counter = KVM_PTP_PHYS_COUNTER; + +	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, +			     ptp_counter, &hvc_res); + +	if ((int)(hvc_res.a0) < 0) +		return -EOPNOTSUPP; + +	ktime = (u64)hvc_res.a0 << 32 | hvc_res.a1; +	*ts = ktime_to_timespec64(ktime); +	if (cycle) +		*cycle = (u64)hvc_res.a2 << 32 | hvc_res.a3; +	if (cs) +		*cs = &clocksource_counter; + +	return 0; +} +EXPORT_SYMBOL_GPL(kvm_arch_ptp_get_crosststamp); | 
