1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2017 The FreeBSD Foundation 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the company nor the name of the author may be used to 15 * endorse or promote products derived from this software without specific 16 * prior written permission. 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 #include <sys/cdefs.h> 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/mutex.h> 38 #include <sys/rman.h> 39 #include <sys/sysctl.h> 40 #include <sys/time.h> 41 #include <sys/timeet.h> 42 #include <sys/timetc.h> 43 44 #include <machine/bus.h> 45 #include <machine/machdep.h> 46 #include <machine/vmm.h> 47 48 #include <arm64/vmm/arm64.h> 49 50 #include <dev/vmm/vmm_vm.h> 51 52 #include "vgic.h" 53 #include "vtimer.h" 54 55 #define RES1 0xffffffffffffffffUL 56 57 #define timer_enabled(ctl) \ 58 (!((ctl) & CNTP_CTL_IMASK) && ((ctl) & CNTP_CTL_ENABLE)) 59 60 static uint32_t tmr_frq; 61 62 #define timer_condition_met(ctl) ((ctl) & CNTP_CTL_ISTATUS) 63 64 SYSCTL_DECL(_hw_vmm); 65 SYSCTL_NODE(_hw_vmm, OID_AUTO, vtimer, CTLFLAG_RW, NULL, NULL); 66 67 static bool allow_ecv_phys = false; 68 SYSCTL_BOOL(_hw_vmm_vtimer, OID_AUTO, allow_ecv_phys, CTLFLAG_RW, 69 &allow_ecv_phys, 0, 70 "Enable hardware access to the physical timer if FEAT_ECV_POFF is supported"); 71 72 static void vtimer_schedule_irq(struct hypctx *hypctx, bool phys); 73 74 static int 75 vtimer_virtual_timer_intr(void *arg) 76 { 77 struct hypctx *hypctx; 78 uint64_t cntpct_el0; 79 uint32_t cntv_ctl; 80 81 hypctx = arm64_get_active_vcpu(); 82 cntv_ctl = READ_SPECIALREG(cntv_ctl_el0); 83 84 if (!hypctx) { 85 /* vm_destroy() was called. */ 86 eprintf("No active vcpu\n"); 87 cntv_ctl = READ_SPECIALREG(cntv_ctl_el0); 88 goto out; 89 } 90 if (!timer_enabled(cntv_ctl)) { 91 eprintf("Timer not enabled\n"); 92 goto out; 93 } 94 if (!timer_condition_met(cntv_ctl)) { 95 eprintf("Timer condition not met\n"); 96 goto out; 97 } 98 99 cntpct_el0 = READ_CNTPCT() - 100 hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 101 if (hypctx->vtimer_cpu.virt_timer.cntx_cval_el0 < cntpct_el0) 102 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 103 GT_VIRT_IRQ, true); 104 105 cntv_ctl = hypctx->vtimer_cpu.virt_timer.cntx_ctl_el0; 106 107 out: 108 /* 109 * Disable the timer interrupt. This will prevent the interrupt from 110 * being reasserted as soon as we exit the handler and getting stuck 111 * in an infinite loop. 112 * 113 * This is safe to do because the guest disabled the timer, and then 114 * enables it as part of the interrupt handling routine. 115 */ 116 cntv_ctl &= ~CNTP_CTL_ENABLE; 117 WRITE_SPECIALREG(cntv_ctl_el0, cntv_ctl); 118 119 return (FILTER_HANDLED); 120 } 121 122 int 123 vtimer_init(void) 124 { 125 /* 126 * The guest *MUST* use the same timer frequency as the host. The 127 * register CNTFRQ_EL0 is accessible to the guest and a different value 128 * in the guest dts file might have unforseen consequences. 129 */ 130 tmr_frq = READ_SPECIALREG(cntfrq_el0); 131 132 return (0); 133 } 134 135 void 136 vtimer_cpuinit(struct hypctx *hypctx) 137 { 138 struct vtimer_cpu *vtimer_cpu; 139 bool ecv_poff; 140 141 vtimer_cpu = &hypctx->vtimer_cpu; 142 /* 143 * Configure physical timer interrupts for the VCPU. 144 * 145 * CNTP_CTL_IMASK: mask interrupts 146 * ~CNTP_CTL_ENABLE: disable the timer 147 */ 148 vtimer_cpu->phys_timer.cntx_ctl_el0 = CNTP_CTL_IMASK & ~CNTP_CTL_ENABLE; 149 150 mtx_init(&vtimer_cpu->phys_timer.mtx, "vtimer phys callout mutex", NULL, 151 MTX_DEF); 152 callout_init_mtx(&vtimer_cpu->phys_timer.callout, 153 &vtimer_cpu->phys_timer.mtx, 0); 154 vtimer_cpu->phys_timer.irqid = GT_PHYS_NS_IRQ; 155 156 mtx_init(&vtimer_cpu->virt_timer.mtx, "vtimer virt callout mutex", NULL, 157 MTX_DEF); 158 callout_init_mtx(&vtimer_cpu->virt_timer.callout, 159 &vtimer_cpu->virt_timer.mtx, 0); 160 vtimer_cpu->virt_timer.irqid = GT_VIRT_IRQ; 161 162 ecv_poff = false; 163 164 if (allow_ecv_phys && (hypctx->hyp->feats & HYP_FEAT_ECV_POFF) != 0) 165 ecv_poff = true; 166 167 /* 168 * Configure the Counter-timer Hypervisor Control Register for the VM. 169 */ 170 if (in_vhe()) { 171 /* 172 * CNTHCTL_E2H_EL0PCTEN: trap EL0 access to CNTP{CT,CTSS}_EL0 173 * CNTHCTL_E2H_EL0VCTEN: don't trap EL0 access to 174 * CNTV{CT,CTXX}_EL0 175 * CNTHCTL_E2H_EL0VTEN: don't trap EL0 access to 176 * CNTV_{CTL,CVAL,TVAL}_EL0 177 * CNTHCTL_E2H_EL0PTEN: trap EL0 access to 178 * CNTP_{CTL,CVAL,TVAL}_EL0 179 * CNTHCTL_E2H_EL1PCTEN: trap access to CNTPCT_EL0 180 * CNTHCTL_E2H_EL1PTEN: trap access to 181 * CNTP_{CTL,CVAL,TVAL}_EL0 182 * CNTHCTL_E2H_EL1VCTEN: don't trap EL0 access to 183 * CNTV{CT,CTSS}_EL0 184 * CNTHCTL_E2H_EL1PCEN: trap EL1 access to 185 * CNTP_{CTL,CVAL,TVAL}_EL0 186 * 187 * TODO: Don't trap when FEAT_ECV is present 188 */ 189 hypctx_write_sys_reg(hypctx, HOST_CNTHCTL_EL2, 190 CNTHCTL_E2H_EL0VCTEN_NOTRAP | 191 CNTHCTL_E2H_EL0VTEN_NOTRAP); 192 if (ecv_poff) { 193 *hypctx_sys_reg(hypctx, HOST_CNTHCTL_EL2) |= 194 CNTHCTL_E2H_EL0PCTEN_NOTRAP | 195 CNTHCTL_E2H_EL0PTEN_NOTRAP | 196 CNTHCTL_E2H_EL1PCTEN_NOTRAP | 197 CNTHCTL_E2H_EL1PTEN_NOTRAP; 198 } else { 199 *hypctx_sys_reg(hypctx, HOST_CNTHCTL_EL2) |= 200 CNTHCTL_E2H_EL0PCTEN_TRAP | 201 CNTHCTL_E2H_EL0PTEN_TRAP | 202 CNTHCTL_E2H_EL1PCTEN_TRAP | 203 CNTHCTL_E2H_EL1PTEN_TRAP; 204 } 205 } else { 206 /* 207 * CNTHCTL_EL1PCEN: trap access to CNTP_{CTL, CVAL, TVAL}_EL0 208 * from EL1 209 * CNTHCTL_EL1PCTEN: trap access to CNTPCT_EL0 210 */ 211 if (ecv_poff) { 212 hypctx_write_sys_reg(hypctx, HOST_CNTHCTL_EL2, 213 CNTHCTL_EL1PCTEN_NOTRAP | 214 CNTHCTL_EL1PCEN_NOTRAP); 215 } else { 216 hypctx_write_sys_reg(hypctx, HOST_CNTHCTL_EL2, 217 CNTHCTL_EL1PCTEN_TRAP | 218 CNTHCTL_EL1PCEN_TRAP); 219 } 220 } 221 222 if (ecv_poff) 223 *hypctx_sys_reg(hypctx, HOST_CNTHCTL_EL2) |= CNTHCTL_ECV_EN; 224 225 hypctx_write_sys_reg(hypctx, HOST_CNTVOFF_EL2, hypctx->hyp->cntvoff_el2); 226 } 227 228 void 229 vtimer_cpucleanup(struct hypctx *hypctx) 230 { 231 struct vtimer_cpu *vtimer_cpu; 232 233 vtimer_cpu = &hypctx->vtimer_cpu; 234 callout_drain(&vtimer_cpu->phys_timer.callout); 235 callout_drain(&vtimer_cpu->virt_timer.callout); 236 mtx_destroy(&vtimer_cpu->phys_timer.mtx); 237 mtx_destroy(&vtimer_cpu->virt_timer.mtx); 238 } 239 240 void 241 vtimer_vmcleanup(struct hyp *hyp) 242 { 243 struct hypctx *hypctx; 244 uint32_t cntv_ctl; 245 246 hypctx = arm64_get_active_vcpu(); 247 if (!hypctx) { 248 /* The active VM was destroyed, stop the timer. */ 249 cntv_ctl = READ_SPECIALREG(cntv_ctl_el0); 250 cntv_ctl &= ~CNTP_CTL_ENABLE; 251 WRITE_SPECIALREG(cntv_ctl_el0, cntv_ctl); 252 } 253 } 254 255 void 256 vtimer_cleanup(void) 257 { 258 } 259 260 static void 261 vtime_sync_timer(struct hypctx *hypctx, struct vtimer_timer *timer, 262 uint64_t cntpct_el0) 263 { 264 if (!timer_enabled(timer->cntx_ctl_el0)) { 265 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 266 timer->irqid, false); 267 } else if (timer->cntx_cval_el0 < cntpct_el0) { 268 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 269 timer->irqid, true); 270 } else { 271 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 272 timer->irqid, false); 273 vtimer_schedule_irq(hypctx, false); 274 } 275 } 276 277 void 278 vtimer_sync_hwstate(struct hypctx *hypctx) 279 { 280 uint64_t cntpct_el0; 281 282 cntpct_el0 = READ_CNTPCT() - 283 hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 284 vtime_sync_timer(hypctx, &hypctx->vtimer_cpu.virt_timer, cntpct_el0); 285 /* If FEAT_ECV_POFF is in use then we need to sync the physical timer */ 286 if ((hypctx_read_sys_reg(hypctx, HOST_CNTHCTL_EL2) & CNTHCTL_ECV_EN) != 0) { 287 vtime_sync_timer(hypctx, &hypctx->vtimer_cpu.phys_timer, 288 cntpct_el0); 289 } 290 } 291 292 static void 293 vtimer_inject_irq_callout_phys(void *context) 294 { 295 struct hypctx *hypctx; 296 297 hypctx = context; 298 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 299 hypctx->vtimer_cpu.phys_timer.irqid, true); 300 } 301 302 static void 303 vtimer_inject_irq_callout_virt(void *context) 304 { 305 struct hypctx *hypctx; 306 307 hypctx = context; 308 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 309 hypctx->vtimer_cpu.virt_timer.irqid, true); 310 } 311 312 static void 313 vtimer_schedule_irq(struct hypctx *hypctx, bool phys) 314 { 315 sbintime_t time; 316 struct vtimer_timer *timer; 317 uint64_t cntpct_el0; 318 uint64_t diff; 319 320 if (phys) 321 timer = &hypctx->vtimer_cpu.phys_timer; 322 else 323 timer = &hypctx->vtimer_cpu.virt_timer; 324 cntpct_el0 = READ_CNTPCT() - 325 hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 326 if (timer->cntx_cval_el0 < cntpct_el0) { 327 /* Timer set in the past, trigger interrupt */ 328 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu), 329 timer->irqid, true); 330 } else { 331 diff = timer->cntx_cval_el0 - cntpct_el0; 332 time = diff * SBT_1S / tmr_frq; 333 if (phys) 334 callout_reset_sbt(&timer->callout, time, 0, 335 vtimer_inject_irq_callout_phys, hypctx, 0); 336 else 337 callout_reset_sbt(&timer->callout, time, 0, 338 vtimer_inject_irq_callout_virt, hypctx, 0); 339 } 340 } 341 342 static void 343 vtimer_remove_irq(struct hypctx *hypctx, struct vcpu *vcpu) 344 { 345 struct vtimer_cpu *vtimer_cpu; 346 struct vtimer_timer *timer; 347 348 vtimer_cpu = &hypctx->vtimer_cpu; 349 timer = &vtimer_cpu->phys_timer; 350 351 callout_drain(&timer->callout); 352 /* 353 * The interrupt needs to be deactivated here regardless of the callout 354 * function having been executed. The timer interrupt can be masked with 355 * the CNTP_CTL_EL0.IMASK bit instead of reading the IAR register. 356 * Masking the interrupt doesn't remove it from the list registers. 357 */ 358 vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(vcpu), timer->irqid, false); 359 } 360 361 /* 362 * Timer emulation functions. 363 * 364 * The guest should use the virtual timer, however some software, e.g. u-boot, 365 * used the physical timer. Emulate this in software for the guest to use. 366 * 367 * Adjust for cntvoff_el2 so the physical and virtual timers are at similar 368 * times. This simplifies interrupt handling in the virtual timer as the 369 * adjustment will have already happened. 370 */ 371 372 int 373 vtimer_phys_ctl_read(struct vcpu *vcpu, uint64_t *rval, void *arg) 374 { 375 struct hypctx *hypctx; 376 struct vtimer_cpu *vtimer_cpu; 377 uint64_t cntpct_el0; 378 379 hypctx = vcpu_get_cookie(vcpu); 380 vtimer_cpu = &hypctx->vtimer_cpu; 381 382 cntpct_el0 = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 383 if (vtimer_cpu->phys_timer.cntx_cval_el0 < cntpct_el0) 384 /* Timer condition met */ 385 *rval = vtimer_cpu->phys_timer.cntx_ctl_el0 | CNTP_CTL_ISTATUS; 386 else 387 *rval = vtimer_cpu->phys_timer.cntx_ctl_el0 & ~CNTP_CTL_ISTATUS; 388 389 return (0); 390 } 391 392 int 393 vtimer_phys_ctl_write(struct vcpu *vcpu, uint64_t wval, void *arg) 394 { 395 struct hypctx *hypctx; 396 struct vtimer_cpu *vtimer_cpu; 397 uint64_t ctl_el0; 398 bool timer_toggled_on; 399 400 hypctx = vcpu_get_cookie(vcpu); 401 vtimer_cpu = &hypctx->vtimer_cpu; 402 403 timer_toggled_on = false; 404 ctl_el0 = vtimer_cpu->phys_timer.cntx_ctl_el0; 405 406 if (!timer_enabled(ctl_el0) && timer_enabled(wval)) 407 timer_toggled_on = true; 408 else if (timer_enabled(ctl_el0) && !timer_enabled(wval)) 409 vtimer_remove_irq(hypctx, vcpu); 410 411 vtimer_cpu->phys_timer.cntx_ctl_el0 = wval; 412 413 if (timer_toggled_on) 414 vtimer_schedule_irq(hypctx, true); 415 416 return (0); 417 } 418 419 int 420 vtimer_phys_cnt_read(struct vcpu *vcpu, uint64_t *rval, void *arg) 421 { 422 struct hypctx *hypctx; 423 424 hypctx = vcpu_get_cookie(vcpu); 425 *rval = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 426 return (0); 427 } 428 429 int 430 vtimer_phys_cnt_write(struct vcpu *vcpu, uint64_t wval, void *arg) 431 { 432 return (0); 433 } 434 435 int 436 vtimer_phys_cval_read(struct vcpu *vcpu, uint64_t *rval, void *arg) 437 { 438 struct hypctx *hypctx; 439 struct vtimer_cpu *vtimer_cpu; 440 441 hypctx = vcpu_get_cookie(vcpu); 442 vtimer_cpu = &hypctx->vtimer_cpu; 443 444 *rval = vtimer_cpu->phys_timer.cntx_cval_el0; 445 446 return (0); 447 } 448 449 int 450 vtimer_phys_cval_write(struct vcpu *vcpu, uint64_t wval, void *arg) 451 { 452 struct hypctx *hypctx; 453 struct vtimer_cpu *vtimer_cpu; 454 455 hypctx = vcpu_get_cookie(vcpu); 456 vtimer_cpu = &hypctx->vtimer_cpu; 457 458 vtimer_cpu->phys_timer.cntx_cval_el0 = wval; 459 460 vtimer_remove_irq(hypctx, vcpu); 461 if (timer_enabled(vtimer_cpu->phys_timer.cntx_ctl_el0)) { 462 vtimer_schedule_irq(hypctx, true); 463 } 464 465 return (0); 466 } 467 468 int 469 vtimer_phys_tval_read(struct vcpu *vcpu, uint64_t *rval, void *arg) 470 { 471 struct hypctx *hypctx; 472 struct vtimer_cpu *vtimer_cpu; 473 uint32_t cntpct_el0; 474 475 hypctx = vcpu_get_cookie(vcpu); 476 vtimer_cpu = &hypctx->vtimer_cpu; 477 478 if (!(vtimer_cpu->phys_timer.cntx_ctl_el0 & CNTP_CTL_ENABLE)) { 479 /* 480 * ARMv8 Architecture Manual, p. D7-2702: the result of reading 481 * TVAL when the timer is disabled is UNKNOWN. I have chosen to 482 * return the maximum value possible on 32 bits which means the 483 * timer will fire very far into the future. 484 */ 485 *rval = (uint32_t)RES1; 486 } else { 487 cntpct_el0 = READ_CNTPCT() - 488 hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 489 *rval = vtimer_cpu->phys_timer.cntx_cval_el0 - cntpct_el0; 490 } 491 492 return (0); 493 } 494 495 int 496 vtimer_phys_tval_write(struct vcpu *vcpu, uint64_t wval, void *arg) 497 { 498 struct hypctx *hypctx; 499 struct vtimer_cpu *vtimer_cpu; 500 uint64_t cntpct_el0; 501 502 hypctx = vcpu_get_cookie(vcpu); 503 vtimer_cpu = &hypctx->vtimer_cpu; 504 505 cntpct_el0 = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2); 506 vtimer_cpu->phys_timer.cntx_cval_el0 = (int32_t)wval + cntpct_el0; 507 508 vtimer_remove_irq(hypctx, vcpu); 509 if (timer_enabled(vtimer_cpu->phys_timer.cntx_ctl_el0)) { 510 vtimer_schedule_irq(hypctx, true); 511 } 512 513 return (0); 514 } 515 516 struct vtimer_softc { 517 struct resource *res; 518 void *ihl; 519 int rid; 520 }; 521 522 static int 523 vtimer_probe(device_t dev) 524 { 525 device_set_desc(dev, "Virtual timer"); 526 return (BUS_PROBE_DEFAULT); 527 } 528 529 static int 530 vtimer_attach(device_t dev) 531 { 532 struct vtimer_softc *sc; 533 534 sc = device_get_softc(dev); 535 536 sc->rid = 0; 537 sc->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid, RF_ACTIVE); 538 if (sc->res == NULL) 539 return (ENXIO); 540 541 bus_setup_intr(dev, sc->res, INTR_TYPE_CLK, vtimer_virtual_timer_intr, 542 NULL, NULL, &sc->ihl); 543 544 return (0); 545 } 546 547 static device_method_t vtimer_methods[] = { 548 /* Device interface */ 549 DEVMETHOD(device_probe, vtimer_probe), 550 DEVMETHOD(device_attach, vtimer_attach), 551 552 /* End */ 553 DEVMETHOD_END 554 }; 555 556 DEFINE_CLASS_0(vtimer, vtimer_driver, vtimer_methods, 557 sizeof(struct vtimer_softc)); 558 559 DRIVER_MODULE(vtimer, generic_timer, vtimer_driver, 0, 0); 560