Lines Matching refs:vrtc

76 struct vrtc {  struct
86 #define VRTC_LOCK(vrtc) mtx_lock(&((vrtc)->mtx)) argument
87 #define VRTC_UNLOCK(vrtc) mtx_unlock(&((vrtc)->mtx)) argument
88 #define VRTC_LOCKED(vrtc) mtx_owned(&((vrtc)->mtx)) argument
100 #define rtc_halted(vrtc) ((vrtc->rtcdev.reg_b & RTCSB_HALT) != 0) argument
101 #define aintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_AINTR) != 0) argument
102 #define pintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_PINTR) != 0) argument
103 #define uintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_UINTR) != 0) argument
106 static void vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval);
111 SYSCTL_NODE(_hw_vmm, OID_AUTO, vrtc, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
128 update_enabled(struct vrtc *vrtc) in update_enabled() argument
136 if (!divider_enabled(vrtc->rtcdev.reg_a)) in update_enabled()
139 if (rtc_halted(vrtc)) in update_enabled()
142 if (vrtc->base_rtctime == VRTC_BROKEN_TIME) in update_enabled()
149 vrtc_curtime(struct vrtc *vrtc, sbintime_t *basetime) in vrtc_curtime() argument
154 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_curtime()
156 t = vrtc->base_rtctime; in vrtc_curtime()
157 *basetime = vrtc->base_uptime; in vrtc_curtime()
158 if (update_enabled(vrtc)) { in vrtc_curtime()
160 delta = now - vrtc->base_uptime; in vrtc_curtime()
162 "%#lx to %#lx", vrtc->base_uptime, now)); in vrtc_curtime()
181 secs_to_rtc(time_t rtctime, struct vrtc *vrtc, int force_update) in secs_to_rtc() argument
188 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in secs_to_rtc()
201 if (rtc_halted(vrtc) && !force_update) in secs_to_rtc()
223 rtc = &vrtc->rtcdev; in secs_to_rtc()
282 rtc_to_secs(struct vrtc *vrtc) in rtc_to_secs() argument
288 struct vm *vm = vrtc->vm; in rtc_to_secs()
292 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in rtc_to_secs()
294 rtc = &vrtc->rtcdev; in rtc_to_secs()
396 VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected"); in rtc_to_secs()
401 vrtc_time_update(struct vrtc *vrtc, time_t newtime, sbintime_t newbase) in vrtc_time_update() argument
407 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_time_update()
409 rtc = &vrtc->rtcdev; in vrtc_time_update()
414 oldtime = vrtc->base_rtctime; in vrtc_time_update()
415 VM_CTR2(vrtc->vm, "Updating RTC secs from %#lx to %#lx", in vrtc_time_update()
418 VM_CTR2(vrtc->vm, "Updating RTC base uptime from %#lx to %#lx", in vrtc_time_update()
419 vrtc->base_uptime, newbase); in vrtc_time_update()
420 vrtc->base_uptime = newbase; in vrtc_time_update()
431 vrtc->base_rtctime = VRTC_BROKEN_TIME; in vrtc_time_update()
438 if (rtc_halted(vrtc)) { in vrtc_time_update()
439 VM_CTR0(vrtc->vm, "RTC update halted by guest"); in vrtc_time_update()
451 if (aintr_enabled(vrtc) && oldtime != VRTC_BROKEN_TIME) in vrtc_time_update()
452 vrtc->base_rtctime++; in vrtc_time_update()
454 vrtc->base_rtctime = newtime; in vrtc_time_update()
456 if (aintr_enabled(vrtc)) { in vrtc_time_update()
461 secs_to_rtc(vrtc->base_rtctime, vrtc, 0); in vrtc_time_update()
466 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_ALARM); in vrtc_time_update()
469 } while (vrtc->base_rtctime != newtime); in vrtc_time_update()
471 if (uintr_enabled(vrtc)) in vrtc_time_update()
472 vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE); in vrtc_time_update()
478 vrtc_freq(struct vrtc *vrtc) in vrtc_freq() argument
501 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_freq()
510 if (pintr_enabled(vrtc) && divider_enabled(vrtc->rtcdev.reg_a)) { in vrtc_freq()
511 ratesel = vrtc->rtcdev.reg_a & 0xf; in vrtc_freq()
513 } else if (aintr_enabled(vrtc) && update_enabled(vrtc)) { in vrtc_freq()
515 } else if (uintr_enabled(vrtc) && update_enabled(vrtc)) { in vrtc_freq()
523 vrtc_callout_reset(struct vrtc *vrtc, sbintime_t freqsbt) in vrtc_callout_reset() argument
526 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_callout_reset()
529 if (callout_active(&vrtc->callout)) { in vrtc_callout_reset()
530 VM_CTR0(vrtc->vm, "RTC callout stopped"); in vrtc_callout_reset()
531 callout_stop(&vrtc->callout); in vrtc_callout_reset()
535 VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt); in vrtc_callout_reset()
536 callout_reset_sbt(&vrtc->callout, freqsbt, 0, vrtc_callout_handler, in vrtc_callout_reset()
537 vrtc, 0); in vrtc_callout_reset()
543 struct vrtc *vrtc = arg; in vrtc_callout_handler() local
548 VM_CTR0(vrtc->vm, "vrtc callout fired"); in vrtc_callout_handler()
550 VRTC_LOCK(vrtc); in vrtc_callout_handler()
551 if (callout_pending(&vrtc->callout)) /* callout was reset */ in vrtc_callout_handler()
554 if (!callout_active(&vrtc->callout)) /* callout was stopped */ in vrtc_callout_handler()
557 callout_deactivate(&vrtc->callout); in vrtc_callout_handler()
559 KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) != 0, in vrtc_callout_handler()
562 if (pintr_enabled(vrtc)) in vrtc_callout_handler()
563 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c | RTCIR_PERIOD); in vrtc_callout_handler()
565 if (aintr_enabled(vrtc) || uintr_enabled(vrtc)) { in vrtc_callout_handler()
566 rtctime = vrtc_curtime(vrtc, &basetime); in vrtc_callout_handler()
567 error = vrtc_time_update(vrtc, rtctime, basetime); in vrtc_callout_handler()
572 freqsbt = vrtc_freq(vrtc); in vrtc_callout_handler()
574 vrtc_callout_reset(vrtc, freqsbt); in vrtc_callout_handler()
576 VRTC_UNLOCK(vrtc); in vrtc_callout_handler()
580 vrtc_callout_check(struct vrtc *vrtc, sbintime_t freq) in vrtc_callout_check() argument
584 active = callout_active(&vrtc->callout) ? 1 : 0; in vrtc_callout_check()
591 vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval) in vrtc_set_reg_c() argument
597 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_set_reg_c()
599 rtc = &vrtc->rtcdev; in vrtc_set_reg_c()
603 if ((aintr_enabled(vrtc) && (newval & RTCIR_ALARM) != 0) || in vrtc_set_reg_c()
604 (pintr_enabled(vrtc) && (newval & RTCIR_PERIOD) != 0) || in vrtc_set_reg_c()
605 (uintr_enabled(vrtc) && (newval & RTCIR_UPDATE) != 0)) { in vrtc_set_reg_c()
615 VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to %#x", in vrtc_set_reg_c()
620 VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ); in vrtc_set_reg_c()
621 vatpic_pulse_irq(vrtc->vm, RTC_IRQ); in vrtc_set_reg_c()
622 vioapic_pulse_irq(vrtc->vm, RTC_IRQ); in vrtc_set_reg_c()
624 VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ); in vrtc_set_reg_c()
629 vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval) in vrtc_set_reg_b() argument
637 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_set_reg_b()
639 rtc = &vrtc->rtcdev; in vrtc_set_reg_b()
641 oldfreq = vrtc_freq(vrtc); in vrtc_set_reg_b()
646 VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to %#x", in vrtc_set_reg_b()
652 rtctime = rtc_to_secs(vrtc); in vrtc_set_reg_b()
659 curtime = vrtc_curtime(vrtc, &basetime); in vrtc_set_reg_b()
660 KASSERT(curtime == vrtc->base_rtctime, ("%s: mismatch " in vrtc_set_reg_b()
662 __func__, vrtc->base_rtctime, curtime)); in vrtc_set_reg_b()
669 secs_to_rtc(curtime, vrtc, 1); in vrtc_set_reg_b()
678 error = vrtc_time_update(vrtc, rtctime, basetime); in vrtc_set_reg_b()
686 vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c); in vrtc_set_reg_b()
691 newfreq = vrtc_freq(vrtc); in vrtc_set_reg_b()
693 vrtc_callout_reset(vrtc, newfreq); in vrtc_set_reg_b()
695 vrtc_callout_check(vrtc, newfreq); in vrtc_set_reg_b()
705 vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval) in vrtc_set_reg_a() argument
710 KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__)); in vrtc_set_reg_a()
713 oldval = vrtc->rtcdev.reg_a; in vrtc_set_reg_a()
714 oldfreq = vrtc_freq(vrtc); in vrtc_set_reg_a()
717 VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx", in vrtc_set_reg_a()
718 vrtc->base_rtctime, vrtc->base_uptime); in vrtc_set_reg_a()
726 vrtc->base_uptime = sbinuptime(); in vrtc_set_reg_a()
727 VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx", in vrtc_set_reg_a()
728 vrtc->base_rtctime, vrtc->base_uptime); in vrtc_set_reg_a()
733 vrtc->rtcdev.reg_a = newval; in vrtc_set_reg_a()
736 VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x", in vrtc_set_reg_a()
743 newfreq = vrtc_freq(vrtc); in vrtc_set_reg_a()
745 vrtc_callout_reset(vrtc, newfreq); in vrtc_set_reg_a()
747 vrtc_callout_check(vrtc, newfreq); in vrtc_set_reg_a()
753 struct vrtc *vrtc; in vrtc_set_time() local
756 vrtc = vm_rtc(vm); in vrtc_set_time()
757 VRTC_LOCK(vrtc); in vrtc_set_time()
758 error = vrtc_time_update(vrtc, secs, sbinuptime()); in vrtc_set_time()
759 VRTC_UNLOCK(vrtc); in vrtc_set_time()
762 VM_CTR2(vrtc->vm, "Error %d setting RTC time to %#lx", error, in vrtc_set_time()
765 VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs); in vrtc_set_time()
774 struct vrtc *vrtc; in vrtc_get_time() local
778 vrtc = vm_rtc(vm); in vrtc_get_time()
779 VRTC_LOCK(vrtc); in vrtc_get_time()
780 t = vrtc_curtime(vrtc, &basetime); in vrtc_get_time()
781 VRTC_UNLOCK(vrtc); in vrtc_get_time()
789 struct vrtc *vrtc; in vrtc_nvram_write() local
792 vrtc = vm_rtc(vm); in vrtc_nvram_write()
799 VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d", in vrtc_nvram_write()
804 VRTC_LOCK(vrtc); in vrtc_nvram_write()
805 ptr = (uint8_t *)(&vrtc->rtcdev); in vrtc_nvram_write()
807 VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset); in vrtc_nvram_write()
808 VRTC_UNLOCK(vrtc); in vrtc_nvram_write()
816 struct vrtc *vrtc; in vrtc_nvram_read() local
827 vrtc = vm_rtc(vm); in vrtc_nvram_read()
828 VRTC_LOCK(vrtc); in vrtc_nvram_read()
834 curtime = vrtc_curtime(vrtc, &basetime); in vrtc_nvram_read()
835 secs_to_rtc(curtime, vrtc, 0); in vrtc_nvram_read()
838 ptr = (uint8_t *)(&vrtc->rtcdev); in vrtc_nvram_read()
841 VRTC_UNLOCK(vrtc); in vrtc_nvram_read()
848 struct vrtc *vrtc; in vrtc_addr_handler() local
850 vrtc = vm_rtc(vm); in vrtc_addr_handler()
860 VRTC_LOCK(vrtc); in vrtc_addr_handler()
861 vrtc->addr = *val & 0x7f; in vrtc_addr_handler()
862 VRTC_UNLOCK(vrtc); in vrtc_addr_handler()
870 struct vrtc *vrtc; in vrtc_data_handler() local
876 vrtc = vm_rtc(vm); in vrtc_data_handler()
877 rtc = &vrtc->rtcdev; in vrtc_data_handler()
882 VRTC_LOCK(vrtc); in vrtc_data_handler()
883 offset = vrtc->addr; in vrtc_data_handler()
885 VRTC_UNLOCK(vrtc); in vrtc_data_handler()
890 curtime = vrtc_curtime(vrtc, &basetime); in vrtc_data_handler()
891 vrtc_time_update(vrtc, curtime, basetime); in vrtc_data_handler()
901 secs_to_rtc(curtime, vrtc, 0); in vrtc_data_handler()
910 *val = vrtc->rtcdev.reg_c; in vrtc_data_handler()
911 vrtc_set_reg_c(vrtc, 0); in vrtc_data_handler()
921 vrtc_set_reg_a(vrtc, *val); in vrtc_data_handler()
925 error = vrtc_set_reg_b(vrtc, *val); in vrtc_data_handler()
952 if (offset == RTC_CENTURY && !rtc_halted(vrtc)) { in vrtc_data_handler()
953 curtime = rtc_to_secs(vrtc); in vrtc_data_handler()
954 error = vrtc_time_update(vrtc, curtime, sbinuptime()); in vrtc_data_handler()
960 VRTC_UNLOCK(vrtc); in vrtc_data_handler()
965 vrtc_reset(struct vrtc *vrtc) in vrtc_reset() argument
969 VRTC_LOCK(vrtc); in vrtc_reset()
971 rtc = &vrtc->rtcdev; in vrtc_reset()
972 vrtc_set_reg_b(vrtc, rtc->reg_b & ~(RTCSB_ALL_INTRS | RTCSB_SQWE)); in vrtc_reset()
973 vrtc_set_reg_c(vrtc, 0); in vrtc_reset()
974 KASSERT(!callout_active(&vrtc->callout), ("rtc callout still active")); in vrtc_reset()
976 VRTC_UNLOCK(vrtc); in vrtc_reset()
979 struct vrtc *
982 struct vrtc *vrtc; in vrtc_init() local
986 vrtc = malloc(sizeof(struct vrtc), M_VRTC, M_WAITOK | M_ZERO); in vrtc_init()
987 vrtc->vm = vm; in vrtc_init()
988 mtx_init(&vrtc->mtx, "vrtc lock", NULL, MTX_DEF); in vrtc_init()
989 callout_init(&vrtc->callout, 1); in vrtc_init()
992 rtc = &vrtc->rtcdev; in vrtc_init()
999 vrtc->addr = RTC_STATUSD; in vrtc_init()
1006 VRTC_LOCK(vrtc); in vrtc_init()
1007 vrtc->base_rtctime = VRTC_BROKEN_TIME; in vrtc_init()
1008 vrtc_time_update(vrtc, curtime, sbinuptime()); in vrtc_init()
1009 secs_to_rtc(curtime, vrtc, 0); in vrtc_init()
1010 VRTC_UNLOCK(vrtc); in vrtc_init()
1012 return (vrtc); in vrtc_init()
1016 vrtc_cleanup(struct vrtc *vrtc) in vrtc_cleanup() argument
1019 callout_drain(&vrtc->callout); in vrtc_cleanup()
1020 mtx_destroy(&vrtc->mtx); in vrtc_cleanup()
1021 free(vrtc, M_VRTC); in vrtc_cleanup()
1026 vrtc_snapshot(struct vrtc *vrtc, struct vm_snapshot_meta *meta) in vrtc_snapshot() argument
1030 VRTC_LOCK(vrtc); in vrtc_snapshot()
1032 SNAPSHOT_VAR_OR_LEAVE(vrtc->addr, meta, ret, done); in vrtc_snapshot()
1034 vrtc->base_uptime = sbinuptime(); in vrtc_snapshot()
1035 SNAPSHOT_VAR_OR_LEAVE(vrtc->base_rtctime, meta, ret, done); in vrtc_snapshot()
1037 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.sec, meta, ret, done); in vrtc_snapshot()
1038 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_sec, meta, ret, done); in vrtc_snapshot()
1039 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.min, meta, ret, done); in vrtc_snapshot()
1040 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_min, meta, ret, done); in vrtc_snapshot()
1041 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.hour, meta, ret, done); in vrtc_snapshot()
1042 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_hour, meta, ret, done); in vrtc_snapshot()
1043 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_week, meta, ret, done); in vrtc_snapshot()
1044 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_month, meta, ret, done); in vrtc_snapshot()
1045 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.month, meta, ret, done); in vrtc_snapshot()
1046 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.year, meta, ret, done); in vrtc_snapshot()
1047 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_a, meta, ret, done); in vrtc_snapshot()
1048 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_b, meta, ret, done); in vrtc_snapshot()
1049 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_c, meta, ret, done); in vrtc_snapshot()
1050 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_d, meta, ret, done); in vrtc_snapshot()
1051 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram, sizeof(vrtc->rtcdev.nvram), in vrtc_snapshot()
1053 SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.century, meta, ret, done); in vrtc_snapshot()
1054 SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram2, sizeof(vrtc->rtcdev.nvram2), in vrtc_snapshot()
1057 vrtc_callout_reset(vrtc, vrtc_freq(vrtc)); in vrtc_snapshot()
1059 VRTC_UNLOCK(vrtc); in vrtc_snapshot()