PERFORCE change 89281 for review
Kip Macy
kmacy at FreeBSD.org
Fri Jan 6 10:48:42 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=89281
Change 89281 by kmacy at kmacy:freebsd7_xen3 on 2006/01/06 18:48:06
add dom0 support to clock driver still confused between setting time of day
and rtc add in new option for setting hardware rtc
Affected files ...
.. //depot/projects/xen3/src/sys/conf/options.i386-xen#3 edit
.. //depot/projects/xen3/src/sys/i386-xen/i386-xen/clock.c#7 edit
Differences ...
==== //depot/projects/xen3/src/sys/conf/options.i386-xen#3 (text+ko) ====
@@ -39,6 +39,10 @@
# support physical device access
XEN_PHYSDEV_ACCESS opt_global.h
+# unclear how this differs from the being PHYSDEV_ACCESS + INITDOMAIN but
+# stay consistent with mainline for now
+XEN_PRIVILEGED_GUEST opt_global.h
+
# Physical address extensions and support for >4G ram. As above.
PAE opt_global.h
==== //depot/projects/xen3/src/sys/i386-xen/i386-xen/clock.c#7 (text+ko) ====
@@ -44,16 +44,7 @@
* Routines to handle clock hardware.
*/
-/*
- * inittodr, settodr and support routines written
- * by Christoph Robitschko <chmr at edvz.tu-graz.ac.at>
- *
- * reintroduced and updated by Chris Stenton <chris at gnome.co.uk> 8/10/94
- */
-
#include "opt_clock.h"
-#include "opt_isa.h"
-#include "opt_mca.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -110,6 +101,7 @@
#define TIMER_FREQ 1193182
#endif
int wall_cmos_clock;
+int independent_wallclock;
u_int timer_freq = TIMER_FREQ;
struct mtx clock_lock;
@@ -134,7 +126,10 @@
uint32_t shadow_tv_version;
+SYSCTL_INT(_machdep, OID_AUTO, independent_wallclock,
+ CTLFLAG_RW, &independent_wallclock, 0, "");
+
#define do_div(n,base) ({ \
unsigned long __upper, __low, __high, __mod, __base; \
__base = (base); \
@@ -518,6 +513,7 @@
rdtscll(alarm);
}
+#ifdef XEN_PRIVILEGED_GUEST
/*
* Initialize the time of day register, based on the time base which is, e.g.
* from a filesystem.
@@ -525,6 +521,143 @@
void
inittodr(time_t base)
{
+ unsigned long sec, days;
+ int year, month;
+ int y, m, s;
+ struct timespec ts;
+
+ if (base) {
+ s = splclock();
+ ts.tv_sec = base;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
+ splx(s);
+ }
+
+ /* Look if we have a RTC present and the time is valid */
+ if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
+ goto wrong_time;
+
+ /* wait for time update to complete */
+ /* If RTCSA_TUP is zero, we have at least 244us before next update */
+ s = splhigh();
+ while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
+ splx(s);
+ s = splhigh();
+ }
+
+ days = 0;
+#ifdef USE_RTC_CENTURY
+ year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
+#else
+ year = readrtc(RTC_YEAR) + 1900;
+ if (year < 1970)
+ year += 100;
+#endif
+ if (year < 1970) {
+ splx(s);
+ goto wrong_time;
+ }
+ month = readrtc(RTC_MONTH);
+ for (m = 1; m < month; m++)
+ days += daysinmonth[m-1];
+ if ((month > 2) && LEAPYEAR(year))
+ days ++;
+ days += readrtc(RTC_DAY) - 1;
+ for (y = 1970; y < year; y++)
+ days += DAYSPERYEAR + LEAPYEAR(y);
+ sec = ((( days * 24 +
+ readrtc(RTC_HRS)) * 60 +
+ readrtc(RTC_MIN)) * 60 +
+ readrtc(RTC_SEC));
+ /* sec now contains the number of seconds, since Jan 1 1970,
+ in the local time zone */
+
+ sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
+
+ y = time_second - sec;
+ if (y <= -2 || y >= 2) {
+ /* badly off, adjust it */
+ ts.tv_sec = sec;
+ ts.tv_nsec = 0;
+ tc_setclock(&ts);
+ }
+ splx(s);
+ return;
+
+wrong_time:
+ printf("Invalid time in real time clock.\n");
+ printf("Check and reset the date immediately!\n");
+}
+
+
+
+/*
+ * Write system time back to RTC
+ */
+void
+resettodr()
+{
+ unsigned long tm;
+ int y, m, s;
+
+ if (disable_rtc_set)
+ return;
+
+ s = splclock();
+ tm = time_second;
+ splx(s);
+
+ /* Disable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
+
+ /* Calculate local time to put in RTC */
+
+ tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
+
+ writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */
+ writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */
+ writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24; /* Write back Hours */
+
+ /* We have now the days since 01-01-1970 in tm */
+ writertc(RTC_WDAY, (tm + 4) % 7 + 1); /* Write back Weekday */
+ for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
+ tm >= m;
+ y++, m = DAYSPERYEAR + LEAPYEAR(y))
+ tm -= m;
+
+ /* Now we have the years in y and the day-of-the-year in tm */
+ writertc(RTC_YEAR, bin2bcd(y%100)); /* Write back Year */
+#ifdef USE_RTC_CENTURY
+ writertc(RTC_CENTURY, bin2bcd(y/100)); /* ... and Century */
+#endif
+ for (m = 0; ; m++) {
+ int ml;
+
+ ml = daysinmonth[m];
+ if (m == 1 && LEAPYEAR(y))
+ ml++;
+ if (tm < ml)
+ break;
+ tm -= ml;
+ }
+
+ writertc(RTC_MONTH, bin2bcd(m + 1)); /* Write back Month */
+ writertc(RTC_DAY, bin2bcd(tm + 1)); /* Write back Month Day */
+
+ /* Reenable RTC updates and interrupts. */
+ writertc(RTC_STATUSB, rtc_statusb);
+ rtcin(RTC_INTR);
+}
+
+#else
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+void
+inittodr(time_t base)
+{
unsigned long sec;
int s, y;
struct timespec ts;
@@ -549,13 +682,41 @@
}
/*
- * Write system time back to RTC. Not supported for guest domains.
+ * Write system time back to RTC.
*/
void
resettodr()
{
+ unsigned long tm;
+ int s;
+ dom0_op_t op;
+ struct shadow_time_info *shadow;
+
+ shadow = &per_cpu(shadow_time, smp_processor_id());
+ if (disable_rtc_set)
+ return;
+
+ s = splclock();
+ tm = time_second;
+ splx(s);
+
+ tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
+
+ if ((xen_start_info->flags & SIF_INITDOMAIN) &&
+ !independent_wallclock)
+ {
+ op.cmd = DOM0_SETTIME;
+ op.u.settime.secs = tm;
+ op.u.settime.nsecs = 0;
+ op.u.settime.system_time = shadow->system_timestamp;
+ HYPERVISOR_dom0_op(&op);
+ update_wallclock();
+ } else if (independent_wallclock) {
+ /* notyet */
+ ;
+ }
}
-
+#endif
/*
* Start clocks running.
More information about the p4-projects
mailing list