LCOV - code coverage report
Current view: top level - arch/x86/kernel - time.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 22 35 62.9 %
Date: 2022-03-28 16:04:14 Functions: 6 7 85.7 %
Branches: 6 22 27.3 %

           Branch data     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                 :            : #ifdef CONFIG_X86_64
      29                 :            : __visible volatile unsigned long jiffies __cacheline_aligned_in_smp = INITIAL_JIFFIES;
      30                 :            : #endif
      31                 :            : 
      32                 :          0 : unsigned long profile_pc(struct pt_regs *regs)
      33                 :            : {
      34         [ #  # ]:          0 :         unsigned long pc = instruction_pointer(regs);
      35                 :            : 
      36   [ #  #  #  # ]:          0 :         if (!user_mode(regs) && in_lock_functions(pc)) {
      37                 :            : #ifdef CONFIG_FRAME_POINTER
      38                 :            :                 return *(unsigned long *)(regs->bp + sizeof(long));
      39                 :            : #else
      40                 :          0 :                 unsigned long *sp = (unsigned long *)regs->sp;
      41                 :            :                 /*
      42                 :            :                  * Return address is either directly at stack pointer
      43                 :            :                  * or above a saved flags. Eflags has bits 22-31 zero,
      44                 :            :                  * kernel addresses don't.
      45                 :            :                  */
      46         [ #  # ]:          0 :                 if (sp[0] >> 22)
      47                 :            :                         return sp[0];
      48         [ #  # ]:          0 :                 if (sp[1] >> 22)
      49                 :          0 :                         return sp[1];
      50                 :            : #endif
      51                 :            :         }
      52                 :            :         return pc;
      53                 :            : }
      54                 :            : EXPORT_SYMBOL(profile_pc);
      55                 :            : 
      56                 :            : /*
      57                 :            :  * Default timer interrupt handler for PIT/HPET
      58                 :            :  */
      59                 :       1515 : static irqreturn_t timer_interrupt(int irq, void *dev_id)
      60                 :            : {
      61                 :       1515 :         global_clock_event->event_handler(global_clock_event);
      62                 :       1515 :         return IRQ_HANDLED;
      63                 :            : }
      64                 :            : 
      65                 :            : static struct irqaction irq0  = {
      66                 :            :         .handler = timer_interrupt,
      67                 :            :         .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
      68                 :            :         .name = "timer"
      69                 :            : };
      70                 :            : 
      71                 :         13 : static void __init setup_default_timer_irq(void)
      72                 :            : {
      73                 :            :         /*
      74                 :            :          * Unconditionally register the legacy timer; even without legacy
      75                 :            :          * PIC/PIT we need this for the HPET0 in legacy replacement mode.
      76                 :            :          */
      77         [ -  + ]:         13 :         if (setup_irq(0, &irq0))
      78                 :          0 :                 pr_info("Failed to register legacy timer interrupt\n");
      79                 :         13 : }
      80                 :            : 
      81                 :            : /* Default timer init function */
      82                 :         13 : void __init hpet_time_init(void)
      83                 :            : {
      84         [ -  + ]:         13 :         if (!hpet_enable()) {
      85         [ #  # ]:          0 :                 if (!pit_timer_init())
      86                 :            :                         return;
      87                 :            :         }
      88                 :            : 
      89                 :         13 :         setup_default_timer_irq();
      90                 :            : }
      91                 :            : 
      92                 :         13 : static __init void x86_late_time_init(void)
      93                 :            : {
      94                 :            :         /*
      95                 :            :          * Before PIT/HPET init, select the interrupt mode. This is required
      96                 :            :          * to make the decision whether PIT should be initialized correct.
      97                 :            :          */
      98                 :         13 :         x86_init.irqs.intr_mode_select();
      99                 :            : 
     100                 :            :         /* Setup the legacy timers */
     101                 :         13 :         x86_init.timers.timer_init();
     102                 :            : 
     103                 :            :         /*
     104                 :            :          * After PIT/HPET timers init, set up the final interrupt mode for
     105                 :            :          * delivering IRQs.
     106                 :            :          */
     107                 :         13 :         x86_init.irqs.intr_mode_init();
     108                 :         13 :         tsc_init();
     109                 :         13 : }
     110                 :            : 
     111                 :            : /*
     112                 :            :  * Initialize TSC and delay the periodic timer init to
     113                 :            :  * late x86_late_time_init() so ioremap works.
     114                 :            :  */
     115                 :         13 : void __init time_init(void)
     116                 :            : {
     117                 :         13 :         late_time_init = x86_late_time_init;
     118                 :         13 : }
     119                 :            : 
     120                 :            : /*
     121                 :            :  * Sanity check the vdso related archdata content.
     122                 :            :  */
     123                 :         91 : void clocksource_arch_init(struct clocksource *cs)
     124                 :            : {
     125         [ +  + ]:         91 :         if (cs->archdata.vclock_mode == VCLOCK_NONE)
     126                 :            :                 return;
     127                 :            : 
     128         [ -  + ]:         26 :         if (cs->archdata.vclock_mode > VCLOCK_MAX) {
     129                 :          0 :                 pr_warn("clocksource %s registered with invalid vclock_mode %d. Disabling vclock.\n",
     130                 :            :                         cs->name, cs->archdata.vclock_mode);
     131                 :          0 :                 cs->archdata.vclock_mode = VCLOCK_NONE;
     132                 :            :         }
     133                 :            : 
     134         [ -  + ]:         26 :         if (cs->mask != CLOCKSOURCE_MASK(64)) {
     135                 :          0 :                 pr_warn("clocksource %s registered with invalid mask %016llx. Disabling vclock.\n",
     136                 :            :                         cs->name, cs->mask);
     137                 :          0 :                 cs->archdata.vclock_mode = VCLOCK_NONE;
     138                 :            :         }
     139                 :            : }

Generated by: LCOV version 1.14