linux/arch/x86/xen/time.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Xen time implementation.
 *
 * This is implemented in terms of a clocksource driver which uses
 * the hypervisor clock as a nanosecond timebase, and a clockevent
 * driver which uses the hypervisor's timer mechanism.
 *
 * Jeremy Fitzhardinge <[email protected]>, XenSource Inc, 2007
 */
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/pvclock_gtod.h>
#include <linux/timekeeper_internal.h>

#include <asm/pvclock.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/cpuid.h>

#include <xen/events.h>
#include <xen/features.h>
#include <xen/interface/xen.h>
#include <xen/interface/vcpu.h>

#include "xen-ops.h"

/* Minimum amount of time until next clock event fires */
#define TIMER_SLOP

static u64 xen_sched_clock_offset __read_mostly;

/* Get the TSC speed from Xen */
static unsigned long xen_tsc_khz(void)
{}

static u64 xen_clocksource_read(void)
{}

static u64 xen_clocksource_get_cycles(struct clocksource *cs)
{}

static noinstr u64 xen_sched_clock(void)
{}

static void xen_read_wallclock(struct timespec64 *ts)
{}

static void xen_get_wallclock(struct timespec64 *now)
{}

static int xen_set_wallclock(const struct timespec64 *now)
{}

static int xen_pvclock_gtod_notify(struct notifier_block *nb,
				   unsigned long was_set, void *priv)
{}

static struct notifier_block xen_pvclock_gtod_notifier =;

static int xen_cs_enable(struct clocksource *cs)
{}

static struct clocksource xen_clocksource __read_mostly =;

/*
   Xen clockevent implementation

   Xen has two clockevent implementations:

   The old timer_op one works with all released versions of Xen prior
   to version 3.0.4.  This version of the hypervisor provides a
   single-shot timer with nanosecond resolution.  However, sharing the
   same event channel is a 100Hz tick which is delivered while the
   vcpu is running.  We don't care about or use this tick, but it will
   cause the core time code to think the timer fired too soon, and
   will end up resetting it each time.  It could be filtered, but
   doing so has complications when the ktime clocksource is not yet
   the xen clocksource (ie, at boot time).

   The new vcpu_op-based timer interface allows the tick timer period
   to be changed or turned off.  The tick timer is not useful as a
   periodic timer because events are only delivered to running vcpus.
   The one-shot timer can report when a timeout is in the past, so
   set_next_event is capable of returning -ETIME when appropriate.
   This interface is used when available.
*/


/*
  Get a hypervisor absolute time.  In theory we could maintain an
  offset between the kernel's time and the hypervisor's time, and
  apply that to a kernel's absolute timeout.  Unfortunately the
  hypervisor and kernel times can drift even if the kernel is using
  the Xen clocksource, because ntp can warp the kernel's clocksource.
*/
static s64 get_abs_timeout(unsigned long delta)
{}

static int xen_timerop_shutdown(struct clock_event_device *evt)
{}

static int xen_timerop_set_next_event(unsigned long delta,
				      struct clock_event_device *evt)
{}

static struct clock_event_device xen_timerop_clockevent __ro_after_init =;

static int xen_vcpuop_shutdown(struct clock_event_device *evt)
{}

static int xen_vcpuop_set_oneshot(struct clock_event_device *evt)
{}

static int xen_vcpuop_set_next_event(unsigned long delta,
				     struct clock_event_device *evt)
{}

static struct clock_event_device xen_vcpuop_clockevent __ro_after_init =;

static const struct clock_event_device *xen_clockevent =;

struct xen_clock_event_device {};
static DEFINE_PER_CPU(struct xen_clock_event_device, xen_clock_events) =;

static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
{}

void xen_teardown_timer(int cpu)
{}

void xen_setup_timer(int cpu)
{}


void xen_setup_cpu_clockevents(void)
{}

void xen_timer_resume(void)
{}

static struct pvclock_vsyscall_time_info *xen_clock __read_mostly;
static u64 xen_clock_value_saved;

void xen_save_time_memory_area(void)
{}

void xen_restore_time_memory_area(void)
{}

static void xen_setup_vsyscall_time_info(void)
{}

/*
 * Check if it is possible to safely use the tsc as a clocksource.  This is
 * only true if the hypervisor notifies the guest that its tsc is invariant,
 * the tsc is stable, and the tsc instruction will never be emulated.
 */
static int __init xen_tsc_safe_clocksource(void)
{}

static void __init xen_time_init(void)
{}

static void __init xen_init_time_common(void)
{}

void __init xen_init_time_ops(void)
{}

#ifdef CONFIG_XEN_PVHVM
static void xen_hvm_setup_cpu_clockevents(void)
{}

void __init xen_hvm_init_time_ops(void)
{}
#endif

/* Kernel parameter to specify Xen timer slop */
static int __init parse_xen_timer_slop(char *ptr)
{}
early_param();