.. | .. |
---|
10 | 10 | * |
---|
11 | 11 | */ |
---|
12 | 12 | |
---|
| 13 | +#include <linux/clocksource.h> |
---|
13 | 14 | #include <linux/clockchips.h> |
---|
14 | 15 | #include <linux/interrupt.h> |
---|
15 | 16 | #include <linux/irq.h> |
---|
.. | .. |
---|
32 | 33 | #ifdef CONFIG_FRAME_POINTER |
---|
33 | 34 | return *(unsigned long *)(regs->bp + sizeof(long)); |
---|
34 | 35 | #else |
---|
35 | | - unsigned long *sp = |
---|
36 | | - (unsigned long *)kernel_stack_pointer(regs); |
---|
| 36 | + unsigned long *sp = (unsigned long *)regs->sp; |
---|
37 | 37 | /* |
---|
38 | 38 | * Return address is either directly at stack pointer |
---|
39 | 39 | * or above a saved flags. Eflags has bits 22-31 zero, |
---|
.. | .. |
---|
58 | 58 | return IRQ_HANDLED; |
---|
59 | 59 | } |
---|
60 | 60 | |
---|
61 | | -static struct irqaction irq0 = { |
---|
62 | | - .handler = timer_interrupt, |
---|
63 | | - .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, |
---|
64 | | - .name = "timer" |
---|
65 | | -}; |
---|
66 | | - |
---|
67 | 61 | static void __init setup_default_timer_irq(void) |
---|
68 | 62 | { |
---|
| 63 | + unsigned long flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER; |
---|
| 64 | + |
---|
69 | 65 | /* |
---|
70 | | - * Unconditionally register the legacy timer; even without legacy |
---|
71 | | - * PIC/PIT we need this for the HPET0 in legacy replacement mode. |
---|
| 66 | + * Unconditionally register the legacy timer interrupt; even |
---|
| 67 | + * without legacy PIC/PIT we need this for the HPET0 in legacy |
---|
| 68 | + * replacement mode. |
---|
72 | 69 | */ |
---|
73 | | - if (setup_irq(0, &irq0)) |
---|
| 70 | + if (request_irq(0, timer_interrupt, flags, "timer", NULL)) |
---|
74 | 71 | pr_info("Failed to register legacy timer interrupt\n"); |
---|
75 | 72 | } |
---|
76 | 73 | |
---|
77 | 74 | /* Default timer init function */ |
---|
78 | 75 | void __init hpet_time_init(void) |
---|
79 | 76 | { |
---|
80 | | - if (!hpet_enable()) |
---|
81 | | - setup_pit_timer(); |
---|
| 77 | + if (!hpet_enable()) { |
---|
| 78 | + if (!pit_timer_init()) |
---|
| 79 | + return; |
---|
| 80 | + } |
---|
| 81 | + |
---|
82 | 82 | setup_default_timer_irq(); |
---|
83 | 83 | } |
---|
84 | 84 | |
---|
85 | 85 | static __init void x86_late_time_init(void) |
---|
86 | 86 | { |
---|
87 | | - x86_init.timers.timer_init(); |
---|
88 | 87 | /* |
---|
89 | | - * After PIT/HPET timers init, select and setup |
---|
90 | | - * the final interrupt mode for delivering IRQs. |
---|
| 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 | + x86_init.irqs.intr_mode_select(); |
---|
| 92 | + |
---|
| 93 | + /* Setup the legacy timers */ |
---|
| 94 | + x86_init.timers.timer_init(); |
---|
| 95 | + |
---|
| 96 | + /* |
---|
| 97 | + * After PIT/HPET timers init, set up the final interrupt mode for |
---|
| 98 | + * delivering IRQs. |
---|
91 | 99 | */ |
---|
92 | 100 | x86_init.irqs.intr_mode_init(); |
---|
93 | 101 | tsc_init(); |
---|
| 102 | + |
---|
| 103 | + if (static_cpu_has(X86_FEATURE_WAITPKG)) |
---|
| 104 | + use_tpause_delay(); |
---|
94 | 105 | } |
---|
95 | 106 | |
---|
96 | 107 | /* |
---|
.. | .. |
---|
101 | 112 | { |
---|
102 | 113 | late_time_init = x86_late_time_init; |
---|
103 | 114 | } |
---|
| 115 | + |
---|
| 116 | +/* |
---|
| 117 | + * Sanity check the vdso related archdata content. |
---|
| 118 | + */ |
---|
| 119 | +void clocksource_arch_init(struct clocksource *cs) |
---|
| 120 | +{ |
---|
| 121 | + if (cs->vdso_clock_mode == VDSO_CLOCKMODE_NONE) |
---|
| 122 | + return; |
---|
| 123 | + |
---|
| 124 | + if (cs->mask != CLOCKSOURCE_MASK(64)) { |
---|
| 125 | + pr_warn("clocksource %s registered with invalid mask %016llx for VDSO. Disabling VDSO support.\n", |
---|
| 126 | + cs->name, cs->mask); |
---|
| 127 | + cs->vdso_clock_mode = VDSO_CLOCKMODE_NONE; |
---|
| 128 | + } |
---|
| 129 | +} |
---|