]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/rtclock.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / osfmk / i386 / rtclock.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25
26/*
27 * File: i386/rtclock.c
28 * Purpose: Routines for handling the machine dependent
29 * real-time clock. This clock is generated by
30 * the Intel 8254 Programmable Interval Timer.
31 */
32
33#include <cpus.h>
34#include <platforms.h>
1c79356b 35#include <mach_kdb.h>
55e303ae
A
36
37#include <mach/mach_types.h>
38
1c79356b
A
39#include <kern/cpu_number.h>
40#include <kern/cpu_data.h>
41#include <kern/clock.h>
55e303ae 42#include <kern/host_notify.h>
1c79356b
A
43#include <kern/macro_help.h>
44#include <kern/misc_protos.h>
45#include <kern/spl.h>
46#include <machine/mach_param.h> /* HZ */
47#include <mach/vm_prot.h>
48#include <vm/pmap.h>
49#include <vm/vm_kern.h> /* for kernel_map */
50#include <i386/ipl.h>
51#include <i386/pit.h>
52#include <i386/pio.h>
53#include <i386/misc_protos.h>
54#include <i386/rtclock_entries.h>
55#include <i386/hardclock_entries.h>
55e303ae
A
56#include <i386/proc_reg.h>
57#include <i386/machine_cpu.h>
58#include <pexpert/pexpert.h>
59
60#define DISPLAYENTER(x) printf("[RTCLOCK] entering " #x "\n");
61#define DISPLAYEXIT(x) printf("[RTCLOCK] leaving " #x "\n");
62#define DISPLAYVALUE(x,y) printf("[RTCLOCK] " #x ":" #y " = 0x%08x \n",y);
1c79356b
A
63
64int sysclk_config(void);
65
66int sysclk_init(void);
67
68kern_return_t sysclk_gettime(
69 mach_timespec_t *cur_time);
70
71kern_return_t sysclk_getattr(
72 clock_flavor_t flavor,
73 clock_attr_t attr,
74 mach_msg_type_number_t *count);
75
76kern_return_t sysclk_setattr(
77 clock_flavor_t flavor,
78 clock_attr_t attr,
79 mach_msg_type_number_t count);
80
81void sysclk_setalarm(
82 mach_timespec_t *alarm_time);
83
84extern void (*IOKitRegisterInterruptHook)(void *, int irq, int isclock);
85
86/*
87 * Lists of clock routines.
88 */
89struct clock_ops sysclk_ops = {
90 sysclk_config, sysclk_init,
91 sysclk_gettime, 0,
92 sysclk_getattr, sysclk_setattr,
93 sysclk_setalarm,
94};
95
96int calend_config(void);
97
98int calend_init(void);
99
100kern_return_t calend_gettime(
101 mach_timespec_t *cur_time);
102
1c79356b
A
103kern_return_t calend_getattr(
104 clock_flavor_t flavor,
105 clock_attr_t attr,
106 mach_msg_type_number_t *count);
107
108struct clock_ops calend_ops = {
109 calend_config, calend_init,
55e303ae 110 calend_gettime, 0,
1c79356b
A
111 calend_getattr, 0,
112 0,
113};
114
115/* local data declarations */
116mach_timespec_t *RtcTime = (mach_timespec_t *)0;
117mach_timespec_t *RtcAlrm;
118clock_res_t RtcDelt;
119
120/* global data declarations */
121struct {
0b4e3aa0 122 uint64_t abstime;
1c79356b
A
123
124 mach_timespec_t time;
125 mach_timespec_t alarm_time; /* time of next alarm */
126
127 mach_timespec_t calend_offset;
128 boolean_t calend_is_set;
129
55e303ae
A
130 int64_t calend_adjtotal;
131 int32_t calend_adjdelta;
132
0b4e3aa0 133 uint64_t timer_deadline;
1c79356b
A
134 boolean_t timer_is_set;
135 clock_timer_func_t timer_expire;
136
137 clock_res_t new_ires; /* pending new resolution (nano ) */
138 clock_res_t intr_nsec; /* interrupt resolution (nano) */
55e303ae 139 mach_timebase_info_data_t timebase_const;
1c79356b
A
140
141 decl_simple_lock_data(,lock) /* real-time clock device lock */
142} rtclock;
143
144unsigned int clknum; /* clks per second */
145unsigned int new_clknum; /* pending clknum */
146unsigned int time_per_clk; /* time per clk in ZHZ */
147unsigned int clks_per_int; /* clks per interrupt */
148unsigned int clks_per_int_99;
55e303ae
A
149int rtc_intr_count; /* interrupt counter */
150int rtc_intr_hertz; /* interrupts per HZ */
151int rtc_intr_freq; /* interrupt frequency */
152int rtc_print_lost_tick; /* print lost tick */
1c79356b 153
9bccf70c 154uint32_t rtc_cyc_per_sec; /* processor cycles per seconds */
55e303ae 155uint32_t rtc_quant_scale; /* used internally to convert clocks to nanos */
9bccf70c 156
1c79356b
A
157/*
158 * Macros to lock/unlock real-time clock device.
159 */
160#define LOCK_RTC(s) \
161MACRO_BEGIN \
162 (s) = splclock(); \
163 simple_lock(&rtclock.lock); \
164MACRO_END
165
166#define UNLOCK_RTC(s) \
167MACRO_BEGIN \
168 simple_unlock(&rtclock.lock); \
169 splx(s); \
170MACRO_END
171
172/*
173 * i8254 control. ** MONUMENT **
174 *
175 * The i8254 is a traditional PC device with some arbitrary characteristics.
176 * Basically, it is a register that counts at a fixed rate and can be
177 * programmed to generate an interrupt every N counts. The count rate is
178 * clknum counts per second (see pit.h), historically 1193167 we believe.
179 * Various constants are computed based on this value, and we calculate
180 * them at init time for execution efficiency. To obtain sufficient
181 * accuracy, some of the calculation are most easily done in floating
182 * point and then converted to int.
183 *
184 * We want an interrupt every 10 milliseconds, approximately. The count
185 * which will do that is clks_per_int. However, that many counts is not
186 * *exactly* 10 milliseconds; it is a bit more or less depending on
187 * roundoff. The actual time per tick is calculated and saved in
188 * rtclock.intr_nsec, and it is that value which is added to the time
189 * register on each tick.
190 *
191 * The i8254 counter can be read between interrupts in order to determine
192 * the time more accurately. The counter counts down from the preset value
193 * toward 0, and we have to handle the case where the counter has been
194 * reset just before being read and before the interrupt has been serviced.
195 * Given a count since the last interrupt, the time since then is given
196 * by (count * time_per_clk). In order to minimize integer truncation,
197 * we perform this calculation in an arbitrary unit of time which maintains
198 * the maximum precision, i.e. such that one tick is 1.0e9 of these units,
199 * or close to the precision of a 32-bit int. We then divide by this unit
200 * (which doesn't lose precision) to get nanoseconds. For notation
201 * purposes, this unit is defined as ZHZ = zanoseconds per nanosecond.
202 *
203 * This sequence to do all this is in sysclk_gettime. For efficiency, this
204 * sequence also needs the value that the counter will have if it has just
55e303ae
A
205 * overflowed, so we precompute that also.
206 *
207 * The fix for certain really old certain platforms has been removed
1c79356b
A
208 * (specifically the DEC XL5100) have been observed to have problem
209 * with latching the counter, and they occasionally (say, one out of
210 * 100,000 times) return a bogus value. Hence, the present code reads
211 * the counter twice and checks for a consistent pair of values.
55e303ae
A
212 * the code was:
213 * do {
214 * READ_8254(val);
215 * READ_8254(val2);
216 * } while ( val2 > val || val2 < val - 10 );
217 *
1c79356b
A
218 *
219 * Some attributes of the rt clock can be changed, including the
220 * interrupt resolution. We default to the minimum resolution (10 ms),
221 * but allow a finer resolution to be requested. The assumed frequency
222 * of the clock can also be set since it appears that the actual
223 * frequency of real-world hardware can vary from the nominal by
224 * 200 ppm or more. When the frequency is set, the values above are
225 * recomputed and we continue without resetting or changing anything else.
226 */
227#define RTC_MINRES (NSEC_PER_SEC / HZ) /* nsec per tick */
228#define RTC_MAXRES (RTC_MINRES / 20) /* nsec per tick */
229#define ZANO (1000000000)
230#define ZHZ (ZANO / (NSEC_PER_SEC / HZ))
231#define READ_8254(val) { \
232 outb(PITCTL_PORT, PIT_C0); \
233 (val) = inb(PITCTR0_PORT); \
234 (val) |= inb(PITCTR0_PORT) << 8 ; }
235
55e303ae
A
236#define UI_CPUFREQ_ROUNDING_FACTOR 10000000
237
1c79356b
A
238
239/*
240 * Forward decl.
241 */
242
1c79356b
A
243void rtc_setvals( unsigned int, clock_res_t );
244
9bccf70c
A
245static void rtc_set_cyc_per_sec();
246
55e303ae
A
247/* define assembly routines */
248
249
250/*
251 * Inlines to get timestamp counter value.
252 */
253
254inline static uint64_t
255rdtsc_64(void)
256{
257 uint64_t result;
258 asm volatile("rdtsc": "=A" (result));
259 return result;
260}
261
262// create_mul_quant_GHZ create a constant that can be used to multiply
263// the TSC by to create nanoseconds. This is a 32 bit number
264// and the TSC *MUST* have a frequency higher than 1000Mhz for this routine to work
265//
266// The theory here is that we know how many TSCs-per-sec the processor runs at. Normally to convert this
267// to nanoseconds you would multiply the current time stamp by 1000000000 (a billion) then divide
268// by TSCs-per-sec to get nanoseconds. Unfortunatly the TSC is 64 bits which would leave us with
269// 96 bit intermediate results from the dultiply that must be divided by.
270// usually thats
271// uint96 = tsc * numer
272// nanos = uint96 / denom
273// Instead, we create this quant constant and it becomes the numerator, the denominator
274// can then be 0x100000000 which makes our division as simple as forgetting the lower 32 bits
275// of the result. We can also pass this number to user space as the numer and pass 0xFFFFFFFF
276// as the denom to converting raw counts to nanos. the difference is so small as to be undetectable
277// by anything.
278// unfortunatly we can not do this for sub GHZ processors. In that case, all we do is pass the CPU
279// speed in raw as the denom and we pass in 1000000000 as the numerator. No short cuts allowed
280
281inline static uint32_t
282create_mul_quant_GHZ(uint32_t quant)
283{
284 return (uint32_t)((50000000ULL << 32) / quant);
285}
286
287// this routine takes a value of raw TSC ticks and applies the passed mul_quant
288// generated by create_mul_quant() This is our internal routine for creating
289// nanoseconds
290// since we don't really have uint96_t this routine basically does this....
291// uint96_t intermediate = (*value) * scale
292// return (intermediate >> 32)
293inline static uint64_t
294fast_get_nano_from_abs(uint64_t value, int scale)
295{
296 asm (" movl %%edx,%%esi \n\t"
297 " mull %%ecx \n\t"
298 " movl %%edx,%%edi \n\t"
299 " movl %%esi,%%eax \n\t"
300 " mull %%ecx \n\t"
301 " xorl %%ecx,%%ecx \n\t"
302 " addl %%edi,%%eax \n\t"
303 " adcl %%ecx,%%edx "
304 : "+A" (value)
305 : "c" (scale)
306 : "%esi", "%edi");
307 return value;
308}
309
310/*
311 * this routine basically does this...
312 * ts.tv_sec = nanos / 1000000000; create seconds
313 * ts.tv_nsec = nanos % 1000000000; create remainder nanos
314 */
315inline static mach_timespec_t
316nanos_to_timespec(uint64_t nanos)
317{
318 union {
319 mach_timespec_t ts;
320 uint64_t u64;
321 } ret;
322 ret.u64 = nanos;
323 asm volatile("divl %1" : "+A" (ret.u64) : "r" (NSEC_PER_SEC));
324 return ret.ts;
325}
326
327// the following two routine perform the 96 bit arithmetic we need to
328// convert generic absolute<->nanoseconds
329// the multiply routine takes a uint64_t and a uint32_t and returns the result in a
330// uint32_t[3] array. the dicide routine takes this uint32_t[3] array and
331// divides it by a uint32_t returning a uint64_t
332inline static void
333longmul(uint64_t *abstime, uint32_t multiplicand, uint32_t *result)
334{
335 asm volatile(
336 " pushl %%ebx \n\t"
337 " movl %%eax,%%ebx \n\t"
338 " movl (%%eax),%%eax \n\t"
339 " mull %%ecx \n\t"
340 " xchg %%eax,%%ebx \n\t"
341 " pushl %%edx \n\t"
342 " movl 4(%%eax),%%eax \n\t"
343 " mull %%ecx \n\t"
344 " movl %2,%%ecx \n\t"
345 " movl %%ebx,(%%ecx) \n\t"
346 " popl %%ebx \n\t"
347 " addl %%ebx,%%eax \n\t"
348 " popl %%ebx \n\t"
349 " movl %%eax,4(%%ecx) \n\t"
350 " adcl $0,%%edx \n\t"
351 " movl %%edx,8(%%ecx) // and save it"
352 : : "a"(abstime), "c"(multiplicand), "m"(result));
353
354}
355
356inline static uint64_t
357longdiv(uint32_t *numer, uint32_t denom)
358{
359 uint64_t result;
360 asm volatile(
361 " pushl %%ebx \n\t"
362 " movl %%eax,%%ebx \n\t"
363 " movl 8(%%eax),%%edx \n\t"
364 " movl 4(%%eax),%%eax \n\t"
365 " divl %%ecx \n\t"
366 " xchg %%ebx,%%eax \n\t"
367 " movl (%%eax),%%eax \n\t"
368 " divl %%ecx \n\t"
369 " xchg %%ebx,%%edx \n\t"
370 " popl %%ebx \n\t"
371 : "=A"(result) : "a"(numer),"c"(denom));
372 return result;
373}
374
375#define PIT_Mode4 0x08 /* turn on mode 4 one shot software trigger */
376
377// Enable or disable timer 2.
378inline static void
379enable_PIT2()
380{
381 asm volatile(
382 " inb $97,%%al \n\t"
383 " and $253,%%al \n\t"
384 " or $1,%%al \n\t"
385 " outb %%al,$97 \n\t"
386 : : : "%al" );
387}
388
389inline static void
390disable_PIT2()
391{
392 asm volatile(
393 " inb $97,%%al \n\t"
394 " and $253,%%al \n\t"
395 " outb %%al,$97 \n\t"
396 : : : "%al" );
397}
398
399// ctimeRDTSC() routine sets up counter 2 to count down 1/20 of a second
400// it pauses until the value is latched in the counter
401// and then reads the time stamp counter to return to the caller
402// utility routine
403// Code to calculate how many processor cycles are in a second...
404inline static void
405set_PIT2(int value)
406{
407// first, tell the clock we are going to write 16 bytes to the counter and enable one-shot mode
408// then write the two bytes into the clock register.
409// loop until the value is "realized" in the clock, this happens on the next tick
410//
411 asm volatile(
412 " movb $184,%%al \n\t"
413 " outb %%al,$67 \n\t"
414 " movb %%dl,%%al \n\t"
415 " outb %%al,$66 \n\t"
416 " movb %%dh,%%al \n\t"
417 " outb %%al,$66 \n"
418"1: inb $66,%%al \n\t"
419 " inb $66,%%al \n\t"
420 " cmp %%al,%%dh \n\t"
421 " jne 1b"
422 : : "d"(value) : "%al");
423}
424
425inline static uint64_t
426get_PIT2(unsigned int *value)
427{
428// this routine first latches the time, then gets the time stamp so we know
429// how long the read will take later. Reads
430 register uint64_t result;
431 asm volatile(
432 " xorl %%ecx,%%ecx \n\t"
433 " movb $128,%%al \n\t"
434 " outb %%al,$67 \n\t"
435 " rdtsc \n\t"
436 " pushl %%eax \n\t"
437 " inb $66,%%al \n\t"
438 " movb %%al,%%cl \n\t"
439 " inb $66,%%al \n\t"
440 " movb %%al,%%ch \n\t"
441 " popl %%eax "
442 : "=A"(result), "=c"(*value));
443 return result;
444}
445
446static uint32_t
447timeRDTSC(void)
448{
449 uint64_t latchTime;
450 uint64_t saveTime,intermediate;
451 unsigned int timerValue,x;
452 boolean_t int_enabled;
453 uint64_t fact[6] = { 2000011734ll,
454 2000045259ll,
455 2000078785ll,
456 2000112312ll,
457 2000145841ll,
458 2000179371ll};
459
460 int_enabled = ml_set_interrupts_enabled(FALSE);
461
462 enable_PIT2(); // turn on PIT2
463 set_PIT2(0); // reset timer 2 to be zero
464 latchTime = rdtsc_64(); // get the time stamp to time
465 latchTime = get_PIT2(&timerValue) - latchTime; // time how long this takes
466 set_PIT2(59658); // set up the timer to count 1/20th a second
467 saveTime = rdtsc_64(); // now time how ling a 20th a second is...
468 get_PIT2(&x);
469 do { get_PIT2(&timerValue); x = timerValue;} while (timerValue > x);
470 do {
471 intermediate = get_PIT2(&timerValue);
472 if (timerValue>x) printf("Hey we are going backwards! %d, %d\n",timerValue,x);
473 x = timerValue;
474 } while ((timerValue != 0) && (timerValue >5));
475 printf("Timer value:%d\n",timerValue);
476 printf("intermediate 0x%08x:0x%08x\n",intermediate);
477 printf("saveTime 0x%08x:0x%08x\n",saveTime);
478
479 intermediate = intermediate - saveTime; // raw # of tsc's it takes for about 1/20 second
480 intermediate = intermediate * fact[timerValue]; // actual time spent
481 intermediate = intermediate / 2000000000ll; // rescale so its exactly 1/20 a second
482 intermediate = intermediate + latchTime; // add on our save fudge
483 set_PIT2(0); // reset timer 2 to be zero
484 disable_PIT2(0); // turn off PIT 2
485 ml_set_interrupts_enabled(int_enabled);
486 return intermediate;
487}
488
489static uint64_t
490rdtsctime_to_nanoseconds( void )
491{
492 uint32_t numer;
493 uint32_t denom;
494 uint64_t abstime;
495
496 uint32_t intermediate[3];
497
498 numer = rtclock.timebase_const.numer;
499 denom = rtclock.timebase_const.denom;
500 abstime = rdtsc_64();
501 if (denom == 0xFFFFFFFF) {
502 abstime = fast_get_nano_from_abs(abstime, numer);
503 } else {
504 longmul(&abstime, numer, intermediate);
505 abstime = longdiv(intermediate, denom);
506 }
507 return abstime;
508}
509
510inline static mach_timespec_t
511rdtsc_to_timespec(void)
512{
513 uint64_t currNanos;
514 currNanos = rdtsctime_to_nanoseconds();
515 return nanos_to_timespec(currNanos);
516}
517
1c79356b
A
518/*
519 * Initialize non-zero clock structure values.
520 */
521void
522rtc_setvals(
523 unsigned int new_clknum,
524 clock_res_t new_ires
525 )
526{
527 unsigned int timeperclk;
528 unsigned int scale0;
529 unsigned int scale1;
530 unsigned int res;
531
532 clknum = new_clknum;
533 rtc_intr_freq = (NSEC_PER_SEC / new_ires);
534 rtc_intr_hertz = rtc_intr_freq / HZ;
535 clks_per_int = (clknum + (rtc_intr_freq / 2)) / rtc_intr_freq;
536 clks_per_int_99 = clks_per_int - clks_per_int/100;
537
538 /*
539 * The following calculations are done with scaling integer operations
540 * in order that the integer results are accurate to the lsb.
541 */
542 timeperclk = div_scale(ZANO, clknum, &scale0); /* 838.105647 nsec */
543
544 time_per_clk = mul_scale(ZHZ, timeperclk, &scale1); /* 83810 */
545 if (scale0 > scale1)
546 time_per_clk >>= (scale0 - scale1);
547 else if (scale0 < scale1)
548 panic("rtc_clock: time_per_clk overflow\n");
549
550 /*
551 * Notice that rtclock.intr_nsec is signed ==> use unsigned int res
552 */
553 res = mul_scale(clks_per_int, timeperclk, &scale1); /* 10000276 */
554 if (scale0 > scale1)
555 rtclock.intr_nsec = res >> (scale0 - scale1);
556 else
557 panic("rtc_clock: rtclock.intr_nsec overflow\n");
558
559 rtc_intr_count = 1;
560 RtcDelt = rtclock.intr_nsec/2;
561}
562
563/*
564 * Configure the real-time clock device. Return success (1)
565 * or failure (0).
566 */
567
568int
569sysclk_config(void)
570{
571 int RtcFlag;
572 int pic;
573
574#if NCPUS > 1
575 mp_disable_preemption();
576 if (cpu_number() != master_cpu) {
577 mp_enable_preemption();
578 return(1);
579 }
580 mp_enable_preemption();
581#endif
582 /*
583 * Setup device.
584 */
1c79356b 585 pic = 0; /* FIXME .. interrupt registration moved to AppleIntelClock */
1c79356b
A
586
587
588 /*
589 * We should attempt to test the real-time clock
590 * device here. If it were to fail, we should panic
591 * the system.
592 */
593 RtcFlag = /* test device */1;
594 printf("realtime clock configured\n");
595
596 simple_lock_init(&rtclock.lock, ETAP_NO_TRACE);
597 return (RtcFlag);
598}
599
600/*
601 * Initialize the real-time clock device. Return success (1)
602 * or failure (0). Since the real-time clock is required to
603 * provide canonical mapped time, we allocate a page to keep
604 * the clock time value. In addition, various variables used
605 * to support the clock are initialized. Note: the clock is
606 * not started until rtclock_reset is called.
607 */
608int
609sysclk_init(void)
610{
611 vm_offset_t *vp;
612#if NCPUS > 1
613 mp_disable_preemption();
614 if (cpu_number() != master_cpu) {
615 mp_enable_preemption();
616 return(1);
617 }
618 mp_enable_preemption();
619#endif
620
621 RtcTime = &rtclock.time;
622 rtc_setvals( CLKNUM, RTC_MINRES ); /* compute constants */
9bccf70c 623 rtc_set_cyc_per_sec(); /* compute number of tsc beats per second */
55e303ae 624 clock_timebase_init();
1c79356b
A
625 return (1);
626}
627
628static volatile unsigned int last_ival = 0;
629
630/*
631 * Get the clock device time. This routine is responsible
632 * for converting the device's machine dependent time value
633 * into a canonical mach_timespec_t value.
634 */
635kern_return_t
636sysclk_gettime(
637 mach_timespec_t *cur_time) /* OUT */
638{
1c79356b
A
639 if (!RtcTime) {
640 /* Uninitialized */
641 cur_time->tv_nsec = 0;
642 cur_time->tv_sec = 0;
643 return (KERN_SUCCESS);
644 }
645
55e303ae 646 *cur_time = rdtsc_to_timespec();
1c79356b
A
647 return (KERN_SUCCESS);
648}
649
650kern_return_t
651sysclk_gettime_internal(
652 mach_timespec_t *cur_time) /* OUT */
653{
1c79356b
A
654 if (!RtcTime) {
655 /* Uninitialized */
656 cur_time->tv_nsec = 0;
657 cur_time->tv_sec = 0;
658 return (KERN_SUCCESS);
659 }
55e303ae 660 *cur_time = rdtsc_to_timespec();
1c79356b
A
661 return (KERN_SUCCESS);
662}
663
664/*
665 * Get the clock device time when ALL interrupts are already disabled.
666 * Same as above except for turning interrupts off and on.
667 * This routine is responsible for converting the device's machine dependent
668 * time value into a canonical mach_timespec_t value.
669 */
670void
671sysclk_gettime_interrupts_disabled(
672 mach_timespec_t *cur_time) /* OUT */
673{
1c79356b
A
674 if (!RtcTime) {
675 /* Uninitialized */
676 cur_time->tv_nsec = 0;
677 cur_time->tv_sec = 0;
678 return;
679 }
55e303ae 680 *cur_time = rdtsc_to_timespec();
1c79356b
A
681}
682
9bccf70c
A
683// utility routine
684// Code to calculate how many processor cycles are in a second...
1c79356b 685
9bccf70c
A
686static void
687rtc_set_cyc_per_sec()
688{
1c79356b 689
55e303ae
A
690 uint32_t twen_cycles;
691 uint32_t cycles;
9bccf70c 692
55e303ae
A
693 twen_cycles = timeRDTSC();
694 if (twen_cycles> (1000000000/20)) {
695 // we create this value so that you can use just a "fast" multiply to get nanos
696 rtc_quant_scale = create_mul_quant_GHZ(twen_cycles);
697 rtclock.timebase_const.numer = rtc_quant_scale; // because ctimeRDTSC gives us 1/20 a seconds worth
698 rtclock.timebase_const.denom = 0xffffffff; // so that nanoseconds = (TSC * numer) / denom
699
700 } else {
701 rtclock.timebase_const.numer = 1000000000/20; // because ctimeRDTSC gives us 1/20 a seconds worth
702 rtclock.timebase_const.denom = twen_cycles; // so that nanoseconds = (TSC * numer) / denom
9bccf70c 703 }
55e303ae
A
704 cycles = twen_cycles; // number of cycles in 1/20th a second
705 rtc_cyc_per_sec = cycles*20; // multiply it by 20 and we are done.. BUT we also want to calculate...
706
707 cycles = ((rtc_cyc_per_sec + UI_CPUFREQ_ROUNDING_FACTOR - 1) / UI_CPUFREQ_ROUNDING_FACTOR) * UI_CPUFREQ_ROUNDING_FACTOR;
708 gPEClockFrequencyInfo.cpu_clock_rate_hz = cycles;
709DISPLAYVALUE(rtc_set_cyc_per_sec,rtc_cyc_per_sec);
710DISPLAYEXIT(rtc_set_cyc_per_sec);
9bccf70c 711}
1c79356b 712
55e303ae
A
713void
714clock_get_system_microtime(
715 uint32_t *secs,
716 uint32_t *microsecs)
9bccf70c 717{
55e303ae
A
718 mach_timespec_t now;
719
720 sysclk_gettime(&now);
721
722 *secs = now.tv_sec;
723 *microsecs = now.tv_nsec / NSEC_PER_USEC;
1c79356b
A
724}
725
55e303ae
A
726void
727clock_get_system_nanotime(
728 uint32_t *secs,
729 uint32_t *nanosecs)
730{
731 mach_timespec_t now;
732
733 sysclk_gettime(&now);
734
735 *secs = now.tv_sec;
736 *nanosecs = now.tv_nsec;
737}
9bccf70c 738
1c79356b
A
739/*
740 * Get clock device attributes.
741 */
742kern_return_t
743sysclk_getattr(
744 clock_flavor_t flavor,
745 clock_attr_t attr, /* OUT */
746 mach_msg_type_number_t *count) /* IN/OUT */
747{
748 spl_t s;
749
750 if (*count != 1)
751 return (KERN_FAILURE);
752 switch (flavor) {
753
754 case CLOCK_GET_TIME_RES: /* >0 res */
55e303ae 755#if (NCPUS == 1)
1c79356b
A
756 LOCK_RTC(s);
757 *(clock_res_t *) attr = 1000;
758 UNLOCK_RTC(s);
759 break;
55e303ae 760#endif /* (NCPUS == 1) */
1c79356b
A
761 case CLOCK_ALARM_CURRES: /* =0 no alarm */
762 LOCK_RTC(s);
763 *(clock_res_t *) attr = rtclock.intr_nsec;
764 UNLOCK_RTC(s);
765 break;
766
767 case CLOCK_ALARM_MAXRES:
768 *(clock_res_t *) attr = RTC_MAXRES;
769 break;
770
771 case CLOCK_ALARM_MINRES:
772 *(clock_res_t *) attr = RTC_MINRES;
773 break;
774
775 default:
776 return (KERN_INVALID_VALUE);
777 }
778 return (KERN_SUCCESS);
779}
780
781/*
782 * Set clock device attributes.
783 */
784kern_return_t
785sysclk_setattr(
786 clock_flavor_t flavor,
787 clock_attr_t attr, /* IN */
788 mach_msg_type_number_t count) /* IN */
789{
790 spl_t s;
791 int freq;
792 int adj;
793 clock_res_t new_ires;
794
795 if (count != 1)
796 return (KERN_FAILURE);
797 switch (flavor) {
798
799 case CLOCK_GET_TIME_RES:
800 case CLOCK_ALARM_MAXRES:
801 case CLOCK_ALARM_MINRES:
802 return (KERN_FAILURE);
803
804 case CLOCK_ALARM_CURRES:
805 new_ires = *(clock_res_t *) attr;
806
807 /*
808 * The new resolution must be within the predetermined
809 * range. If the desired resolution cannot be achieved
810 * to within 0.1%, an error is returned.
811 */
812 if (new_ires < RTC_MAXRES || new_ires > RTC_MINRES)
813 return (KERN_INVALID_VALUE);
814 freq = (NSEC_PER_SEC / new_ires);
815 adj = (((clknum % freq) * new_ires) / clknum);
816 if (adj > (new_ires / 1000))
817 return (KERN_INVALID_VALUE);
818 /*
819 * Record the new alarm resolution which will take effect
820 * on the next HZ aligned clock tick.
821 */
822 LOCK_RTC(s);
823 if ( freq != rtc_intr_freq ) {
824 rtclock.new_ires = new_ires;
825 new_clknum = clknum;
826 }
827 UNLOCK_RTC(s);
828 return (KERN_SUCCESS);
829
830 default:
831 return (KERN_INVALID_VALUE);
832 }
833}
834
835/*
836 * Set next alarm time for the clock device. This call
837 * always resets the time to deliver an alarm for the
838 * clock.
839 */
840void
841sysclk_setalarm(
842 mach_timespec_t *alarm_time)
843{
844 spl_t s;
845
846 LOCK_RTC(s);
847 rtclock.alarm_time = *alarm_time;
848 RtcAlrm = &rtclock.alarm_time;
849 UNLOCK_RTC(s);
850}
851
852/*
853 * Configure the calendar clock.
854 */
855int
856calend_config(void)
857{
858 return bbc_config();
859}
860
861/*
862 * Initialize calendar clock.
863 */
864int
865calend_init(void)
866{
867 return (1);
868}
869
870/*
871 * Get the current clock time.
872 */
873kern_return_t
874calend_gettime(
875 mach_timespec_t *cur_time) /* OUT */
876{
877 spl_t s;
878
879 LOCK_RTC(s);
880 if (!rtclock.calend_is_set) {
881 UNLOCK_RTC(s);
882 return (KERN_FAILURE);
883 }
884
885 (void) sysclk_gettime_internal(cur_time);
886 ADD_MACH_TIMESPEC(cur_time, &rtclock.calend_offset);
887 UNLOCK_RTC(s);
888
889 return (KERN_SUCCESS);
890}
891
55e303ae
A
892void
893clock_get_calendar_microtime(
894 uint32_t *secs,
895 uint32_t *microsecs)
896{
897 mach_timespec_t now;
898
899 calend_gettime(&now);
900
901 *secs = now.tv_sec;
902 *microsecs = now.tv_nsec / NSEC_PER_USEC;
903}
904
905void
906clock_get_calendar_nanotime(
907 uint32_t *secs,
908 uint32_t *nanosecs)
1c79356b 909{
55e303ae
A
910 mach_timespec_t now;
911
912 calend_gettime(&now);
913
914 *secs = now.tv_sec;
915 *nanosecs = now.tv_nsec;
916}
917
918void
919clock_set_calendar_microtime(
920 uint32_t secs,
921 uint32_t microsecs)
922{
923 mach_timespec_t new_time, curr_time;
1c79356b
A
924 spl_t s;
925
926 LOCK_RTC(s);
927 (void) sysclk_gettime_internal(&curr_time);
55e303ae
A
928 rtclock.calend_offset.tv_sec = new_time.tv_sec = secs;
929 rtclock.calend_offset.tv_nsec = new_time.tv_nsec = microsecs * NSEC_PER_USEC;
1c79356b
A
930 SUB_MACH_TIMESPEC(&rtclock.calend_offset, &curr_time);
931 rtclock.calend_is_set = TRUE;
932 UNLOCK_RTC(s);
933
55e303ae 934 (void) bbc_settime(&new_time);
1c79356b 935
55e303ae 936 host_notify_calendar_change();
1c79356b
A
937}
938
939/*
940 * Get clock device attributes.
941 */
942kern_return_t
943calend_getattr(
944 clock_flavor_t flavor,
945 clock_attr_t attr, /* OUT */
946 mach_msg_type_number_t *count) /* IN/OUT */
947{
948 spl_t s;
949
950 if (*count != 1)
951 return (KERN_FAILURE);
952 switch (flavor) {
953
954 case CLOCK_GET_TIME_RES: /* >0 res */
55e303ae 955#if (NCPUS == 1)
1c79356b
A
956 LOCK_RTC(s);
957 *(clock_res_t *) attr = 1000;
958 UNLOCK_RTC(s);
959 break;
55e303ae 960#else /* (NCPUS == 1) */
1c79356b
A
961 LOCK_RTC(s);
962 *(clock_res_t *) attr = rtclock.intr_nsec;
963 UNLOCK_RTC(s);
964 break;
55e303ae 965#endif /* (NCPUS == 1) */
1c79356b
A
966
967 case CLOCK_ALARM_CURRES: /* =0 no alarm */
968 case CLOCK_ALARM_MINRES:
969 case CLOCK_ALARM_MAXRES:
970 *(clock_res_t *) attr = 0;
971 break;
972
973 default:
974 return (KERN_INVALID_VALUE);
975 }
976 return (KERN_SUCCESS);
977}
978
55e303ae
A
979#define tickadj (40*NSEC_PER_USEC) /* "standard" skew, ns / tick */
980#define bigadj (NSEC_PER_SEC) /* use 10x skew above bigadj ns */
981
982uint32_t
983clock_set_calendar_adjtime(
984 int32_t *secs,
985 int32_t *microsecs)
1c79356b 986{
55e303ae
A
987 int64_t total, ototal;
988 uint32_t interval = 0;
989 spl_t s;
990
991 total = (int64_t)*secs * NSEC_PER_SEC + *microsecs * NSEC_PER_USEC;
1c79356b
A
992
993 LOCK_RTC(s);
55e303ae
A
994 ototal = rtclock.calend_adjtotal;
995
996 if (total != 0) {
997 int32_t delta = tickadj;
998
999 if (total > 0) {
1000 if (total > bigadj)
1001 delta *= 10;
1002 if (delta > total)
1003 delta = total;
1004 }
1005 else {
1006 if (total < -bigadj)
1007 delta *= 10;
1008 delta = -delta;
1009 if (delta < total)
1010 delta = total;
1011 }
1012
1013 rtclock.calend_adjtotal = total;
1014 rtclock.calend_adjdelta = delta;
1015
1016 interval = (NSEC_PER_SEC / HZ);
1017 }
1018 else
1019 rtclock.calend_adjdelta = rtclock.calend_adjtotal = 0;
1020
1021 UNLOCK_RTC(s);
1022
1023 if (ototal == 0)
1024 *secs = *microsecs = 0;
1025 else {
1026 *secs = ototal / NSEC_PER_SEC;
1027 *microsecs = ototal % NSEC_PER_SEC;
1028 }
1029
1030 return (interval);
1031}
1032
1033uint32_t
1034clock_adjust_calendar(void)
1035{
1036 uint32_t interval = 0;
1037 int32_t delta;
1038 spl_t s;
1039
1040 LOCK_RTC(s);
1041 delta = rtclock.calend_adjdelta;
1042 ADD_MACH_TIMESPEC_NSEC(&rtclock.calend_offset, delta);
1043
1044 rtclock.calend_adjtotal -= delta;
1045
1046 if (delta > 0) {
1047 if (delta > rtclock.calend_adjtotal)
1048 rtclock.calend_adjdelta = rtclock.calend_adjtotal;
1049 }
1050 else
1051 if (delta < 0) {
1052 if (delta < rtclock.calend_adjtotal)
1053 rtclock.calend_adjdelta = rtclock.calend_adjtotal;
1054 }
1055
1056 if (rtclock.calend_adjdelta != 0)
1057 interval = (NSEC_PER_SEC / HZ);
1058
1c79356b 1059 UNLOCK_RTC(s);
55e303ae
A
1060
1061 return (interval);
1c79356b
A
1062}
1063
1064void
1065clock_initialize_calendar(void)
1066{
1067 mach_timespec_t bbc_time, curr_time;
1068 spl_t s;
1069
1070 if (bbc_gettime(&bbc_time) != KERN_SUCCESS)
1071 return;
1072
1073 LOCK_RTC(s);
1074 if (!rtclock.calend_is_set) {
1075 (void) sysclk_gettime_internal(&curr_time);
1076 rtclock.calend_offset = bbc_time;
1077 SUB_MACH_TIMESPEC(&rtclock.calend_offset, &curr_time);
1078 rtclock.calend_is_set = TRUE;
1079 }
1080 UNLOCK_RTC(s);
1c79356b 1081
55e303ae 1082 host_notify_calendar_change();
1c79356b
A
1083}
1084
1085void
1086clock_timebase_info(
1087 mach_timebase_info_t info)
1088{
1089 spl_t s;
1090
1091 LOCK_RTC(s);
55e303ae
A
1092 if (rtclock.timebase_const.denom == 0xFFFFFFFF) {
1093 info->numer = info->denom = rtc_quant_scale;
1094 } else {
1095 info->numer = info->denom = 1;
1096 }
1c79356b
A
1097 UNLOCK_RTC(s);
1098}
1099
1100void
1101clock_set_timer_deadline(
0b4e3aa0 1102 uint64_t deadline)
1c79356b
A
1103{
1104 spl_t s;
1105
1106 LOCK_RTC(s);
1107 rtclock.timer_deadline = deadline;
1108 rtclock.timer_is_set = TRUE;
1109 UNLOCK_RTC(s);
1110}
1111
1112void
1113clock_set_timer_func(
1114 clock_timer_func_t func)
1115{
1116 spl_t s;
1117
1118 LOCK_RTC(s);
1119 if (rtclock.timer_expire == NULL)
1120 rtclock.timer_expire = func;
1121 UNLOCK_RTC(s);
1122}
1123
1124\f
1125
1126/*
1127 * Load the count register and start the clock.
1128 */
1129#define RTCLOCK_RESET() { \
1130 outb(PITCTL_PORT, PIT_C0|PIT_NDIVMODE|PIT_READMODE); \
1131 outb(PITCTR0_PORT, (clks_per_int & 0xff)); \
1132 outb(PITCTR0_PORT, (clks_per_int >> 8)); \
1133}
1134
1135/*
1136 * Reset the clock device. This causes the realtime clock
1137 * device to reload its mode and count value (frequency).
1138 * Note: the CPU should be calibrated
1139 * before starting the clock for the first time.
1140 */
1141
1142void
1143rtclock_reset(void)
1144{
1145 int s;
1146
55e303ae 1147#if NCPUS > 1
1c79356b
A
1148 mp_disable_preemption();
1149 if (cpu_number() != master_cpu) {
1150 mp_enable_preemption();
1151 return;
1152 }
1153 mp_enable_preemption();
55e303ae 1154#endif /* NCPUS > 1 */
1c79356b
A
1155 LOCK_RTC(s);
1156 RTCLOCK_RESET();
1157 UNLOCK_RTC(s);
1158}
1159
1160/*
1161 * Real-time clock device interrupt. Called only on the
1162 * master processor. Updates the clock time and upcalls
1163 * into the higher level clock code to deliver alarms.
1164 */
1165int
55e303ae 1166rtclock_intr(struct i386_interrupt_state *regs)
1c79356b 1167{
55e303ae 1168 uint64_t abstime;
1c79356b 1169 mach_timespec_t clock_time;
55e303ae
A
1170 int i;
1171 spl_t s;
1172 boolean_t usermode;
1c79356b
A
1173
1174 /*
1175 * Update clock time. Do the update so that the macro
1176 * MTS_TO_TS() for reading the mapped time works (e.g.
1177 * update in order: mtv_csec, mtv_time.tv_nsec, mtv_time.tv_sec).
1178 */
1179 LOCK_RTC(s);
55e303ae
A
1180 abstime = rdtsctime_to_nanoseconds(); // get the time as of the TSC
1181 clock_time = nanos_to_timespec(abstime); // turn it into a timespec
1182 rtclock.time.tv_nsec = clock_time.tv_nsec;
1183 rtclock.time.tv_sec = clock_time.tv_sec;
1184 rtclock.abstime = abstime;
1185
1c79356b
A
1186 /* note time now up to date */
1187 last_ival = 0;
1188
55e303ae
A
1189 /*
1190 * On a HZ-tick boundary: return 0 and adjust the clock
1191 * alarm resolution (if requested). Otherwise return a
1192 * non-zero value.
1193 */
1194 if ((i = --rtc_intr_count) == 0) {
1195 if (rtclock.new_ires) {
1196 rtc_setvals(new_clknum, rtclock.new_ires);
1197 RTCLOCK_RESET(); /* lock clock register */
1198 rtclock.new_ires = 0;
1199 }
1200 rtc_intr_count = rtc_intr_hertz;
1201 UNLOCK_RTC(s);
1202 usermode = (regs->efl & EFL_VM) || ((regs->cs & 0x03) != 0);
1203 hertz_tick(usermode, regs->eip);
1204 LOCK_RTC(s);
1205 }
1206
0b4e3aa0
A
1207 if ( rtclock.timer_is_set &&
1208 rtclock.timer_deadline <= abstime ) {
1c79356b
A
1209 rtclock.timer_is_set = FALSE;
1210 UNLOCK_RTC(s);
1211
1212 (*rtclock.timer_expire)(abstime);
1213
1214 LOCK_RTC(s);
1215 }
1216
1217 /*
1218 * Perform alarm clock processing if needed. The time
1219 * passed up is incremented by a half-interrupt tick
1220 * to trigger alarms closest to their desired times.
1221 * The clock_alarm_intr() routine calls sysclk_setalrm()
1222 * before returning if later alarms are pending.
1223 */
1224
1225 if (RtcAlrm && (RtcAlrm->tv_sec < RtcTime->tv_sec ||
1226 (RtcAlrm->tv_sec == RtcTime->tv_sec &&
1227 RtcDelt >= RtcAlrm->tv_nsec - RtcTime->tv_nsec))) {
1228 clock_time.tv_sec = 0;
1229 clock_time.tv_nsec = RtcDelt;
1230 ADD_MACH_TIMESPEC (&clock_time, RtcTime);
1231 RtcAlrm = 0;
1232 UNLOCK_RTC(s);
1233 /*
1234 * Call clock_alarm_intr() without RTC-lock.
1235 * The lock ordering is always CLOCK-lock
1236 * before RTC-lock.
1237 */
1238 clock_alarm_intr(SYSTEM_CLOCK, &clock_time);
1239 LOCK_RTC(s);
1240 }
1241
1c79356b
A
1242 UNLOCK_RTC(s);
1243 return (i);
1244}
1245
1246void
1247clock_get_uptime(
0b4e3aa0 1248 uint64_t *result)
1c79356b 1249{
55e303ae
A
1250 *result = rdtsctime_to_nanoseconds();
1251}
1c79356b 1252
55e303ae
A
1253uint64_t
1254mach_absolute_time(void)
1255{
1256 return rdtsctime_to_nanoseconds();
1c79356b
A
1257}
1258
1259void
1260clock_interval_to_deadline(
0b4e3aa0
A
1261 uint32_t interval,
1262 uint32_t scale_factor,
1263 uint64_t *result)
1c79356b 1264{
0b4e3aa0 1265 uint64_t abstime;
1c79356b
A
1266
1267 clock_get_uptime(result);
1268
1269 clock_interval_to_absolutetime_interval(interval, scale_factor, &abstime);
1270
0b4e3aa0 1271 *result += abstime;
1c79356b
A
1272}
1273
1274void
1275clock_interval_to_absolutetime_interval(
0b4e3aa0
A
1276 uint32_t interval,
1277 uint32_t scale_factor,
1278 uint64_t *result)
1c79356b 1279{
0b4e3aa0 1280 *result = (uint64_t)interval * scale_factor;
1c79356b
A
1281}
1282
1283void
1284clock_absolutetime_interval_to_deadline(
0b4e3aa0
A
1285 uint64_t abstime,
1286 uint64_t *result)
1c79356b
A
1287{
1288 clock_get_uptime(result);
1289
0b4e3aa0 1290 *result += abstime;
1c79356b
A
1291}
1292
1293void
1294absolutetime_to_nanoseconds(
0b4e3aa0
A
1295 uint64_t abstime,
1296 uint64_t *result)
1c79356b 1297{
0b4e3aa0 1298 *result = abstime;
1c79356b
A
1299}
1300
1301void
1302nanoseconds_to_absolutetime(
0b4e3aa0
A
1303 uint64_t nanoseconds,
1304 uint64_t *result)
1c79356b 1305{
0b4e3aa0 1306 *result = nanoseconds;
1c79356b
A
1307}
1308
1309/*
55e303ae 1310 * Spin-loop delay primitives.
1c79356b 1311 */
55e303ae
A
1312void
1313delay_for_interval(
1314 uint32_t interval,
1315 uint32_t scale_factor)
1c79356b 1316{
55e303ae 1317 uint64_t now, end;
1c79356b 1318
55e303ae 1319 clock_interval_to_deadline(interval, scale_factor, &end);
1c79356b 1320
55e303ae
A
1321 do {
1322 cpu_pause();
1323 now = mach_absolute_time();
1324 } while (now < end);
1c79356b
A
1325}
1326
1c79356b 1327void
55e303ae
A
1328clock_delay_until(
1329 uint64_t deadline)
1330{
1331 uint64_t now;
1332
1333 do {
1334 cpu_pause();
1335 now = mach_absolute_time();
1336 } while (now < deadline);
1337}
1c79356b
A
1338
1339void
55e303ae
A
1340delay(
1341 int usec)
1c79356b 1342{
55e303ae 1343 delay_for_interval((usec < 0)? -usec: usec, NSEC_PER_USEC);
1c79356b 1344}