1 /*
2  * QEMU 8253/8254 interval timer emulation
3  *
4  * Copyright (c) 2003-2004 Fabrice Bellard
5  * Copyright (c) 2006 Intel Corperation
6  * Copyright (c) 2007 Keir Fraser, XenSource Inc.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to
10  * deal in the Software without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12  * sell copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24  * IN THE SOFTWARE.
25  */
26 
27 #include <xen/types.h>
28 #include <xen/mm.h>
29 #include <xen/xmalloc.h>
30 #include <xen/lib.h>
31 #include <xen/errno.h>
32 #include <xen/sched.h>
33 #include <xen/trace.h>
34 #include <asm/time.h>
35 #include <asm/hvm/hvm.h>
36 #include <asm/hvm/io.h>
37 #include <asm/hvm/support.h>
38 #include <asm/hvm/vpt.h>
39 #include <asm/current.h>
40 
41 #define domain_vpit(x) (&(x)->arch.vpit)
42 #define vcpu_vpit(x)   (domain_vpit((x)->domain))
43 #define vpit_domain(x) (container_of((x), struct domain, arch.vpit))
44 #define vpit_vcpu(x)   (pt_global_vcpu_target(vpit_domain(x)))
45 
46 #define RW_STATE_LSB 1
47 #define RW_STATE_MSB 2
48 #define RW_STATE_WORD0 3
49 #define RW_STATE_WORD1 4
50 
51 static int handle_pit_io(
52     int dir, unsigned int port, unsigned int bytes, uint32_t *val);
53 static int handle_speaker_io(
54     int dir, unsigned int port, unsigned int bytes, uint32_t *val);
55 
56 #define get_guest_time(v) \
57    (is_hvm_vcpu(v) ? hvm_get_guest_time(v) : (u64)get_s_time())
58 
pit_get_count(PITState * pit,int channel)59 static int pit_get_count(PITState *pit, int channel)
60 {
61     uint64_t d;
62     int  counter;
63     struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
64     struct vcpu *v = vpit_vcpu(pit);
65 
66     ASSERT(spin_is_locked(&pit->lock));
67 
68     d = muldiv64(get_guest_time(v) - pit->count_load_time[channel],
69                  PIT_FREQ, SYSTEM_TIME_HZ);
70 
71     switch ( c->mode )
72     {
73     case 0:
74     case 1:
75     case 4:
76     case 5:
77         counter = (c->count - d) & 0xffff;
78         break;
79     case 3:
80         /* XXX: may be incorrect for odd counts */
81         counter = c->count - ((2 * d) % c->count);
82         break;
83     default:
84         counter = c->count - (d % c->count);
85         break;
86     }
87     return counter;
88 }
89 
pit_get_out(PITState * pit,int channel)90 static int pit_get_out(PITState *pit, int channel)
91 {
92     struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
93     uint64_t d;
94     int out;
95     struct vcpu *v = vpit_vcpu(pit);
96 
97     ASSERT(spin_is_locked(&pit->lock));
98 
99     d = muldiv64(get_guest_time(v) - pit->count_load_time[channel],
100                  PIT_FREQ, SYSTEM_TIME_HZ);
101 
102     switch ( s->mode )
103     {
104     default:
105     case 0:
106         out = (d >= s->count);
107         break;
108     case 1:
109         out = (d < s->count);
110         break;
111     case 2:
112         out = (((d % s->count) == 0) && (d != 0));
113         break;
114     case 3:
115         out = ((d % s->count) < ((s->count + 1) >> 1));
116         break;
117     case 4:
118     case 5:
119         out = (d == s->count);
120         break;
121     }
122 
123     return out;
124 }
125 
pit_set_gate(PITState * pit,int channel,int val)126 static void pit_set_gate(PITState *pit, int channel, int val)
127 {
128     struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
129     struct vcpu *v = vpit_vcpu(pit);
130 
131     ASSERT(spin_is_locked(&pit->lock));
132 
133     switch ( s->mode )
134     {
135     default:
136     case 0:
137     case 4:
138         /* XXX: just disable/enable counting */
139         break;
140     case 1:
141     case 5:
142     case 2:
143     case 3:
144         /* Restart counting on rising edge. */
145         if ( s->gate < val )
146             pit->count_load_time[channel] = get_guest_time(v);
147         break;
148     }
149 
150     s->gate = val;
151 }
152 
pit_get_gate(PITState * pit,int channel)153 static int pit_get_gate(PITState *pit, int channel)
154 {
155     ASSERT(spin_is_locked(&pit->lock));
156     return pit->hw.channels[channel].gate;
157 }
158 
pit_time_fired(struct vcpu * v,void * priv)159 static void pit_time_fired(struct vcpu *v, void *priv)
160 {
161     uint64_t *count_load_time = priv;
162     TRACE_0D(TRC_HVM_EMUL_PIT_TIMER_CB);
163     *count_load_time = get_guest_time(v);
164 }
165 
pit_load_count(PITState * pit,int channel,int val)166 static void pit_load_count(PITState *pit, int channel, int val)
167 {
168     u32 period;
169     struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
170     struct vcpu *v = vpit_vcpu(pit);
171 
172     ASSERT(spin_is_locked(&pit->lock));
173 
174     if ( val == 0 )
175         val = 0x10000;
176 
177     if ( v == NULL )
178         pit->count_load_time[channel] = 0;
179     else
180         pit->count_load_time[channel] = get_guest_time(v);
181     s->count = val;
182     period = DIV_ROUND(val * SYSTEM_TIME_HZ, PIT_FREQ);
183 
184     if ( (v == NULL) || !is_hvm_vcpu(v) || (channel != 0) )
185         return;
186 
187     switch ( s->mode )
188     {
189     case 2:
190     case 3:
191         /* Periodic timer. */
192         TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, period);
193         create_periodic_time(v, &pit->pt0, period, period, 0, pit_time_fired,
194                              &pit->count_load_time[channel], false);
195         break;
196     case 1:
197     case 4:
198         /* One-shot timer. */
199         TRACE_2D(TRC_HVM_EMUL_PIT_START_TIMER, period, 0);
200         create_periodic_time(v, &pit->pt0, period, 0, 0, pit_time_fired,
201                              &pit->count_load_time[channel], false);
202         break;
203     default:
204         TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
205         destroy_periodic_time(&pit->pt0);
206         break;
207     }
208 }
209 
pit_latch_count(PITState * pit,int channel)210 static void pit_latch_count(PITState *pit, int channel)
211 {
212     struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
213 
214     ASSERT(spin_is_locked(&pit->lock));
215 
216     if ( !c->count_latched )
217     {
218         c->latched_count = pit_get_count(pit, channel);
219         c->count_latched = c->rw_mode;
220     }
221 }
222 
pit_latch_status(PITState * pit,int channel)223 static void pit_latch_status(PITState *pit, int channel)
224 {
225     struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
226 
227     ASSERT(spin_is_locked(&pit->lock));
228 
229     if ( !c->status_latched )
230     {
231         /* TODO: Return NULL COUNT (bit 6). */
232         c->status = ((pit_get_out(pit, channel) << 7) |
233                      (c->rw_mode << 4) |
234                      (c->mode << 1) |
235                      c->bcd);
236         c->status_latched = 1;
237     }
238 }
239 
pit_ioport_write(struct PITState * pit,uint32_t addr,uint32_t val)240 static void pit_ioport_write(struct PITState *pit, uint32_t addr, uint32_t val)
241 {
242     int channel, access;
243     struct hvm_hw_pit_channel *s;
244 
245     val  &= 0xff;
246     addr &= 3;
247 
248     spin_lock(&pit->lock);
249 
250     if ( addr == 3 )
251     {
252         channel = val >> 6;
253         if ( channel == 3 )
254         {
255             /* Read-Back Command. */
256             for ( channel = 0; channel < 3; channel++ )
257             {
258                 s = &pit->hw.channels[channel];
259                 if ( val & (2 << channel) )
260                 {
261                     if ( !(val & 0x20) )
262                         pit_latch_count(pit, channel);
263                     if ( !(val & 0x10) )
264                         pit_latch_status(pit, channel);
265                 }
266             }
267         }
268         else
269         {
270             /* Select Counter <channel>. */
271             s = &pit->hw.channels[channel];
272             access = (val >> 4) & 3;
273             if ( access == 0 )
274             {
275                 pit_latch_count(pit, channel);
276             }
277             else
278             {
279                 s->rw_mode = access;
280                 s->read_state = access;
281                 s->write_state = access;
282                 s->mode = (val >> 1) & 7;
283                 if ( s->mode > 5 )
284                     s->mode -= 4;
285                 s->bcd = val & 1;
286                 /* XXX: update irq timer ? */
287             }
288         }
289     }
290     else
291     {
292         /* Write Count. */
293         s = &pit->hw.channels[addr];
294         switch ( s->write_state )
295         {
296         default:
297         case RW_STATE_LSB:
298             pit_load_count(pit, addr, val);
299             break;
300         case RW_STATE_MSB:
301             pit_load_count(pit, addr, val << 8);
302             break;
303         case RW_STATE_WORD0:
304             s->write_latch = val;
305             s->write_state = RW_STATE_WORD1;
306             break;
307         case RW_STATE_WORD1:
308             pit_load_count(pit, addr, s->write_latch | (val << 8));
309             s->write_state = RW_STATE_WORD0;
310             break;
311         }
312     }
313 
314     spin_unlock(&pit->lock);
315 }
316 
pit_ioport_read(struct PITState * pit,uint32_t addr)317 static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
318 {
319     int ret, count;
320     struct hvm_hw_pit_channel *s;
321 
322     addr &= 3;
323     s = &pit->hw.channels[addr];
324 
325     spin_lock(&pit->lock);
326 
327     if ( s->status_latched )
328     {
329         s->status_latched = 0;
330         ret = s->status;
331     }
332     else if ( s->count_latched )
333     {
334         switch ( s->count_latched )
335         {
336         default:
337         case RW_STATE_LSB:
338             ret = s->latched_count & 0xff;
339             s->count_latched = 0;
340             break;
341         case RW_STATE_MSB:
342             ret = s->latched_count >> 8;
343             s->count_latched = 0;
344             break;
345         case RW_STATE_WORD0:
346             ret = s->latched_count & 0xff;
347             s->count_latched = RW_STATE_MSB;
348             break;
349         }
350     }
351     else
352     {
353         switch ( s->read_state )
354         {
355         default:
356         case RW_STATE_LSB:
357             count = pit_get_count(pit, addr);
358             ret = count & 0xff;
359             break;
360         case RW_STATE_MSB:
361             count = pit_get_count(pit, addr);
362             ret = (count >> 8) & 0xff;
363             break;
364         case RW_STATE_WORD0:
365             count = pit_get_count(pit, addr);
366             ret = count & 0xff;
367             s->read_state = RW_STATE_WORD1;
368             break;
369         case RW_STATE_WORD1:
370             count = pit_get_count(pit, addr);
371             ret = (count >> 8) & 0xff;
372             s->read_state = RW_STATE_WORD0;
373             break;
374         }
375     }
376 
377     spin_unlock(&pit->lock);
378 
379     return ret;
380 }
381 
382 #ifdef CONFIG_HVM
pit_stop_channel0_irq(PITState * pit)383 void pit_stop_channel0_irq(PITState *pit)
384 {
385     if ( !has_vpit(current->domain) )
386         return;
387 
388     TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
389     spin_lock(&pit->lock);
390     destroy_periodic_time(&pit->pt0);
391     spin_unlock(&pit->lock);
392 }
393 
pit_save(struct vcpu * v,hvm_domain_context_t * h)394 static int pit_save(struct vcpu *v, hvm_domain_context_t *h)
395 {
396     struct domain *d = v->domain;
397     PITState *pit = domain_vpit(d);
398     int rc;
399 
400     if ( !has_vpit(d) )
401         return 0;
402 
403     spin_lock(&pit->lock);
404 
405     rc = hvm_save_entry(PIT, 0, h, &pit->hw);
406 
407     spin_unlock(&pit->lock);
408 
409     return rc;
410 }
411 
pit_load(struct domain * d,hvm_domain_context_t * h)412 static int pit_load(struct domain *d, hvm_domain_context_t *h)
413 {
414     PITState *pit = domain_vpit(d);
415     int i;
416 
417     if ( !has_vpit(d) )
418         return -ENODEV;
419 
420     spin_lock(&pit->lock);
421 
422     if ( hvm_load_entry(PIT, h, &pit->hw) )
423     {
424         spin_unlock(&pit->lock);
425         return 1;
426     }
427 
428     /*
429      * Recreate platform timers from hardware state.  There will be some
430      * time jitter here, but the wall-clock will have jumped massively, so
431      * we hope the guest can handle it.
432      */
433     pit->pt0.last_plt_gtime = get_guest_time(d->vcpu[0]);
434     for ( i = 0; i < 3; i++ )
435         pit_load_count(pit, i, pit->hw.channels[i].count);
436 
437     spin_unlock(&pit->lock);
438 
439     return 0;
440 }
441 
442 HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);
443 #endif
444 
pit_reset(struct domain * d)445 void pit_reset(struct domain *d)
446 {
447     PITState *pit = domain_vpit(d);
448     struct hvm_hw_pit_channel *s;
449     int i;
450 
451     if ( !has_vpit(d) )
452         return;
453 
454     if ( is_hvm_domain(d) )
455     {
456         TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
457         destroy_periodic_time(&pit->pt0);
458         pit->pt0.source = PTSRC_isa;
459     }
460 
461     spin_lock(&pit->lock);
462 
463     for ( i = 0; i < 3; i++ )
464     {
465         s = &pit->hw.channels[i];
466         s->mode = 0xff; /* the init mode */
467         s->gate = (i != 2);
468         pit_load_count(pit, i, 0);
469     }
470 
471     spin_unlock(&pit->lock);
472 }
473 
pit_init(struct domain * d,unsigned long cpu_khz)474 void pit_init(struct domain *d, unsigned long cpu_khz)
475 {
476     PITState *pit = domain_vpit(d);
477 
478     if ( !has_vpit(d) )
479         return;
480 
481     spin_lock_init(&pit->lock);
482 
483     if ( is_hvm_domain(d) )
484     {
485         register_portio_handler(d, PIT_BASE, 4, handle_pit_io);
486         register_portio_handler(d, 0x61, 1, handle_speaker_io);
487     }
488 
489     pit_reset(d);
490 }
491 
pit_deinit(struct domain * d)492 void pit_deinit(struct domain *d)
493 {
494     PITState *pit = domain_vpit(d);
495 
496     if ( !has_vpit(d) )
497         return;
498 
499     if ( is_hvm_domain(d) )
500     {
501         TRACE_0D(TRC_HVM_EMUL_PIT_STOP_TIMER);
502         destroy_periodic_time(&pit->pt0);
503     }
504 }
505 
506 /* the intercept action for PIT DM retval:0--not handled; 1--handled */
handle_pit_io(int dir,unsigned int port,unsigned int bytes,uint32_t * val)507 static int handle_pit_io(
508     int dir, unsigned int port, unsigned int bytes, uint32_t *val)
509 {
510     struct PITState *vpit = vcpu_vpit(current);
511 
512     if ( bytes != 1 )
513     {
514         gdprintk(XENLOG_WARNING, "PIT bad access\n");
515         *val = ~0;
516         return X86EMUL_OKAY;
517     }
518 
519     if ( dir == IOREQ_WRITE )
520     {
521         pit_ioport_write(vpit, port, *val);
522     }
523     else
524     {
525         if ( (port & 3) != 3 )
526             *val = pit_ioport_read(vpit, port);
527         else
528             gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n");
529     }
530 
531     return X86EMUL_OKAY;
532 }
533 
speaker_ioport_write(struct PITState * pit,uint32_t addr,uint32_t val)534 static void speaker_ioport_write(
535     struct PITState *pit, uint32_t addr, uint32_t val)
536 {
537     pit->hw.speaker_data_on = (val >> 1) & 1;
538     pit_set_gate(pit, 2, val & 1);
539 }
540 
speaker_ioport_read(struct PITState * pit,uint32_t addr)541 static uint32_t speaker_ioport_read(
542     struct PITState *pit, uint32_t addr)
543 {
544     /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
545     unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
546     return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) |
547             (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));
548 }
549 
handle_speaker_io(int dir,unsigned int port,uint32_t bytes,uint32_t * val)550 static int handle_speaker_io(
551     int dir, unsigned int port, uint32_t bytes, uint32_t *val)
552 {
553     struct PITState *vpit = vcpu_vpit(current);
554 
555     BUG_ON(bytes != 1);
556 
557     spin_lock(&vpit->lock);
558 
559     if ( dir == IOREQ_WRITE )
560         speaker_ioport_write(vpit, port, *val);
561     else
562         *val = speaker_ioport_read(vpit, port);
563 
564     spin_unlock(&vpit->lock);
565 
566     return X86EMUL_OKAY;
567 }
568 
pv_pit_handler(int port,int data,int write)569 int pv_pit_handler(int port, int data, int write)
570 {
571     ioreq_t ioreq = {
572         .size = 1,
573         .type = IOREQ_TYPE_PIO,
574         .addr = port,
575         .dir  = write ? IOREQ_WRITE : IOREQ_READ,
576         .data = data
577     };
578 
579     if ( !has_vpit(current->domain) )
580         return ~0;
581 
582     if ( is_hardware_domain(current->domain) && hwdom_pit_access(&ioreq) )
583     {
584         /* nothing to do */;
585     }
586     else
587     {
588         uint32_t val = data;
589         if ( port == 0x61 )
590             handle_speaker_io(ioreq.dir, port, 1, &val);
591         else
592             handle_pit_io(ioreq.dir, port, 1, &val);
593         ioreq.data = val;
594     }
595 
596     return !write ? ioreq.data : 0;
597 }
598 
599 /*
600  * Local variables:
601  * mode: C
602  * c-file-style: "BSD"
603  * c-basic-offset: 4
604  * indent-tabs-mode: nil
605  * End:
606  */
607