• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Based heavily on GCE VMM's pit.cc.
6 
7 use std::io::Error as IoError;
8 use std::sync::Arc;
9 use std::time::Duration;
10 use std::time::Instant;
11 
12 use anyhow::Context;
13 use base::error;
14 use base::warn;
15 use base::Error as SysError;
16 use base::EventToken;
17 use base::WaitContext;
18 use bit_field::BitField1;
19 use bit_field::*;
20 use hypervisor::PitChannelState;
21 use hypervisor::PitRWMode;
22 use hypervisor::PitRWState;
23 use hypervisor::PitState;
24 use remain::sorted;
25 use sync::Mutex;
26 use thiserror::Error;
27 
28 cfg_if::cfg_if! {
29     if #[cfg(test)] {
30         use base::FakeClock as Clock;
31         use base::FakeTimer as Timer;
32     } else {
33         use base::Clock;
34         use base::Timer;
35     }
36 }
37 
38 use base::WorkerThread;
39 
40 use crate::bus::BusAccessInfo;
41 use crate::pci::CrosvmDeviceId;
42 use crate::BusDevice;
43 use crate::DeviceId;
44 use crate::IrqEdgeEvent;
45 use crate::Suspendable;
46 
47 // Bitmask for areas of standard (non-ReadBack) Control Word Format. Constant
48 // names are kept the same as Intel PIT data sheet.
49 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
50 enum CommandBit {
51     CommandBCD = 0x01,  // Binary/BCD input. x86 only uses binary mode.
52     CommandMode = 0x0e, // Operating Mode (mode 0-5).
53     CommandRW = 0x30,   // Access mode: Choose high/low byte(s) to Read/Write.
54     CommandSC = 0xc0,   // Select Counter/Read-back command.
55 }
56 
57 // Selects which counter is to be used by the associated command in the lower
58 // six bits of the byte. However, if 0xc0 is specified, it indicates that the
59 // command is a "Read-Back", which can latch count and/or status of the
60 // counters selected in the lower bits. See Intel 8254 data sheet for details.
61 #[allow(dead_code)]
62 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
63 enum CommandCounter {
64     CommandCounter0 = 0x00, // Select counter 0.
65     CommandCounter1 = 0x40, // Select counter 1.
66     CommandCounter2 = 0x80, // Select counter 2.
67     CommandReadBack = 0xc0, // Execute Read-Back.
68 }
69 
70 // Used for both CommandRW and ReadBackAccess.
71 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
72 enum CommandAccess {
73     CommandLatch = 0x00,   // Latch specified counter.
74     CommandRWLeast = 0x10, // Read/Write least significant byte.
75     CommandRWMost = 0x20,  // Read/Write most significant byte.
76     CommandRWBoth = 0x30,  // Read/Write both bytes.
77 }
78 
79 // Used for both CommandMode and ReadBackMode.
80 // For mode 2 & 3, bit 3 is don't care bit (does not matter to be 0 or 1) but
81 // per 8254 spec, should be 0 to insure compatibility with future Intel
82 // products.
83 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
84 enum CommandMode {
85     // NOTE:  No h/w modes are currently implemented.
86     CommandInterrupt = 0x00,     // Mode 0, interrupt on terminal count.
87     CommandHWOneShot = 0x02,     // Mode 1, h/w re-triggerable one-shot.
88     CommandRateGen = 0x04,       // Mode 2, rate generator.
89     CommandSquareWaveGen = 0x06, // Mode 3, square wave generator.
90     CommandSWStrobe = 0x08,      // Mode 4, s/w triggered strobe.
91     CommandHWStrobe = 0x0a,      // Mode 5, h/w triggered strobe.
92 }
93 
94 // Bitmask for the latch portion of the ReadBack command.
95 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
96 #[rustfmt::skip]  // rustfmt mangles comment indentation for trailing line comments.
97 enum CommandReadBackLatch {
98     CommandRBLatchBits = 0x30,   // Mask bits that determine latching.
99     CommandRBLatchBoth = 0x00,   // Latch both count and status. This should
100                                  // never happen in device, since bit 4 and 5 in
101                                  // read back command are inverted.
102     CommandRBLatchCount = 0x10,  // Latch count.
103     CommandRBLatchStatus = 0x20, // Latch status.
104 }
105 
106 // Bitmask for the counter portion of the ReadBack command.
107 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
108 enum CommandReadBackCounters {
109     //CommandRBCounters = 0x0e, // Counters for which to provide ReadBack info.
110     CommandRBCounter2 = 0x08,
111     CommandRBCounter1 = 0x04,
112     CommandRBCounter0 = 0x02,
113 }
114 
115 // Bitmask for the ReadBack status command.
116 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
117 #[rustfmt::skip]  // rustfmt mangles comment indentation for last line of this enum.
118 enum ReadBackData {
119     // Output format for ReadBack command.
120     ReadBackOutput = 0x80, // Output pin status.
121     ReadBackNullCount = 0x40, // Whether counter has value.
122     // ReadBackAccess, ReadBackMode, and ReadBackBCD intentionally omitted.
123 }
124 
125 // I/O Port mappings in I/O bus.
126 #[derive(Debug, Clone, Copy, PartialEq, Eq, enumn::N)]
127 enum PortIOSpace {
128     PortCounter0Data = 0x40, // Read/write.
129     PortCounter1Data = 0x41, // Read/write.
130     PortCounter2Data = 0x42, // Read/write.
131     PortCommand = 0x43,      // Write only.
132     PortSpeaker = 0x61,      // Read/write.
133 }
134 
135 #[bitfield]
136 #[derive(Clone, Copy, PartialEq, Eq)]
137 pub struct SpeakerPortFields {
138     // This field is documented in the chipset spec as NMI status and control
139     // register.  Bits 2, 3, 6, 7 and low level hardware bits that need no
140     // emulation for virtualized environments.  We call it speaker port because
141     // kvm, qemu, linux, and plan9 still call it speaker port, even though it
142     // has these other uses and is called something differently in the spec.
143     gate: BitField1,
144     speaker_on: BitField1,
145     pic_serr: BitField1,
146     iochk_enable: BitField1,
147     // This value changes as part of the refresh frequency of the board for
148     // piix4, this is about 1/15us.
149     refresh_clock: BitField1,
150     output: BitField1,
151     iochk_nmi: BitField1,
152     serr_nmi: BitField1,
153 }
154 
155 // PIT frequency (in Hertz). See http://wiki.osdev.org/pit.
156 const FREQUENCY_HZ: u64 = 1193182;
157 
158 const NUM_OF_COUNTERS: usize = 3;
159 
160 const NANOS_PER_SEC: u64 = 1_000_000_000;
161 
162 const MAX_TIMER_FREQ: u32 = 65536;
163 
164 #[derive(EventToken)]
165 enum Token {
166     // The timer expired.
167     TimerExpire,
168     // The parent thread requested an exit.
169     Kill,
170 }
171 
172 #[sorted]
173 #[derive(Error, Debug)]
174 pub enum PitError {
175     /// Error while cloning event for worker thread.
176     #[error("failed to clone event: {0}")]
177     CloneEvent(SysError),
178     /// Error while creating event.
179     #[error("failed to create event: {0}")]
180     CreateEvent(SysError),
181     /// Creating WaitContext failed.
182     #[error("failed to create poll context: {0}")]
183     CreateWaitContext(SysError),
184     /// Error while trying to create worker thread.
185     #[error("failed to spawn thread: {0}")]
186     SpawnThread(IoError),
187     /// Error while trying to create timer.
188     #[error("failed to create pit counter due to timer fd: {0}")]
189     TimerCreateError(SysError),
190     /// Error while waiting for events.
191     #[error("failed to wait for events: {0}")]
192     WaitError(SysError),
193 }
194 
195 type PitResult<T> = std::result::Result<T, PitError>;
196 
197 pub struct Pit {
198     // Structs that store each counter's state.
199     counters: Vec<Arc<Mutex<PitCounter>>>,
200     // Worker thread to update counter 0's state asynchronously. Counter 0 needs to send interrupts
201     // when timers expire, so it needs asynchronous updates. All other counters need only update
202     // when queried directly by the guest.
203     worker_thread: Option<WorkerThread<PitResult<()>>>,
204     activated: bool,
205 }
206 
207 impl BusDevice for Pit {
debug_label(&self) -> String208     fn debug_label(&self) -> String {
209         "userspace PIT".to_string()
210     }
211 
device_id(&self) -> DeviceId212     fn device_id(&self) -> DeviceId {
213         CrosvmDeviceId::Pit.into()
214     }
215 
write(&mut self, info: BusAccessInfo, data: &[u8])216     fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
217         self.ensure_started();
218 
219         if data.len() != 1 {
220             warn!("Bad write size for Pit: {}", data.len());
221             return;
222         }
223         match PortIOSpace::n(info.address as i64) {
224             Some(PortIOSpace::PortCounter0Data) => self.counters[0].lock().write_counter(data[0]),
225             Some(PortIOSpace::PortCounter1Data) => self.counters[1].lock().write_counter(data[0]),
226             Some(PortIOSpace::PortCounter2Data) => self.counters[2].lock().write_counter(data[0]),
227             Some(PortIOSpace::PortCommand) => self.command_write(data[0]),
228             Some(PortIOSpace::PortSpeaker) => self.counters[2].lock().write_speaker(data[0]),
229             None => warn!("PIT: bad write to {}", info),
230         }
231     }
232 
read(&mut self, info: BusAccessInfo, data: &mut [u8])233     fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
234         self.ensure_started();
235 
236         if data.len() != 1 {
237             warn!("Bad read size for Pit: {}", data.len());
238             return;
239         }
240         data[0] = match PortIOSpace::n(info.address as i64) {
241             Some(PortIOSpace::PortCounter0Data) => self.counters[0].lock().read_counter(),
242             Some(PortIOSpace::PortCounter1Data) => self.counters[1].lock().read_counter(),
243             Some(PortIOSpace::PortCounter2Data) => self.counters[2].lock().read_counter(),
244             // This should function as a no-op, since the specification doesn't allow the
245             // command register to be read. However, software is free to ask for it to
246             // to be read.
247             Some(PortIOSpace::PortCommand) => {
248                 warn!("Ignoring read to command reg");
249                 0
250             }
251             Some(PortIOSpace::PortSpeaker) => self.counters[2].lock().read_speaker(),
252             None => {
253                 warn!("PIT: bad read from {}", info);
254                 return;
255             }
256         };
257     }
258 }
259 
260 impl Pit {
new(interrupt_evt: IrqEdgeEvent, clock: Arc<Mutex<Clock>>) -> PitResult<Pit>261     pub fn new(interrupt_evt: IrqEdgeEvent, clock: Arc<Mutex<Clock>>) -> PitResult<Pit> {
262         let mut counters = Vec::new();
263         let mut interrupt = Some(interrupt_evt);
264         for i in 0..NUM_OF_COUNTERS {
265             let pit_counter = PitCounter::new(i, interrupt, clock.clone())?;
266             counters.push(Arc::new(Mutex::new(pit_counter)));
267             // pass interrupt IrqFd ONLY to counter 0; the rest do not deliver interrupts.
268             interrupt = None;
269         }
270         // We asssert here because:
271         // (a) this code only gets invoked at VM startup
272         // (b) the assert is very loud and would be easy to notice in tests
273         // (c) if we have the wrong number of counters, something is very wrong with the PIT and it
274         // may not make sense to continue operation.
275         assert_eq!(counters.len(), NUM_OF_COUNTERS);
276 
277         Ok(Pit {
278             counters,
279             worker_thread: None,
280             activated: false,
281         })
282     }
283 
ensure_started(&mut self)284     fn ensure_started(&mut self) {
285         if self.worker_thread.is_some() {
286             return;
287         }
288         if let Err(e) = self.start() {
289             error!("failed to start PIT: {}", e);
290         }
291     }
292 
start(&mut self) -> PitResult<()>293     fn start(&mut self) -> PitResult<()> {
294         let pit_counter = self.counters[0].clone();
295         self.worker_thread = Some(WorkerThread::start("pit counter worker", move |kill_evt| {
296             let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
297                 (&pit_counter.lock().timer, Token::TimerExpire),
298                 (&kill_evt, Token::Kill),
299             ])
300             .map_err(PitError::CreateWaitContext)?;
301 
302             let mut worker = Worker {
303                 pit_counter,
304                 wait_ctx,
305             };
306 
307             worker.run()
308         }));
309         self.activated = true;
310         Ok(())
311     }
312 
command_write(&mut self, control_word: u8)313     fn command_write(&mut self, control_word: u8) {
314         let command: u16 = (control_word & CommandBit::CommandSC as u8).into();
315         let counter_index: usize = (command >> 6).into();
316         if command == (CommandCounter::CommandReadBack as u16) {
317             // ReadBack commands can apply to multiple counters.
318             if (control_word & (CommandReadBackCounters::CommandRBCounter0 as u8)) != 0 {
319                 self.counters[0].lock().read_back_command(control_word);
320             }
321             if (control_word & (CommandReadBackCounters::CommandRBCounter1 as u8)) != 0 {
322                 self.counters[1].lock().read_back_command(control_word);
323             }
324             if (control_word & (CommandReadBackCounters::CommandRBCounter2 as u8)) != 0 {
325                 self.counters[2].lock().read_back_command(control_word);
326             }
327         } else if (control_word & (CommandBit::CommandRW as u8))
328             == (CommandAccess::CommandLatch as u8)
329         {
330             self.counters[counter_index].lock().latch_counter();
331         } else {
332             self.counters[counter_index]
333                 .lock()
334                 .store_command(control_word);
335         }
336     }
337 
get_pit_state(&self) -> PitState338     pub fn get_pit_state(&self) -> PitState {
339         PitState {
340             channels: [
341                 self.counters[0].lock().get_channel_state(),
342                 self.counters[1].lock().get_channel_state(),
343                 self.counters[2].lock().get_channel_state(),
344             ],
345             flags: 0,
346         }
347     }
348 
set_pit_state(&mut self, state: &PitState)349     pub fn set_pit_state(&mut self, state: &PitState) {
350         self.counters[0]
351             .lock()
352             .set_channel_state(&state.channels[0]);
353         self.counters[1]
354             .lock()
355             .set_channel_state(&state.channels[1]);
356         self.counters[2]
357             .lock()
358             .set_channel_state(&state.channels[2]);
359     }
360 }
361 
362 impl Suspendable for Pit {
sleep(&mut self) -> anyhow::Result<()>363     fn sleep(&mut self) -> anyhow::Result<()> {
364         if let Some(thread) = self.worker_thread.take() {
365             thread
366                 .stop()
367                 .context("pit worker thread exited with error")?;
368         }
369         Ok(())
370     }
371 
wake(&mut self) -> anyhow::Result<()>372     fn wake(&mut self) -> anyhow::Result<()> {
373         if self.activated {
374             if let Err(e) = self.start() {
375                 error!("failed to start PIT: {}", e);
376             }
377         }
378         Ok(())
379     }
380 }
381 
382 // Each instance of this represents one of the PIT counters. They are used to
383 // implement one-shot and repeating timer alarms. An 8254 has three counters.
384 struct PitCounter {
385     // Event to write when asserting an interrupt.
386     interrupt_evt: Option<IrqEdgeEvent>,
387     // Stores the value with which the counter was initialized. Counters are 16-
388     // bit values with an effective range of 1-65536 (65536 represented by 0).
389     reload_value: u16,
390     // Stores value when latch was called.
391     latched_value: u16,
392     // Stores last command from command register.
393     command: u8,
394     // Stores status from readback command
395     status: u8,
396     // Stores time of starting timer. Used for calculating remaining count, if an alarm is
397     // scheduled.
398     start: Option<Instant>,
399     // Current time.
400     clock: Arc<Mutex<Clock>>,
401     // Time when object was created. Used for a 15us counter.
402     creation_time: Instant,
403     // The number of the counter. The behavior for each counter is slightly different.
404     // Note that once a PitCounter is created, this value should never change.
405     counter_id: usize,
406     // Indicates if the low byte has been written in RWBoth.
407     wrote_low_byte: bool,
408     // Indicates if the low byte has been read in RWBoth.
409     read_low_byte: bool,
410     // Indicates whether counter has been latched.
411     latched: bool,
412     // Indicates whether ReadBack status has been latched.
413     status_latched: bool,
414     // Only should be used for counter 2. See http://wiki.osdev.org/PIT.
415     gate: bool,
416     speaker_on: bool,
417     // The starting value for the counter.
418     count: u32,
419     // Indicates whether the current timer is valid.
420     timer_valid: bool,
421     // Timer to set and receive periodic notifications.
422     timer: Timer,
423 }
424 
425 impl Drop for PitCounter {
drop(&mut self)426     fn drop(&mut self) {
427         if self.timer_valid {
428             // This should not fail - timer.clear() only fails if timerfd_settime fails, which
429             // only happens due to invalid arguments or bad file descriptors. The arguments to
430             // timerfd_settime are constant, so its arguments won't be invalid, and it manages
431             // the file descriptor safely (we don't use the unsafe FromRawDescriptor) so its file
432             // descriptor will be valid.
433             self.timer.clear().unwrap();
434         }
435     }
436 }
437 
adjust_count(count: u32) -> u32438 fn adjust_count(count: u32) -> u32 {
439     // As per spec 0 means max.
440     if count == 0 {
441         MAX_TIMER_FREQ
442     } else {
443         count
444     }
445 }
446 
447 impl PitCounter {
new( counter_id: usize, interrupt_evt: Option<IrqEdgeEvent>, clock: Arc<Mutex<Clock>>, ) -> PitResult<PitCounter>448     fn new(
449         counter_id: usize,
450         interrupt_evt: Option<IrqEdgeEvent>,
451         clock: Arc<Mutex<Clock>>,
452     ) -> PitResult<PitCounter> {
453         #[cfg(not(test))]
454         let timer = Timer::new().map_err(PitError::TimerCreateError)?;
455         #[cfg(test)]
456         let timer = Timer::new(clock.clone());
457         Ok(PitCounter {
458             interrupt_evt,
459             reload_value: 0,
460             latched_value: 0,
461             command: 0,
462             status: 0,
463             start: None,
464             clock: clock.clone(),
465             creation_time: clock.lock().now(),
466             counter_id,
467             wrote_low_byte: false,
468             read_low_byte: false,
469             latched: false,
470             status_latched: false,
471             gate: false,
472             speaker_on: false,
473             // `count` is undefined in real hardware and can't ever be programmed to 0, so we
474             // initialize it to max to prevent a misbehaving guest from triggering a divide by 0.
475             count: MAX_TIMER_FREQ,
476             timer_valid: false,
477             timer,
478         })
479     }
480 
get_channel_state(&self) -> PitChannelState481     fn get_channel_state(&self) -> PitChannelState {
482         let load_time = match &self.start {
483             Some(t) => t.saturating_duration_since(self.creation_time).as_nanos() as u64,
484             None => 0,
485         };
486 
487         let mut state = PitChannelState {
488             count: self.count,
489             latched_count: self.latched_value,
490             status_latched: self.status_latched,
491             status: self.status,
492             reload_value: self.reload_value,
493             mode: (self.command & CommandBit::CommandMode as u8) >> 1,
494             bcd: false,
495             gate: self.gate,
496             count_load_time: load_time,
497             rw_mode: PitRWMode::None,
498             read_state: PitRWState::None,
499             write_state: PitRWState::None,
500             count_latched: PitRWState::None,
501         };
502 
503         match self.get_access_mode() {
504             Some(CommandAccess::CommandRWLeast) => {
505                 // If access mode is least, RWStates are always LSB
506                 state.rw_mode = PitRWMode::Least;
507                 state.read_state = PitRWState::LSB;
508                 state.write_state = PitRWState::LSB;
509             }
510             Some(CommandAccess::CommandRWMost) => {
511                 // If access mode is most, RWStates are always MSB
512                 state.rw_mode = PitRWMode::Most;
513                 state.read_state = PitRWState::MSB;
514                 state.write_state = PitRWState::MSB;
515             }
516             Some(CommandAccess::CommandRWBoth) => {
517                 state.rw_mode = PitRWMode::Both;
518                 // read_state depends on whether or not we've read the low byte already
519                 state.read_state = if self.read_low_byte {
520                     PitRWState::Word1
521                 } else {
522                     PitRWState::Word0
523                 };
524                 // write_state depends on whether or not we've written the low byte already
525                 state.write_state = if self.wrote_low_byte {
526                     PitRWState::Word1
527                 } else {
528                     PitRWState::Word0
529                 };
530             }
531             _ => {}
532         };
533 
534         // Count_latched should be PitRWSTate::None unless we're latched
535         if self.latched {
536             state.count_latched = state.read_state;
537         }
538 
539         state
540     }
541 
set_channel_state(&mut self, state: &PitChannelState)542     fn set_channel_state(&mut self, state: &PitChannelState) {
543         self.count = state.count;
544         self.latched_value = state.latched_count;
545         self.status_latched = state.status_latched;
546         self.status = state.status;
547         self.reload_value = state.reload_value;
548 
549         // the command consists of:
550         //  - 1 bcd bit, which we don't care about because we don't support non-binary mode
551         //  - 3 mode bits
552         //  - 2 access mode bits
553         //  - 2 counter select bits, which aren't used by the counter/channel itself
554         self.command = (state.mode << 1) | ((state.rw_mode as u8) << 4);
555         self.gate = state.gate;
556         self.latched = state.count_latched != PitRWState::None;
557         self.read_low_byte = state.read_state == PitRWState::Word1;
558         self.wrote_low_byte = state.write_state == PitRWState::Word1;
559 
560         self.start = self
561             .creation_time
562             .checked_add(Duration::from_nanos(state.count_load_time));
563     }
564 
get_access_mode(&self) -> Option<CommandAccess>565     fn get_access_mode(&self) -> Option<CommandAccess> {
566         CommandAccess::n(self.command & (CommandBit::CommandRW as u8))
567     }
568 
get_command_mode(&self) -> Option<CommandMode>569     fn get_command_mode(&self) -> Option<CommandMode> {
570         CommandMode::n(self.command & CommandBit::CommandMode as u8)
571     }
572 
read_counter(&mut self) -> u8573     fn read_counter(&mut self) -> u8 {
574         if self.status_latched {
575             self.status_latched = false;
576             return self.status;
577         };
578         let data_value: u16 = if self.latched {
579             self.latched_value
580         } else {
581             self.get_read_value()
582         };
583 
584         let access_mode = self.get_access_mode();
585         // Latch may be true without being indicated by the access mode if
586         // a ReadBack was issued.
587         match (access_mode, self.read_low_byte) {
588             (Some(CommandAccess::CommandRWLeast), _) => {
589                 self.latched = false; // Unlatch if only reading the low byte.
590                 (data_value & 0xff) as u8
591             }
592             (Some(CommandAccess::CommandRWBoth), false) => {
593                 self.read_low_byte = true;
594                 (data_value & 0xff) as u8
595             }
596             (Some(CommandAccess::CommandRWBoth), true)
597             | (Some(CommandAccess::CommandRWMost), _) => {
598                 self.read_low_byte = false; // Allow for future reads for RWBoth.
599                 self.latched = false;
600                 (data_value >> 8) as u8
601             }
602             (_, _) => 0, // Default for erroneous call
603         }
604     }
605 
write_counter(&mut self, written_datum: u8)606     fn write_counter(&mut self, written_datum: u8) {
607         let access_mode = self.get_access_mode();
608         let datum: u16 = written_datum.into();
609         let mut should_start_timer = true;
610         self.reload_value = match access_mode {
611             Some(CommandAccess::CommandRWLeast) => datum,
612             Some(CommandAccess::CommandRWMost) => datum << 8,
613             Some(CommandAccess::CommandRWBoth) => {
614                 // In kCommandRWBoth mode, the first guest write is the low byte and the
615                 // the second guest write is the high byte.  The timer isn't started
616                 // until after the second byte is written.
617                 if self.wrote_low_byte {
618                     self.wrote_low_byte = false;
619                     self.reload_value | (datum << 8)
620                 } else {
621                     self.wrote_low_byte = true;
622                     should_start_timer = false; // Don't start until high byte written.
623                     datum
624                 }
625             }
626             _ => {
627                 should_start_timer = false;
628                 self.reload_value
629             }
630         };
631         if should_start_timer {
632             let reload: u32 = self.reload_value.into();
633             self.load_and_start_timer(reload);
634         }
635     }
636 
get_output(&self) -> bool637     fn get_output(&self) -> bool {
638         let ticks_passed = self.get_ticks_passed();
639         let count: u64 = self.count.into();
640         match self.get_command_mode() {
641             Some(CommandMode::CommandInterrupt) => ticks_passed >= count,
642             Some(CommandMode::CommandHWOneShot) => ticks_passed < count,
643             Some(CommandMode::CommandRateGen) => ticks_passed != 0 && ticks_passed % count == 0,
644             Some(CommandMode::CommandSquareWaveGen) => ticks_passed < (count + 1) / 2,
645             Some(CommandMode::CommandSWStrobe) | Some(CommandMode::CommandHWStrobe) => {
646                 ticks_passed == count
647             }
648             None => {
649                 warn!("Invalid command mode based on command: {:#x}", self.command);
650                 false
651             }
652         }
653     }
654 
read_speaker(&self) -> u8655     fn read_speaker(&self) -> u8 {
656         // Refresh clock is a value independent of the actual
657         // counter that goes up and down approx every 15 us (~66000/s).
658         let us = self
659             .clock
660             .lock()
661             .now()
662             .duration_since(self.creation_time)
663             .subsec_micros();
664         let refresh_clock = us % 15 == 0;
665         let mut speaker = SpeakerPortFields::new();
666         speaker.set_gate(self.gate.into());
667         speaker.set_speaker_on(self.speaker_on.into());
668         speaker.set_iochk_enable(0);
669         speaker.set_refresh_clock(refresh_clock.into());
670         speaker.set_output(self.get_output().into());
671         speaker.set_iochk_nmi(0);
672         speaker.set_serr_nmi(0);
673         speaker.get(/*offset=*/ 0, /*width=*/ 8) as u8
674     }
675 
write_speaker(&mut self, datum: u8)676     fn write_speaker(&mut self, datum: u8) {
677         let mut speaker = SpeakerPortFields::new();
678         speaker.set(/*offset=*/ 0, /*width=*/ 8, datum.into());
679         let new_gate = speaker.get_gate() != 0;
680         match self.get_command_mode() {
681             Some(CommandMode::CommandInterrupt) | Some(CommandMode::CommandSWStrobe) => (),
682             Some(_) => {
683                 if new_gate && !self.gate {
684                     self.start = Some(self.clock.lock().now());
685                 }
686             }
687             None => {
688                 warn!("Invalid command mode based on command {:#x}", self.command);
689                 return;
690             }
691         }
692         self.speaker_on = speaker.get_speaker_on() != 0;
693         self.gate = new_gate;
694     }
695 
load_and_start_timer(&mut self, initial_count: u32)696     fn load_and_start_timer(&mut self, initial_count: u32) {
697         self.count = adjust_count(initial_count);
698         self.start_timer();
699     }
700 
start_timer(&mut self)701     fn start_timer(&mut self) {
702         self.start = Some(self.clock.lock().now());
703 
704         // Counter 0 is the only counter that generates interrupts, so we
705         // don't need to set a timer for the other two counters.
706         if self.counter_id != 0 {
707             return;
708         }
709 
710         let timer_len = Duration::from_nanos(u64::from(self.count) * NANOS_PER_SEC / FREQUENCY_HZ);
711 
712         let period_ns = match self.get_command_mode() {
713             Some(CommandMode::CommandInterrupt)
714             | Some(CommandMode::CommandHWOneShot)
715             | Some(CommandMode::CommandSWStrobe)
716             | Some(CommandMode::CommandHWStrobe) => None,
717             Some(CommandMode::CommandRateGen) | Some(CommandMode::CommandSquareWaveGen) => {
718                 Some(timer_len)
719             }
720             // Don't arm timer if invalid mode.
721             None => {
722                 // This will still result in start being set to the current time.
723                 // Per spec:
724                 //   A new initial count may be written to a Counter at any time without affecting
725                 //   the Counter’s programmed Mode in any way. Counting will be affected as
726                 //   described in the Mode definitions. The new count must follow the programmed
727                 //   count format
728                 // It's unclear whether setting `self.start` in this case is entirely compliant,
729                 // but the spec is fairly quiet on expected behavior in error cases, so OSs
730                 // shouldn't enter invalid modes in the first place.  If they do, and then try to
731                 // get out of it by first setting the counter then the command, this behavior will
732                 // (perhaps) be minimally surprising, but arguments can be made for other behavior.
733                 // It's uncertain if this behavior matches real PIT hardware.
734                 warn!("Invalid command mode based on command {:#x}", self.command);
735                 return;
736             }
737         };
738 
739         self.safe_arm_timer(timer_len, period_ns);
740         self.timer_valid = true;
741     }
742 
read_back_command(&mut self, control_word: u8)743     fn read_back_command(&mut self, control_word: u8) {
744         let latch_cmd =
745             CommandReadBackLatch::n(control_word & CommandReadBackLatch::CommandRBLatchBits as u8);
746         match latch_cmd {
747             Some(CommandReadBackLatch::CommandRBLatchCount) => {
748                 self.latch_counter();
749             }
750             Some(CommandReadBackLatch::CommandRBLatchStatus) => {
751                 self.latch_status();
752             }
753             _ => warn!(
754                 "Unexpected ReadBackLatch. control_word: {:#x}",
755                 control_word
756             ),
757         };
758     }
759 
latch_counter(&mut self)760     fn latch_counter(&mut self) {
761         if self.latched {
762             return;
763         }
764 
765         self.latched_value = self.get_read_value();
766         self.latched = true;
767         self.read_low_byte = false;
768     }
769 
latch_status(&mut self)770     fn latch_status(&mut self) {
771         // Including BCD here, even though it currently never gets used.
772         self.status = self.command
773             & (CommandBit::CommandRW as u8
774                 | CommandBit::CommandMode as u8
775                 | CommandBit::CommandBCD as u8);
776         if self.start.is_none() {
777             self.status |= ReadBackData::ReadBackNullCount as u8;
778         }
779         if self.get_output() {
780             self.status |= ReadBackData::ReadBackOutput as u8;
781         }
782         self.status_latched = true;
783     }
784 
store_command(&mut self, datum: u8)785     fn store_command(&mut self, datum: u8) {
786         self.command = datum;
787         self.latched = false;
788 
789         // If a new RW command is written, cancel the current timer.
790         if self.timer_valid {
791             self.start = None;
792             self.timer_valid = false;
793             // See the comment in the impl of Drop for PitCounter for justification of the unwrap()
794             self.timer.clear().unwrap();
795         }
796 
797         self.wrote_low_byte = false;
798         self.read_low_byte = false;
799     }
800 
timer_handler(&mut self)801     fn timer_handler(&mut self) {
802         if let Err(e) = self.timer.mark_waited() {
803             // Under the current Timer implementation (as of Jan 2019), this failure shouldn't
804             // happen but implementation details may change in the future, and the failure
805             // cases are complex to reason about. Because of this, avoid unwrap().
806             error!("pit: timer wait unexpectedly failed: {}", e);
807             return;
808         }
809         let mode = self.get_command_mode();
810         if mode == Some(CommandMode::CommandRateGen)
811             || mode == Some(CommandMode::CommandSquareWaveGen)
812         {
813             // Reset the start time for timer modes that repeat.
814             self.start = Some(self.clock.lock().now());
815         }
816 
817         // For square wave mode, this isn't quite accurate to the spec, but the
818         // difference isn't meaningfully visible to the guest in any important way,
819         // and the code is simpler without the special case.
820         if let Some(interrupt) = &mut self.interrupt_evt {
821             // This is safe because the file descriptor is nonblocking and we're writing 1.
822             interrupt.trigger().unwrap();
823         }
824     }
825 
safe_arm_timer(&mut self, mut due: Duration, period: Option<Duration>)826     fn safe_arm_timer(&mut self, mut due: Duration, period: Option<Duration>) {
827         if due == Duration::new(0, 0) {
828             due = Duration::from_nanos(1);
829         }
830 
831         if let Err(e) = self.timer.reset(due, period) {
832             error!("failed to reset timer: {}", e);
833         }
834     }
835 
get_ticks_passed(&self) -> u64836     fn get_ticks_passed(&self) -> u64 {
837         match self.start {
838             None => 0,
839             Some(t) => {
840                 let dur = self.clock.lock().now().duration_since(t);
841                 let dur_ns: u64 = dur.as_secs() * NANOS_PER_SEC + u64::from(dur.subsec_nanos());
842                 dur_ns * FREQUENCY_HZ / NANOS_PER_SEC
843             }
844         }
845     }
846 
get_read_value(&self) -> u16847     fn get_read_value(&self) -> u16 {
848         match self.start {
849             None => 0,
850             Some(_) => {
851                 let count: u64 = adjust_count(self.reload_value.into()).into();
852                 let ticks_passed = self.get_ticks_passed();
853                 match self.get_command_mode() {
854                     Some(CommandMode::CommandInterrupt)
855                     | Some(CommandMode::CommandHWOneShot)
856                     | Some(CommandMode::CommandSWStrobe)
857                     | Some(CommandMode::CommandHWStrobe) => {
858                         if ticks_passed > count {
859                             // Some risk of raciness here in that the count may return a value
860                             // indicating that the count has expired when the interrupt hasn't
861                             // yet been injected.
862                             0
863                         } else {
864                             ((count - ticks_passed) & 0xFFFF) as u16
865                         }
866                     }
867                     Some(CommandMode::CommandRateGen) => (count - (ticks_passed % count)) as u16,
868                     Some(CommandMode::CommandSquareWaveGen) => {
869                         (count - ((ticks_passed * 2) % count)) as u16
870                     }
871                     None => {
872                         warn!("Invalid command mode: command = {:#x}", self.command);
873                         0
874                     }
875                 }
876             }
877         }
878     }
879 }
880 
881 struct Worker {
882     pit_counter: Arc<Mutex<PitCounter>>,
883     wait_ctx: WaitContext<Token>,
884 }
885 
886 impl Worker {
run(&mut self) -> PitResult<()>887     fn run(&mut self) -> PitResult<()> {
888         loop {
889             let events = self.wait_ctx.wait().map_err(PitError::WaitError)?;
890             for event in events.iter().filter(|e| e.is_readable) {
891                 match event.token {
892                     Token::TimerExpire => {
893                         let mut pit = self.pit_counter.lock();
894                         pit.timer_handler();
895                     }
896                     Token::Kill => return Ok(()),
897                 }
898             }
899         }
900     }
901 }
902 
903 #[cfg(test)]
904 mod tests {
905     use base::Event;
906 
907     use super::*;
908 
909     struct TestData {
910         pit: Pit,
911         irqfd: Event,
912         clock: Arc<Mutex<Clock>>,
913     }
914 
pit_bus_address(address: PortIOSpace) -> BusAccessInfo915     fn pit_bus_address(address: PortIOSpace) -> BusAccessInfo {
916         // The PIT is added to the io_bus in two locations, so the offset depends on which
917         // address range the address is in. The PIT implementation currently does not use the
918         // offset, but we're setting it accurately here in case it does in the future.
919         let offset = match address as u64 {
920             x if x >= PortIOSpace::PortCounter0Data as u64
921                 && x < PortIOSpace::PortCounter0Data as u64 + 0x8 =>
922             {
923                 address as u64 - PortIOSpace::PortCounter0Data as u64
924             }
925             x if x == PortIOSpace::PortSpeaker as u64 => 0,
926             _ => panic!("invalid PIT address: {:#x}", address as u64),
927         };
928 
929         BusAccessInfo {
930             offset,
931             address: address as u64,
932             id: 0,
933         }
934     }
935 
936     /// Utility method for writing a command word to a command register.
write_command(pit: &mut Pit, command: u8)937     fn write_command(pit: &mut Pit, command: u8) {
938         pit.write(pit_bus_address(PortIOSpace::PortCommand), &[command])
939     }
940 
941     /// Utility method for writing a command word to the speaker register.
write_speaker(pit: &mut Pit, command: u8)942     fn write_speaker(pit: &mut Pit, command: u8) {
943         pit.write(pit_bus_address(PortIOSpace::PortSpeaker), &[command])
944     }
945 
946     /// Utility method for writing to a counter.
write_counter(pit: &mut Pit, counter_idx: usize, data: u16, access_mode: CommandAccess)947     fn write_counter(pit: &mut Pit, counter_idx: usize, data: u16, access_mode: CommandAccess) {
948         let port = match counter_idx {
949             0 => PortIOSpace::PortCounter0Data,
950             1 => PortIOSpace::PortCounter1Data,
951             2 => PortIOSpace::PortCounter2Data,
952             _ => panic!("Invalid counter_idx: {}", counter_idx),
953         };
954         // Write the least, then the most, significant byte.
955         if access_mode == CommandAccess::CommandRWLeast
956             || access_mode == CommandAccess::CommandRWBoth
957         {
958             pit.write(pit_bus_address(port), &[(data & 0xff) as u8]);
959         }
960         if access_mode == CommandAccess::CommandRWMost
961             || access_mode == CommandAccess::CommandRWBoth
962         {
963             pit.write(pit_bus_address(port), &[(data >> 8) as u8]);
964         }
965     }
966 
967     /// Utility method for reading a counter. Check if the read value matches expected_value.
read_counter(pit: &mut Pit, counter_idx: usize, expected: u16, access_mode: CommandAccess)968     fn read_counter(pit: &mut Pit, counter_idx: usize, expected: u16, access_mode: CommandAccess) {
969         let port = match counter_idx {
970             0 => PortIOSpace::PortCounter0Data,
971             1 => PortIOSpace::PortCounter1Data,
972             2 => PortIOSpace::PortCounter2Data,
973             _ => panic!("Invalid counter_idx: {}", counter_idx),
974         };
975         let mut result: u16 = 0;
976         if access_mode == CommandAccess::CommandRWLeast
977             || access_mode == CommandAccess::CommandRWBoth
978         {
979             let mut buffer = [0];
980             pit.read(pit_bus_address(port), &mut buffer);
981             result = buffer[0].into();
982         }
983         if access_mode == CommandAccess::CommandRWMost
984             || access_mode == CommandAccess::CommandRWBoth
985         {
986             let mut buffer = [0];
987             pit.read(pit_bus_address(port), &mut buffer);
988             result |= u16::from(buffer[0]) << 8;
989         }
990         assert_eq!(result, expected);
991     }
992 
set_up() -> TestData993     fn set_up() -> TestData {
994         let evt = IrqEdgeEvent::new().unwrap();
995         let clock = Arc::new(Mutex::new(Clock::new()));
996         TestData {
997             irqfd: evt.get_trigger().try_clone().unwrap(),
998             pit: Pit::new(evt, clock.clone()).unwrap(),
999             clock,
1000         }
1001     }
1002 
advance_by_tick(data: &mut TestData)1003     fn advance_by_tick(data: &mut TestData) {
1004         advance_by_ticks(data, 1);
1005     }
1006 
advance_by_ticks(data: &mut TestData, ticks: u64)1007     fn advance_by_ticks(data: &mut TestData, ticks: u64) {
1008         println!(
1009             "Advancing by {:#x} ticks ({} ns)",
1010             ticks,
1011             (NANOS_PER_SEC * ticks) / FREQUENCY_HZ + 1
1012         );
1013         let mut lock = data.clock.lock();
1014         lock.add_ns((NANOS_PER_SEC * ticks) / FREQUENCY_HZ + 1);
1015     }
1016 
1017     /// Tests the ability to write a command and data and read the data back using latch.
1018     #[test]
write_and_latch()1019     fn write_and_latch() {
1020         let mut data = set_up();
1021         let both_interrupt =
1022             CommandAccess::CommandRWBoth as u8 | CommandMode::CommandInterrupt as u8;
1023         // Issue a command to write both digits of counter 0 in interrupt mode.
1024         write_command(
1025             &mut data.pit,
1026             CommandCounter::CommandCounter0 as u8 | both_interrupt,
1027         );
1028         write_counter(&mut data.pit, 0, 24, CommandAccess::CommandRWBoth);
1029         // Advance time by one tick -- value read back should decrease.
1030         advance_by_tick(&mut data);
1031 
1032         // Latch and read back the value written.
1033         write_command(
1034             &mut data.pit,
1035             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1036         );
1037         // Advance again after latching to verify that value read back doesn't change.
1038         advance_by_tick(&mut data);
1039         read_counter(&mut data.pit, 0, 23, CommandAccess::CommandRWBoth);
1040 
1041         // Repeat with counter 1.
1042         write_command(
1043             &mut data.pit,
1044             CommandCounter::CommandCounter1 as u8 | both_interrupt,
1045         );
1046         write_counter(&mut data.pit, 1, 314, CommandAccess::CommandRWBoth);
1047         advance_by_tick(&mut data);
1048         write_command(
1049             &mut data.pit,
1050             CommandCounter::CommandCounter1 as u8 | CommandAccess::CommandLatch as u8,
1051         );
1052         advance_by_tick(&mut data);
1053         read_counter(&mut data.pit, 1, 313, CommandAccess::CommandRWBoth);
1054 
1055         // Repeat with counter 2.
1056         write_command(
1057             &mut data.pit,
1058             CommandCounter::CommandCounter2 as u8 | both_interrupt,
1059         );
1060         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1061         advance_by_tick(&mut data);
1062         write_command(
1063             &mut data.pit,
1064             CommandCounter::CommandCounter2 as u8 | CommandAccess::CommandLatch as u8,
1065         );
1066         advance_by_tick(&mut data);
1067         read_counter(&mut data.pit, 2, 0xfffe, CommandAccess::CommandRWBoth);
1068     }
1069 
1070     /// Tests the ability to read only the least significant byte.
1071     #[test]
write_and_read_least()1072     fn write_and_read_least() {
1073         let mut data = set_up();
1074         write_command(
1075             &mut data.pit,
1076             CommandCounter::CommandCounter0 as u8
1077                 | CommandAccess::CommandRWLeast as u8
1078                 | CommandMode::CommandInterrupt as u8,
1079         );
1080         write_counter(&mut data.pit, 0, 0x3424, CommandAccess::CommandRWLeast);
1081         read_counter(&mut data.pit, 0, 0x0024, CommandAccess::CommandRWLeast);
1082         write_command(
1083             &mut data.pit,
1084             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1085         );
1086         advance_by_tick(&mut data);
1087         read_counter(&mut data.pit, 0, 0x0024, CommandAccess::CommandRWLeast);
1088     }
1089 
1090     /// Tests the ability to read only the most significant byte.
1091     #[test]
write_and_read_most()1092     fn write_and_read_most() {
1093         let mut data = set_up();
1094         write_command(
1095             &mut data.pit,
1096             CommandCounter::CommandCounter0 as u8
1097                 | CommandAccess::CommandRWMost as u8
1098                 | CommandMode::CommandInterrupt as u8,
1099         );
1100         write_counter(&mut data.pit, 0, 0x3424, CommandAccess::CommandRWMost);
1101         read_counter(&mut data.pit, 0, 0x3400, CommandAccess::CommandRWMost);
1102         write_command(
1103             &mut data.pit,
1104             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1105         );
1106         advance_by_tick(&mut data);
1107         read_counter(&mut data.pit, 0, 0x3400, CommandAccess::CommandRWMost);
1108     }
1109 
1110     /// Tests that reading the command register does nothing.
1111     #[test]
read_command()1112     fn read_command() {
1113         let mut data = set_up();
1114         let mut buf = [0];
1115         data.pit
1116             .read(pit_bus_address(PortIOSpace::PortCommand), &mut buf);
1117         assert_eq!(buf, [0]);
1118     }
1119 
1120     /// Tests that latching prevents the read time from actually advancing.
1121     #[test]
test_timed_latch()1122     fn test_timed_latch() {
1123         let mut data = set_up();
1124         write_command(
1125             &mut data.pit,
1126             CommandCounter::CommandCounter0 as u8
1127                 | CommandAccess::CommandRWBoth as u8
1128                 | CommandMode::CommandInterrupt as u8,
1129         );
1130         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1131         write_command(
1132             &mut data.pit,
1133             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1134         );
1135         data.clock.lock().add_ns(25_000_000);
1136         // The counter should ignore this second latch.
1137         write_command(
1138             &mut data.pit,
1139             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1140         );
1141         read_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1142         // It should, however, store the count for this latch.
1143         write_command(
1144             &mut data.pit,
1145             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
1146         );
1147         read_counter(
1148             &mut data.pit,
1149             0,
1150             0xffff - ((25_000_000 * FREQUENCY_HZ) / NANOS_PER_SEC) as u16,
1151             CommandAccess::CommandRWBoth,
1152         );
1153     }
1154 
1155     /// Tests Mode 0 (Interrupt on terminal count); checks whether IRQ has been asserted.
1156     #[test]
interrupt_mode()1157     fn interrupt_mode() {
1158         let mut data = set_up();
1159         write_command(
1160             &mut data.pit,
1161             CommandCounter::CommandCounter0 as u8
1162                 | CommandAccess::CommandRWBoth as u8
1163                 | CommandMode::CommandInterrupt as u8,
1164         );
1165         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1166         // Advance clock enough to trigger interrupt.
1167         advance_by_ticks(&mut data, 0xffff);
1168         data.irqfd.wait().unwrap();
1169     }
1170 
1171     /// Tests that Rate Generator mode (mode 2) handls the interrupt properly when the timer
1172     /// expires and that it resets the timer properly.
1173     #[test]
rate_gen_mode()1174     fn rate_gen_mode() {
1175         let mut data = set_up();
1176         write_command(
1177             &mut data.pit,
1178             CommandCounter::CommandCounter0 as u8
1179                 | CommandAccess::CommandRWBoth as u8
1180                 | CommandMode::CommandRateGen as u8,
1181         );
1182         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1183         // Repatedly advance clock and expect interrupt.
1184         advance_by_ticks(&mut data, 0xffff);
1185         data.irqfd.wait().unwrap();
1186 
1187         // Repatedly advance clock and expect interrupt.
1188         advance_by_ticks(&mut data, 0xffff);
1189         data.irqfd.wait().unwrap();
1190 
1191         // Repatedly advance clock and expect interrupt.
1192         advance_by_ticks(&mut data, 0xffff);
1193         data.irqfd.wait().unwrap();
1194     }
1195 
1196     /// Tests that square wave mode advances the counter correctly.
1197     #[test]
square_wave_counter_read()1198     fn square_wave_counter_read() {
1199         let mut data = set_up();
1200         write_command(
1201             &mut data.pit,
1202             CommandCounter::CommandCounter0 as u8
1203                 | CommandAccess::CommandRWBoth as u8
1204                 | CommandMode::CommandSquareWaveGen as u8,
1205         );
1206         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1207 
1208         advance_by_ticks(&mut data, 10_000);
1209         read_counter(
1210             &mut data.pit,
1211             0,
1212             0xffff - 10_000 * 2,
1213             CommandAccess::CommandRWBoth,
1214         );
1215     }
1216 
1217     /// Tests that rategen mode updates the counter correctly.
1218     #[test]
rate_gen_counter_read()1219     fn rate_gen_counter_read() {
1220         let mut data = set_up();
1221         write_command(
1222             &mut data.pit,
1223             CommandCounter::CommandCounter0 as u8
1224                 | CommandAccess::CommandRWBoth as u8
1225                 | CommandMode::CommandRateGen as u8,
1226         );
1227         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1228 
1229         advance_by_ticks(&mut data, 10_000);
1230         read_counter(
1231             &mut data.pit,
1232             0,
1233             0xffff - 10_000,
1234             CommandAccess::CommandRWBoth,
1235         );
1236     }
1237 
1238     /// Tests that interrupt counter mode updates the counter correctly.
1239     #[test]
interrupt_counter_read()1240     fn interrupt_counter_read() {
1241         let mut data = set_up();
1242         write_command(
1243             &mut data.pit,
1244             CommandCounter::CommandCounter0 as u8
1245                 | CommandAccess::CommandRWBoth as u8
1246                 | CommandMode::CommandInterrupt as u8,
1247         );
1248         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1249 
1250         advance_by_ticks(&mut data, 10_000);
1251         read_counter(
1252             &mut data.pit,
1253             0,
1254             0xffff - 10_000,
1255             CommandAccess::CommandRWBoth,
1256         );
1257 
1258         advance_by_ticks(&mut data, 3 * FREQUENCY_HZ);
1259         read_counter(&mut data.pit, 0, 0, CommandAccess::CommandRWBoth);
1260     }
1261 
1262     /// Tests that ReadBack count works properly for `low` access mode.
1263     #[test]
read_back_count_access_low()1264     fn read_back_count_access_low() {
1265         let mut data = set_up();
1266         write_command(
1267             &mut data.pit,
1268             CommandCounter::CommandCounter0 as u8
1269                 | CommandAccess::CommandRWLeast as u8
1270                 | CommandMode::CommandInterrupt as u8,
1271         );
1272         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWLeast);
1273         write_command(
1274             &mut data.pit,
1275             CommandCounter::CommandReadBack as u8
1276                 | CommandReadBackLatch::CommandRBLatchCount as u8
1277                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1278         );
1279 
1280         // Advance 100 ticks and verify that low byte of counter is appropriately updated.
1281         advance_by_ticks(&mut data, 100);
1282         write_command(
1283             &mut data.pit,
1284             CommandCounter::CommandReadBack as u8
1285                 | CommandReadBackLatch::CommandRBLatchCount as u8
1286                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1287         );
1288         read_counter(&mut data.pit, 0, 0x00ff, CommandAccess::CommandRWLeast);
1289         write_command(
1290             &mut data.pit,
1291             CommandCounter::CommandReadBack as u8
1292                 | CommandReadBackLatch::CommandRBLatchCount as u8
1293                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1294         );
1295         read_counter(
1296             &mut data.pit,
1297             0,
1298             (0xffff - 100) & 0x00ff,
1299             CommandAccess::CommandRWLeast,
1300         );
1301     }
1302 
1303     /// Tests that ReadBack count works properly for `high` access mode.
1304     #[test]
read_back_count_access_high()1305     fn read_back_count_access_high() {
1306         let mut data = set_up();
1307         write_command(
1308             &mut data.pit,
1309             CommandCounter::CommandCounter0 as u8
1310                 | CommandAccess::CommandRWMost as u8
1311                 | CommandMode::CommandInterrupt as u8,
1312         );
1313         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWLeast);
1314         write_command(
1315             &mut data.pit,
1316             CommandCounter::CommandReadBack as u8
1317                 | CommandReadBackLatch::CommandRBLatchCount as u8
1318                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1319         );
1320 
1321         // Advance 100 ticks and verify that low byte of counter is appropriately updated.
1322         advance_by_ticks(&mut data, 512);
1323         write_command(
1324             &mut data.pit,
1325             CommandCounter::CommandReadBack as u8
1326                 | CommandReadBackLatch::CommandRBLatchCount as u8
1327                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1328         );
1329         read_counter(&mut data.pit, 0, 0xff00, CommandAccess::CommandRWMost);
1330         write_command(
1331             &mut data.pit,
1332             CommandCounter::CommandReadBack as u8
1333                 | CommandReadBackLatch::CommandRBLatchCount as u8
1334                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1335         );
1336         read_counter(
1337             &mut data.pit,
1338             0,
1339             (0xffff - 512) & 0xff00,
1340             CommandAccess::CommandRWMost,
1341         );
1342     }
1343 
1344     /// Tests that ReadBack status returns the expected values.
1345     #[test]
read_back_status()1346     fn read_back_status() {
1347         let mut data = set_up();
1348         write_command(
1349             &mut data.pit,
1350             CommandCounter::CommandCounter0 as u8
1351                 | CommandAccess::CommandRWBoth as u8
1352                 | CommandMode::CommandSWStrobe as u8,
1353         );
1354         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1355         write_command(
1356             &mut data.pit,
1357             CommandCounter::CommandReadBack as u8
1358                 | CommandReadBackLatch::CommandRBLatchStatus as u8
1359                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1360         );
1361 
1362         read_counter(
1363             &mut data.pit,
1364             0,
1365             CommandAccess::CommandRWBoth as u16 | CommandMode::CommandSWStrobe as u16,
1366             CommandAccess::CommandRWLeast,
1367         );
1368     }
1369 
1370     #[test]
speaker_square_wave()1371     fn speaker_square_wave() {
1372         let mut data = set_up();
1373         write_command(
1374             &mut data.pit,
1375             CommandCounter::CommandCounter2 as u8
1376                 | CommandAccess::CommandRWBoth as u8
1377                 | CommandMode::CommandSquareWaveGen as u8,
1378         );
1379         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1380 
1381         advance_by_ticks(&mut data, 128);
1382         read_counter(
1383             &mut data.pit,
1384             2,
1385             0xffff - 128 * 2,
1386             CommandAccess::CommandRWBoth,
1387         );
1388     }
1389 
1390     #[test]
speaker_rate_gen()1391     fn speaker_rate_gen() {
1392         let mut data = set_up();
1393         write_command(
1394             &mut data.pit,
1395             CommandCounter::CommandCounter2 as u8
1396                 | CommandAccess::CommandRWBoth as u8
1397                 | CommandMode::CommandRateGen as u8,
1398         );
1399         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1400 
1401         // In Rate Gen mode, the counter should start over when the gate is
1402         // set to high using SpeakerWrite.
1403         advance_by_ticks(&mut data, 128);
1404         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1405 
1406         write_speaker(&mut data.pit, 0x1);
1407         advance_by_ticks(&mut data, 128);
1408         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1409     }
1410 
1411     #[test]
speaker_interrupt()1412     fn speaker_interrupt() {
1413         let mut data = set_up();
1414 
1415         write_command(
1416             &mut data.pit,
1417             CommandCounter::CommandCounter2 as u8
1418                 | CommandAccess::CommandRWBoth as u8
1419                 | CommandMode::CommandInterrupt as u8,
1420         );
1421         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1422 
1423         // In Interrupt mode, the counter should NOT start over when the gate is
1424         // set to high using SpeakerWrite.
1425         advance_by_ticks(&mut data, 128);
1426         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1427 
1428         write_speaker(&mut data.pit, 0x1);
1429         advance_by_ticks(&mut data, 128);
1430         read_counter(&mut data.pit, 2, 0xffff - 256, CommandAccess::CommandRWBoth);
1431     }
1432 
1433     /// Verify that invalid reads and writes do not cause crashes.
1434     #[test]
invalid_write_and_read()1435     fn invalid_write_and_read() {
1436         let mut data = set_up();
1437         data.pit.write(
1438             BusAccessInfo {
1439                 address: 0x44,
1440                 offset: 0x4,
1441                 id: 0,
1442             },
1443             &[0],
1444         );
1445         data.pit.read(
1446             BusAccessInfo {
1447                 address: 0x55,
1448                 offset: 0x15,
1449                 id: 0,
1450             },
1451             &mut [0],
1452         );
1453     }
1454 }
1455