1 /*-
2 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3 * Copyright (c) 2011 NetApp, Inc.
4 * All rights reserved.
5 * Copyright (c) 2018 Joyent, Inc.
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, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 #include "opt_bhyve_snapshot.h"
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/queue.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/systm.h>
40
41 #include <machine/vmm.h>
42 #include <machine/vmm_snapshot.h>
43
44 #include <dev/vmm/vmm_ktr.h>
45
46 #include "vatpic.h"
47 #include "vioapic.h"
48 #include "vatpit.h"
49
50 static MALLOC_DEFINE(M_VATPIT, "atpit", "bhyve virtual atpit (8254)");
51
52 #define VATPIT_LOCK(vatpit) mtx_lock_spin(&((vatpit)->mtx))
53 #define VATPIT_UNLOCK(vatpit) mtx_unlock_spin(&((vatpit)->mtx))
54 #define VATPIT_LOCKED(vatpit) mtx_owned(&((vatpit)->mtx))
55
56 #define TIMER_SEL_MASK 0xc0
57 #define TIMER_RW_MASK 0x30
58 #define TIMER_MODE_MASK 0x0f
59 #define TIMER_SEL_READBACK 0xc0
60
61 #define TIMER_STS_OUT 0x80
62 #define TIMER_STS_NULLCNT 0x40
63
64 #define TIMER_RB_LCTR 0x20
65 #define TIMER_RB_LSTATUS 0x10
66 #define TIMER_RB_CTR_2 0x08
67 #define TIMER_RB_CTR_1 0x04
68 #define TIMER_RB_CTR_0 0x02
69
70 #define TMR2_OUT_STS 0x20
71
72 #define PIT_8254_FREQ 1193182
73 #define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz))
74
75 struct vatpit_callout_arg {
76 struct vatpit *vatpit;
77 int channel_num;
78 };
79
80 struct channel {
81 int mode;
82 uint16_t initial; /* initial counter value */
83 struct bintime now_bt; /* uptime when counter was loaded */
84 uint8_t cr[2];
85 uint8_t ol[2];
86 bool slatched; /* status latched */
87 uint8_t status;
88 int crbyte;
89 int olbyte;
90 int frbyte;
91 struct callout callout;
92 struct bintime callout_bt; /* target time */
93 struct vatpit_callout_arg callout_arg;
94 };
95
96 struct vatpit {
97 struct vm *vm;
98 struct mtx mtx;
99
100 struct bintime freq_bt;
101
102 struct channel channel[3];
103 };
104
105 static void pit_timer_start_cntr0(struct vatpit *vatpit);
106
107 static uint64_t
vatpit_delta_ticks(struct vatpit * vatpit,struct channel * c)108 vatpit_delta_ticks(struct vatpit *vatpit, struct channel *c)
109 {
110 struct bintime delta;
111 uint64_t result;
112
113 binuptime(&delta);
114 bintime_sub(&delta, &c->now_bt);
115
116 result = delta.sec * PIT_8254_FREQ;
117 result += delta.frac / vatpit->freq_bt.frac;
118
119 return (result);
120 }
121
122 static int
vatpit_get_out(struct vatpit * vatpit,int channel)123 vatpit_get_out(struct vatpit *vatpit, int channel)
124 {
125 struct channel *c;
126 uint64_t delta_ticks;
127 int out;
128
129 c = &vatpit->channel[channel];
130
131 switch (c->mode) {
132 case TIMER_INTTC:
133 delta_ticks = vatpit_delta_ticks(vatpit, c);
134 out = (delta_ticks >= c->initial);
135 break;
136 default:
137 out = 0;
138 break;
139 }
140
141 return (out);
142 }
143
144 static void
vatpit_callout_handler(void * a)145 vatpit_callout_handler(void *a)
146 {
147 struct vatpit_callout_arg *arg = a;
148 struct vatpit *vatpit;
149 struct callout *callout;
150 struct channel *c;
151
152 vatpit = arg->vatpit;
153 c = &vatpit->channel[arg->channel_num];
154 callout = &c->callout;
155
156 VM_CTR1(vatpit->vm, "atpit t%d fired", arg->channel_num);
157
158 VATPIT_LOCK(vatpit);
159
160 if (callout_pending(callout)) /* callout was reset */
161 goto done;
162
163 if (!callout_active(callout)) /* callout was stopped */
164 goto done;
165
166 callout_deactivate(callout);
167
168 if (c->mode == TIMER_RATEGEN) {
169 pit_timer_start_cntr0(vatpit);
170 }
171
172 vatpic_pulse_irq(vatpit->vm, 0);
173 vioapic_pulse_irq(vatpit->vm, 2);
174
175 done:
176 VATPIT_UNLOCK(vatpit);
177 return;
178 }
179
180 static void
pit_timer_start_cntr0(struct vatpit * vatpit)181 pit_timer_start_cntr0(struct vatpit *vatpit)
182 {
183 struct channel *c;
184 struct bintime now, delta;
185 sbintime_t precision;
186
187 c = &vatpit->channel[0];
188 if (c->initial != 0) {
189 delta.sec = 0;
190 delta.frac = vatpit->freq_bt.frac * c->initial;
191 bintime_add(&c->callout_bt, &delta);
192 precision = bttosbt(delta) >> tc_precexp;
193
194 /*
195 * Reset 'callout_bt' if the time that the callout
196 * was supposed to fire is more than 'c->initial'
197 * ticks in the past.
198 */
199 binuptime(&now);
200 if (bintime_cmp(&c->callout_bt, &now, <)) {
201 c->callout_bt = now;
202 bintime_add(&c->callout_bt, &delta);
203 }
204
205 callout_reset_sbt(&c->callout, bttosbt(c->callout_bt),
206 precision, vatpit_callout_handler, &c->callout_arg,
207 C_ABSOLUTE);
208 }
209 }
210
211 static uint16_t
pit_update_counter(struct vatpit * vatpit,struct channel * c,bool latch)212 pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch)
213 {
214 uint16_t lval;
215 uint64_t delta_ticks;
216
217 /* cannot latch a new value until the old one has been consumed */
218 if (latch && c->olbyte != 0)
219 return (0);
220
221 if (c->initial == 0) {
222 /*
223 * This is possibly an o/s bug - reading the value of
224 * the timer without having set up the initial value.
225 *
226 * The original user-space version of this code set
227 * the timer to 100hz in this condition; do the same
228 * here.
229 */
230 c->initial = TIMER_DIV(PIT_8254_FREQ, 100);
231 binuptime(&c->now_bt);
232 c->status &= ~TIMER_STS_NULLCNT;
233 }
234
235 delta_ticks = vatpit_delta_ticks(vatpit, c);
236 lval = c->initial - delta_ticks % c->initial;
237
238 if (latch) {
239 c->olbyte = 2;
240 c->ol[1] = lval; /* LSB */
241 c->ol[0] = lval >> 8; /* MSB */
242 }
243
244 return (lval);
245 }
246
247 static int
pit_readback1(struct vatpit * vatpit,int channel,uint8_t cmd)248 pit_readback1(struct vatpit *vatpit, int channel, uint8_t cmd)
249 {
250 struct channel *c;
251
252 c = &vatpit->channel[channel];
253
254 /*
255 * Latch the count/status of the timer if not already latched.
256 * N.B. that the count/status latch-select bits are active-low.
257 */
258 if (!(cmd & TIMER_RB_LCTR) && !c->olbyte) {
259 (void) pit_update_counter(vatpit, c, true);
260 }
261
262 if (!(cmd & TIMER_RB_LSTATUS) && !c->slatched) {
263 c->slatched = true;
264 /*
265 * For mode 0, see if the elapsed time is greater
266 * than the initial value - this results in the
267 * output pin being set to 1 in the status byte.
268 */
269 if (c->mode == TIMER_INTTC && vatpit_get_out(vatpit, channel))
270 c->status |= TIMER_STS_OUT;
271 else
272 c->status &= ~TIMER_STS_OUT;
273 }
274
275 return (0);
276 }
277
278 static int
pit_readback(struct vatpit * vatpit,uint8_t cmd)279 pit_readback(struct vatpit *vatpit, uint8_t cmd)
280 {
281 int error;
282
283 /*
284 * The readback command can apply to all timers.
285 */
286 error = 0;
287 if (cmd & TIMER_RB_CTR_0)
288 error = pit_readback1(vatpit, 0, cmd);
289 if (!error && cmd & TIMER_RB_CTR_1)
290 error = pit_readback1(vatpit, 1, cmd);
291 if (!error && cmd & TIMER_RB_CTR_2)
292 error = pit_readback1(vatpit, 2, cmd);
293
294 return (error);
295 }
296
297 static int
vatpit_update_mode(struct vatpit * vatpit,uint8_t val)298 vatpit_update_mode(struct vatpit *vatpit, uint8_t val)
299 {
300 struct channel *c;
301 int sel, rw, mode;
302
303 sel = val & TIMER_SEL_MASK;
304 rw = val & TIMER_RW_MASK;
305 mode = val & TIMER_MODE_MASK;
306
307 if (sel == TIMER_SEL_READBACK)
308 return (pit_readback(vatpit, val));
309
310 if (rw != TIMER_LATCH && rw != TIMER_16BIT)
311 return (-1);
312
313 if (rw != TIMER_LATCH) {
314 /*
315 * Counter mode is not affected when issuing a
316 * latch command.
317 */
318 if (mode != TIMER_INTTC &&
319 mode != TIMER_RATEGEN &&
320 mode != TIMER_SQWAVE &&
321 mode != TIMER_SWSTROBE)
322 return (-1);
323 }
324
325 c = &vatpit->channel[sel >> 6];
326 if (rw == TIMER_LATCH)
327 pit_update_counter(vatpit, c, true);
328 else {
329 c->mode = mode;
330 c->olbyte = 0; /* reset latch after reprogramming */
331 c->status |= TIMER_STS_NULLCNT;
332 }
333
334 return (0);
335 }
336
337 int
vatpit_handler(struct vm * vm,bool in,int port,int bytes,uint32_t * eax)338 vatpit_handler(struct vm *vm, bool in, int port, int bytes, uint32_t *eax)
339 {
340 struct vatpit *vatpit;
341 struct channel *c;
342 uint8_t val;
343 int error;
344
345 vatpit = vm_atpit(vm);
346
347 if (bytes != 1)
348 return (-1);
349
350 val = *eax;
351
352 if (port == TIMER_MODE) {
353 if (in) {
354 VM_CTR0(vatpit->vm, "vatpit attempt to read mode");
355 return (-1);
356 }
357
358 VATPIT_LOCK(vatpit);
359 error = vatpit_update_mode(vatpit, val);
360 VATPIT_UNLOCK(vatpit);
361
362 return (error);
363 }
364
365 /* counter ports */
366 KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2,
367 ("invalid port 0x%x", port));
368 c = &vatpit->channel[port - TIMER_CNTR0];
369
370 VATPIT_LOCK(vatpit);
371 if (in && c->slatched) {
372 /*
373 * Return the status byte if latched
374 */
375 *eax = c->status;
376 c->slatched = false;
377 c->status = 0;
378 } else if (in) {
379 /*
380 * The spec says that once the output latch is completely
381 * read it should revert to "following" the counter. Use
382 * the free running counter for this case (i.e. Linux
383 * TSC calibration). Assuming the access mode is 16-bit,
384 * toggle the MSB/LSB bit on each read.
385 */
386 if (c->olbyte == 0) {
387 uint16_t tmp;
388
389 tmp = pit_update_counter(vatpit, c, false);
390 if (c->frbyte)
391 tmp >>= 8;
392 tmp &= 0xff;
393 *eax = tmp;
394 c->frbyte ^= 1;
395 } else
396 *eax = c->ol[--c->olbyte];
397 } else {
398 c->cr[c->crbyte++] = *eax;
399 if (c->crbyte == 2) {
400 c->status &= ~TIMER_STS_NULLCNT;
401 c->frbyte = 0;
402 c->crbyte = 0;
403 c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8;
404 binuptime(&c->now_bt);
405 /* Start an interval timer for channel 0 */
406 if (port == TIMER_CNTR0) {
407 c->callout_bt = c->now_bt;
408 pit_timer_start_cntr0(vatpit);
409 }
410 if (c->initial == 0)
411 c->initial = 0xffff;
412 }
413 }
414 VATPIT_UNLOCK(vatpit);
415
416 return (0);
417 }
418
419 int
vatpit_nmisc_handler(struct vm * vm,bool in,int port,int bytes,uint32_t * eax)420 vatpit_nmisc_handler(struct vm *vm, bool in, int port, int bytes,
421 uint32_t *eax)
422 {
423 struct vatpit *vatpit;
424
425 vatpit = vm_atpit(vm);
426
427 if (in) {
428 VATPIT_LOCK(vatpit);
429 if (vatpit_get_out(vatpit, 2))
430 *eax = TMR2_OUT_STS;
431 else
432 *eax = 0;
433
434 VATPIT_UNLOCK(vatpit);
435 }
436
437 return (0);
438 }
439
440 struct vatpit *
vatpit_init(struct vm * vm)441 vatpit_init(struct vm *vm)
442 {
443 struct vatpit *vatpit;
444 struct vatpit_callout_arg *arg;
445 int i;
446
447 vatpit = malloc(sizeof(struct vatpit), M_VATPIT, M_WAITOK | M_ZERO);
448 vatpit->vm = vm;
449
450 mtx_init(&vatpit->mtx, "vatpit lock", NULL, MTX_SPIN);
451
452 FREQ2BT(PIT_8254_FREQ, &vatpit->freq_bt);
453
454 for (i = 0; i < 3; i++) {
455 callout_init(&vatpit->channel[i].callout, 1);
456 arg = &vatpit->channel[i].callout_arg;
457 arg->vatpit = vatpit;
458 arg->channel_num = i;
459 }
460
461 return (vatpit);
462 }
463
464 void
vatpit_cleanup(struct vatpit * vatpit)465 vatpit_cleanup(struct vatpit *vatpit)
466 {
467 int i;
468
469 for (i = 0; i < 3; i++)
470 callout_drain(&vatpit->channel[i].callout);
471
472 mtx_destroy(&vatpit->mtx);
473 free(vatpit, M_VATPIT);
474 }
475
476 #ifdef BHYVE_SNAPSHOT
477 int
vatpit_snapshot(struct vatpit * vatpit,struct vm_snapshot_meta * meta)478 vatpit_snapshot(struct vatpit *vatpit, struct vm_snapshot_meta *meta)
479 {
480 int ret;
481 int i;
482 struct channel *channel;
483
484 SNAPSHOT_VAR_OR_LEAVE(vatpit->freq_bt.sec, meta, ret, done);
485 SNAPSHOT_VAR_OR_LEAVE(vatpit->freq_bt.frac, meta, ret, done);
486
487 /* properly restore timers; they will NOT work currently */
488 printf("%s: snapshot restore does not reset timers!\r\n", __func__);
489
490 for (i = 0; i < nitems(vatpit->channel); i++) {
491 channel = &vatpit->channel[i];
492
493 SNAPSHOT_VAR_OR_LEAVE(channel->mode, meta, ret, done);
494 SNAPSHOT_VAR_OR_LEAVE(channel->initial, meta, ret, done);
495 SNAPSHOT_VAR_OR_LEAVE(channel->now_bt.sec, meta, ret, done);
496 SNAPSHOT_VAR_OR_LEAVE(channel->now_bt.frac, meta, ret, done);
497 SNAPSHOT_BUF_OR_LEAVE(channel->cr, sizeof(channel->cr),
498 meta, ret, done);
499 SNAPSHOT_BUF_OR_LEAVE(channel->ol, sizeof(channel->ol),
500 meta, ret, done);
501 SNAPSHOT_VAR_OR_LEAVE(channel->slatched, meta, ret, done);
502 SNAPSHOT_VAR_OR_LEAVE(channel->status, meta, ret, done);
503 SNAPSHOT_VAR_OR_LEAVE(channel->crbyte, meta, ret, done);
504 SNAPSHOT_VAR_OR_LEAVE(channel->frbyte, meta, ret, done);
505 SNAPSHOT_VAR_OR_LEAVE(channel->callout_bt.sec, meta, ret, done);
506 SNAPSHOT_VAR_OR_LEAVE(channel->callout_bt.frac, meta, ret,
507 done);
508 }
509
510 done:
511 return (ret);
512 }
513 #endif
514