2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
30 * File: i386/rtclock.c
31 * Purpose: Routines for handling the machine dependent
32 * real-time clock. This clock is generated by
33 * the Intel 8254 Programmable Interval Timer.
37 #include <platforms.h>
40 #include <mach/mach_types.h>
42 #include <kern/cpu_number.h>
43 #include <kern/cpu_data.h>
44 #include <kern/clock.h>
45 #include <kern/host_notify.h>
46 #include <kern/macro_help.h>
47 #include <kern/misc_protos.h>
49 #include <machine/mach_param.h> /* HZ */
50 #include <mach/vm_prot.h>
52 #include <vm/vm_kern.h> /* for kernel_map */
56 #include <i386/misc_protos.h>
57 #include <i386/rtclock_entries.h>
58 #include <i386/hardclock_entries.h>
59 #include <i386/proc_reg.h>
60 #include <i386/machine_cpu.h>
61 #include <pexpert/pexpert.h>
63 #define DISPLAYENTER(x) printf("[RTCLOCK] entering " #x "\n");
64 #define DISPLAYEXIT(x) printf("[RTCLOCK] leaving " #x "\n");
65 #define DISPLAYVALUE(x,y) printf("[RTCLOCK] " #x ":" #y " = 0x%08x \n",y);
67 int sysclk_config(void);
69 int sysclk_init(void);
71 kern_return_t
sysclk_gettime(
72 mach_timespec_t
*cur_time
);
74 kern_return_t
sysclk_getattr(
75 clock_flavor_t flavor
,
77 mach_msg_type_number_t
*count
);
79 kern_return_t
sysclk_setattr(
80 clock_flavor_t flavor
,
82 mach_msg_type_number_t count
);
85 mach_timespec_t
*alarm_time
);
87 extern void (*IOKitRegisterInterruptHook
)(void *, int irq
, int isclock
);
90 * Lists of clock routines.
92 struct clock_ops sysclk_ops
= {
93 sysclk_config
, sysclk_init
,
95 sysclk_getattr
, sysclk_setattr
,
99 int calend_config(void);
101 int calend_init(void);
103 kern_return_t
calend_gettime(
104 mach_timespec_t
*cur_time
);
106 kern_return_t
calend_getattr(
107 clock_flavor_t flavor
,
109 mach_msg_type_number_t
*count
);
111 struct clock_ops calend_ops
= {
112 calend_config
, calend_init
,
118 /* local data declarations */
119 mach_timespec_t
*RtcTime
= (mach_timespec_t
*)0;
120 mach_timespec_t
*RtcAlrm
;
123 /* global data declarations */
127 mach_timespec_t time
;
128 mach_timespec_t alarm_time
; /* time of next alarm */
130 mach_timespec_t calend_offset
;
131 boolean_t calend_is_set
;
133 int64_t calend_adjtotal
;
134 int32_t calend_adjdelta
;
136 uint64_t timer_deadline
;
137 boolean_t timer_is_set
;
138 clock_timer_func_t timer_expire
;
140 clock_res_t new_ires
; /* pending new resolution (nano ) */
141 clock_res_t intr_nsec
; /* interrupt resolution (nano) */
142 mach_timebase_info_data_t timebase_const
;
144 decl_simple_lock_data(,lock
) /* real-time clock device lock */
147 unsigned int clknum
; /* clks per second */
148 unsigned int new_clknum
; /* pending clknum */
149 unsigned int time_per_clk
; /* time per clk in ZHZ */
150 unsigned int clks_per_int
; /* clks per interrupt */
151 unsigned int clks_per_int_99
;
152 int rtc_intr_count
; /* interrupt counter */
153 int rtc_intr_hertz
; /* interrupts per HZ */
154 int rtc_intr_freq
; /* interrupt frequency */
155 int rtc_print_lost_tick
; /* print lost tick */
157 uint32_t rtc_cyc_per_sec
; /* processor cycles per seconds */
158 uint32_t rtc_quant_scale
; /* used internally to convert clocks to nanos */
161 * Macros to lock/unlock real-time clock device.
163 #define LOCK_RTC(s) \
166 simple_lock(&rtclock.lock); \
169 #define UNLOCK_RTC(s) \
171 simple_unlock(&rtclock.lock); \
176 * i8254 control. ** MONUMENT **
178 * The i8254 is a traditional PC device with some arbitrary characteristics.
179 * Basically, it is a register that counts at a fixed rate and can be
180 * programmed to generate an interrupt every N counts. The count rate is
181 * clknum counts per second (see pit.h), historically 1193167 we believe.
182 * Various constants are computed based on this value, and we calculate
183 * them at init time for execution efficiency. To obtain sufficient
184 * accuracy, some of the calculation are most easily done in floating
185 * point and then converted to int.
187 * We want an interrupt every 10 milliseconds, approximately. The count
188 * which will do that is clks_per_int. However, that many counts is not
189 * *exactly* 10 milliseconds; it is a bit more or less depending on
190 * roundoff. The actual time per tick is calculated and saved in
191 * rtclock.intr_nsec, and it is that value which is added to the time
192 * register on each tick.
194 * The i8254 counter can be read between interrupts in order to determine
195 * the time more accurately. The counter counts down from the preset value
196 * toward 0, and we have to handle the case where the counter has been
197 * reset just before being read and before the interrupt has been serviced.
198 * Given a count since the last interrupt, the time since then is given
199 * by (count * time_per_clk). In order to minimize integer truncation,
200 * we perform this calculation in an arbitrary unit of time which maintains
201 * the maximum precision, i.e. such that one tick is 1.0e9 of these units,
202 * or close to the precision of a 32-bit int. We then divide by this unit
203 * (which doesn't lose precision) to get nanoseconds. For notation
204 * purposes, this unit is defined as ZHZ = zanoseconds per nanosecond.
206 * This sequence to do all this is in sysclk_gettime. For efficiency, this
207 * sequence also needs the value that the counter will have if it has just
208 * overflowed, so we precompute that also.
210 * The fix for certain really old certain platforms has been removed
211 * (specifically the DEC XL5100) have been observed to have problem
212 * with latching the counter, and they occasionally (say, one out of
213 * 100,000 times) return a bogus value. Hence, the present code reads
214 * the counter twice and checks for a consistent pair of values.
219 * } while ( val2 > val || val2 < val - 10 );
222 * Some attributes of the rt clock can be changed, including the
223 * interrupt resolution. We default to the minimum resolution (10 ms),
224 * but allow a finer resolution to be requested. The assumed frequency
225 * of the clock can also be set since it appears that the actual
226 * frequency of real-world hardware can vary from the nominal by
227 * 200 ppm or more. When the frequency is set, the values above are
228 * recomputed and we continue without resetting or changing anything else.
230 #define RTC_MINRES (NSEC_PER_SEC / HZ) /* nsec per tick */
231 #define RTC_MAXRES (RTC_MINRES / 20) /* nsec per tick */
232 #define ZANO (1000000000)
233 #define ZHZ (ZANO / (NSEC_PER_SEC / HZ))
234 #define READ_8254(val) { \
235 outb(PITCTL_PORT, PIT_C0); \
236 (val) = inb(PITCTR0_PORT); \
237 (val) |= inb(PITCTR0_PORT) << 8 ; }
239 #define UI_CPUFREQ_ROUNDING_FACTOR 10000000
246 void rtc_setvals( unsigned int, clock_res_t
);
248 static void rtc_set_cyc_per_sec();
250 /* define assembly routines */
254 * Inlines to get timestamp counter value.
257 inline static uint64_t
261 asm volatile("rdtsc": "=A" (result
));
265 // create_mul_quant_GHZ create a constant that can be used to multiply
266 // the TSC by to create nanoseconds. This is a 32 bit number
267 // and the TSC *MUST* have a frequency higher than 1000Mhz for this routine to work
269 // The theory here is that we know how many TSCs-per-sec the processor runs at. Normally to convert this
270 // to nanoseconds you would multiply the current time stamp by 1000000000 (a billion) then divide
271 // by TSCs-per-sec to get nanoseconds. Unfortunatly the TSC is 64 bits which would leave us with
272 // 96 bit intermediate results from the dultiply that must be divided by.
274 // uint96 = tsc * numer
275 // nanos = uint96 / denom
276 // Instead, we create this quant constant and it becomes the numerator, the denominator
277 // can then be 0x100000000 which makes our division as simple as forgetting the lower 32 bits
278 // of the result. We can also pass this number to user space as the numer and pass 0xFFFFFFFF
279 // as the denom to converting raw counts to nanos. the difference is so small as to be undetectable
281 // unfortunatly we can not do this for sub GHZ processors. In that case, all we do is pass the CPU
282 // speed in raw as the denom and we pass in 1000000000 as the numerator. No short cuts allowed
284 inline static uint32_t
285 create_mul_quant_GHZ(uint32_t quant
)
287 return (uint32_t)((50000000ULL << 32) / quant
);
290 // this routine takes a value of raw TSC ticks and applies the passed mul_quant
291 // generated by create_mul_quant() This is our internal routine for creating
293 // since we don't really have uint96_t this routine basically does this....
294 // uint96_t intermediate = (*value) * scale
295 // return (intermediate >> 32)
296 inline static uint64_t
297 fast_get_nano_from_abs(uint64_t value
, int scale
)
299 asm (" movl %%edx,%%esi \n\t"
301 " movl %%edx,%%edi \n\t"
302 " movl %%esi,%%eax \n\t"
304 " xorl %%ecx,%%ecx \n\t"
305 " addl %%edi,%%eax \n\t"
314 * this routine basically does this...
315 * ts.tv_sec = nanos / 1000000000; create seconds
316 * ts.tv_nsec = nanos % 1000000000; create remainder nanos
318 inline static mach_timespec_t
319 nanos_to_timespec(uint64_t nanos
)
326 asm volatile("divl %1" : "+A" (ret
.u64
) : "r" (NSEC_PER_SEC
));
330 // the following two routine perform the 96 bit arithmetic we need to
331 // convert generic absolute<->nanoseconds
332 // the multiply routine takes a uint64_t and a uint32_t and returns the result in a
333 // uint32_t[3] array. the dicide routine takes this uint32_t[3] array and
334 // divides it by a uint32_t returning a uint64_t
336 longmul(uint64_t *abstime
, uint32_t multiplicand
, uint32_t *result
)
340 " movl %%eax,%%ebx \n\t"
341 " movl (%%eax),%%eax \n\t"
343 " xchg %%eax,%%ebx \n\t"
345 " movl 4(%%eax),%%eax \n\t"
347 " movl %2,%%ecx \n\t"
348 " movl %%ebx,(%%ecx) \n\t"
350 " addl %%ebx,%%eax \n\t"
352 " movl %%eax,4(%%ecx) \n\t"
353 " adcl $0,%%edx \n\t"
354 " movl %%edx,8(%%ecx) // and save it"
355 : : "a"(abstime
), "c"(multiplicand
), "m"(result
));
359 inline static uint64_t
360 longdiv(uint32_t *numer
, uint32_t denom
)
365 " movl %%eax,%%ebx \n\t"
366 " movl 8(%%eax),%%edx \n\t"
367 " movl 4(%%eax),%%eax \n\t"
369 " xchg %%ebx,%%eax \n\t"
370 " movl (%%eax),%%eax \n\t"
372 " xchg %%ebx,%%edx \n\t"
374 : "=A"(result
) : "a"(numer
),"c"(denom
));
378 #define PIT_Mode4 0x08 /* turn on mode 4 one shot software trigger */
380 // Enable or disable timer 2.
386 " and $253,%%al \n\t"
388 " outb %%al,$97 \n\t"
397 " and $253,%%al \n\t"
398 " outb %%al,$97 \n\t"
402 // ctimeRDTSC() routine sets up counter 2 to count down 1/20 of a second
403 // it pauses until the value is latched in the counter
404 // and then reads the time stamp counter to return to the caller
406 // Code to calculate how many processor cycles are in a second...
410 // first, tell the clock we are going to write 16 bytes to the counter and enable one-shot mode
411 // then write the two bytes into the clock register.
412 // loop until the value is "realized" in the clock, this happens on the next tick
415 " movb $184,%%al \n\t"
416 " outb %%al,$67 \n\t"
417 " movb %%dl,%%al \n\t"
418 " outb %%al,$66 \n\t"
419 " movb %%dh,%%al \n\t"
421 "1: inb $66,%%al \n\t"
423 " cmp %%al,%%dh \n\t"
425 : : "d"(value
) : "%al");
428 inline static uint64_t
429 get_PIT2(unsigned int *value
)
431 // this routine first latches the time, then gets the time stamp so we know
432 // how long the read will take later. Reads
433 register uint64_t result
;
435 " xorl %%ecx,%%ecx \n\t"
436 " movb $128,%%al \n\t"
437 " outb %%al,$67 \n\t"
441 " movb %%al,%%cl \n\t"
443 " movb %%al,%%ch \n\t"
445 : "=A"(result
), "=c"(*value
));
453 uint64_t saveTime
,intermediate
;
454 unsigned int timerValue
,x
;
455 boolean_t int_enabled
;
456 uint64_t fact
[6] = { 2000011734ll,
463 int_enabled
= ml_set_interrupts_enabled(FALSE
);
465 enable_PIT2(); // turn on PIT2
466 set_PIT2(0); // reset timer 2 to be zero
467 latchTime
= rdtsc_64(); // get the time stamp to time
468 latchTime
= get_PIT2(&timerValue
) - latchTime
; // time how long this takes
469 set_PIT2(59658); // set up the timer to count 1/20th a second
470 saveTime
= rdtsc_64(); // now time how ling a 20th a second is...
472 do { get_PIT2(&timerValue
); x
= timerValue
;} while (timerValue
> x
);
474 intermediate
= get_PIT2(&timerValue
);
475 if (timerValue
>x
) printf("Hey we are going backwards! %d, %d\n",timerValue
,x
);
477 } while ((timerValue
!= 0) && (timerValue
>5));
478 printf("Timer value:%d\n",timerValue
);
479 printf("intermediate 0x%08x:0x%08x\n",intermediate
);
480 printf("saveTime 0x%08x:0x%08x\n",saveTime
);
482 intermediate
= intermediate
- saveTime
; // raw # of tsc's it takes for about 1/20 second
483 intermediate
= intermediate
* fact
[timerValue
]; // actual time spent
484 intermediate
= intermediate
/ 2000000000ll; // rescale so its exactly 1/20 a second
485 intermediate
= intermediate
+ latchTime
; // add on our save fudge
486 set_PIT2(0); // reset timer 2 to be zero
487 disable_PIT2(0); // turn off PIT 2
488 ml_set_interrupts_enabled(int_enabled
);
493 rdtsctime_to_nanoseconds( void )
499 uint32_t intermediate
[3];
501 numer
= rtclock
.timebase_const
.numer
;
502 denom
= rtclock
.timebase_const
.denom
;
503 abstime
= rdtsc_64();
504 if (denom
== 0xFFFFFFFF) {
505 abstime
= fast_get_nano_from_abs(abstime
, numer
);
507 longmul(&abstime
, numer
, intermediate
);
508 abstime
= longdiv(intermediate
, denom
);
513 inline static mach_timespec_t
514 rdtsc_to_timespec(void)
517 currNanos
= rdtsctime_to_nanoseconds();
518 return nanos_to_timespec(currNanos
);
522 * Initialize non-zero clock structure values.
526 unsigned int new_clknum
,
530 unsigned int timeperclk
;
536 rtc_intr_freq
= (NSEC_PER_SEC
/ new_ires
);
537 rtc_intr_hertz
= rtc_intr_freq
/ HZ
;
538 clks_per_int
= (clknum
+ (rtc_intr_freq
/ 2)) / rtc_intr_freq
;
539 clks_per_int_99
= clks_per_int
- clks_per_int
/100;
542 * The following calculations are done with scaling integer operations
543 * in order that the integer results are accurate to the lsb.
545 timeperclk
= div_scale(ZANO
, clknum
, &scale0
); /* 838.105647 nsec */
547 time_per_clk
= mul_scale(ZHZ
, timeperclk
, &scale1
); /* 83810 */
549 time_per_clk
>>= (scale0
- scale1
);
550 else if (scale0
< scale1
)
551 panic("rtc_clock: time_per_clk overflow\n");
554 * Notice that rtclock.intr_nsec is signed ==> use unsigned int res
556 res
= mul_scale(clks_per_int
, timeperclk
, &scale1
); /* 10000276 */
558 rtclock
.intr_nsec
= res
>> (scale0
- scale1
);
560 panic("rtc_clock: rtclock.intr_nsec overflow\n");
563 RtcDelt
= rtclock
.intr_nsec
/2;
567 * Configure the real-time clock device. Return success (1)
578 mp_disable_preemption();
579 if (cpu_number() != master_cpu
) {
580 mp_enable_preemption();
583 mp_enable_preemption();
588 pic
= 0; /* FIXME .. interrupt registration moved to AppleIntelClock */
592 * We should attempt to test the real-time clock
593 * device here. If it were to fail, we should panic
596 RtcFlag
= /* test device */1;
597 printf("realtime clock configured\n");
599 simple_lock_init(&rtclock
.lock
, ETAP_NO_TRACE
);
604 * Initialize the real-time clock device. Return success (1)
605 * or failure (0). Since the real-time clock is required to
606 * provide canonical mapped time, we allocate a page to keep
607 * the clock time value. In addition, various variables used
608 * to support the clock are initialized. Note: the clock is
609 * not started until rtclock_reset is called.
616 mp_disable_preemption();
617 if (cpu_number() != master_cpu
) {
618 mp_enable_preemption();
621 mp_enable_preemption();
624 RtcTime
= &rtclock
.time
;
625 rtc_setvals( CLKNUM
, RTC_MINRES
); /* compute constants */
626 rtc_set_cyc_per_sec(); /* compute number of tsc beats per second */
627 clock_timebase_init();
631 static volatile unsigned int last_ival
= 0;
634 * Get the clock device time. This routine is responsible
635 * for converting the device's machine dependent time value
636 * into a canonical mach_timespec_t value.
640 mach_timespec_t
*cur_time
) /* OUT */
644 cur_time
->tv_nsec
= 0;
645 cur_time
->tv_sec
= 0;
646 return (KERN_SUCCESS
);
649 *cur_time
= rdtsc_to_timespec();
650 return (KERN_SUCCESS
);
654 sysclk_gettime_internal(
655 mach_timespec_t
*cur_time
) /* OUT */
659 cur_time
->tv_nsec
= 0;
660 cur_time
->tv_sec
= 0;
661 return (KERN_SUCCESS
);
663 *cur_time
= rdtsc_to_timespec();
664 return (KERN_SUCCESS
);
668 * Get the clock device time when ALL interrupts are already disabled.
669 * Same as above except for turning interrupts off and on.
670 * This routine is responsible for converting the device's machine dependent
671 * time value into a canonical mach_timespec_t value.
674 sysclk_gettime_interrupts_disabled(
675 mach_timespec_t
*cur_time
) /* OUT */
679 cur_time
->tv_nsec
= 0;
680 cur_time
->tv_sec
= 0;
683 *cur_time
= rdtsc_to_timespec();
687 // Code to calculate how many processor cycles are in a second...
690 rtc_set_cyc_per_sec()
693 uint32_t twen_cycles
;
696 twen_cycles
= timeRDTSC();
697 if (twen_cycles
> (1000000000/20)) {
698 // we create this value so that you can use just a "fast" multiply to get nanos
699 rtc_quant_scale
= create_mul_quant_GHZ(twen_cycles
);
700 rtclock
.timebase_const
.numer
= rtc_quant_scale
; // because ctimeRDTSC gives us 1/20 a seconds worth
701 rtclock
.timebase_const
.denom
= 0xffffffff; // so that nanoseconds = (TSC * numer) / denom
704 rtclock
.timebase_const
.numer
= 1000000000/20; // because ctimeRDTSC gives us 1/20 a seconds worth
705 rtclock
.timebase_const
.denom
= twen_cycles
; // so that nanoseconds = (TSC * numer) / denom
707 cycles
= twen_cycles
; // number of cycles in 1/20th a second
708 rtc_cyc_per_sec
= cycles
*20; // multiply it by 20 and we are done.. BUT we also want to calculate...
710 cycles
= ((rtc_cyc_per_sec
+ UI_CPUFREQ_ROUNDING_FACTOR
- 1) / UI_CPUFREQ_ROUNDING_FACTOR
) * UI_CPUFREQ_ROUNDING_FACTOR
;
711 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= cycles
;
712 DISPLAYVALUE(rtc_set_cyc_per_sec
,rtc_cyc_per_sec
);
713 DISPLAYEXIT(rtc_set_cyc_per_sec
);
717 clock_get_system_microtime(
723 sysclk_gettime(&now
);
726 *microsecs
= now
.tv_nsec
/ NSEC_PER_USEC
;
730 clock_get_system_nanotime(
736 sysclk_gettime(&now
);
739 *nanosecs
= now
.tv_nsec
;
743 * Get clock device attributes.
747 clock_flavor_t flavor
,
748 clock_attr_t attr
, /* OUT */
749 mach_msg_type_number_t
*count
) /* IN/OUT */
754 return (KERN_FAILURE
);
757 case CLOCK_GET_TIME_RES
: /* >0 res */
760 *(clock_res_t
*) attr
= 1000;
763 #endif /* (NCPUS == 1) */
764 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
766 *(clock_res_t
*) attr
= rtclock
.intr_nsec
;
770 case CLOCK_ALARM_MAXRES
:
771 *(clock_res_t
*) attr
= RTC_MAXRES
;
774 case CLOCK_ALARM_MINRES
:
775 *(clock_res_t
*) attr
= RTC_MINRES
;
779 return (KERN_INVALID_VALUE
);
781 return (KERN_SUCCESS
);
785 * Set clock device attributes.
789 clock_flavor_t flavor
,
790 clock_attr_t attr
, /* IN */
791 mach_msg_type_number_t count
) /* IN */
796 clock_res_t new_ires
;
799 return (KERN_FAILURE
);
802 case CLOCK_GET_TIME_RES
:
803 case CLOCK_ALARM_MAXRES
:
804 case CLOCK_ALARM_MINRES
:
805 return (KERN_FAILURE
);
807 case CLOCK_ALARM_CURRES
:
808 new_ires
= *(clock_res_t
*) attr
;
811 * The new resolution must be within the predetermined
812 * range. If the desired resolution cannot be achieved
813 * to within 0.1%, an error is returned.
815 if (new_ires
< RTC_MAXRES
|| new_ires
> RTC_MINRES
)
816 return (KERN_INVALID_VALUE
);
817 freq
= (NSEC_PER_SEC
/ new_ires
);
818 adj
= (((clknum
% freq
) * new_ires
) / clknum
);
819 if (adj
> (new_ires
/ 1000))
820 return (KERN_INVALID_VALUE
);
822 * Record the new alarm resolution which will take effect
823 * on the next HZ aligned clock tick.
826 if ( freq
!= rtc_intr_freq
) {
827 rtclock
.new_ires
= new_ires
;
831 return (KERN_SUCCESS
);
834 return (KERN_INVALID_VALUE
);
839 * Set next alarm time for the clock device. This call
840 * always resets the time to deliver an alarm for the
845 mach_timespec_t
*alarm_time
)
850 rtclock
.alarm_time
= *alarm_time
;
851 RtcAlrm
= &rtclock
.alarm_time
;
856 * Configure the calendar clock.
865 * Initialize calendar clock.
874 * Get the current clock time.
878 mach_timespec_t
*cur_time
) /* OUT */
883 if (!rtclock
.calend_is_set
) {
885 return (KERN_FAILURE
);
888 (void) sysclk_gettime_internal(cur_time
);
889 ADD_MACH_TIMESPEC(cur_time
, &rtclock
.calend_offset
);
892 return (KERN_SUCCESS
);
896 clock_get_calendar_microtime(
902 calend_gettime(&now
);
905 *microsecs
= now
.tv_nsec
/ NSEC_PER_USEC
;
909 clock_get_calendar_nanotime(
915 calend_gettime(&now
);
918 *nanosecs
= now
.tv_nsec
;
922 clock_set_calendar_microtime(
926 mach_timespec_t new_time
, curr_time
;
930 (void) sysclk_gettime_internal(&curr_time
);
931 rtclock
.calend_offset
.tv_sec
= new_time
.tv_sec
= secs
;
932 rtclock
.calend_offset
.tv_nsec
= new_time
.tv_nsec
= microsecs
* NSEC_PER_USEC
;
933 SUB_MACH_TIMESPEC(&rtclock
.calend_offset
, &curr_time
);
934 rtclock
.calend_is_set
= TRUE
;
937 (void) bbc_settime(&new_time
);
939 host_notify_calendar_change();
943 * Get clock device attributes.
947 clock_flavor_t flavor
,
948 clock_attr_t attr
, /* OUT */
949 mach_msg_type_number_t
*count
) /* IN/OUT */
954 return (KERN_FAILURE
);
957 case CLOCK_GET_TIME_RES
: /* >0 res */
960 *(clock_res_t
*) attr
= 1000;
963 #else /* (NCPUS == 1) */
965 *(clock_res_t
*) attr
= rtclock
.intr_nsec
;
968 #endif /* (NCPUS == 1) */
970 case CLOCK_ALARM_CURRES
: /* =0 no alarm */
971 case CLOCK_ALARM_MINRES
:
972 case CLOCK_ALARM_MAXRES
:
973 *(clock_res_t
*) attr
= 0;
977 return (KERN_INVALID_VALUE
);
979 return (KERN_SUCCESS
);
982 #define tickadj (40*NSEC_PER_USEC) /* "standard" skew, ns / tick */
983 #define bigadj (NSEC_PER_SEC) /* use 10x skew above bigadj ns */
986 clock_set_calendar_adjtime(
990 int64_t total
, ototal
;
991 uint32_t interval
= 0;
994 total
= (int64_t)*secs
* NSEC_PER_SEC
+ *microsecs
* NSEC_PER_USEC
;
997 ototal
= rtclock
.calend_adjtotal
;
1000 int32_t delta
= tickadj
;
1009 if (total
< -bigadj
)
1016 rtclock
.calend_adjtotal
= total
;
1017 rtclock
.calend_adjdelta
= delta
;
1019 interval
= (NSEC_PER_SEC
/ HZ
);
1022 rtclock
.calend_adjdelta
= rtclock
.calend_adjtotal
= 0;
1027 *secs
= *microsecs
= 0;
1029 *secs
= ototal
/ NSEC_PER_SEC
;
1030 *microsecs
= ototal
% NSEC_PER_SEC
;
1037 clock_adjust_calendar(void)
1039 uint32_t interval
= 0;
1044 delta
= rtclock
.calend_adjdelta
;
1045 ADD_MACH_TIMESPEC_NSEC(&rtclock
.calend_offset
, delta
);
1047 rtclock
.calend_adjtotal
-= delta
;
1050 if (delta
> rtclock
.calend_adjtotal
)
1051 rtclock
.calend_adjdelta
= rtclock
.calend_adjtotal
;
1055 if (delta
< rtclock
.calend_adjtotal
)
1056 rtclock
.calend_adjdelta
= rtclock
.calend_adjtotal
;
1059 if (rtclock
.calend_adjdelta
!= 0)
1060 interval
= (NSEC_PER_SEC
/ HZ
);
1068 clock_initialize_calendar(void)
1070 mach_timespec_t bbc_time
, curr_time
;
1073 if (bbc_gettime(&bbc_time
) != KERN_SUCCESS
)
1077 if (!rtclock
.calend_is_set
) {
1078 (void) sysclk_gettime_internal(&curr_time
);
1079 rtclock
.calend_offset
= bbc_time
;
1080 SUB_MACH_TIMESPEC(&rtclock
.calend_offset
, &curr_time
);
1081 rtclock
.calend_is_set
= TRUE
;
1085 host_notify_calendar_change();
1089 clock_timebase_info(
1090 mach_timebase_info_t info
)
1095 if (rtclock
.timebase_const
.denom
== 0xFFFFFFFF) {
1096 info
->numer
= info
->denom
= rtc_quant_scale
;
1098 info
->numer
= info
->denom
= 1;
1104 clock_set_timer_deadline(
1110 rtclock
.timer_deadline
= deadline
;
1111 rtclock
.timer_is_set
= TRUE
;
1116 clock_set_timer_func(
1117 clock_timer_func_t func
)
1122 if (rtclock
.timer_expire
== NULL
)
1123 rtclock
.timer_expire
= func
;
1130 * Load the count register and start the clock.
1132 #define RTCLOCK_RESET() { \
1133 outb(PITCTL_PORT, PIT_C0|PIT_NDIVMODE|PIT_READMODE); \
1134 outb(PITCTR0_PORT, (clks_per_int & 0xff)); \
1135 outb(PITCTR0_PORT, (clks_per_int >> 8)); \
1139 * Reset the clock device. This causes the realtime clock
1140 * device to reload its mode and count value (frequency).
1141 * Note: the CPU should be calibrated
1142 * before starting the clock for the first time.
1151 mp_disable_preemption();
1152 if (cpu_number() != master_cpu
) {
1153 mp_enable_preemption();
1156 mp_enable_preemption();
1157 #endif /* NCPUS > 1 */
1164 * Real-time clock device interrupt. Called only on the
1165 * master processor. Updates the clock time and upcalls
1166 * into the higher level clock code to deliver alarms.
1169 rtclock_intr(struct i386_interrupt_state
*regs
)
1172 mach_timespec_t clock_time
;
1178 * Update clock time. Do the update so that the macro
1179 * MTS_TO_TS() for reading the mapped time works (e.g.
1180 * update in order: mtv_csec, mtv_time.tv_nsec, mtv_time.tv_sec).
1183 abstime
= rdtsctime_to_nanoseconds(); // get the time as of the TSC
1184 clock_time
= nanos_to_timespec(abstime
); // turn it into a timespec
1185 rtclock
.time
.tv_nsec
= clock_time
.tv_nsec
;
1186 rtclock
.time
.tv_sec
= clock_time
.tv_sec
;
1187 rtclock
.abstime
= abstime
;
1189 /* note time now up to date */
1193 * On a HZ-tick boundary: return 0 and adjust the clock
1194 * alarm resolution (if requested). Otherwise return a
1197 if ((i
= --rtc_intr_count
) == 0) {
1198 if (rtclock
.new_ires
) {
1199 rtc_setvals(new_clknum
, rtclock
.new_ires
);
1200 RTCLOCK_RESET(); /* lock clock register */
1201 rtclock
.new_ires
= 0;
1203 rtc_intr_count
= rtc_intr_hertz
;
1205 usermode
= (regs
->efl
& EFL_VM
) || ((regs
->cs
& 0x03) != 0);
1206 hertz_tick(usermode
, regs
->eip
);
1210 if ( rtclock
.timer_is_set
&&
1211 rtclock
.timer_deadline
<= abstime
) {
1212 rtclock
.timer_is_set
= FALSE
;
1215 (*rtclock
.timer_expire
)(abstime
);
1221 * Perform alarm clock processing if needed. The time
1222 * passed up is incremented by a half-interrupt tick
1223 * to trigger alarms closest to their desired times.
1224 * The clock_alarm_intr() routine calls sysclk_setalrm()
1225 * before returning if later alarms are pending.
1228 if (RtcAlrm
&& (RtcAlrm
->tv_sec
< RtcTime
->tv_sec
||
1229 (RtcAlrm
->tv_sec
== RtcTime
->tv_sec
&&
1230 RtcDelt
>= RtcAlrm
->tv_nsec
- RtcTime
->tv_nsec
))) {
1231 clock_time
.tv_sec
= 0;
1232 clock_time
.tv_nsec
= RtcDelt
;
1233 ADD_MACH_TIMESPEC (&clock_time
, RtcTime
);
1237 * Call clock_alarm_intr() without RTC-lock.
1238 * The lock ordering is always CLOCK-lock
1241 clock_alarm_intr(SYSTEM_CLOCK
, &clock_time
);
1253 *result
= rdtsctime_to_nanoseconds();
1257 mach_absolute_time(void)
1259 return rdtsctime_to_nanoseconds();
1263 clock_interval_to_deadline(
1265 uint32_t scale_factor
,
1270 clock_get_uptime(result
);
1272 clock_interval_to_absolutetime_interval(interval
, scale_factor
, &abstime
);
1278 clock_interval_to_absolutetime_interval(
1280 uint32_t scale_factor
,
1283 *result
= (uint64_t)interval
* scale_factor
;
1287 clock_absolutetime_interval_to_deadline(
1291 clock_get_uptime(result
);
1297 absolutetime_to_nanoseconds(
1305 nanoseconds_to_absolutetime(
1306 uint64_t nanoseconds
,
1309 *result
= nanoseconds
;
1313 * Spin-loop delay primitives.
1318 uint32_t scale_factor
)
1322 clock_interval_to_deadline(interval
, scale_factor
, &end
);
1326 now
= mach_absolute_time();
1327 } while (now
< end
);
1338 now
= mach_absolute_time();
1339 } while (now
< deadline
);
1346 delay_for_interval((usec
< 0)? -usec
: usec
, NSEC_PER_USEC
);