]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/xen/clock.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / i386 / xen / clock.c
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
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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  */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41
42 /* #define DELAYDEBUG */
43 /*
44  * Routines to handle clock hardware.
45  */
46
47 #include "opt_ddb.h"
48 #include "opt_clock.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/bus.h>
53 #include <sys/clock.h>
54 #include <sys/lock.h>
55 #include <sys/mutex.h>
56 #include <sys/proc.h>
57 #include <sys/time.h>
58 #include <sys/timetc.h>
59 #include <sys/kernel.h>
60 #include <sys/limits.h>
61 #include <sys/sysctl.h>
62 #include <sys/cons.h>
63 #include <sys/power.h>
64
65 #include <machine/clock.h>
66 #include <machine/cputypes.h>
67 #include <machine/frame.h>
68 #include <machine/intr_machdep.h>
69 #include <machine/md_var.h>
70 #include <machine/psl.h>
71 #if defined(SMP)
72 #include <machine/smp.h>
73 #endif
74 #include <machine/specialreg.h>
75 #include <machine/timerreg.h>
76
77 #include <i386/isa/icu.h>
78 #include <i386/isa/isa.h>
79 #include <isa/rtc.h>
80
81 #include <machine/xen/xen_intr.h>
82 #include <vm/vm.h>
83 #include <vm/pmap.h>
84 #include <machine/pmap.h>
85 #include <machine/xen/hypervisor.h>
86 #include <machine/xen/xen-os.h>
87 #include <machine/xen/xenfunc.h>
88 #include <xen/interface/vcpu.h>
89 #include <machine/cpu.h>
90
91 /*
92  * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
93  * can use a simple formula for leap years.
94  */
95 #define LEAPYEAR(y)     (!((y) % 4))
96 #define DAYSPERYEAR     (28+30*4+31*7)
97
98 #ifndef TIMER_FREQ
99 #define TIMER_FREQ      1193182
100 #endif
101
102 #ifdef CYC2NS_SCALE_FACTOR
103 #undef  CYC2NS_SCALE_FACTOR
104 #endif
105 #define CYC2NS_SCALE_FACTOR     10
106
107 /* Values for timerX_state: */
108 #define RELEASED        0
109 #define RELEASE_PENDING 1
110 #define ACQUIRED        2
111 #define ACQUIRE_PENDING 3
112
113 struct mtx clock_lock;
114 #define RTC_LOCK_INIT                                                   \
115         mtx_init(&clock_lock, "clk", NULL, MTX_SPIN | MTX_NOPROFILE)
116 #define RTC_LOCK        mtx_lock_spin(&clock_lock)
117 #define RTC_UNLOCK      mtx_unlock_spin(&clock_lock)
118
119 int adjkerntz;          /* local offset from GMT in seconds */
120 int clkintr_pending;
121 int pscnt = 1;
122 int psdiv = 1;
123 int statclock_disable;
124 int wall_cmos_clock;
125 u_int timer_freq = TIMER_FREQ;
126 static int independent_wallclock;
127 static int xen_disable_rtc_set;
128 static u_long cached_gtm;       /* cached quotient for TSC -> microseconds */
129 static u_long cyc2ns_scale; 
130 static struct timespec shadow_tv;
131 static uint32_t shadow_tv_version;      /* XXX: lazy locking */
132 static uint64_t processed_system_time;  /* stime (ns) at last processing. */
133
134 static  const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
135
136 SYSCTL_INT(_machdep, OID_AUTO, independent_wallclock,
137     CTLFLAG_RW, &independent_wallclock, 0, "");
138 SYSCTL_INT(_machdep, OID_AUTO, xen_disable_rtc_set,
139     CTLFLAG_RW, &xen_disable_rtc_set, 1, "");
140
141
142 #define do_div(n,base) ({ \
143         unsigned long __upper, __low, __high, __mod, __base; \
144         __base = (base); \
145         __asm("":"=a" (__low), "=d" (__high):"A" (n)); \
146         __upper = __high; \
147         if (__high) { \
148                 __upper = __high % (__base); \
149                 __high = __high / (__base); \
150         } \
151         __asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \
152         __asm("":"=A" (n):"a" (__low),"d" (__high)); \
153         __mod; \
154 })
155
156
157 /* These are peridically updated in shared_info, and then copied here. */
158 struct shadow_time_info {
159         uint64_t tsc_timestamp;     /* TSC at last update of time vals.  */
160         uint64_t system_timestamp;  /* Time, in nanosecs, since boot.    */
161         uint32_t tsc_to_nsec_mul;
162         uint32_t tsc_to_usec_mul;
163         int tsc_shift;
164         uint32_t version;
165 };
166 static DEFINE_PER_CPU(uint64_t, processed_system_time);
167 static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
168
169
170 #define NS_PER_TICK (1000000000ULL/hz)
171
172 #define rdtscll(val) \
173     __asm__ __volatile__("rdtsc" : "=A" (val))
174
175
176 /* convert from cycles(64bits) => nanoseconds (64bits)
177  *  basic equation:
178  *              ns = cycles / (freq / ns_per_sec)
179  *              ns = cycles * (ns_per_sec / freq)
180  *              ns = cycles * (10^9 / (cpu_mhz * 10^6))
181  *              ns = cycles * (10^3 / cpu_mhz)
182  *
183  *      Then we use scaling math (suggested by george@mvista.com) to get:
184  *              ns = cycles * (10^3 * SC / cpu_mhz) / SC
185  *              ns = cycles * cyc2ns_scale / SC
186  *
187  *      And since SC is a constant power of two, we can convert the div
188  *  into a shift.   
189  *                      -johnstul@us.ibm.com "math is hard, lets go shopping!"
190  */
191 static inline void set_cyc2ns_scale(unsigned long cpu_mhz)
192 {
193         cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz;
194 }
195
196 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
197 {
198         return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
199 }
200
201 /*
202  * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
203  * yielding a 64-bit result.
204  */
205 static inline uint64_t 
206 scale_delta(uint64_t delta, uint32_t mul_frac, int shift)
207 {
208         uint64_t product;
209         uint32_t tmp1, tmp2;
210
211         if ( shift < 0 )
212                 delta >>= -shift;
213         else
214                 delta <<= shift;
215
216         __asm__ (
217                 "mul  %5       ; "
218                 "mov  %4,%%eax ; "
219                 "mov  %%edx,%4 ; "
220                 "mul  %5       ; "
221                 "add  %4,%%eax ; "
222                 "xor  %5,%5    ; "
223                 "adc  %5,%%edx ; "
224                 : "=A" (product), "=r" (tmp1), "=r" (tmp2)
225                 : "a" ((uint32_t)delta), "1" ((uint32_t)(delta >> 32)), "2" (mul_frac) );
226
227         return product;
228 }
229
230 static uint64_t get_nsec_offset(struct shadow_time_info *shadow)
231 {
232         uint64_t now, delta;
233         rdtscll(now);
234         delta = now - shadow->tsc_timestamp;
235         return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift);
236 }
237
238 static void update_wallclock(void)
239 {
240         shared_info_t *s = HYPERVISOR_shared_info;
241
242         do {
243                 shadow_tv_version = s->wc_version;
244                 rmb();
245                 shadow_tv.tv_sec  = s->wc_sec;
246                 shadow_tv.tv_nsec = s->wc_nsec;
247                 rmb();
248         }
249         while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
250
251 }
252
253 /*
254  * Reads a consistent set of time-base values from Xen, into a shadow data
255  * area. Must be called with the xtime_lock held for writing.
256  */
257 static void __get_time_values_from_xen(void)
258 {
259         shared_info_t           *s = HYPERVISOR_shared_info;
260         struct vcpu_time_info   *src;
261         struct shadow_time_info *dst;
262
263         src = &s->vcpu_info[smp_processor_id()].time;
264         dst = &per_cpu(shadow_time, smp_processor_id());
265
266         do {
267                 dst->version = src->version;
268                 rmb();
269                 dst->tsc_timestamp     = src->tsc_timestamp;
270                 dst->system_timestamp  = src->system_time;
271                 dst->tsc_to_nsec_mul   = src->tsc_to_system_mul;
272                 dst->tsc_shift         = src->tsc_shift;
273                 rmb();
274         }
275         while ((src->version & 1) | (dst->version ^ src->version));
276
277         dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
278 }
279
280 static inline int time_values_up_to_date(int cpu)
281 {
282         struct vcpu_time_info   *src;
283         struct shadow_time_info *dst;
284
285         src = &HYPERVISOR_shared_info->vcpu_info[cpu].time; 
286         dst = &per_cpu(shadow_time, cpu); 
287
288         rmb();
289         return (dst->version == src->version);
290 }
291
292 static  unsigned xen_get_timecount(struct timecounter *tc);
293
294 static struct timecounter xen_timecounter = {
295         xen_get_timecount,      /* get_timecount */
296         0,                      /* no poll_pps */
297         ~0u,                    /* counter_mask */
298         0,                      /* frequency */
299         "ixen",                 /* name */
300         0                       /* quality */
301 };
302
303 static void 
304 clkintr(struct trapframe *frame)
305 {
306         int64_t delta_cpu, delta;
307         int cpu = smp_processor_id();
308         struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu);
309
310         do {
311                 __get_time_values_from_xen();
312                 
313                 delta = delta_cpu = 
314                         shadow->system_timestamp + get_nsec_offset(shadow);
315                 delta     -= processed_system_time;
316                 delta_cpu -= per_cpu(processed_system_time, cpu);
317
318         } while (!time_values_up_to_date(cpu));
319         
320         if (unlikely(delta < (int64_t)0) || unlikely(delta_cpu < (int64_t)0)) {
321                 printf("Timer ISR: Time went backwards: %lld\n", delta);
322                 return;
323         }
324         
325         /* Process elapsed ticks since last call. */
326         if (delta >= NS_PER_TICK) {
327                 processed_system_time += (delta / NS_PER_TICK) * NS_PER_TICK;
328                 per_cpu(processed_system_time, cpu) += (delta_cpu / NS_PER_TICK) * NS_PER_TICK;
329         }
330         hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
331
332         /*
333          * Take synchronised time from Xen once a minute if we're not
334          * synchronised ourselves, and we haven't chosen to keep an independent
335          * time base.
336          */
337         
338         if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
339                 update_wallclock();
340                 tc_setclock(&shadow_tv);
341         }
342         
343         /* XXX TODO */
344 }
345
346 static uint32_t
347 getit(void)
348 {
349         struct shadow_time_info *shadow;
350         shadow = &per_cpu(shadow_time, smp_processor_id());
351         __get_time_values_from_xen();
352         return shadow->system_timestamp + get_nsec_offset(shadow);
353 }
354
355
356 /*
357  * XXX: timer needs more SMP work.
358  */
359 void
360 i8254_init(void)
361 {
362
363         RTC_LOCK_INIT;
364 }
365
366 /*
367  * Wait "n" microseconds.
368  * Relies on timer 1 counting down from (timer_freq / hz)
369  * Note: timer had better have been programmed before this is first used!
370  */
371 void
372 DELAY(int n)
373 {
374         int delta, ticks_left;
375         uint32_t tick, prev_tick;
376 #ifdef DELAYDEBUG
377         int getit_calls = 1;
378         int n1;
379         static int state = 0;
380
381         if (state == 0) {
382                 state = 1;
383                 for (n1 = 1; n1 <= 10000000; n1 *= 10)
384                         DELAY(n1);
385                 state = 2;
386         }
387         if (state == 1)
388                 printf("DELAY(%d)...", n);
389 #endif
390         /*
391          * Read the counter first, so that the rest of the setup overhead is
392          * counted.  Guess the initial overhead is 20 usec (on most systems it
393          * takes about 1.5 usec for each of the i/o's in getit().  The loop
394          * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
395          * multiplications and divisions to scale the count take a while).
396          *
397          * However, if ddb is active then use a fake counter since reading
398          * the i8254 counter involves acquiring a lock.  ddb must not go
399          * locking for many reasons, but it calls here for at least atkbd
400          * input.
401          */
402         prev_tick = getit();
403
404         n -= 0;                 /* XXX actually guess no initial overhead */
405         /*
406          * Calculate (n * (timer_freq / 1e6)) without using floating point
407          * and without any avoidable overflows.
408          */
409         if (n <= 0)
410                 ticks_left = 0;
411         else if (n < 256)
412                 /*
413                  * Use fixed point to avoid a slow division by 1000000.
414                  * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
415                  * 2^15 is the first power of 2 that gives exact results
416                  * for n between 0 and 256.
417                  */
418                 ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
419         else
420                 /*
421                  * Don't bother using fixed point, although gcc-2.7.2
422                  * generates particularly poor code for the long long
423                  * division, since even the slow way will complete long
424                  * before the delay is up (unless we're interrupted).
425                  */
426                 ticks_left = ((u_int)n * (long long)timer_freq + 999999)
427                         / 1000000;
428
429         while (ticks_left > 0) {
430                 tick = getit();
431 #ifdef DELAYDEBUG
432                 ++getit_calls;
433 #endif
434                 delta = tick - prev_tick;
435                 prev_tick = tick;
436                 if (delta < 0) {
437                         /*
438                          * Guard against timer0_max_count being wrong.
439                          * This shouldn't happen in normal operation,
440                          * but it may happen if set_timer_freq() is
441                          * traced.
442                          */
443                         /* delta += timer0_max_count; ??? */
444                         if (delta < 0)
445                                 delta = 0;
446                 }
447                 ticks_left -= delta;
448         }
449 #ifdef DELAYDEBUG
450         if (state == 1)
451                 printf(" %d calls to getit() at %d usec each\n",
452                        getit_calls, (n + 5) / getit_calls);
453 #endif
454 }
455
456
457 /*
458  * Restore all the timers non-atomically (XXX: should be atomically).
459  *
460  * This function is called from pmtimer_resume() to restore all the timers.
461  * This should not be necessary, but there are broken laptops that do not
462  * restore all the timers on resume.
463  */
464 void
465 timer_restore(void)
466 {
467         /* Get timebases for new environment. */ 
468         __get_time_values_from_xen();
469
470         /* Reset our own concept of passage of system time. */
471         processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
472         per_cpu(processed_system_time, 0) = processed_system_time;
473 }
474
475 void
476 startrtclock()
477 {
478         unsigned long long alarm;
479         uint64_t __cpu_khz;
480         uint32_t cpu_khz;
481         struct vcpu_time_info *info;
482
483         /* initialize xen values */
484         __get_time_values_from_xen();
485         processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
486         per_cpu(processed_system_time, 0) = processed_system_time;
487
488         __cpu_khz = 1000000ULL << 32;
489         info = &HYPERVISOR_shared_info->vcpu_info[0].time;
490
491         do_div(__cpu_khz, info->tsc_to_system_mul);
492         if ( info->tsc_shift < 0 )
493                 cpu_khz = __cpu_khz << -info->tsc_shift;
494         else
495                 cpu_khz = __cpu_khz >> info->tsc_shift;
496
497         printf("Xen reported: %u.%03u MHz processor.\n", 
498                cpu_khz / 1000, cpu_khz % 1000);
499
500         /* (10^6 * 2^32) / cpu_hz = (10^3 * 2^32) / cpu_khz =
501            (2^32 * 1 / (clocks/us)) */
502         {       
503                 unsigned long eax=0, edx=1000;
504                 __asm__("divl %2"
505                         :"=a" (cached_gtm), "=d" (edx)
506                         :"r" (cpu_khz),
507                         "0" (eax), "1" (edx));
508         }
509
510         set_cyc2ns_scale(cpu_khz/1000);
511         tsc_freq = cpu_khz * 1000;
512
513         timer_freq = xen_timecounter.tc_frequency = 1000000000LL;
514         tc_init(&xen_timecounter);
515
516
517         rdtscll(alarm);
518 }
519
520 /*
521  * RTC support routines
522  */
523
524
525 static __inline int
526 readrtc(int port)
527 {
528         return(bcd2bin(rtcin(port)));
529 }
530
531
532 #ifdef XEN_PRIVILEGED_GUEST
533
534 /*
535  * Initialize the time of day register, based on the time base which is, e.g.
536  * from a filesystem.
537  */
538 static void
539 domu_inittodr(time_t base)
540 {
541         unsigned long   sec;
542         int             s, y;
543         struct timespec ts;
544
545         update_wallclock();
546         
547         RTC_LOCK;
548         
549         if (base) {
550                 ts.tv_sec = base;
551                 ts.tv_nsec = 0;
552                 tc_setclock(&ts);
553         }
554
555         sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
556
557         y = time_second - shadow_tv.tv_sec;
558         if (y <= -2 || y >= 2) {
559                 /* badly off, adjust it */
560                 tc_setclock(&shadow_tv);
561         }
562         RTC_UNLOCK;
563 }
564
565 /*
566  * Write system time back to RTC.  
567  */
568 static void
569 domu_resettodr(void)
570 {
571         unsigned long tm;
572         int s;
573         dom0_op_t op;
574         struct shadow_time_info *shadow;
575
576         shadow = &per_cpu(shadow_time, smp_processor_id());
577         if (xen_disable_rtc_set)
578                 return;
579         
580         s = splclock();
581         tm = time_second;
582         splx(s);
583         
584         tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
585         
586         if ((xen_start_info->flags & SIF_INITDOMAIN) &&
587             !independent_wallclock)
588         {
589                 op.cmd = DOM0_SETTIME;
590                 op.u.settime.secs        = tm;
591                 op.u.settime.nsecs       = 0;
592                 op.u.settime.system_time = shadow->system_timestamp;
593                 HYPERVISOR_dom0_op(&op);
594                 update_wallclock();
595         } else if (independent_wallclock) {
596                 /* notyet */
597                 ;
598         }               
599 }
600
601 /*
602  * Initialize the time of day register, based on the time base which is, e.g.
603  * from a filesystem.
604  */
605 void
606 inittodr(time_t base)
607 {
608         unsigned long   sec, days;
609         int             year, month;
610         int             y, m, s;
611         struct timespec ts;
612
613         if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
614                 domu_inittodr(base);
615                 return;
616         }
617
618         if (base) {
619                 s = splclock();
620                 ts.tv_sec = base;
621                 ts.tv_nsec = 0;
622                 tc_setclock(&ts);
623                 splx(s);
624         }
625
626         /* Look if we have a RTC present and the time is valid */
627         if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
628                 goto wrong_time;
629
630         /* wait for time update to complete */
631         /* If RTCSA_TUP is zero, we have at least 244us before next update */
632         s = splhigh();
633         while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
634                 splx(s);
635                 s = splhigh();
636         }
637
638         days = 0;
639 #ifdef USE_RTC_CENTURY
640         year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
641 #else
642         year = readrtc(RTC_YEAR) + 1900;
643         if (year < 1970)
644                 year += 100;
645 #endif
646         if (year < 1970) {
647                 splx(s);
648                 goto wrong_time;
649         }
650         month = readrtc(RTC_MONTH);
651         for (m = 1; m < month; m++)
652                 days += daysinmonth[m-1];
653         if ((month > 2) && LEAPYEAR(year))
654                 days ++;
655         days += readrtc(RTC_DAY) - 1;
656         for (y = 1970; y < year; y++)
657                 days += DAYSPERYEAR + LEAPYEAR(y);
658         sec = ((( days * 24 +
659                   readrtc(RTC_HRS)) * 60 +
660                 readrtc(RTC_MIN)) * 60 +
661                readrtc(RTC_SEC));
662         /* sec now contains the number of seconds, since Jan 1 1970,
663            in the local time zone */
664
665         sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
666
667         y = time_second - sec;
668         if (y <= -2 || y >= 2) {
669                 /* badly off, adjust it */
670                 ts.tv_sec = sec;
671                 ts.tv_nsec = 0;
672                 tc_setclock(&ts);
673         }
674         splx(s);
675         return;
676
677  wrong_time:
678         printf("Invalid time in real time clock.\n");
679         printf("Check and reset the date immediately!\n");
680 }
681
682
683 /*
684  * Write system time back to RTC
685  */
686 void
687 resettodr()
688 {
689         unsigned long   tm;
690         int             y, m, s;
691
692         if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
693                 domu_resettodr();
694                 return;
695         }
696                
697         if (xen_disable_rtc_set)
698                 return;
699
700         s = splclock();
701         tm = time_second;
702         splx(s);
703
704         /* Disable RTC updates and interrupts. */
705         writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
706
707         /* Calculate local time to put in RTC */
708
709         tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
710
711         writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;    /* Write back Seconds */
712         writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;    /* Write back Minutes */
713         writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;    /* Write back Hours   */
714
715         /* We have now the days since 01-01-1970 in tm */
716         writertc(RTC_WDAY, (tm + 4) % 7 + 1);           /* Write back Weekday */
717         for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
718              tm >= m;
719              y++,      m = DAYSPERYEAR + LEAPYEAR(y))
720                 tm -= m;
721
722         /* Now we have the years in y and the day-of-the-year in tm */
723         writertc(RTC_YEAR, bin2bcd(y%100));             /* Write back Year    */
724 #ifdef USE_RTC_CENTURY
725         writertc(RTC_CENTURY, bin2bcd(y/100));          /* ... and Century    */
726 #endif
727         for (m = 0; ; m++) {
728                 int ml;
729
730                 ml = daysinmonth[m];
731                 if (m == 1 && LEAPYEAR(y))
732                         ml++;
733                 if (tm < ml)
734                         break;
735                 tm -= ml;
736         }
737
738         writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
739         writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
740
741         /* Reenable RTC updates and interrupts. */
742         writertc(RTC_STATUSB, RTCSB_24HR);
743         rtcin(RTC_INTR);
744 }
745 #endif
746
747 static struct vcpu_set_periodic_timer xen_set_periodic_tick;
748
749 /*
750  * Start clocks running.
751  */
752 void
753 cpu_initclocks(void)
754 {
755         int time_irq;
756
757         xen_set_periodic_tick.period_ns = NS_PER_TICK;
758
759         HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
760                            &xen_set_periodic_tick);
761
762         if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk", 
763                                                 (driver_filter_t *)clkintr, NULL,
764                                                 INTR_TYPE_CLK | INTR_FAST)) < 0) {
765                 panic("failed to register clock interrupt\n");
766         }
767
768         /* should fast clock be enabled ? */
769 }
770
771 /*
772  *
773  * XXX 
774  */
775 #if 0 && defined(SMP)
776 void
777 ap_cpu_initclocks(void)
778 {
779         int irq;
780         int cpu = smp_processor_id();
781         
782         per_cpu(processed_system_time, cpu) = processed_system_time;
783
784         irq = bind_virq_to_irq(VIRQ_TIMER);
785         PCPU_SET(time_irq, irq);
786         PANIC_IF(intr_add_handler("clk", irq, (driver_filter_t *)clkintr, NULL,
787                                   NULL, INTR_TYPE_CLK | INTR_FAST, NULL));
788 }
789 #endif
790
791 void
792 cpu_startprofclock(void)
793 {
794
795         printf("cpu_startprofclock: profiling clock is not supported\n");
796 }
797
798 void
799 cpu_stopprofclock(void)
800 {
801
802         printf("cpu_stopprofclock: profiling clock is not supported\n");
803 }
804 #define NSEC_PER_USEC 1000
805
806 static uint32_t
807 xen_get_timecount(struct timecounter *tc)
808 {       
809         uint64_t clk;
810         struct shadow_time_info *shadow;
811         shadow = &per_cpu(shadow_time, smp_processor_id());
812
813         __get_time_values_from_xen();
814         
815         clk = shadow->system_timestamp + get_nsec_offset(shadow);
816
817         return (uint32_t)((clk / NS_PER_TICK) * NS_PER_TICK);
818
819 }
820
821 /* Return system time offset by ticks */
822 uint64_t
823 get_system_time(int ticks)
824 {
825     return processed_system_time + (ticks * NS_PER_TICK);
826 }
827
828 /*
829  * Track behavior of cur_timer->get_offset() functionality in timer_tsc.c
830  */
831
832 #if 0
833 static uint32_t
834 xen_get_offset(void)
835 {
836         register unsigned long eax, edx;
837
838         /* Read the Time Stamp Counter */
839
840         rdtsc(eax,edx);
841
842         /* .. relative to previous jiffy (32 bits is enough) */
843         eax -= shadow_tsc_stamp;
844
845         /*
846          * Time offset = (tsc_low delta) * cached_gtm
847          *             = (tsc_low delta) * (usecs_per_clock)
848          *             = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
849          *
850          * Using a mull instead of a divl saves up to 31 clock cycles
851          * in the critical path.
852          */
853
854         __asm__("mull %2"
855                 :"=a" (eax), "=d" (edx)
856                 :"rm" (cached_gtm),
857                 "0" (eax));
858
859         /* our adjusted time offset in microseconds */
860         return edx;
861 }
862 #endif
863 void
864 idle_block(void)
865 {
866
867         __get_time_values_from_xen();
868         PANIC_IF(HYPERVISOR_set_timer_op(processed_system_time + NS_PER_TICK) != 0);
869         HYPERVISOR_sched_op(SCHEDOP_block, 0);
870 }
871
872 int
873 timer_spkr_acquire(void)
874 {
875
876         return (0);
877 }
878
879 int
880 timer_spkr_release(void)
881 {
882
883         return (0);
884 }
885
886 void
887 timer_spkr_setfreq(int freq)
888 {
889
890 }
891
892
893         
894