diff options
Diffstat (limited to 'arch/x86/kernel/time_64.c')
-rw-r--r-- | arch/x86/kernel/time_64.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index e3d49c553af2..cb19d650c216 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/mca.h> | ||
19 | 20 | ||
20 | #include <asm/i8253.h> | 21 | #include <asm/i8253.h> |
21 | #include <asm/hpet.h> | 22 | #include <asm/hpet.h> |
@@ -33,23 +34,34 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
33 | /* Assume the lock function has either no stack frame or a copy | 34 | /* Assume the lock function has either no stack frame or a copy |
34 | of flags from PUSHF | 35 | of flags from PUSHF |
35 | Eflags always has bits 22 and up cleared unlike kernel addresses. */ | 36 | Eflags always has bits 22 and up cleared unlike kernel addresses. */ |
36 | if (!user_mode(regs) && in_lock_functions(pc)) { | 37 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
38 | #ifdef CONFIG_FRAME_POINTER | ||
39 | return *(unsigned long *)(regs->bp + sizeof(long)); | ||
40 | #else | ||
37 | unsigned long *sp = (unsigned long *)regs->sp; | 41 | unsigned long *sp = (unsigned long *)regs->sp; |
38 | if (sp[0] >> 22) | 42 | if (sp[0] >> 22) |
39 | return sp[0]; | 43 | return sp[0]; |
40 | if (sp[1] >> 22) | 44 | if (sp[1] >> 22) |
41 | return sp[1]; | 45 | return sp[1]; |
46 | #endif | ||
42 | } | 47 | } |
43 | return pc; | 48 | return pc; |
44 | } | 49 | } |
45 | EXPORT_SYMBOL(profile_pc); | 50 | EXPORT_SYMBOL(profile_pc); |
46 | 51 | ||
47 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) | 52 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
48 | { | 53 | { |
49 | add_pda(irq0_irqs, 1); | 54 | add_pda(irq0_irqs, 1); |
50 | 55 | ||
51 | global_clock_event->event_handler(global_clock_event); | 56 | global_clock_event->event_handler(global_clock_event); |
52 | 57 | ||
58 | #ifdef CONFIG_MCA | ||
59 | if (MCA_bus) { | ||
60 | u8 irq_v = inb_p(0x61); /* read the current state */ | ||
61 | outb_p(irq_v|0x80, 0x61); /* reset the IRQ */ | ||
62 | } | ||
63 | #endif | ||
64 | |||
53 | return IRQ_HANDLED; | 65 | return IRQ_HANDLED; |
54 | } | 66 | } |
55 | 67 | ||
@@ -100,7 +112,7 @@ unsigned long __init calibrate_cpu(void) | |||
100 | } | 112 | } |
101 | 113 | ||
102 | static struct irqaction irq0 = { | 114 | static struct irqaction irq0 = { |
103 | .handler = timer_event_interrupt, | 115 | .handler = timer_interrupt, |
104 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, | 116 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, |
105 | .mask = CPU_MASK_NONE, | 117 | .mask = CPU_MASK_NONE, |
106 | .name = "timer" | 118 | .name = "timer" |
@@ -111,16 +123,13 @@ void __init hpet_time_init(void) | |||
111 | if (!hpet_enable()) | 123 | if (!hpet_enable()) |
112 | setup_pit_timer(); | 124 | setup_pit_timer(); |
113 | 125 | ||
126 | irq0.mask = cpumask_of_cpu(0); | ||
114 | setup_irq(0, &irq0); | 127 | setup_irq(0, &irq0); |
115 | } | 128 | } |
116 | 129 | ||
117 | void __init time_init(void) | 130 | void __init time_init(void) |
118 | { | 131 | { |
119 | tsc_init(); | 132 | tsc_init(); |
120 | if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP)) | ||
121 | vgetcpu_mode = VGETCPU_RDTSCP; | ||
122 | else | ||
123 | vgetcpu_mode = VGETCPU_LSL; | ||
124 | 133 | ||
125 | late_time_init = choose_time_init(); | 134 | late_time_init = choose_time_init(); |
126 | } | 135 | } |