time_64.c 10.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 *  linux/arch/x86-64/kernel/time.c
 *
 *  "High Precision Event Timer" based timekeeping.
 *
 *  Copyright (c) 1991,1992,1995  Linus Torvalds
 *  Copyright (c) 1994  Alan Modra
 *  Copyright (c) 1995  Markus Kuhn
 *  Copyright (c) 1996  Ingo Molnar
 *  Copyright (c) 1998  Andrea Arcangeli
11
 *  Copyright (c) 2002,2006  Vojtech Pavlik
L
Linus Torvalds 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *  Copyright (c) 2003  Andi Kleen
 *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c
 */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <linux/time.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/bcd.h>
27 28
#include <linux/notifier.h>
#include <linux/cpu.h>
L
Linus Torvalds 已提交
29
#include <linux/kallsyms.h>
A
Andi Kleen 已提交
30
#include <linux/acpi.h>
31
#ifdef CONFIG_ACPI
A
Andi Kleen 已提交
32
#include <acpi/achware.h>	/* for PM timer frequency */
33
#include <acpi/acpi_bus.h>
34
#endif
L
Linus Torvalds 已提交
35
#include <asm/8253pit.h>
36
#include <asm/i8253.h>
L
Linus Torvalds 已提交
37 38 39 40 41 42 43 44
#include <asm/pgtable.h>
#include <asm/vsyscall.h>
#include <asm/timex.h>
#include <asm/proto.h>
#include <asm/hpet.h>
#include <asm/sections.h>
#include <linux/hpet.h>
#include <asm/apic.h>
45
#include <asm/hpet.h>
46
#include <asm/mpspec.h>
47
#include <asm/nmi.h>
48
#include <asm/vgtod.h>
L
Linus Torvalds 已提交
49

50
static char *timename = NULL;
51

L
Linus Torvalds 已提交
52
DEFINE_SPINLOCK(rtc_lock);
53
EXPORT_SYMBOL(rtc_lock);
L
Linus Torvalds 已提交
54
DEFINE_SPINLOCK(i8253_lock);
55
EXPORT_SYMBOL(i8253_lock);
L
Linus Torvalds 已提交
56 57 58 59 60 61 62

volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;

unsigned long profile_pc(struct pt_regs *regs)
{
	unsigned long pc = instruction_pointer(regs);

63 64 65
	/* Assume the lock function has either no stack frame or a copy
	   of eflags from PUSHF
	   Eflags always has bits 22 and up cleared unlike kernel addresses. */
66
	if (!user_mode(regs) && in_lock_functions(pc)) {
67 68 69 70 71
		unsigned long *sp = (unsigned long *)regs->rsp;
		if (sp[0] >> 22)
			return sp[0];
		if (sp[1] >> 22)
			return sp[1];
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84
	}
	return pc;
}
EXPORT_SYMBOL(profile_pc);

/*
 * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
 * ms after the second nowtime has started, because when nowtime is written
 * into the registers of the CMOS clock, it will jump to the next second
 * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
 * sheet for details.
 */

85
static int set_rtc_mmss(unsigned long nowtime)
L
Linus Torvalds 已提交
86
{
87
	int retval = 0;
L
Linus Torvalds 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
	int real_seconds, real_minutes, cmos_minutes;
	unsigned char control, freq_select;

/*
 * IRQs are disabled when we're called from the timer interrupt,
 * no need for spin_lock_irqsave()
 */

	spin_lock(&rtc_lock);

/*
 * Tell the clock it's being set and stop it.
 */

	control = CMOS_READ(RTC_CONTROL);
	CMOS_WRITE(control | RTC_SET, RTC_CONTROL);

	freq_select = CMOS_READ(RTC_FREQ_SELECT);
	CMOS_WRITE(freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);

	cmos_minutes = CMOS_READ(RTC_MINUTES);
		BCD_TO_BIN(cmos_minutes);

/*
 * since we're only adjusting minutes and seconds, don't interfere with hour
 * overflow. This avoids messing with unknown time zones but requires your RTC
 * not to be off by more than 15 minutes. Since we're calling it only when
 * our clock is externally synchronized using NTP, this shouldn't be a problem.
 */

	real_seconds = nowtime % 60;
	real_minutes = nowtime / 60;
	if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
		real_minutes += 30;		/* correct for half hour time zone */
	real_minutes %= 60;

	if (abs(real_minutes - cmos_minutes) >= 30) {
		printk(KERN_WARNING "time.c: can't update CMOS clock "
		       "from %d to %d\n", cmos_minutes, real_minutes);
127
		retval = -1;
128
	} else {
129 130
		BIN_TO_BCD(real_seconds);
		BIN_TO_BCD(real_minutes);
L
Linus Torvalds 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
		CMOS_WRITE(real_seconds, RTC_SECONDS);
		CMOS_WRITE(real_minutes, RTC_MINUTES);
	}

/*
 * The following flags have to be released exactly in this order, otherwise the
 * DS12887 (popular MC146818A clone with integrated battery and quartz) will
 * not reset the oscillator and will not update precisely 500 ms later. You
 * won't find this mentioned in the Dallas Semiconductor data sheets, but who
 * believes data sheets anyway ... -- Markus Kuhn
 */

	CMOS_WRITE(control, RTC_CONTROL);
	CMOS_WRITE(freq_select, RTC_FREQ_SELECT);

	spin_unlock(&rtc_lock);
147 148

	return retval;
L
Linus Torvalds 已提交
149 150
}

151 152 153 154
int update_persistent_clock(struct timespec now)
{
	return set_rtc_mmss(now.tv_sec);
}
L
Linus Torvalds 已提交
155

156
void main_timer_handler(void)
L
Linus Torvalds 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170
{
/*
 * Here we are in the timer irq handler. We have irqs locally disabled (so we
 * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
 * on the other CPU, so we need a lock. We also need to lock the vsyscall
 * variables, because both do_timer() and us change them -arca+vojtech
 */

	write_seqlock(&xtime_lock);

/*
 * Do the timer stuff.
 */

171
	do_timer(1);
L
Linus Torvalds 已提交
172
#ifndef CONFIG_SMP
173
	update_process_times(user_mode(get_irq_regs()));
L
Linus Torvalds 已提交
174 175 176 177 178 179 180 181 182
#endif

/*
 * In the SMP case we use the local APIC timer interrupt to do the profiling,
 * except when we simulate SMP mode on a uniprocessor system, in that case we
 * have to call the local interrupt handler.
 */

	if (!using_apic_timer)
183
		smp_local_timer_interrupt();
L
Linus Torvalds 已提交
184 185

	write_sequnlock(&xtime_lock);
186
}
L
Linus Torvalds 已提交
187

188
static irqreturn_t timer_interrupt(int irq, void *dev_id)
189 190 191
{
	if (apic_runs_main_timer > 1)
		return IRQ_HANDLED;
192
	main_timer_handler();
193 194
	if (using_apic_timer)
		smp_send_timer_broadcast_ipi();
L
Linus Torvalds 已提交
195 196 197
	return IRQ_HANDLED;
}

T
Thomas Gleixner 已提交
198
unsigned long read_persistent_clock(void)
L
Linus Torvalds 已提交
199
{
200
	unsigned int year, mon, day, hour, min, sec;
L
Linus Torvalds 已提交
201
	unsigned long flags;
202
	unsigned century = 0;
L
Linus Torvalds 已提交
203 204 205

	spin_lock_irqsave(&rtc_lock, flags);

206 207 208 209 210 211 212
	do {
		sec = CMOS_READ(RTC_SECONDS);
		min = CMOS_READ(RTC_MINUTES);
		hour = CMOS_READ(RTC_HOURS);
		day = CMOS_READ(RTC_DAY_OF_MONTH);
		mon = CMOS_READ(RTC_MONTH);
		year = CMOS_READ(RTC_YEAR);
213
#ifdef CONFIG_ACPI
214 215 216
		if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
					acpi_gbl_FADT.century)
			century = CMOS_READ(acpi_gbl_FADT.century);
217
#endif
218
	} while (sec != CMOS_READ(RTC_SECONDS));
219

L
Linus Torvalds 已提交
220 221
	spin_unlock_irqrestore(&rtc_lock, flags);

222 223 224
	/*
	 * We know that x86-64 always uses BCD format, no need to check the
	 * config register.
225
	 */
L
Linus Torvalds 已提交
226

227 228 229 230 231 232
	BCD_TO_BIN(sec);
	BCD_TO_BIN(min);
	BCD_TO_BIN(hour);
	BCD_TO_BIN(day);
	BCD_TO_BIN(mon);
	BCD_TO_BIN(year);
L
Linus Torvalds 已提交
233

234 235 236 237
	if (century) {
		BCD_TO_BIN(century);
		year += century * 100;
		printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
238
	} else {
239 240 241
		/*
		 * x86-64 systems only exists since 2002.
		 * This will work up to Dec 31, 2100
242
		 */
243 244
		year += 2000;
	}
L
Linus Torvalds 已提交
245 246 247 248

	return mktime(year, mon, day, hour, min, sec);
}

249 250 251 252 253
/* calibrate_cpu is used on systems with fixed rate TSCs to determine
 * processor frequency */
#define TICK_COUNT 100000000
static unsigned int __init tsc_calibrate_cpu_khz(void)
{
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
	int tsc_start, tsc_now;
	int i, no_ctr_free;
	unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
	unsigned long flags;

	for (i = 0; i < 4; i++)
		if (avail_to_resrv_perfctr_nmi_bit(i))
			break;
	no_ctr_free = (i == 4);
	if (no_ctr_free) {
		i = 3;
		rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
		wrmsrl(MSR_K7_EVNTSEL3, 0);
		rdmsrl(MSR_K7_PERFCTR3, pmc3);
	} else {
		reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
		reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
	}
	local_irq_save(flags);
	/* start meauring cycles, incrementing from 0 */
	wrmsrl(MSR_K7_PERFCTR0 + i, 0);
	wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
	rdtscl(tsc_start);
	do {
		rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
		tsc_now = get_cycles_sync();
	} while ((tsc_now - tsc_start) < TICK_COUNT);

	local_irq_restore(flags);
	if (no_ctr_free) {
		wrmsrl(MSR_K7_EVNTSEL3, 0);
		wrmsrl(MSR_K7_PERFCTR3, pmc3);
		wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
	} else {
		release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
		release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
	}

	return pmc_now * tsc_khz / (tsc_now - tsc_start);
293
}
L
Linus Torvalds 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314

/*
 * pit_calibrate_tsc() uses the speaker output (channel 2) of
 * the PIT. This is better than using the timer interrupt output,
 * because we can read the value of the speaker with just one inb(),
 * where we need three i/o operations for the interrupt channel.
 * We count how many ticks the TSC does in 50 ms.
 */

static unsigned int __init pit_calibrate_tsc(void)
{
	unsigned long start, end;
	unsigned long flags;

	spin_lock_irqsave(&i8253_lock, flags);

	outb((inb(0x61) & ~0x02) | 0x01, 0x61);

	outb(0xb0, 0x43);
	outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
	outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42);
315
	start = get_cycles_sync();
L
Linus Torvalds 已提交
316
	while ((inb(0x61) & 0x20) == 0);
317
	end = get_cycles_sync();
L
Linus Torvalds 已提交
318 319

	spin_unlock_irqrestore(&i8253_lock, flags);
320

L
Linus Torvalds 已提交
321 322 323
	return (end - start) / 50;
}

324 325 326
#define PIT_MODE 0x43
#define PIT_CH0  0x40

327
static void __pit_init(int val, u8 mode)
L
Linus Torvalds 已提交
328 329 330 331
{
	unsigned long flags;

	spin_lock_irqsave(&i8253_lock, flags);
332 333 334
	outb_p(mode, PIT_MODE);
	outb_p(val & 0xff, PIT_CH0);	/* LSB */
	outb_p(val >> 8, PIT_CH0);	/* MSB */
L
Linus Torvalds 已提交
335 336 337
	spin_unlock_irqrestore(&i8253_lock, flags);
}

338 339 340 341 342
void __init pit_init(void)
{
	__pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
}

343
void pit_stop_interrupt(void)
344 345 346 347
{
	__pit_init(0, 0x30); /* mode 0 */
}

348
void stop_timer_interrupt(void)
349 350
{
	char *name;
351
	if (hpet_address) {
352 353 354 355 356 357 358 359 360
		name = "HPET";
		hpet_timer_stop_set_go(0);
	} else {
		name = "PIT";
		pit_stop_interrupt();
	}
	printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
}

L
Linus Torvalds 已提交
361
static struct irqaction irq0 = {
B
Bernhard Walle 已提交
362
	.handler	= timer_interrupt,
363
	.flags		= IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
B
Bernhard Walle 已提交
364
	.mask		= CPU_MASK_NONE,
365
	.name		= "timer"
L
Linus Torvalds 已提交
366 367
};

368 369
void __init time_init(void)
{
L
Linus Torvalds 已提交
370
	if (nohpet)
371
		hpet_address = 0;
L
Linus Torvalds 已提交
372

373
	if (hpet_arch_init())
374
		hpet_address = 0;
375 376

	if (hpet_use_timer) {
377
		/* set tick_nsec to use the proper rate for HPET */
378
		tick_nsec = TICK_NSEC_HPET;
379
		tsc_khz = hpet_calibrate_tsc();
L
Linus Torvalds 已提交
380 381 382
		timename = "HPET";
	} else {
		pit_init();
383
		tsc_khz = pit_calibrate_tsc();
L
Linus Torvalds 已提交
384 385 386
		timename = "PIT";
	}

387 388 389 390 391 392
	cpu_khz = tsc_khz;
	if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
		boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
		boot_cpu_data.x86 == 16)
		cpu_khz = tsc_calibrate_cpu_khz();

A
Andi Kleen 已提交
393
	if (unsynchronized_tsc())
394
		mark_tsc_unstable("TSCs unsynchronized");
395

396
	if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP))
397 398 399 400
		vgetcpu_mode = VGETCPU_RDTSCP;
	else
		vgetcpu_mode = VGETCPU_LSL;

401
	set_cyc2ns_scale(tsc_khz);
402 403
	printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
		cpu_khz / 1000, cpu_khz % 1000);
404 405
	init_tsc_clocksource();

406
	setup_irq(0, &irq0);
L
Linus Torvalds 已提交
407 408
}

409 410 411 412
/*
 * sysfs support for the timer.
 */

413
static int timer_suspend(struct sys_device *dev, pm_message_t state)
L
Linus Torvalds 已提交
414 415 416 417 418 419
{
	return 0;
}

static int timer_resume(struct sys_device *dev)
{
420
	if (hpet_address)
L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432
		hpet_reenable();
	else
		i8254_timer_resume();
	return 0;
}

static struct sysdev_class timer_sysclass = {
	.resume = timer_resume,
	.suspend = timer_suspend,
	set_kset_name("timer"),
};

433
/* XXX this sysfs stuff should probably go elsewhere later -john */
L
Linus Torvalds 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447
static struct sys_device device_timer = {
	.id	= 0,
	.cls	= &timer_sysclass,
};

static int time_init_device(void)
{
	int error = sysdev_class_register(&timer_sysclass);
	if (!error)
		error = sysdev_register(&device_timer);
	return error;
}

device_initcall(time_init_device);