LCOV - code coverage report
Current view: top level - arch/x86/kernel - time.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 16 35 45.7 %
Date: 2021-04-22 12:43:58 Functions: 4 7 57.1 %

          Line data    Source code
       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           0 : unsigned long profile_pc(struct pt_regs *regs)
      29             : {
      30           0 :         unsigned long pc = instruction_pointer(regs);
      31             : 
      32           0 :         if (!user_mode(regs) && in_lock_functions(pc)) {
      33             : #ifdef CONFIG_FRAME_POINTER
      34             :                 return *(unsigned long *)(regs->bp + sizeof(long));
      35             : #else
      36           0 :                 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           0 :                 if (sp[0] >> 22)
      43             :                         return sp[0];
      44           0 :                 if (sp[1] >> 22)
      45           0 :                         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           0 : static irqreturn_t timer_interrupt(int irq, void *dev_id)
      56             : {
      57           0 :         global_clock_event->event_handler(global_clock_event);
      58           0 :         return IRQ_HANDLED;
      59             : }
      60             : 
      61           0 : static void __init setup_default_timer_irq(void)
      62             : {
      63           0 :         unsigned long flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER;
      64             : 
      65             :         /*
      66             :          * Unconditionally register the legacy timer interrupt; even
      67             :          * without legacy PIC/PIT we need this for the HPET0 in legacy
      68             :          * replacement mode.
      69             :          */
      70           0 :         if (request_irq(0, timer_interrupt, flags, "timer", NULL))
      71           0 :                 pr_info("Failed to register legacy timer interrupt\n");
      72           0 : }
      73             : 
      74             : /* Default timer init function */
      75           1 : void __init hpet_time_init(void)
      76             : {
      77           1 :         if (!hpet_enable()) {
      78           1 :                 if (!pit_timer_init())
      79             :                         return;
      80             :         }
      81             : 
      82           0 :         setup_default_timer_irq();
      83             : }
      84             : 
      85           1 : static __init void x86_late_time_init(void)
      86             : {
      87             :         /*
      88             :          * Before PIT/HPET init, select the interrupt mode. This is required
      89             :          * to make the decision whether PIT should be initialized correct.
      90             :          */
      91           1 :         x86_init.irqs.intr_mode_select();
      92             : 
      93             :         /* Setup the legacy timers */
      94           1 :         x86_init.timers.timer_init();
      95             : 
      96             :         /*
      97             :          * After PIT/HPET timers init, set up the final interrupt mode for
      98             :          * delivering IRQs.
      99             :          */
     100           1 :         x86_init.irqs.intr_mode_init();
     101           1 :         tsc_init();
     102             : 
     103           1 :         if (static_cpu_has(X86_FEATURE_WAITPKG))
     104           0 :                 use_tpause_delay();
     105           1 : }
     106             : 
     107             : /*
     108             :  * Initialize TSC and delay the periodic timer init to
     109             :  * late x86_late_time_init() so ioremap works.
     110             :  */
     111           1 : void __init time_init(void)
     112             : {
     113           1 :         late_time_init = x86_late_time_init;
     114           1 : }
     115             : 
     116             : /*
     117             :  * Sanity check the vdso related archdata content.
     118             :  */
     119           5 : void clocksource_arch_init(struct clocksource *cs)
     120             : {
     121           5 :         if (cs->vdso_clock_mode == VDSO_CLOCKMODE_NONE)
     122             :                 return;
     123             : 
     124           2 :         if (cs->mask != CLOCKSOURCE_MASK(64)) {
     125           0 :                 pr_warn("clocksource %s registered with invalid mask %016llx for VDSO. Disabling VDSO support.\n",
     126             :                         cs->name, cs->mask);
     127           0 :                 cs->vdso_clock_mode = VDSO_CLOCKMODE_NONE;
     128             :         }
     129             : }

Generated by: LCOV version 1.14