1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2014 Bryan Venteicher <bryanv@FreeBSD.org> 5 * Copyright (c) 2021 Mathieu Chouquet-Stringer 6 * Copyright (c) 2021 Juniper Networks, Inc. 7 * Copyright (c) 2021 Klara, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Linux KVM paravirtual clock support 33 * 34 * References: 35 * - [1] https://www.kernel.org/doc/html/latest/virt/kvm/cpuid.html 36 * - [2] https://www.kernel.org/doc/html/latest/virt/kvm/msr.html 37 */ 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include <sys/param.h> 43 #include <sys/bus.h> 44 #include <sys/domainset.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/module.h> 48 #include <sys/smp.h> 49 #include <sys/sysctl.h> 50 51 #include <vm/vm.h> 52 #include <vm/pmap.h> 53 #include <vm/vm_extern.h> 54 55 #include <machine/pvclock.h> 56 #include <x86/kvm.h> 57 58 #include "clock_if.h" 59 60 #define KVM_CLOCK_DEVNAME "kvmclock" 61 /* 62 * Note: Chosen to be (1) above HPET's value (always 950), (2) above the TSC's 63 * default value of 800, and (3) below the TSC's value when it supports the 64 * "Invariant TSC" feature and is believed to be synchronized across all CPUs. 65 */ 66 #define KVM_CLOCK_TC_QUALITY 975 67 68 struct kvm_clock_softc { 69 struct pvclock pvc; 70 struct pvclock_wall_clock wc; 71 struct pvclock_vcpu_time_info *timeinfos; 72 u_int msr_tc; 73 u_int msr_wc; 74 }; 75 76 static devclass_t kvm_clock_devclass; 77 78 static struct pvclock_wall_clock *kvm_clock_get_wallclock(void *arg); 79 static void kvm_clock_system_time_enable(struct kvm_clock_softc *sc); 80 static void kvm_clock_system_time_enable_pcpu(void *arg); 81 static void kvm_clock_setup_sysctl(device_t); 82 83 static struct pvclock_wall_clock * 84 kvm_clock_get_wallclock(void *arg) 85 { 86 struct kvm_clock_softc *sc = arg; 87 88 wrmsr(sc->msr_wc, vtophys(&sc->wc)); 89 return (&sc->wc); 90 } 91 92 static void 93 kvm_clock_system_time_enable(struct kvm_clock_softc *sc) 94 { 95 smp_rendezvous(NULL, kvm_clock_system_time_enable_pcpu, NULL, sc); 96 } 97 98 static void 99 kvm_clock_system_time_enable_pcpu(void *arg) 100 { 101 struct kvm_clock_softc *sc = arg; 102 103 /* 104 * See [2]; the lsb of this MSR is the system time enable bit. 105 */ 106 wrmsr(sc->msr_tc, vtophys(&(sc->timeinfos)[curcpu]) | 1); 107 } 108 109 static void 110 kvm_clock_identify(driver_t *driver, device_t parent) 111 { 112 u_int regs[4]; 113 114 kvm_cpuid_get_features(regs); 115 if ((regs[0] & 116 (KVM_FEATURE_CLOCKSOURCE2 | KVM_FEATURE_CLOCKSOURCE)) == 0) 117 return; 118 if (device_find_child(parent, KVM_CLOCK_DEVNAME, -1)) 119 return; 120 BUS_ADD_CHILD(parent, 0, KVM_CLOCK_DEVNAME, 0); 121 } 122 123 static int 124 kvm_clock_probe(device_t dev) 125 { 126 device_set_desc(dev, "KVM paravirtual clock"); 127 return (BUS_PROBE_DEFAULT); 128 } 129 130 static int 131 kvm_clock_attach(device_t dev) 132 { 133 u_int regs[4]; 134 struct kvm_clock_softc *sc = device_get_softc(dev); 135 bool stable_flag_supported; 136 137 /* Process KVM "features" CPUID leaf content: */ 138 kvm_cpuid_get_features(regs); 139 if ((regs[0] & KVM_FEATURE_CLOCKSOURCE2) != 0) { 140 sc->msr_tc = KVM_MSR_SYSTEM_TIME_NEW; 141 sc->msr_wc = KVM_MSR_WALL_CLOCK_NEW; 142 } else { 143 KASSERT((regs[0] & KVM_FEATURE_CLOCKSOURCE) != 0, 144 ("Clocksource feature flags disappeared since " 145 "kvm_clock_identify: regs[0] %#0x.", regs[0])); 146 sc->msr_tc = KVM_MSR_SYSTEM_TIME; 147 sc->msr_wc = KVM_MSR_WALL_CLOCK; 148 } 149 stable_flag_supported = 150 (regs[0] & KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) != 0; 151 152 /* Set up 'struct pvclock_vcpu_time_info' page(s): */ 153 sc->timeinfos = (struct pvclock_vcpu_time_info *)kmem_malloc(mp_ncpus * 154 sizeof(struct pvclock_vcpu_time_info), M_WAITOK | M_ZERO); 155 kvm_clock_system_time_enable(sc); 156 157 /* 158 * Init pvclock; register KVM clock wall clock, register KVM clock 159 * timecounter, and set up the requisite infrastructure for vDSO access 160 * to this timecounter. 161 * Regarding 'tc_flags': Since the KVM MSR documentation does not 162 * specifically discuss suspend/resume scenarios, conservatively 163 * leave 'TC_FLAGS_SUSPEND_SAFE' cleared and assume that the system 164 * time must be re-inited in such cases. 165 */ 166 sc->pvc.get_wallclock = kvm_clock_get_wallclock; 167 sc->pvc.get_wallclock_arg = sc; 168 sc->pvc.timeinfos = sc->timeinfos; 169 sc->pvc.stable_flag_supported = stable_flag_supported; 170 pvclock_init(&sc->pvc, dev, KVM_CLOCK_DEVNAME, KVM_CLOCK_TC_QUALITY, 0); 171 kvm_clock_setup_sysctl(dev); 172 return (0); 173 } 174 175 static int 176 kvm_clock_detach(device_t dev) 177 { 178 struct kvm_clock_softc *sc = device_get_softc(dev); 179 180 return (pvclock_destroy(&sc->pvc)); 181 } 182 183 static int 184 kvm_clock_suspend(device_t dev) 185 { 186 return (0); 187 } 188 189 static int 190 kvm_clock_resume(device_t dev) 191 { 192 /* 193 * See note in 'kvm_clock_attach()' regarding 'TC_FLAGS_SUSPEND_SAFE'; 194 * conservatively assume that the system time must be re-inited in 195 * suspend/resume scenarios. 196 */ 197 kvm_clock_system_time_enable(device_get_softc(dev)); 198 pvclock_resume(); 199 inittodr(time_second); 200 return (0); 201 } 202 203 static int 204 kvm_clock_gettime(device_t dev, struct timespec *ts) 205 { 206 struct kvm_clock_softc *sc = device_get_softc(dev); 207 208 pvclock_gettime(&sc->pvc, ts); 209 return (0); 210 } 211 212 static int 213 kvm_clock_settime(device_t dev, struct timespec *ts) 214 { 215 /* 216 * Even though it is not possible to set the KVM clock's wall clock, to 217 * avoid the possibility of periodic benign error messages from 218 * 'settime_task_func()', report success rather than, e.g., 'ENODEV'. 219 */ 220 return (0); 221 } 222 223 static int 224 kvm_clock_tsc_freq_sysctl(SYSCTL_HANDLER_ARGS) 225 { 226 struct kvm_clock_softc *sc = oidp->oid_arg1; 227 uint64_t freq = pvclock_tsc_freq(sc->timeinfos); 228 229 return (sysctl_handle_64(oidp, &freq, 0, req)); 230 } 231 232 static void 233 kvm_clock_setup_sysctl(device_t dev) 234 { 235 struct kvm_clock_softc *sc = device_get_softc(dev); 236 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 237 struct sysctl_oid *tree = device_get_sysctl_tree(dev); 238 struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 239 240 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tsc_freq", 241 CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, 242 kvm_clock_tsc_freq_sysctl, "QU", 243 "Time Stamp Counter frequency"); 244 } 245 246 static device_method_t kvm_clock_methods[] = { 247 DEVMETHOD(device_identify, kvm_clock_identify), 248 DEVMETHOD(device_probe, kvm_clock_probe), 249 DEVMETHOD(device_attach, kvm_clock_attach), 250 DEVMETHOD(device_detach, kvm_clock_detach), 251 DEVMETHOD(device_suspend, kvm_clock_suspend), 252 DEVMETHOD(device_resume, kvm_clock_resume), 253 /* clock interface */ 254 DEVMETHOD(clock_gettime, kvm_clock_gettime), 255 DEVMETHOD(clock_settime, kvm_clock_settime), 256 257 DEVMETHOD_END 258 }; 259 260 static driver_t kvm_clock_driver = { 261 KVM_CLOCK_DEVNAME, 262 kvm_clock_methods, 263 sizeof(struct kvm_clock_softc), 264 }; 265 266 DRIVER_MODULE(kvm_clock, nexus, kvm_clock_driver, kvm_clock_devclass, 0, 0); 267