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