clock.c (32052) | clock.c (32054) |
---|---|
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz and Don Ahn. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 | 1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz and Don Ahn. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 |
37 * $Id: clock.c,v 1.105 1997/12/26 20:42:05 phk Exp $ | 37 * $Id: clock.c,v 1.106 1997/12/28 13:36:07 phk Exp $ |
38 */ 39 40/* 41 * Routines to handle clock hardware. 42 */ 43 44/* 45 * inittodr, settodr and support routines written --- 16 unchanged lines hidden (view full) --- 62#include <machine/clock.h> 63#ifdef CLK_CALIBRATION_LOOP 64#include <machine/cons.h> 65#endif 66#include <machine/cputypes.h> 67#include <machine/frame.h> 68#include <machine/ipl.h> 69#include <machine/limits.h> | 38 */ 39 40/* 41 * Routines to handle clock hardware. 42 */ 43 44/* 45 * inittodr, settodr and support routines written --- 16 unchanged lines hidden (view full) --- 62#include <machine/clock.h> 63#ifdef CLK_CALIBRATION_LOOP 64#include <machine/cons.h> 65#endif 66#include <machine/cputypes.h> 67#include <machine/frame.h> 68#include <machine/ipl.h> 69#include <machine/limits.h> |
70#include <machine/md_var.h> |
|
70#ifdef APIC_IO 71#include <machine/segments.h> 72#endif 73#if defined(SMP) || defined(APIC_IO) 74#include <machine/smp.h> 75#endif /* SMP || APIC_IO */ | 71#ifdef APIC_IO 72#include <machine/segments.h> 73#endif 74#if defined(SMP) || defined(APIC_IO) 75#include <machine/smp.h> 76#endif /* SMP || APIC_IO */ |
77#include <machine/specialreg.h> |
|
76 77#include <i386/isa/icu.h> 78#include <i386/isa/isa.h> 79#include <i386/isa/rtc.h> 80#include <i386/isa/timerreg.h> 81 82#include <sys/interrupt.h> 83 --- 37 unchanged lines hidden (view full) --- 121#ifdef TIMER_FREQ 122u_int timer_freq = TIMER_FREQ; 123#else 124u_int timer_freq = 1193182; 125#endif 126int timer0_max_count; 127u_int timer0_overflow_threshold; 128u_int timer0_prescaler_count; | 78 79#include <i386/isa/icu.h> 80#include <i386/isa/isa.h> 81#include <i386/isa/rtc.h> 82#include <i386/isa/timerreg.h> 83 84#include <sys/interrupt.h> 85 --- 37 unchanged lines hidden (view full) --- 123#ifdef TIMER_FREQ 124u_int timer_freq = TIMER_FREQ; 125#else 126u_int timer_freq = 1193182; 127#endif 128int timer0_max_count; 129u_int timer0_overflow_threshold; 130u_int timer0_prescaler_count; |
129#if defined(I586_CPU) || defined(I686_CPU) 130#ifndef SMP | |
131u_int tsc_bias; 132u_int tsc_comultiplier; | 131u_int tsc_bias; 132u_int tsc_comultiplier; |
133#endif | |
134u_int tsc_freq; | 133u_int tsc_freq; |
135#ifndef SMP | |
136u_int tsc_multiplier; | 134u_int tsc_multiplier; |
137#endif 138#endif | 135u_int tsc_present; |
139int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 140 141static int beeping = 0; 142static u_int clk_imask = HWI_MASK | SWI_MASK; 143static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 144static u_int hardclock_max_count; 145/* 146 * XXX new_function and timer_func should not handle clockframes, but --- 11 unchanged lines hidden (view full) --- 158#define RELEASE_PENDING 1 159#define ACQUIRED 2 160#define ACQUIRE_PENDING 3 161 162static u_char timer0_state; 163static u_char timer2_state; 164static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 165 | 136int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ 137 138static int beeping = 0; 139static u_int clk_imask = HWI_MASK | SWI_MASK; 140static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 141static u_int hardclock_max_count; 142/* 143 * XXX new_function and timer_func should not handle clockframes, but --- 11 unchanged lines hidden (view full) --- 155#define RELEASE_PENDING 1 156#define ACQUIRED 2 157#define ACQUIRE_PENDING 3 158 159static u_char timer0_state; 160static u_char timer2_state; 161static void (*timer_func) __P((struct clockframe *frame)) = hardclock; 162 |
166#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) 167static void set_tsc_freq(u_int i586_freq, u_int i8254_freq); 168#endif | 163static void set_tsc_freq(u_int tsc_count, u_int i8254_freq); |
169static void set_timer_freq(u_int freq, int intr_freq); 170 171static void 172clkintr(struct clockframe frame) 173{ 174 timer_func(&frame); 175 switch (timer0_state) { 176 --- 392 unchanged lines hidden (view full) --- 569 } 570 571 /* Start keeping track of the i8254 counter. */ 572 prev_count = getit(); 573 if (prev_count == 0 || prev_count > timer0_max_count) 574 goto fail; 575 tot_count = 0; 576 | 164static void set_timer_freq(u_int freq, int intr_freq); 165 166static void 167clkintr(struct clockframe frame) 168{ 169 timer_func(&frame); 170 switch (timer0_state) { 171 --- 392 unchanged lines hidden (view full) --- 564 } 565 566 /* Start keeping track of the i8254 counter. */ 567 prev_count = getit(); 568 if (prev_count == 0 || prev_count > timer0_max_count) 569 goto fail; 570 tot_count = 0; 571 |
577#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) 578 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) | 572 if (tsc_present) |
579 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ | 573 wrmsr(0x10, 0LL); /* XXX 0x10 is the MSR for the TSC */ |
580#endif | |
581 582 /* 583 * Wait for the mc146818A seconds counter to change. Read the i8254 584 * counter for each iteration since this is convenient and only 585 * costs a few usec of inaccuracy. The timing of the final reads 586 * of the counters almost matches the timing of the initial reads, 587 * so the main cause of inaccuracy is the varying latency from 588 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the --- 13 unchanged lines hidden (view full) --- 602 tot_count += prev_count - count; 603 prev_count = count; 604 if (sec != start_sec) 605 break; 606 if (--timeout == 0) 607 goto fail; 608 } 609 | 574 575 /* 576 * Wait for the mc146818A seconds counter to change. Read the i8254 577 * counter for each iteration since this is convenient and only 578 * costs a few usec of inaccuracy. The timing of the final reads 579 * of the counters almost matches the timing of the initial reads, 580 * so the main cause of inaccuracy is the varying latency from 581 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the --- 13 unchanged lines hidden (view full) --- 595 tot_count += prev_count - count; 596 prev_count = count; 597 if (sec != start_sec) 598 break; 599 if (--timeout == 0) 600 goto fail; 601 } 602 |
610#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) | |
611 /* 612 * Read the cpu cycle counter. The timing considerations are 613 * similar to those for the i8254 clock. 614 */ | 603 /* 604 * Read the cpu cycle counter. The timing considerations are 605 * similar to those for the i8254 clock. 606 */ |
615 if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { | 607 if (tsc_present) { |
616 set_tsc_freq((u_int)rdtsc(), tot_count); 617 if (bootverbose) 618 printf("TSC clock: %u Hz, ", tsc_freq); 619 } | 608 set_tsc_freq((u_int)rdtsc(), tot_count); 609 if (bootverbose) 610 printf("TSC clock: %u Hz, ", tsc_freq); 611 } |
620#endif | |
621 622 if (bootverbose) 623 printf("i8254 clock: %u Hz\n", tot_count); 624 return (tot_count); 625 626fail: 627 if (bootverbose) 628 printf("failed, using default i8254 clock of %u Hz\n", --- 22 unchanged lines hidden (view full) --- 651 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 652 * XXX initialization of other timers is unintentionally left blank. 653 */ 654void 655startrtclock() 656{ 657 u_int delta, freq; 658 | 612 613 if (bootverbose) 614 printf("i8254 clock: %u Hz\n", tot_count); 615 return (tot_count); 616 617fail: 618 if (bootverbose) 619 printf("failed, using default i8254 clock of %u Hz\n", --- 22 unchanged lines hidden (view full) --- 642 * Initialize 8253 timer 0 early so that it can be used in DELAY(). 643 * XXX initialization of other timers is unintentionally left blank. 644 */ 645void 646startrtclock() 647{ 648 u_int delta, freq; 649 |
650 if (cpu_feature & CPUID_TSC) 651 tsc_present = 1; 652 else 653 tsc_present = 0; 654 655#ifdef SMP 656 tsc_present = 0; 657#endif 658 |
|
659 writertc(RTC_STATUSA, rtc_statusa); 660 writertc(RTC_STATUSB, RTCSB_24HR); 661 662 set_timer_freq(timer_freq, hz); 663 freq = calibrate_clocks(); 664#ifdef CLK_CALIBRATION_LOOP 665 if (bootverbose) { 666 printf( --- 17 unchanged lines hidden (view full) --- 684 freq = timer_freq; 685#endif 686 timer_freq = freq; 687 } else { 688 if (bootverbose) 689 printf( 690 "%d Hz differs from default of %d Hz by more than 1%%\n", 691 freq, timer_freq); | 659 writertc(RTC_STATUSA, rtc_statusa); 660 writertc(RTC_STATUSB, RTCSB_24HR); 661 662 set_timer_freq(timer_freq, hz); 663 freq = calibrate_clocks(); 664#ifdef CLK_CALIBRATION_LOOP 665 if (bootverbose) { 666 printf( --- 17 unchanged lines hidden (view full) --- 684 freq = timer_freq; 685#endif 686 timer_freq = freq; 687 } else { 688 if (bootverbose) 689 printf( 690 "%d Hz differs from default of %d Hz by more than 1%%\n", 691 freq, timer_freq); |
692#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) | |
693 tsc_freq = 0; | 692 tsc_freq = 0; |
694#endif | |
695 } 696 697 set_timer_freq(timer_freq, hz); 698 | 693 } 694 695 set_timer_freq(timer_freq, hz); 696 |
699#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) | |
700#ifndef CLK_USE_TSC_CALIBRATION 701 if (tsc_freq != 0) { 702 if (bootverbose) 703 printf( 704"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n"); 705 tsc_freq = 0; 706 } 707#endif | 697#ifndef CLK_USE_TSC_CALIBRATION 698 if (tsc_freq != 0) { 699 if (bootverbose) 700 printf( 701"CLK_USE_TSC_CALIBRATION not specified - using old calibration method\n"); 702 tsc_freq = 0; 703 } 704#endif |
708 if (tsc_freq == 0 && 709 (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686)) { | 705 if (tsc_present && tsc_freq == 0) { |
710 /* 711 * Calibration of the i586 clock relative to the mc146818A 712 * clock failed. Do a less accurate calibration relative 713 * to the i8254 clock. 714 */ 715 wrmsr(0x10, 0LL); /* XXX */ 716 DELAY(1000000); 717 set_tsc_freq((u_int)rdtsc(), timer_freq); | 706 /* 707 * Calibration of the i586 clock relative to the mc146818A 708 * clock failed. Do a less accurate calibration relative 709 * to the i8254 clock. 710 */ 711 wrmsr(0x10, 0LL); /* XXX */ 712 DELAY(1000000); 713 set_tsc_freq((u_int)rdtsc(), timer_freq); |
718#ifdef CLK_USE_I586_CALIBRATION | 714#ifdef CLK_USE_TSC_CALIBRATION |
719 if (bootverbose) 720 printf("TSC clock: %u Hz\n", tsc_freq); 721#endif 722 } | 715 if (bootverbose) 716 printf("TSC clock: %u Hz\n", tsc_freq); 717#endif 718 } |
723#endif | |
724} 725 726/* 727 * Initialize the time of day register, based on the time base which is, e.g. 728 * from a filesystem. 729 */ 730void 731inittodr(time_t base) --- 188 unchanged lines hidden (view full) --- 920 921 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 922 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 923 /* unit */ 0); 924 INTREN(IRQ0); 925 926#endif /* APIC_IO */ 927 | 719} 720 721/* 722 * Initialize the time of day register, based on the time base which is, e.g. 723 * from a filesystem. 724 */ 725void 726inittodr(time_t base) --- 188 unchanged lines hidden (view full) --- 915 916 register_intr(/* irq */ 0, /* XXX id */ 0, /* flags */ 0, 917 /* XXX */ (inthand2_t *)clkintr, &clk_imask, 918 /* unit */ 0); 919 INTREN(IRQ0); 920 921#endif /* APIC_IO */ 922 |
928#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) | |
929 /* 930 * Finish setting up anti-jitter measures. 931 */ 932 if (tsc_freq != 0) 933 tsc_bias = rdtsc(); | 923 /* 924 * Finish setting up anti-jitter measures. 925 */ 926 if (tsc_freq != 0) 927 tsc_bias = rdtsc(); |
934#endif | |
935 936 /* Initialize RTC. */ 937 writertc(RTC_STATUSA, rtc_statusa); 938 writertc(RTC_STATUSB, RTCSB_24HR); 939 940 /* Don't bother enabling the statistics clock. */ 941 if (statclock_disable) 942 return; --- 40 unchanged lines hidden (view full) --- 983 * is is too generic. Should use it everywhere. 984 */ 985 freq = timer_freq; 986 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 987 if (error == 0 && req->newptr != NULL) { 988 if (timer0_state != 0) 989 return (EBUSY); /* too much trouble to handle */ 990 set_timer_freq(freq, hz); | 928 929 /* Initialize RTC. */ 930 writertc(RTC_STATUSA, rtc_statusa); 931 writertc(RTC_STATUSB, RTCSB_24HR); 932 933 /* Don't bother enabling the statistics clock. */ 934 if (statclock_disable) 935 return; --- 40 unchanged lines hidden (view full) --- 976 * is is too generic. Should use it everywhere. 977 */ 978 freq = timer_freq; 979 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 980 if (error == 0 && req->newptr != NULL) { 981 if (timer0_state != 0) 982 return (EBUSY); /* too much trouble to handle */ 983 set_timer_freq(freq, hz); |
991#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) 992 set_tsc_freq(tsc_freq, timer_freq); 993#endif | 984 if (tsc_present) 985 set_tsc_freq(tsc_freq, timer_freq); |
994 } 995 return (error); 996} 997 998SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 999 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 1000 | 986 } 987 return (error); 988} 989 990SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW, 991 0, sizeof(u_int), sysctl_machdep_i8254_freq, "I", ""); 992 |
1001#if (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) | |
1002static void | 993static void |
1003set_tsc_freq(u_int i586_freq, u_int i8254_freq) | 994set_tsc_freq(u_int tsc_count, u_int i8254_freq) |
1004{ 1005 u_int comultiplier, multiplier; 1006 u_long ef; 1007 | 995{ 996 u_int comultiplier, multiplier; 997 u_long ef; 998 |
1008 if (i586_freq == 0) { 1009 tsc_freq = i586_freq; | 999 if (tsc_count == 0) { 1000 tsc_freq = tsc_count; |
1010 return; 1011 } | 1001 return; 1002 } |
1012 comultiplier = ((unsigned long long)i586_freq | 1003 comultiplier = ((unsigned long long)tsc_count |
1013 << TSC_COMULTIPLIER_SHIFT) / i8254_freq; | 1004 << TSC_COMULTIPLIER_SHIFT) / i8254_freq; |
1014 multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / i586_freq; | 1005 multiplier = (1000000LL << TSC_MULTIPLIER_SHIFT) / tsc_count; |
1015 ef = read_eflags(); 1016 disable_intr(); | 1006 ef = read_eflags(); 1007 disable_intr(); |
1017 tsc_freq = i586_freq; | 1008 tsc_freq = tsc_count; |
1018 tsc_comultiplier = comultiplier; 1019 tsc_multiplier = multiplier; 1020 CLOCK_UNLOCK(); 1021 write_eflags(ef); 1022} 1023 1024static int | 1009 tsc_comultiplier = comultiplier; 1010 tsc_multiplier = multiplier; 1011 CLOCK_UNLOCK(); 1012 write_eflags(ef); 1013} 1014 1015static int |
1025sysctl_machdep_i586_freq SYSCTL_HANDLER_ARGS | 1016sysctl_machdep_tsc_freq SYSCTL_HANDLER_ARGS |
1026{ 1027 int error; 1028 u_int freq; 1029 | 1017{ 1018 int error; 1019 u_int freq; 1020 |
1030 if (cpu_class != CPUCLASS_586 && cpu_class != CPUCLASS_686) | 1021 if (!tsc_present) |
1031 return (EOPNOTSUPP); 1032 freq = tsc_freq; 1033 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 1034 if (error == 0 && req->newptr != NULL) 1035 set_tsc_freq(freq, timer_freq); 1036 return (error); 1037} 1038 | 1022 return (EOPNOTSUPP); 1023 freq = tsc_freq; 1024 error = sysctl_handle_opaque(oidp, &freq, sizeof freq, req); 1025 if (error == 0 && req->newptr != NULL) 1026 set_tsc_freq(freq, timer_freq); 1027 return (error); 1028} 1029 |
1039SYSCTL_PROC(_machdep, OID_AUTO, i586_freq, CTLTYPE_INT | CTLFLAG_RW, 1040 0, sizeof(u_int), sysctl_machdep_i586_freq, "I", ""); 1041#endif /* (defined(I586_CPU) || defined(I686_CPU)) && !defined(SMP) */ | 1030SYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_INT | CTLFLAG_RW, 1031 0, sizeof(u_int), sysctl_machdep_tsc_freq, "I", ""); |