1 /*- 2 * Copyright (c) 2018 Joyent, Inc. 3 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 4 * Copyright (c) 2011 NetApp, Inc. 5 * All rights reserved. 6 * Copyright (c) 2018 Joyent, Inc. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following 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 NETAPP, INC ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 /* 30 * This file and its contents are supplied under the terms of the 31 * Common Development and Distribution License ("CDDL"), version 1.0. 32 * You may only use this file in accordance with the terms of version 33 * 1.0 of the CDDL. 34 * 35 * A full copy of the text of the CDDL should have accompanied this 36 * source. A copy of the CDDL is also available via the Internet at 37 * http://www.illumos.org/license/CDDL. 38 * 39 * Copyright 2022 Oxide Computer Company 40 */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include <sys/param.h> 46 #include <sys/types.h> 47 #include <sys/queue.h> 48 #include <sys/kernel.h> 49 #include <sys/kmem.h> 50 #include <sys/mutex.h> 51 #include <sys/systm.h> 52 53 #include <machine/vmm.h> 54 55 #include "vatpic.h" 56 #include "vioapic.h" 57 #include "vatpit.h" 58 59 #define VATPIT_LOCK(vatpit) mutex_enter(&((vatpit)->lock)) 60 #define VATPIT_UNLOCK(vatpit) mutex_exit(&((vatpit)->lock)) 61 62 #define TIMER_SEL_MASK 0xc0 63 #define TIMER_RW_MASK 0x30 64 #define TIMER_MODE_MASK 0x0f 65 #define TIMER_SEL_READBACK 0xc0 66 67 #define TIMER_STS_OUT 0x80 68 #define TIMER_STS_NULLCNT 0x40 69 70 #define VALID_STATUS_BITS (TIMER_STS_OUT | TIMER_STS_NULLCNT) 71 72 #define TIMER_RB_LCTR 0x20 73 #define TIMER_RB_LSTATUS 0x10 74 #define TIMER_RB_CTR_2 0x08 75 #define TIMER_RB_CTR_1 0x04 76 #define TIMER_RB_CTR_0 0x02 77 78 #define TMR2_OUT_STS 0x20 79 80 #define PIT_8254_FREQ 1193182 81 #define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz)) 82 83 struct vatpit_callout_arg { 84 struct vatpit *vatpit; 85 int channel_num; 86 }; 87 88 struct channel { 89 uint8_t mode; 90 uint16_t initial; /* initial counter value */ 91 92 uint8_t reg_cr[2]; 93 uint8_t reg_ol[2]; 94 uint8_t reg_status; 95 96 bool slatched; /* status latched */ 97 bool olatched; /* output latched */ 98 bool cr_sel; /* read MSB from control register */ 99 bool ol_sel; /* read MSB from output latch */ 100 bool fr_sel; /* read MSB from free-running timer */ 101 102 hrtime_t time_loaded; /* time when counter was loaded */ 103 hrtime_t time_target; /* target time */ 104 uint64_t total_target; 105 106 struct callout callout; 107 struct vatpit_callout_arg callout_arg; 108 }; 109 110 struct vatpit { 111 struct vm *vm; 112 kmutex_t lock; 113 114 struct channel channel[3]; 115 }; 116 117 static void pit_timer_start_cntr0(struct vatpit *vatpit); 118 119 static uint64_t 120 vatpit_delta_ticks(struct vatpit *vatpit, struct channel *c) 121 { 122 const hrtime_t delta = gethrtime() - c->time_loaded; 123 124 return (hrt_freq_count(delta, PIT_8254_FREQ)); 125 } 126 127 static int 128 vatpit_get_out(struct vatpit *vatpit, int channel) 129 { 130 struct channel *c; 131 uint64_t delta_ticks; 132 int out; 133 134 c = &vatpit->channel[channel]; 135 136 switch (c->mode) { 137 case TIMER_INTTC: 138 delta_ticks = vatpit_delta_ticks(vatpit, c); 139 out = (delta_ticks >= c->initial); 140 break; 141 default: 142 out = 0; 143 break; 144 } 145 146 return (out); 147 } 148 149 static void 150 vatpit_callout_handler(void *a) 151 { 152 struct vatpit_callout_arg *arg = a; 153 struct vatpit *vatpit; 154 struct callout *callout; 155 struct channel *c; 156 157 vatpit = arg->vatpit; 158 c = &vatpit->channel[arg->channel_num]; 159 callout = &c->callout; 160 161 VATPIT_LOCK(vatpit); 162 163 if (callout_pending(callout)) /* callout was reset */ 164 goto done; 165 166 if (!callout_active(callout)) /* callout was stopped */ 167 goto done; 168 169 callout_deactivate(callout); 170 171 if (c->mode == TIMER_RATEGEN || c->mode == TIMER_SQWAVE) { 172 pit_timer_start_cntr0(vatpit); 173 } 174 175 (void) vatpic_pulse_irq(vatpit->vm, 0); 176 (void) vioapic_pulse_irq(vatpit->vm, 2); 177 178 done: 179 VATPIT_UNLOCK(vatpit); 180 } 181 182 static void 183 pit_timer_start_cntr0(struct vatpit *vatpit) 184 { 185 struct channel *c = &vatpit->channel[0]; 186 187 if (c->initial == 0) { 188 return; 189 } 190 191 c->total_target += c->initial; 192 c->time_target = c->time_loaded + 193 hrt_freq_interval(PIT_8254_FREQ, c->total_target); 194 195 /* 196 * If we are more than 'c->initial' ticks behind, reset the timer base 197 * to fire at the next 'c->initial' interval boundary. 198 */ 199 hrtime_t now = gethrtime(); 200 if (c->time_target < now) { 201 const uint64_t ticks_behind = 202 hrt_freq_count(now - c->time_target, PIT_8254_FREQ); 203 204 c->total_target += roundup(ticks_behind, c->initial); 205 c->time_target = c->time_loaded + 206 hrt_freq_interval(PIT_8254_FREQ, c->total_target); 207 } 208 209 callout_reset_hrtime(&c->callout, c->time_target, 210 vatpit_callout_handler, &c->callout_arg, C_ABSOLUTE); 211 } 212 213 static uint16_t 214 pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch) 215 { 216 uint16_t lval; 217 uint64_t delta_ticks; 218 219 /* cannot latch a new value until the old one has been consumed */ 220 if (latch && c->olatched) 221 return (0); 222 223 if (c->initial == 0) { 224 /* 225 * This is possibly an OS bug - reading the value of the timer 226 * without having set up the initial value. 227 * 228 * The original user-space version of this code set the timer to 229 * 100hz in this condition; do the same here. 230 */ 231 c->initial = TIMER_DIV(PIT_8254_FREQ, 100); 232 c->time_loaded = gethrtime(); 233 c->reg_status &= ~TIMER_STS_NULLCNT; 234 } 235 236 delta_ticks = vatpit_delta_ticks(vatpit, c); 237 lval = c->initial - delta_ticks % c->initial; 238 239 if (latch) { 240 c->olatched = true; 241 c->ol_sel = true; 242 c->reg_ol[1] = lval; /* LSB */ 243 c->reg_ol[0] = lval >> 8; /* MSB */ 244 } 245 246 return (lval); 247 } 248 249 static int 250 pit_readback1(struct vatpit *vatpit, int channel, uint8_t cmd) 251 { 252 struct channel *c; 253 254 c = &vatpit->channel[channel]; 255 256 /* 257 * Latch the count/status of the timer if not already latched. 258 * N.B. that the count/status latch-select bits are active-low. 259 */ 260 if ((cmd & TIMER_RB_LCTR) == 0 && !c->olatched) { 261 (void) pit_update_counter(vatpit, c, true); 262 } 263 264 if ((cmd & TIMER_RB_LSTATUS) == 0 && !c->slatched) { 265 c->slatched = true; 266 /* 267 * For mode 0, see if the elapsed time is greater 268 * than the initial value - this results in the 269 * output pin being set to 1 in the status byte. 270 */ 271 if (c->mode == TIMER_INTTC && vatpit_get_out(vatpit, channel)) 272 c->reg_status |= TIMER_STS_OUT; 273 else 274 c->reg_status &= ~TIMER_STS_OUT; 275 } 276 277 return (0); 278 } 279 280 static int 281 pit_readback(struct vatpit *vatpit, uint8_t cmd) 282 { 283 int error; 284 285 /* 286 * The readback command can apply to all timers. 287 */ 288 error = 0; 289 if (cmd & TIMER_RB_CTR_0) 290 error = pit_readback1(vatpit, 0, cmd); 291 if (!error && cmd & TIMER_RB_CTR_1) 292 error = pit_readback1(vatpit, 1, cmd); 293 if (!error && cmd & TIMER_RB_CTR_2) 294 error = pit_readback1(vatpit, 2, cmd); 295 296 return (error); 297 } 298 299 static int 300 vatpit_update_mode(struct vatpit *vatpit, uint8_t val) 301 { 302 struct channel *c; 303 int sel, rw; 304 uint8_t mode; 305 306 sel = val & TIMER_SEL_MASK; 307 rw = val & TIMER_RW_MASK; 308 mode = val & TIMER_MODE_MASK; 309 310 /* Clear don't-care bit (M2) when M1 is set */ 311 if ((mode & TIMER_RATEGEN) != 0) { 312 mode &= ~TIMER_SWSTROBE; 313 } 314 315 if (sel == TIMER_SEL_READBACK) 316 return (pit_readback(vatpit, val)); 317 318 if (rw != TIMER_LATCH && rw != TIMER_16BIT) 319 return (-1); 320 321 if (rw != TIMER_LATCH) { 322 /* 323 * Counter mode is not affected when issuing a 324 * latch command. 325 */ 326 if (mode != TIMER_INTTC && 327 mode != TIMER_RATEGEN && 328 mode != TIMER_SQWAVE && 329 mode != TIMER_SWSTROBE) 330 return (-1); 331 } 332 333 c = &vatpit->channel[sel >> 6]; 334 if (rw == TIMER_LATCH) { 335 (void) pit_update_counter(vatpit, c, true); 336 } else { 337 c->mode = mode; 338 c->olatched = false; /* reset latch after reprogramming */ 339 c->reg_status |= TIMER_STS_NULLCNT; 340 } 341 342 return (0); 343 } 344 345 int 346 vatpit_handler(void *arg, bool in, uint16_t port, uint8_t bytes, uint32_t *eax) 347 { 348 struct vatpit *vatpit = arg; 349 struct channel *c; 350 uint8_t val; 351 int error; 352 353 if (bytes != 1) 354 return (-1); 355 356 val = *eax; 357 358 if (port == TIMER_MODE) { 359 if (in) { 360 /* Mode is write-only */ 361 return (-1); 362 } 363 364 VATPIT_LOCK(vatpit); 365 error = vatpit_update_mode(vatpit, val); 366 VATPIT_UNLOCK(vatpit); 367 368 return (error); 369 } 370 371 /* counter ports */ 372 KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2, 373 ("invalid port 0x%x", port)); 374 c = &vatpit->channel[port - TIMER_CNTR0]; 375 376 VATPIT_LOCK(vatpit); 377 if (in && c->slatched) { 378 /* Return the status byte if latched */ 379 *eax = c->reg_status; 380 c->slatched = false; 381 c->reg_status = 0; 382 } else if (in) { 383 /* 384 * The spec says that once the output latch is completely 385 * read it should revert to "following" the counter. Use 386 * the free running counter for this case (i.e. Linux 387 * TSC calibration). Assuming the access mode is 16-bit, 388 * toggle the MSB/LSB bit on each read. 389 */ 390 if (!c->olatched) { 391 uint16_t tmp; 392 393 tmp = pit_update_counter(vatpit, c, false); 394 if (c->fr_sel) { 395 tmp >>= 8; 396 } 397 tmp &= 0xff; 398 *eax = tmp; 399 c->fr_sel = !c->fr_sel; 400 } else { 401 if (c->ol_sel) { 402 *eax = c->reg_ol[1]; 403 c->ol_sel = false; 404 } else { 405 *eax = c->reg_ol[0]; 406 c->olatched = false; 407 } 408 } 409 } else { 410 if (!c->cr_sel) { 411 c->reg_cr[0] = *eax; 412 c->cr_sel = true; 413 } else { 414 c->reg_cr[1] = *eax; 415 c->cr_sel = false; 416 417 c->reg_status &= ~TIMER_STS_NULLCNT; 418 c->fr_sel = false; 419 c->initial = c->reg_cr[0] | (uint16_t)c->reg_cr[1] << 8; 420 c->time_loaded = gethrtime(); 421 /* Start an interval timer for channel 0 */ 422 if (port == TIMER_CNTR0) { 423 c->time_target = c->time_loaded; 424 c->total_target = 0; 425 pit_timer_start_cntr0(vatpit); 426 } 427 if (c->initial == 0) 428 c->initial = 0xffff; 429 } 430 } 431 VATPIT_UNLOCK(vatpit); 432 433 return (0); 434 } 435 436 int 437 vatpit_nmisc_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 438 uint32_t *eax) 439 { 440 struct vatpit *vatpit = arg; 441 442 if (in) { 443 VATPIT_LOCK(vatpit); 444 if (vatpit_get_out(vatpit, 2)) 445 *eax = TMR2_OUT_STS; 446 else 447 *eax = 0; 448 449 VATPIT_UNLOCK(vatpit); 450 } 451 452 return (0); 453 } 454 455 struct vatpit * 456 vatpit_init(struct vm *vm) 457 { 458 struct vatpit *vatpit; 459 struct vatpit_callout_arg *arg; 460 int i; 461 462 vatpit = kmem_zalloc(sizeof (struct vatpit), KM_SLEEP); 463 vatpit->vm = vm; 464 465 mutex_init(&vatpit->lock, NULL, MUTEX_ADAPTIVE, NULL); 466 467 for (i = 0; i < 3; i++) { 468 callout_init(&vatpit->channel[i].callout, 1); 469 arg = &vatpit->channel[i].callout_arg; 470 arg->vatpit = vatpit; 471 arg->channel_num = i; 472 } 473 474 return (vatpit); 475 } 476 477 void 478 vatpit_cleanup(struct vatpit *vatpit) 479 { 480 int i; 481 482 for (i = 0; i < 3; i++) 483 callout_drain(&vatpit->channel[i].callout); 484 485 mutex_destroy(&vatpit->lock); 486 kmem_free(vatpit, sizeof (*vatpit)); 487 } 488 489 void 490 vatpit_localize_resources(struct vatpit *vatpit) 491 { 492 for (uint_t i = 0; i < 3; i++) { 493 /* Only localize channels which might be running */ 494 if (vatpit->channel[i].mode != 0) { 495 vmm_glue_callout_localize(&vatpit->channel[i].callout); 496 } 497 } 498 } 499 500 static int 501 vatpit_data_read(void *datap, const vmm_data_req_t *req) 502 { 503 VERIFY3U(req->vdr_class, ==, VDC_ATPIT); 504 VERIFY3U(req->vdr_version, ==, 1); 505 VERIFY3U(req->vdr_len, ==, sizeof (struct vdi_atpit_v1)); 506 507 struct vatpit *vatpit = datap; 508 struct vdi_atpit_v1 *out = req->vdr_data; 509 510 VATPIT_LOCK(vatpit); 511 for (uint_t i = 0; i < 3; i++) { 512 const struct channel *src = &vatpit->channel[i]; 513 struct vdi_atpit_channel_v1 *chan = &out->va_channel[i]; 514 515 chan->vac_initial = src->initial; 516 chan->vac_reg_cr = 517 (src->reg_cr[0] | (uint16_t)src->reg_cr[1] << 8); 518 chan->vac_reg_ol = 519 (src->reg_ol[0] | (uint16_t)src->reg_ol[1] << 8); 520 chan->vac_reg_status = src->reg_status; 521 chan->vac_mode = src->mode; 522 chan->vac_status = 523 (src->slatched ? (1 << 0) : 0) | 524 (src->olatched ? (1 << 1) : 0) | 525 (src->cr_sel ? (1 << 2) : 0) | 526 (src->ol_sel ? (1 << 3) : 0) | 527 (src->fr_sel ? (1 << 4) : 0); 528 /* Only channel 0 has the timer configured */ 529 if (i == 0) { 530 chan->vac_time_target = 531 vm_normalize_hrtime(vatpit->vm, src->time_target); 532 } else { 533 chan->vac_time_target = 0; 534 } 535 } 536 VATPIT_UNLOCK(vatpit); 537 538 return (0); 539 } 540 541 static bool 542 vatpit_data_validate(const struct vdi_atpit_v1 *src) 543 { 544 for (uint_t i = 0; i < 3; i++) { 545 const struct vdi_atpit_channel_v1 *chan = &src->va_channel[i]; 546 547 if ((chan->vac_status & ~VALID_STATUS_BITS) != 0) { 548 return (false); 549 } 550 } 551 return (true); 552 } 553 554 static int 555 vatpit_data_write(void *datap, const vmm_data_req_t *req) 556 { 557 VERIFY3U(req->vdr_class, ==, VDC_ATPIT); 558 VERIFY3U(req->vdr_version, ==, 1); 559 VERIFY3U(req->vdr_len, ==, sizeof (struct vdi_atpit_v1)); 560 561 struct vatpit *vatpit = datap; 562 const struct vdi_atpit_v1 *src = req->vdr_data; 563 if (!vatpit_data_validate(src)) { 564 return (EINVAL); 565 } 566 567 VATPIT_LOCK(vatpit); 568 for (uint_t i = 0; i < 3; i++) { 569 const struct vdi_atpit_channel_v1 *chan = &src->va_channel[i]; 570 struct channel *out = &vatpit->channel[i]; 571 572 out->initial = chan->vac_initial; 573 out->reg_cr[0] = chan->vac_reg_cr; 574 out->reg_cr[1] = chan->vac_reg_cr >> 8; 575 out->reg_ol[0] = chan->vac_reg_ol; 576 out->reg_ol[1] = chan->vac_reg_ol >> 8; 577 out->reg_status = chan->vac_reg_status; 578 out->mode = chan->vac_mode; 579 out->slatched = (chan->vac_status & (1 << 0)) != 0; 580 out->olatched = (chan->vac_status & (1 << 1)) != 0; 581 out->cr_sel = (chan->vac_status & (1 << 2)) != 0; 582 out->ol_sel = (chan->vac_status & (1 << 3)) != 0; 583 out->fr_sel = (chan->vac_status & (1 << 4)) != 0; 584 585 /* Only channel 0 has the timer configured */ 586 if (i != 0) { 587 continue; 588 } 589 590 struct callout *callout = &out->callout; 591 if (callout_active(callout)) { 592 callout_deactivate(callout); 593 } 594 595 if (chan->vac_time_target == 0) { 596 out->time_loaded = 0; 597 out->time_target = 0; 598 continue; 599 } 600 601 /* back-calculate time_loaded for the appropriate interval */ 602 const uint64_t time_target = 603 vm_denormalize_hrtime(vatpit->vm, chan->vac_time_target); 604 out->total_target = out->initial; 605 out->time_target = time_target; 606 out->time_loaded = time_target - 607 hrt_freq_interval(PIT_8254_FREQ, out->initial); 608 callout_reset_hrtime(callout, out->time_target, 609 vatpit_callout_handler, &out->callout_arg, C_ABSOLUTE); 610 } 611 VATPIT_UNLOCK(vatpit); 612 613 return (0); 614 } 615 616 static const vmm_data_version_entry_t atpit_v1 = { 617 .vdve_class = VDC_ATPIT, 618 .vdve_version = 1, 619 .vdve_len_expect = sizeof (struct vdi_atpit_v1), 620 .vdve_readf = vatpit_data_read, 621 .vdve_writef = vatpit_data_write, 622 }; 623 VMM_DATA_VERSION(atpit_v1); 624