root/arch/x86/kernel/time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. profile_pc
  2. timer_interrupt
  3. setup_default_timer_irq
  4. hpet_time_init
  5. x86_late_time_init
  6. time_init
  7. clocksource_arch_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  Copyright (c) 1991,1992,1995  Linus Torvalds
   4  *  Copyright (c) 1994  Alan Modra
   5  *  Copyright (c) 1995  Markus Kuhn
   6  *  Copyright (c) 1996  Ingo Molnar
   7  *  Copyright (c) 1998  Andrea Arcangeli
   8  *  Copyright (c) 2002,2006  Vojtech Pavlik
   9  *  Copyright (c) 2003  Andi Kleen
  10  *
  11  */
  12 
  13 #include <linux/clocksource.h>
  14 #include <linux/clockchips.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/irq.h>
  17 #include <linux/i8253.h>
  18 #include <linux/time.h>
  19 #include <linux/export.h>
  20 
  21 #include <asm/vsyscall.h>
  22 #include <asm/x86_init.h>
  23 #include <asm/i8259.h>
  24 #include <asm/timer.h>
  25 #include <asm/hpet.h>
  26 #include <asm/time.h>
  27 
  28 unsigned long profile_pc(struct pt_regs *regs)
  29 {
  30         unsigned long pc = instruction_pointer(regs);
  31 
  32         if (!user_mode(regs) && in_lock_functions(pc)) {
  33 #ifdef CONFIG_FRAME_POINTER
  34                 return *(unsigned long *)(regs->bp + sizeof(long));
  35 #else
  36                 unsigned long *sp = (unsigned long *)regs->sp;
  37                 /*
  38                  * Return address is either directly at stack pointer
  39                  * or above a saved flags. Eflags has bits 22-31 zero,
  40                  * kernel addresses don't.
  41                  */
  42                 if (sp[0] >> 22)
  43                         return sp[0];
  44                 if (sp[1] >> 22)
  45                         return sp[1];
  46 #endif
  47         }
  48         return pc;
  49 }
  50 EXPORT_SYMBOL(profile_pc);
  51 
  52 /*
  53  * Default timer interrupt handler for PIT/HPET
  54  */
  55 static irqreturn_t timer_interrupt(int irq, void *dev_id)
  56 {
  57         global_clock_event->event_handler(global_clock_event);
  58         return IRQ_HANDLED;
  59 }
  60 
  61 static struct irqaction irq0  = {
  62         .handler = timer_interrupt,
  63         .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
  64         .name = "timer"
  65 };
  66 
  67 static void __init setup_default_timer_irq(void)
  68 {
  69         /*
  70          * Unconditionally register the legacy timer; even without legacy
  71          * PIC/PIT we need this for the HPET0 in legacy replacement mode.
  72          */
  73         if (setup_irq(0, &irq0))
  74                 pr_info("Failed to register legacy timer interrupt\n");
  75 }
  76 
  77 /* Default timer init function */
  78 void __init hpet_time_init(void)
  79 {
  80         if (!hpet_enable()) {
  81                 if (!pit_timer_init())
  82                         return;
  83         }
  84 
  85         setup_default_timer_irq();
  86 }
  87 
  88 static __init void x86_late_time_init(void)
  89 {
  90         /*
  91          * Before PIT/HPET init, select the interrupt mode. This is required
  92          * to make the decision whether PIT should be initialized correct.
  93          */
  94         x86_init.irqs.intr_mode_select();
  95 
  96         /* Setup the legacy timers */
  97         x86_init.timers.timer_init();
  98 
  99         /*
 100          * After PIT/HPET timers init, set up the final interrupt mode for
 101          * delivering IRQs.
 102          */
 103         x86_init.irqs.intr_mode_init();
 104         tsc_init();
 105 }
 106 
 107 /*
 108  * Initialize TSC and delay the periodic timer init to
 109  * late x86_late_time_init() so ioremap works.
 110  */
 111 void __init time_init(void)
 112 {
 113         late_time_init = x86_late_time_init;
 114 }
 115 
 116 /*
 117  * Sanity check the vdso related archdata content.
 118  */
 119 void clocksource_arch_init(struct clocksource *cs)
 120 {
 121         if (cs->archdata.vclock_mode == VCLOCK_NONE)
 122                 return;
 123 
 124         if (cs->archdata.vclock_mode > VCLOCK_MAX) {
 125                 pr_warn("clocksource %s registered with invalid vclock_mode %d. Disabling vclock.\n",
 126                         cs->name, cs->archdata.vclock_mode);
 127                 cs->archdata.vclock_mode = VCLOCK_NONE;
 128         }
 129 
 130         if (cs->mask != CLOCKSOURCE_MASK(64)) {
 131                 pr_warn("clocksource %s registered with invalid mask %016llx. Disabling vclock.\n",
 132                         cs->name, cs->mask);
 133                 cs->archdata.vclock_mode = VCLOCK_NONE;
 134         }
 135 }

/* [<][>][^][v][top][bottom][index][help] */