The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/vmm/io/vrtc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2014, Neel Natu (neel@freebsd.org)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    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  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_bhyve_snapshot.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/queue.h>
   37 #include <sys/kernel.h>
   38 #include <sys/malloc.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/clock.h>
   42 #include <sys/sysctl.h>
   43 
   44 #include <machine/vmm.h>
   45 #include <machine/vmm_snapshot.h>
   46 
   47 #include <isa/rtc.h>
   48 
   49 #include "vmm_ktr.h"
   50 #include "vatpic.h"
   51 #include "vioapic.h"
   52 #include "vrtc.h"
   53 
   54 /* Register layout of the RTC */
   55 struct rtcdev {
   56         uint8_t sec;
   57         uint8_t alarm_sec;
   58         uint8_t min;
   59         uint8_t alarm_min;
   60         uint8_t hour;
   61         uint8_t alarm_hour;
   62         uint8_t day_of_week;
   63         uint8_t day_of_month;
   64         uint8_t month;
   65         uint8_t year;
   66         uint8_t reg_a;
   67         uint8_t reg_b;
   68         uint8_t reg_c;
   69         uint8_t reg_d;
   70         uint8_t nvram[36];
   71         uint8_t century;
   72         uint8_t nvram2[128 - 51];
   73 } __packed;
   74 CTASSERT(sizeof(struct rtcdev) == 128);
   75 CTASSERT(offsetof(struct rtcdev, century) == RTC_CENTURY);
   76 
   77 struct vrtc {
   78         struct vm       *vm;
   79         struct mtx      mtx;
   80         struct callout  callout;
   81         u_int           addr;           /* RTC register to read or write */
   82         sbintime_t      base_uptime;
   83         time_t          base_rtctime;
   84         struct rtcdev   rtcdev;
   85 };
   86 
   87 #define VRTC_LOCK(vrtc)         mtx_lock(&((vrtc)->mtx))
   88 #define VRTC_UNLOCK(vrtc)       mtx_unlock(&((vrtc)->mtx))
   89 #define VRTC_LOCKED(vrtc)       mtx_owned(&((vrtc)->mtx))
   90 
   91 /*
   92  * RTC time is considered "broken" if:
   93  * - RTC updates are halted by the guest
   94  * - RTC date/time fields have invalid values
   95  */
   96 #define VRTC_BROKEN_TIME        ((time_t)-1)
   97 
   98 #define RTC_IRQ                 8
   99 #define RTCSB_BIN               0x04
  100 #define RTCSB_ALL_INTRS         (RTCSB_UINTR | RTCSB_AINTR | RTCSB_PINTR)
  101 #define rtc_halted(vrtc)        ((vrtc->rtcdev.reg_b & RTCSB_HALT) != 0)
  102 #define aintr_enabled(vrtc)     (((vrtc)->rtcdev.reg_b & RTCSB_AINTR) != 0)
  103 #define pintr_enabled(vrtc)     (((vrtc)->rtcdev.reg_b & RTCSB_PINTR) != 0)
  104 #define uintr_enabled(vrtc)     (((vrtc)->rtcdev.reg_b & RTCSB_UINTR) != 0)
  105 
  106 static void vrtc_callout_handler(void *arg);
  107 static void vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval);
  108 
  109 static MALLOC_DEFINE(M_VRTC, "vrtc", "bhyve virtual rtc");
  110 
  111 SYSCTL_DECL(_hw_vmm);
  112 SYSCTL_NODE(_hw_vmm, OID_AUTO, vrtc, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
  113     NULL);
  114 
  115 static int rtc_flag_broken_time = 1;
  116 SYSCTL_INT(_hw_vmm_vrtc, OID_AUTO, flag_broken_time, CTLFLAG_RDTUN,
  117     &rtc_flag_broken_time, 0, "Stop guest when invalid RTC time is detected");
  118 
  119 static __inline bool
  120 divider_enabled(int reg_a)
  121 {
  122         /*
  123          * The RTC is counting only when dividers are not held in reset.
  124          */
  125         return ((reg_a & 0x70) == 0x20);
  126 }
  127 
  128 static __inline bool
  129 update_enabled(struct vrtc *vrtc)
  130 {
  131         /*
  132          * RTC date/time can be updated only if:
  133          * - divider is not held in reset
  134          * - guest has not disabled updates
  135          * - the date/time fields have valid contents
  136          */
  137         if (!divider_enabled(vrtc->rtcdev.reg_a))
  138                 return (false);
  139 
  140         if (rtc_halted(vrtc))
  141                 return (false);
  142 
  143         if (vrtc->base_rtctime == VRTC_BROKEN_TIME)
  144                 return (false);
  145 
  146         return (true);
  147 }
  148 
  149 static time_t
  150 vrtc_curtime(struct vrtc *vrtc, sbintime_t *basetime)
  151 {
  152         sbintime_t now, delta;
  153         time_t t, secs;
  154 
  155         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  156 
  157         t = vrtc->base_rtctime;
  158         *basetime = vrtc->base_uptime;
  159         if (update_enabled(vrtc)) {
  160                 now = sbinuptime();
  161                 delta = now - vrtc->base_uptime;
  162                 KASSERT(delta >= 0, ("vrtc_curtime: uptime went backwards: "
  163                     "%#lx to %#lx", vrtc->base_uptime, now));
  164                 secs = delta / SBT_1S;
  165                 t += secs;
  166                 *basetime += secs * SBT_1S;
  167         }
  168         return (t);
  169 }
  170 
  171 static __inline uint8_t
  172 rtcset(struct rtcdev *rtc, int val)
  173 {
  174 
  175         KASSERT(val >= 0 && val < 100, ("%s: invalid bin2bcd index %d",
  176             __func__, val));
  177 
  178         return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]);
  179 }
  180 
  181 static void
  182 secs_to_rtc(time_t rtctime, struct vrtc *vrtc, int force_update)
  183 {
  184         struct clocktime ct;
  185         struct timespec ts;
  186         struct rtcdev *rtc;
  187         int hour;
  188 
  189         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  190 
  191         if (rtctime < 0) {
  192                 KASSERT(rtctime == VRTC_BROKEN_TIME,
  193                     ("%s: invalid vrtc time %#lx", __func__, rtctime));
  194                 return;
  195         }
  196 
  197         /*
  198          * If the RTC is halted then the guest has "ownership" of the
  199          * date/time fields. Don't update the RTC date/time fields in
  200          * this case (unless forced).
  201          */
  202         if (rtc_halted(vrtc) && !force_update)
  203                 return;
  204 
  205         ts.tv_sec = rtctime;
  206         ts.tv_nsec = 0;
  207         clock_ts_to_ct(&ts, &ct);
  208 
  209         KASSERT(ct.sec >= 0 && ct.sec <= 59, ("invalid clocktime sec %d",
  210             ct.sec));
  211         KASSERT(ct.min >= 0 && ct.min <= 59, ("invalid clocktime min %d",
  212             ct.min));
  213         KASSERT(ct.hour >= 0 && ct.hour <= 23, ("invalid clocktime hour %d",
  214             ct.hour));
  215         KASSERT(ct.dow >= 0 && ct.dow <= 6, ("invalid clocktime wday %d",
  216             ct.dow));
  217         KASSERT(ct.day >= 1 && ct.day <= 31, ("invalid clocktime mday %d",
  218             ct.day));
  219         KASSERT(ct.mon >= 1 && ct.mon <= 12, ("invalid clocktime month %d",
  220             ct.mon));
  221         KASSERT(ct.year >= POSIX_BASE_YEAR, ("invalid clocktime year %d",
  222             ct.year));
  223 
  224         rtc = &vrtc->rtcdev;
  225         rtc->sec = rtcset(rtc, ct.sec);
  226         rtc->min = rtcset(rtc, ct.min);
  227 
  228         if (rtc->reg_b & RTCSB_24HR) {
  229                 hour = ct.hour;
  230         } else {
  231                 /*
  232                  * Convert to the 12-hour format.
  233                  */
  234                 switch (ct.hour) {
  235                 case 0:                 /* 12 AM */
  236                 case 12:                /* 12 PM */
  237                         hour = 12;
  238                         break;
  239                 default:
  240                         /*
  241                          * The remaining 'ct.hour' values are interpreted as:
  242                          * [1  - 11] ->  1 - 11 AM
  243                          * [13 - 23] ->  1 - 11 PM
  244                          */
  245                         hour = ct.hour % 12;
  246                         break;
  247                 }
  248         }
  249 
  250         rtc->hour = rtcset(rtc, hour);
  251 
  252         if ((rtc->reg_b & RTCSB_24HR) == 0 && ct.hour >= 12)
  253                 rtc->hour |= 0x80;          /* set MSB to indicate PM */
  254 
  255         rtc->day_of_week = rtcset(rtc, ct.dow + 1);
  256         rtc->day_of_month = rtcset(rtc, ct.day);
  257         rtc->month = rtcset(rtc, ct.mon);
  258         rtc->year = rtcset(rtc, ct.year % 100);
  259         rtc->century = rtcset(rtc, ct.year / 100);
  260 }
  261 
  262 static int
  263 rtcget(struct rtcdev *rtc, int val, int *retval)
  264 {
  265         uint8_t upper, lower;
  266 
  267         if (rtc->reg_b & RTCSB_BIN) {
  268                 *retval = val;
  269                 return (0);
  270         }
  271 
  272         lower = val & 0xf;
  273         upper = (val >> 4) & 0xf;
  274 
  275         if (lower > 9 || upper > 9)
  276                 return (-1);
  277 
  278         *retval = upper * 10 + lower;
  279         return (0);
  280 }
  281 
  282 static time_t
  283 rtc_to_secs(struct vrtc *vrtc)
  284 {
  285         struct clocktime ct;
  286         struct timespec ts;
  287         struct rtcdev *rtc;
  288 #ifdef KTR
  289         struct vm *vm = vrtc->vm;
  290 #endif
  291         int century, error, hour, pm, year;
  292 
  293         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  294 
  295         rtc = &vrtc->rtcdev;
  296 
  297         bzero(&ct, sizeof(struct clocktime));
  298 
  299         error = rtcget(rtc, rtc->sec, &ct.sec);
  300         if (error || ct.sec < 0 || ct.sec > 59) {
  301                 VM_CTR2(vm, "Invalid RTC sec %#x/%d", rtc->sec, ct.sec);
  302                 goto fail;
  303         }
  304 
  305         error = rtcget(rtc, rtc->min, &ct.min);
  306         if (error || ct.min < 0 || ct.min > 59) {
  307                 VM_CTR2(vm, "Invalid RTC min %#x/%d", rtc->min, ct.min);
  308                 goto fail;
  309         }
  310 
  311         pm = 0;
  312         hour = rtc->hour;
  313         if ((rtc->reg_b & RTCSB_24HR) == 0) {
  314                 if (hour & 0x80) {
  315                         hour &= ~0x80;
  316                         pm = 1;
  317                 }
  318         }
  319         error = rtcget(rtc, hour, &ct.hour);
  320         if ((rtc->reg_b & RTCSB_24HR) == 0) {
  321                 if (ct.hour >= 1 && ct.hour <= 12) {
  322                         /*
  323                          * Convert from 12-hour format to internal 24-hour
  324                          * representation as follows:
  325                          *
  326                          *    12-hour format            ct.hour
  327                          *      12      AM              0
  328                          *      1 - 11  AM              1 - 11
  329                          *      12      PM              12
  330                          *      1 - 11  PM              13 - 23
  331                          */
  332                         if (ct.hour == 12)
  333                                 ct.hour = 0;
  334                         if (pm)
  335                                 ct.hour += 12;
  336                 } else {
  337                         VM_CTR2(vm, "Invalid RTC 12-hour format %#x/%d",
  338                             rtc->hour, ct.hour);
  339                         goto fail;
  340                 }
  341         }
  342 
  343         if (error || ct.hour < 0 || ct.hour > 23) {
  344                 VM_CTR2(vm, "Invalid RTC hour %#x/%d", rtc->hour, ct.hour);
  345                 goto fail;
  346         }
  347 
  348         /*
  349          * Ignore 'rtc->dow' because some guests like Linux don't bother
  350          * setting it at all while others like OpenBSD/i386 set it incorrectly. 
  351          *
  352          * clock_ct_to_ts() does not depend on 'ct.dow' anyways so ignore it.
  353          */
  354         ct.dow = -1;
  355 
  356         error = rtcget(rtc, rtc->day_of_month, &ct.day);
  357         if (error || ct.day < 1 || ct.day > 31) {
  358                 VM_CTR2(vm, "Invalid RTC mday %#x/%d", rtc->day_of_month,
  359                     ct.day);
  360                 goto fail;
  361         }
  362 
  363         error = rtcget(rtc, rtc->month, &ct.mon);
  364         if (error || ct.mon < 1 || ct.mon > 12) {
  365                 VM_CTR2(vm, "Invalid RTC month %#x/%d", rtc->month, ct.mon);
  366                 goto fail;
  367         }
  368 
  369         error = rtcget(rtc, rtc->year, &year);
  370         if (error || year < 0 || year > 99) {
  371                 VM_CTR2(vm, "Invalid RTC year %#x/%d", rtc->year, year);
  372                 goto fail;
  373         }
  374 
  375         error = rtcget(rtc, rtc->century, &century);
  376         ct.year = century * 100 + year;
  377         if (error || ct.year < POSIX_BASE_YEAR) {
  378                 VM_CTR2(vm, "Invalid RTC century %#x/%d", rtc->century,
  379                     ct.year);
  380                 goto fail;
  381         }
  382 
  383         error = clock_ct_to_ts(&ct, &ts);
  384         if (error || ts.tv_sec < 0) {
  385                 VM_CTR3(vm, "Invalid RTC clocktime.date %04d-%02d-%02d",
  386                     ct.year, ct.mon, ct.day);
  387                 VM_CTR3(vm, "Invalid RTC clocktime.time %02d:%02d:%02d",
  388                     ct.hour, ct.min, ct.sec);
  389                 goto fail;
  390         }
  391         return (ts.tv_sec);             /* success */
  392 fail:
  393         /*
  394          * Stop updating the RTC if the date/time fields programmed by
  395          * the guest are invalid.
  396          */
  397         VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected");
  398         return (VRTC_BROKEN_TIME);
  399 }
  400 
  401 static int
  402 vrtc_time_update(struct vrtc *vrtc, time_t newtime, sbintime_t newbase)
  403 {
  404         struct rtcdev *rtc;
  405         time_t oldtime;
  406         uint8_t alarm_sec, alarm_min, alarm_hour;
  407 
  408         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  409 
  410         rtc = &vrtc->rtcdev;
  411         alarm_sec = rtc->alarm_sec;
  412         alarm_min = rtc->alarm_min;
  413         alarm_hour = rtc->alarm_hour;
  414 
  415         oldtime = vrtc->base_rtctime;
  416         VM_CTR2(vrtc->vm, "Updating RTC secs from %#lx to %#lx",
  417             oldtime, newtime);
  418 
  419         VM_CTR2(vrtc->vm, "Updating RTC base uptime from %#lx to %#lx",
  420             vrtc->base_uptime, newbase);
  421         vrtc->base_uptime = newbase;
  422 
  423         if (newtime == oldtime)
  424                 return (0);
  425 
  426         /*
  427          * If 'newtime' indicates that RTC updates are disabled then just
  428          * record that and return. There is no need to do alarm interrupt
  429          * processing in this case.
  430          */
  431         if (newtime == VRTC_BROKEN_TIME) {
  432                 vrtc->base_rtctime = VRTC_BROKEN_TIME;
  433                 return (0);
  434         }
  435 
  436         /*
  437          * Return an error if RTC updates are halted by the guest.
  438          */
  439         if (rtc_halted(vrtc)) {
  440                 VM_CTR0(vrtc->vm, "RTC update halted by guest");
  441                 return (EBUSY);
  442         }
  443 
  444         do {
  445                 /*
  446                  * If the alarm interrupt is enabled and 'oldtime' is valid
  447                  * then visit all the seconds between 'oldtime' and 'newtime'
  448                  * to check for the alarm condition.
  449                  *
  450                  * Otherwise move the RTC time forward directly to 'newtime'.
  451                  */
  452                 if (aintr_enabled(vrtc) && oldtime != VRTC_BROKEN_TIME)
  453                         vrtc->base_rtctime++;
  454                 else
  455                         vrtc->base_rtctime = newtime;
  456 
  457                 if (aintr_enabled(vrtc)) {
  458                         /*
  459                          * Update the RTC date/time fields before checking
  460                          * if the alarm conditions are satisfied.
  461                          */
  462                         secs_to_rtc(vrtc->base_rtctime, vrtc, 0);
  463 
  464                         if ((alarm_sec >= 0xC0 || alarm_sec == rtc->sec) &&
  465                             (alarm_min >= 0xC0 || alarm_min == rtc->min) &&
  466                             (alarm_hour >= 0xC0 || alarm_hour == rtc->hour)) {
  467                                 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_ALARM);
  468                         }
  469                 }
  470         } while (vrtc->base_rtctime != newtime);
  471 
  472         if (uintr_enabled(vrtc))
  473                 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE);
  474 
  475         return (0);
  476 }
  477 
  478 static sbintime_t
  479 vrtc_freq(struct vrtc *vrtc)
  480 {
  481         int ratesel;
  482 
  483         static sbintime_t pf[16] = {
  484                 0,
  485                 SBT_1S / 256,
  486                 SBT_1S / 128,
  487                 SBT_1S / 8192,
  488                 SBT_1S / 4096,
  489                 SBT_1S / 2048,
  490                 SBT_1S / 1024,
  491                 SBT_1S / 512,
  492                 SBT_1S / 256,
  493                 SBT_1S / 128,
  494                 SBT_1S / 64,
  495                 SBT_1S / 32,
  496                 SBT_1S / 16,
  497                 SBT_1S / 8,
  498                 SBT_1S / 4,
  499                 SBT_1S / 2,
  500         };
  501 
  502         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  503 
  504         /*
  505          * If both periodic and alarm interrupts are enabled then use the
  506          * periodic frequency to drive the callout. The minimum periodic
  507          * frequency (2 Hz) is higher than the alarm frequency (1 Hz) so
  508          * piggyback the alarm on top of it. The same argument applies to
  509          * the update interrupt.
  510          */
  511         if (pintr_enabled(vrtc) && divider_enabled(vrtc->rtcdev.reg_a)) {
  512                 ratesel = vrtc->rtcdev.reg_a & 0xf;
  513                 return (pf[ratesel]);
  514         } else if (aintr_enabled(vrtc) && update_enabled(vrtc)) {
  515                 return (SBT_1S);
  516         } else if (uintr_enabled(vrtc) && update_enabled(vrtc)) {
  517                 return (SBT_1S);
  518         } else {
  519                 return (0);
  520         }
  521 }
  522 
  523 static void
  524 vrtc_callout_reset(struct vrtc *vrtc, sbintime_t freqsbt)
  525 {
  526 
  527         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  528 
  529         if (freqsbt == 0) {
  530                 if (callout_active(&vrtc->callout)) {
  531                         VM_CTR0(vrtc->vm, "RTC callout stopped");
  532                         callout_stop(&vrtc->callout);
  533                 }
  534                 return;
  535         }
  536         VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt);
  537         callout_reset_sbt(&vrtc->callout, freqsbt, 0, vrtc_callout_handler,
  538             vrtc, 0);
  539 }
  540 
  541 static void
  542 vrtc_callout_handler(void *arg)
  543 {
  544         struct vrtc *vrtc = arg;
  545         sbintime_t freqsbt, basetime;
  546         time_t rtctime;
  547         int error __diagused;
  548 
  549         VM_CTR0(vrtc->vm, "vrtc callout fired");
  550 
  551         VRTC_LOCK(vrtc);
  552         if (callout_pending(&vrtc->callout))    /* callout was reset */
  553                 goto done;
  554 
  555         if (!callout_active(&vrtc->callout))    /* callout was stopped */
  556                 goto done;
  557 
  558         callout_deactivate(&vrtc->callout);
  559 
  560         KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) != 0,
  561             ("gratuitous vrtc callout"));
  562 
  563         if (pintr_enabled(vrtc))
  564                 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c | RTCIR_PERIOD);
  565 
  566         if (aintr_enabled(vrtc) || uintr_enabled(vrtc)) {
  567                 rtctime = vrtc_curtime(vrtc, &basetime);
  568                 error = vrtc_time_update(vrtc, rtctime, basetime);
  569                 KASSERT(error == 0, ("%s: vrtc_time_update error %d",
  570                     __func__, error));
  571         }
  572 
  573         freqsbt = vrtc_freq(vrtc);
  574         KASSERT(freqsbt != 0, ("%s: vrtc frequency cannot be zero", __func__));
  575         vrtc_callout_reset(vrtc, freqsbt);
  576 done:
  577         VRTC_UNLOCK(vrtc);
  578 }
  579 
  580 static __inline void
  581 vrtc_callout_check(struct vrtc *vrtc, sbintime_t freq)
  582 {
  583         int active __diagused;
  584 
  585         active = callout_active(&vrtc->callout) ? 1 : 0;
  586         KASSERT((freq == 0 && !active) || (freq != 0 && active),
  587             ("vrtc callout %s with frequency %#lx",
  588             active ? "active" : "inactive", freq));
  589 }
  590 
  591 static void
  592 vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval)
  593 {
  594         struct rtcdev *rtc;
  595         int oldirqf, newirqf;
  596         uint8_t oldval, changed;
  597 
  598         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  599 
  600         rtc = &vrtc->rtcdev;
  601         newval &= RTCIR_ALARM | RTCIR_PERIOD | RTCIR_UPDATE;
  602 
  603         oldirqf = rtc->reg_c & RTCIR_INT;
  604         if ((aintr_enabled(vrtc) && (newval & RTCIR_ALARM) != 0) ||
  605             (pintr_enabled(vrtc) && (newval & RTCIR_PERIOD) != 0) ||
  606             (uintr_enabled(vrtc) && (newval & RTCIR_UPDATE) != 0)) {
  607                 newirqf = RTCIR_INT;
  608         } else {
  609                 newirqf = 0;
  610         }
  611 
  612         oldval = rtc->reg_c;
  613         rtc->reg_c = newirqf | newval;
  614         changed = oldval ^ rtc->reg_c;
  615         if (changed) {
  616                 VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to %#x",
  617                     oldval, rtc->reg_c);
  618         }
  619 
  620         if (!oldirqf && newirqf) {
  621                 VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ);
  622                 vatpic_pulse_irq(vrtc->vm, RTC_IRQ);
  623                 vioapic_pulse_irq(vrtc->vm, RTC_IRQ);
  624         } else if (oldirqf && !newirqf) {
  625                 VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ);
  626         }
  627 }
  628 
  629 static int
  630 vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
  631 {
  632         struct rtcdev *rtc;
  633         sbintime_t oldfreq, newfreq, basetime;
  634         time_t curtime, rtctime;
  635         int error __diagused;
  636         uint8_t oldval, changed;
  637 
  638         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  639 
  640         rtc = &vrtc->rtcdev;
  641         oldval = rtc->reg_b;
  642         oldfreq = vrtc_freq(vrtc);
  643 
  644         rtc->reg_b = newval;
  645         changed = oldval ^ newval;
  646         if (changed) {
  647                 VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to %#x",
  648                     oldval, newval);
  649         }
  650 
  651         if (changed & RTCSB_HALT) {
  652                 if ((newval & RTCSB_HALT) == 0) {
  653                         rtctime = rtc_to_secs(vrtc);
  654                         basetime = sbinuptime();
  655                         if (rtctime == VRTC_BROKEN_TIME) {
  656                                 if (rtc_flag_broken_time)
  657                                         return (-1);
  658                         }
  659                 } else {
  660                         curtime = vrtc_curtime(vrtc, &basetime);
  661                         KASSERT(curtime == vrtc->base_rtctime, ("%s: mismatch "
  662                             "between vrtc basetime (%#lx) and curtime (%#lx)",
  663                             __func__, vrtc->base_rtctime, curtime));
  664 
  665                         /*
  666                          * Force a refresh of the RTC date/time fields so
  667                          * they reflect the time right before the guest set
  668                          * the HALT bit.
  669                          */
  670                         secs_to_rtc(curtime, vrtc, 1);
  671 
  672                         /*
  673                          * Updates are halted so mark 'base_rtctime' to denote
  674                          * that the RTC date/time is in flux.
  675                          */
  676                         rtctime = VRTC_BROKEN_TIME;
  677                         rtc->reg_b &= ~RTCSB_UINTR;
  678                 }
  679                 error = vrtc_time_update(vrtc, rtctime, basetime);
  680                 KASSERT(error == 0, ("vrtc_time_update error %d", error));
  681         }
  682 
  683         /*
  684          * Side effect of changes to the interrupt enable bits.
  685          */
  686         if (changed & RTCSB_ALL_INTRS)
  687                 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c);
  688 
  689         /*
  690          * Change the callout frequency if it has changed.
  691          */
  692         newfreq = vrtc_freq(vrtc);
  693         if (newfreq != oldfreq)
  694                 vrtc_callout_reset(vrtc, newfreq);
  695         else
  696                 vrtc_callout_check(vrtc, newfreq);
  697 
  698         /*
  699          * The side effect of bits that control the RTC date/time format
  700          * is handled lazily when those fields are actually read.
  701          */
  702         return (0);
  703 }
  704 
  705 static void
  706 vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval)
  707 {
  708         sbintime_t oldfreq, newfreq;
  709         uint8_t oldval, changed;
  710 
  711         KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
  712 
  713         newval &= ~RTCSA_TUP;
  714         oldval = vrtc->rtcdev.reg_a;
  715         oldfreq = vrtc_freq(vrtc);
  716 
  717         if (divider_enabled(oldval) && !divider_enabled(newval)) {
  718                 VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx",
  719                     vrtc->base_rtctime, vrtc->base_uptime);
  720         } else if (!divider_enabled(oldval) && divider_enabled(newval)) {
  721                 /*
  722                  * If the dividers are coming out of reset then update
  723                  * 'base_uptime' before this happens. This is done to
  724                  * maintain the illusion that the RTC date/time was frozen
  725                  * while the dividers were disabled.
  726                  */
  727                 vrtc->base_uptime = sbinuptime();
  728                 VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx",
  729                     vrtc->base_rtctime, vrtc->base_uptime);
  730         } else {
  731                 /* NOTHING */
  732         }
  733 
  734         vrtc->rtcdev.reg_a = newval;
  735         changed = oldval ^ newval;
  736         if (changed) {
  737                 VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x",
  738                     oldval, newval);
  739         }
  740 
  741         /*
  742          * Side effect of changes to rate select and divider enable bits.
  743          */
  744         newfreq = vrtc_freq(vrtc);
  745         if (newfreq != oldfreq)
  746                 vrtc_callout_reset(vrtc, newfreq);
  747         else
  748                 vrtc_callout_check(vrtc, newfreq);
  749 }
  750 
  751 int
  752 vrtc_set_time(struct vm *vm, time_t secs)
  753 {
  754         struct vrtc *vrtc;
  755         int error;
  756 
  757         vrtc = vm_rtc(vm);
  758         VRTC_LOCK(vrtc);
  759         error = vrtc_time_update(vrtc, secs, sbinuptime());
  760         VRTC_UNLOCK(vrtc);
  761 
  762         if (error) {
  763                 VM_CTR2(vrtc->vm, "Error %d setting RTC time to %#lx", error,
  764                     secs);
  765         } else {
  766                 VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs);
  767         }
  768 
  769         return (error);
  770 }
  771 
  772 time_t
  773 vrtc_get_time(struct vm *vm)
  774 {
  775         struct vrtc *vrtc;
  776         sbintime_t basetime;
  777         time_t t;
  778 
  779         vrtc = vm_rtc(vm);
  780         VRTC_LOCK(vrtc);
  781         t = vrtc_curtime(vrtc, &basetime);
  782         VRTC_UNLOCK(vrtc);
  783 
  784         return (t);
  785 }
  786 
  787 int
  788 vrtc_nvram_write(struct vm *vm, int offset, uint8_t value)
  789 {
  790         struct vrtc *vrtc;
  791         uint8_t *ptr;
  792 
  793         vrtc = vm_rtc(vm);
  794 
  795         /*
  796          * Don't allow writes to RTC control registers or the date/time fields.
  797          */
  798         if (offset < offsetof(struct rtcdev, nvram[0]) ||
  799             offset == RTC_CENTURY || offset >= sizeof(struct rtcdev)) {
  800                 VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d",
  801                     offset);
  802                 return (EINVAL);
  803         }
  804 
  805         VRTC_LOCK(vrtc);
  806         ptr = (uint8_t *)(&vrtc->rtcdev);
  807         ptr[offset] = value;
  808         VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset);
  809         VRTC_UNLOCK(vrtc);
  810 
  811         return (0);
  812 }
  813 
  814 int
  815 vrtc_nvram_read(struct vm *vm, int offset, uint8_t *retval)
  816 {
  817         struct vrtc *vrtc;
  818         sbintime_t basetime;
  819         time_t curtime;
  820         uint8_t *ptr;
  821 
  822         /*
  823          * Allow all offsets in the RTC to be read.
  824          */
  825         if (offset < 0 || offset >= sizeof(struct rtcdev))
  826                 return (EINVAL);
  827 
  828         vrtc = vm_rtc(vm);
  829         VRTC_LOCK(vrtc);
  830 
  831         /*
  832          * Update RTC date/time fields if necessary.
  833          */
  834         if (offset < 10 || offset == RTC_CENTURY) {
  835                 curtime = vrtc_curtime(vrtc, &basetime);
  836                 secs_to_rtc(curtime, vrtc, 0);
  837         }
  838 
  839         ptr = (uint8_t *)(&vrtc->rtcdev);
  840         *retval = ptr[offset];
  841 
  842         VRTC_UNLOCK(vrtc);
  843         return (0);
  844 }
  845 
  846 int
  847 vrtc_addr_handler(struct vm *vm, bool in, int port, int bytes, uint32_t *val)
  848 {
  849         struct vrtc *vrtc;
  850 
  851         vrtc = vm_rtc(vm);
  852 
  853         if (bytes != 1)
  854                 return (-1);
  855 
  856         if (in) {
  857                 *val = 0xff;
  858                 return (0);
  859         }
  860 
  861         VRTC_LOCK(vrtc);
  862         vrtc->addr = *val & 0x7f;
  863         VRTC_UNLOCK(vrtc);
  864 
  865         return (0);
  866 }
  867 
  868 int
  869 vrtc_data_handler(struct vm *vm, bool in, int port, int bytes, uint32_t *val)
  870 {
  871         struct vrtc *vrtc;
  872         struct rtcdev *rtc;
  873         sbintime_t basetime;
  874         time_t curtime;
  875         int error, offset;
  876 
  877         vrtc = vm_rtc(vm);
  878         rtc = &vrtc->rtcdev;
  879 
  880         if (bytes != 1)
  881                 return (-1);
  882 
  883         VRTC_LOCK(vrtc);
  884         offset = vrtc->addr;
  885         if (offset >= sizeof(struct rtcdev)) {
  886                 VRTC_UNLOCK(vrtc);
  887                 return (-1);
  888         }
  889 
  890         error = 0;
  891         curtime = vrtc_curtime(vrtc, &basetime);
  892         vrtc_time_update(vrtc, curtime, basetime);
  893 
  894         /*
  895          * Update RTC date/time fields if necessary.
  896          *
  897          * This is not just for reads of the RTC. The side-effect of writing
  898          * the century byte requires other RTC date/time fields (e.g. sec)
  899          * to be updated here.
  900          */
  901         if (offset < 10 || offset == RTC_CENTURY)
  902                 secs_to_rtc(curtime, vrtc, 0);
  903 
  904         if (in) {
  905                 if (offset == 12) {
  906                         /*
  907                          * XXX
  908                          * reg_c interrupt flags are updated only if the
  909                          * corresponding interrupt enable bit in reg_b is set.
  910                          */
  911                         *val = vrtc->rtcdev.reg_c;
  912                         vrtc_set_reg_c(vrtc, 0);
  913                 } else {
  914                         *val = *((uint8_t *)rtc + offset);
  915                 }
  916                 VM_CTR2(vm, "Read value %#x from RTC offset %#x",
  917                     *val, offset);
  918         } else {
  919                 switch (offset) {
  920                 case 10:
  921                         VM_CTR1(vm, "RTC reg_a set to %#x", *val);
  922                         vrtc_set_reg_a(vrtc, *val);
  923                         break;
  924                 case 11:
  925                         VM_CTR1(vm, "RTC reg_b set to %#x", *val);
  926                         error = vrtc_set_reg_b(vrtc, *val);
  927                         break;
  928                 case 12:
  929                         VM_CTR1(vm, "RTC reg_c set to %#x (ignored)",
  930                             *val);
  931                         break;
  932                 case 13:
  933                         VM_CTR1(vm, "RTC reg_d set to %#x (ignored)",
  934                             *val);
  935                         break;
  936                 case 0:
  937                         /*
  938                          * High order bit of 'seconds' is readonly.
  939                          */
  940                         *val &= 0x7f;
  941                         /* FALLTHRU */
  942                 default:
  943                         VM_CTR2(vm, "RTC offset %#x set to %#x",
  944                             offset, *val);
  945                         *((uint8_t *)rtc + offset) = *val;
  946                         break;
  947                 }
  948 
  949                 /*
  950                  * XXX some guests (e.g. OpenBSD) write the century byte
  951                  * outside of RTCSB_HALT so re-calculate the RTC date/time.
  952                  */
  953                 if (offset == RTC_CENTURY && !rtc_halted(vrtc)) {
  954                         curtime = rtc_to_secs(vrtc);
  955                         error = vrtc_time_update(vrtc, curtime, sbinuptime());
  956                         KASSERT(!error, ("vrtc_time_update error %d", error));
  957                         if (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time)
  958                                 error = -1;
  959                 }
  960         }
  961         VRTC_UNLOCK(vrtc);
  962         return (error);
  963 }
  964 
  965 void
  966 vrtc_reset(struct vrtc *vrtc)
  967 {
  968         struct rtcdev *rtc;
  969 
  970         VRTC_LOCK(vrtc);
  971 
  972         rtc = &vrtc->rtcdev;
  973         vrtc_set_reg_b(vrtc, rtc->reg_b & ~(RTCSB_ALL_INTRS | RTCSB_SQWE));
  974         vrtc_set_reg_c(vrtc, 0);
  975         KASSERT(!callout_active(&vrtc->callout), ("rtc callout still active"));
  976 
  977         VRTC_UNLOCK(vrtc);
  978 }
  979 
  980 struct vrtc *
  981 vrtc_init(struct vm *vm)
  982 {
  983         struct vrtc *vrtc;
  984         struct rtcdev *rtc;
  985         time_t curtime;
  986 
  987         vrtc = malloc(sizeof(struct vrtc), M_VRTC, M_WAITOK | M_ZERO);
  988         vrtc->vm = vm;
  989         mtx_init(&vrtc->mtx, "vrtc lock", NULL, MTX_DEF);
  990         callout_init(&vrtc->callout, 1);
  991 
  992         /* Allow dividers to keep time but disable everything else */
  993         rtc = &vrtc->rtcdev;
  994         rtc->reg_a = 0x20;
  995         rtc->reg_b = RTCSB_24HR;
  996         rtc->reg_c = 0;
  997         rtc->reg_d = RTCSD_PWR;
  998 
  999         /* Reset the index register to a safe value. */
 1000         vrtc->addr = RTC_STATUSD;
 1001 
 1002         /*
 1003          * Initialize RTC time to 00:00:00 Jan 1, 1970.
 1004          */
 1005         curtime = 0;
 1006 
 1007         VRTC_LOCK(vrtc);
 1008         vrtc->base_rtctime = VRTC_BROKEN_TIME;
 1009         vrtc_time_update(vrtc, curtime, sbinuptime());
 1010         secs_to_rtc(curtime, vrtc, 0);
 1011         VRTC_UNLOCK(vrtc);
 1012 
 1013         return (vrtc);
 1014 }
 1015 
 1016 void
 1017 vrtc_cleanup(struct vrtc *vrtc)
 1018 {
 1019 
 1020         callout_drain(&vrtc->callout);
 1021         mtx_destroy(&vrtc->mtx);
 1022         free(vrtc, M_VRTC);
 1023 }
 1024 
 1025 #ifdef BHYVE_SNAPSHOT
 1026 int
 1027 vrtc_snapshot(struct vrtc *vrtc, struct vm_snapshot_meta *meta)
 1028 {
 1029         int ret;
 1030 
 1031         VRTC_LOCK(vrtc);
 1032 
 1033         SNAPSHOT_VAR_OR_LEAVE(vrtc->addr, meta, ret, done);
 1034         if (meta->op == VM_SNAPSHOT_RESTORE)
 1035                 vrtc->base_uptime = sbinuptime();
 1036         SNAPSHOT_VAR_OR_LEAVE(vrtc->base_rtctime, meta, ret, done);
 1037 
 1038         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.sec, meta, ret, done);
 1039         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_sec, meta, ret, done);
 1040         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.min, meta, ret, done);
 1041         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_min, meta, ret, done);
 1042         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.hour, meta, ret, done);
 1043         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_hour, meta, ret, done);
 1044         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_week, meta, ret, done);
 1045         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_month, meta, ret, done);
 1046         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.month, meta, ret, done);
 1047         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.year, meta, ret, done);
 1048         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_a, meta, ret, done);
 1049         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_b, meta, ret, done);
 1050         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_c, meta, ret, done);
 1051         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_d, meta, ret, done);
 1052         SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram, sizeof(vrtc->rtcdev.nvram),
 1053                               meta, ret, done);
 1054         SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.century, meta, ret, done);
 1055         SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram2, sizeof(vrtc->rtcdev.nvram2),
 1056                               meta, ret, done);
 1057 
 1058         vrtc_callout_reset(vrtc, vrtc_freq(vrtc));
 1059 
 1060         VRTC_UNLOCK(vrtc);
 1061 
 1062 done:
 1063         return (ret);
 1064 }
 1065 #endif

Cache object: f5ed43e9f80368f734a261112931010f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.