vm_superio/
rtc_pl031.rs

1// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
3
4//! Provides emulation for a minimal ARM PL031 Real Time Clock.
5//!
6//! This module implements a PL031 Real Time Clock (RTC) that provides a long
7//! time base counter. This is achieved by generating an interrupt signal after
8//! counting for a programmed number of cycles of a real-time clock input.
9
10use std::convert::TryFrom;
11use std::sync::Arc;
12use std::time::{SystemTime, UNIX_EPOCH};
13
14// The following defines are mapping to the specification:
15// https://developer.arm.com/documentation/ddi0224/c/Programmers-model/Summary-of-RTC-registers
16//
17// From 0x0 to 0x1C we have following registers:
18const RTCDR: u16 = 0x000; // Data Register (RO).
19const RTCMR: u16 = 0x004; // Match Register.
20const RTCLR: u16 = 0x008; // Load Register.
21const RTCCR: u16 = 0x00C; // Control Register.
22const RTCIMSC: u16 = 0x010; // Interrupt Mask Set or Clear Register.
23const RTCRIS: u16 = 0x014; // Raw Interrupt Status (RO).
24const RTCMIS: u16 = 0x018; // Masked Interrupt Status (RO).
25const RTCICR: u16 = 0x01C; // Interrupt Clear Register (WO).
26
27// From 0x020 to 0xFDC => reserved space.
28
29// From 0xFE0 to 0xFFF => Peripheral and PrimeCell Identification Registers
30//  These are read-only registers, so we store their values in a constant array.
31//  The values are found in the 'Reset value' column of Table 3.1 (Summary of
32//  RTC registers) in the the reference manual linked above.
33const AMBA_IDS: [u8; 8] = [0x31, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
34
35// Since we are specifying the AMBA IDs in an array, instead of in individual
36// registers, these constants bound the register addresses where these IDs
37// would normally be located.
38const AMBA_ID_LOW: u16 = 0xFE0;
39const AMBA_ID_HIGH: u16 = 0xFFF;
40
41/// Defines a series of callbacks that are invoked in response to the occurrence of specific
42/// failure or missed events as part of the RTC operation (e.g., write to an invalid offset). The
43/// methods below can be implemented by a backend that keeps track of such events by incrementing
44/// metrics, logging messages, or any other action.
45///
46/// We're using a trait to avoid constraining the concrete characteristics of the backend in
47/// any way, enabling zero-cost abstractions and use case-specific implementations.
48pub trait RtcEvents {
49    /// The driver attempts to read from an invalid offset.
50    fn invalid_read(&self);
51
52    /// The driver attempts to write to an invalid offset.
53    fn invalid_write(&self);
54}
55
56/// Provides a no-op implementation of `RtcEvents` which can be used in situations that
57/// do not require logging or otherwise doing anything in response to the events defined
58/// as part of `RtcEvents`.
59#[derive(Debug, Clone, Copy)]
60pub struct NoEvents;
61
62impl RtcEvents for NoEvents {
63    fn invalid_read(&self) {}
64    fn invalid_write(&self) {}
65}
66
67impl<EV: RtcEvents> RtcEvents for Arc<EV> {
68    fn invalid_read(&self) {
69        self.as_ref().invalid_read();
70    }
71
72    fn invalid_write(&self) {
73        self.as_ref().invalid_write();
74    }
75}
76
77/// A PL031 Real Time Clock (RTC) that emulates a long time base counter.
78///
79/// This structure emulates the registers for the RTC.
80///
81/// # Example
82///
83/// ```rust
84/// # use std::thread;
85/// # use std::io::Error;
86/// # use std::ops::Deref;
87/// # use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
88/// # use vm_superio::Rtc;
89///
90/// let mut data = [0; 4];
91/// let mut rtc = Rtc::new();
92/// const RTCDR: u16 = 0x0; // Data Register.
93/// const RTCLR: u16 = 0x8; // Load Register.
94///
95/// // Write system time since UNIX_EPOCH in seconds to the load register.
96/// let v = SystemTime::now()
97///     .duration_since(UNIX_EPOCH)
98///     .unwrap()
99///     .as_secs() as u32;
100/// data = v.to_le_bytes();
101/// rtc.write(RTCLR, &data);
102///
103/// // Read the value back out of the load register.
104/// rtc.read(RTCLR, &mut data);
105/// assert_eq!(v, u32::from_le_bytes(data));
106///
107/// // Sleep for 1.5 seconds to let the counter tick.
108/// let delay = Duration::from_millis(1500);
109/// thread::sleep(delay);
110///
111/// // Read the current RTC value from the Data Register.
112/// rtc.read(RTCDR, &mut data);
113/// assert!(u32::from_le_bytes(data) > v);
114/// ```
115#[derive(Debug)]
116pub struct Rtc<EV: RtcEvents> {
117    // The load register.
118    lr: u32,
119
120    // The offset applied to the counter to get the RTC value.
121    offset: i64,
122
123    // The MR register is used for implementing the RTC alarm. A
124    // real time clock alarm is a feature that can be used to allow
125    // a computer to 'wake up' after shut down to execute tasks
126    // every day or on a certain day. It can sometimes be found in
127    // the 'Power Management' section of a motherboard's BIOS setup.
128    // This is not currently implemented, so we raise an error.
129    // TODO: Implement the match register functionality.
130    mr: u32,
131
132    // The interrupt mask.
133    imsc: u32,
134
135    // The raw interrupt value.
136    ris: u32,
137
138    // Used for tracking the occurrence of significant events.
139    events: EV,
140}
141
142/// The state of the Rtc device.
143#[derive(Clone, Copy, Debug, Eq, PartialEq)]
144pub struct RtcState {
145    /// The load register.
146    pub lr: u32,
147    /// The offset applied to the counter to get the RTC value.
148    pub offset: i64,
149    /// The MR register.
150    pub mr: u32,
151    /// The interrupt mask.
152    pub imsc: u32,
153    /// The raw interrupt value.
154    pub ris: u32,
155}
156
157fn get_current_time() -> u32 {
158    let epoch_time = SystemTime::now()
159        .duration_since(UNIX_EPOCH)
160        // This expect should never fail because UNIX_EPOCH is in 1970,
161        // and the only possible failure is if `now` time is before UNIX EPOCH.
162        .expect("SystemTime::duration_since failed");
163    // The following conversion is safe because u32::MAX would correspond to
164    // year 2106. By then we would not be able to use the RTC in its
165    // current form because RTC only works with 32-bits registers, and a bigger
166    // time value would not fit.
167    epoch_time.as_secs() as u32
168}
169
170impl Default for Rtc<NoEvents> {
171    fn default() -> Self {
172        Self::new()
173    }
174}
175
176// This is the state from which a fresh Rtc can be created.
177#[allow(clippy::derivable_impls)]
178impl Default for RtcState {
179    fn default() -> Self {
180        RtcState {
181            // The load register is initialized to 0.
182            lr: 0,
183            offset: 0,
184            // The match register is initialised to zero (not currently used).
185            // TODO: Implement the match register functionality.
186            mr: 0,
187            // The interrupt mask is initialised as not set.
188            imsc: 0,
189            // The raw interrupt is initialised as not asserted.
190            ris: 0,
191        }
192    }
193}
194
195impl Rtc<NoEvents> {
196    /// Creates a new `AMBA PL031 RTC` instance without any metric capabilities. The instance is
197    /// created from the default state.
198    pub fn new() -> Self {
199        Self::from_state(&RtcState::default(), NoEvents)
200    }
201}
202
203impl<EV: RtcEvents> Rtc<EV> {
204    /// Creates a new `AMBA PL031 RTC` instance from a given `state` and that is able to track
205    /// events during operation using the passed `rtc_events` object.
206    /// For creating the instance from a fresh state, [`with_events`](#method.with_events) or
207    /// [`new`](#method.new) methods can be used.
208    ///
209    /// # Arguments
210    /// * `state` - A reference to the state from which the `Rtc` is constructed.
211    /// * `rtc_events` - The `RtcEvents` implementation used to track the occurrence
212    ///   of failure or missed events in the RTC operation.
213    pub fn from_state(state: &RtcState, rtc_events: EV) -> Self {
214        Rtc {
215            lr: state.lr,
216            offset: state.offset,
217            mr: state.mr,
218            imsc: state.imsc,
219            ris: state.ris,
220            // A struct implementing `RtcEvents` for tracking the occurrence of
221            // significant events.
222            events: rtc_events,
223        }
224    }
225
226    /// Creates a new `AMBA PL031 RTC` instance that is able to track events during operation using
227    /// the passed `rtc_events` object. The instance is created from the default state.
228    ///
229    /// # Arguments
230    /// * `rtc_events` - The `RtcEvents` implementation used to track the occurrence
231    ///   of failure or missed events in the RTC operation.
232    pub fn with_events(rtc_events: EV) -> Self {
233        Self::from_state(&RtcState::default(), rtc_events)
234    }
235
236    /// Returns the state of the RTC.
237    pub fn state(&self) -> RtcState {
238        RtcState {
239            lr: self.lr,
240            offset: self.offset,
241            mr: self.mr,
242            imsc: self.imsc,
243            ris: self.ris,
244        }
245    }
246
247    /// Provides a reference to the RTC events object.
248    pub fn events(&self) -> &EV {
249        &self.events
250    }
251
252    fn get_rtc_value(&self) -> u32 {
253        // The RTC value is the time + offset as per:
254        // https://developer.arm.com/documentation/ddi0224/c/Functional-overview/RTC-functional-description/Update-block
255        //
256        // In the unlikely case of the value not fitting in an u32, we just set the time to
257        // the current time on the host.
258        let current_host_time = get_current_time();
259        u32::try_from(
260            (current_host_time as i64)
261                .checked_add(self.offset)
262                .unwrap_or(current_host_time as i64),
263        )
264        .unwrap_or(current_host_time)
265    }
266
267    /// Handles a write request from the driver at `offset` offset from the
268    /// base register address.
269    ///
270    /// # Arguments
271    /// * `offset` - The offset from the base register specifying
272    ///   the register to be written.
273    /// * `data` - The little endian, 4 byte array to write to the register
274    ///
275    /// # Example
276    ///
277    /// You can see an example of how to use this function in the
278    /// [`Example` section from `Rtc`](struct.Rtc.html#example).
279    pub fn write(&mut self, offset: u16, data: &[u8; 4]) {
280        let val = u32::from_le_bytes(*data);
281
282        match offset {
283            RTCMR => {
284                // Set the match register.
285                // TODO: Implement the match register functionality.
286                self.mr = val;
287            }
288            RTCLR => {
289                // The guest can make adjustments to its time by writing to
290                // this register. When these adjustments happen, we calculate the
291                // offset as the difference between the LR value and the host time.
292                // This offset is later used to calculate the RTC value (see
293                // `get_rtc_value`).
294                self.lr = val;
295                // Both lr & offset are u32, hence the following
296                // conversions are safe, and the result fits in an i64.
297                self.offset = self.lr as i64 - get_current_time() as i64;
298            }
299            RTCCR => {
300                // Writing 1 to the control register resets the RTC value,
301                // which means both the load register and the offset are reset.
302                if val == 1 {
303                    self.lr = 0;
304                    self.offset = 0;
305                }
306            }
307            RTCIMSC => {
308                // Set or clear the interrupt mask.
309                self.imsc = val & 1;
310            }
311            RTCICR => {
312                // Writing 1 clears the interrupt; however, since the match
313                // register is unimplemented, this should never be necessary.
314                self.ris &= !val;
315            }
316            _ => {
317                // RTCDR, RTCRIS, and RTCMIS are read-only, so writes to these
318                // registers or to an invalid offset are ignored; however,
319                // We increment the invalid_write() method of the events struct.
320                self.events.invalid_write();
321            }
322        };
323    }
324
325    /// Handles a read request from the driver at `offset` offset from the
326    /// base register address.
327    ///
328    /// # Arguments
329    /// * `offset` - The offset from the base register specifying
330    ///   the register to be read.
331    /// * `data` - The little-endian, 4 byte array storing the read value.
332    ///
333    /// # Example
334    ///
335    /// You can see an example of how to use this function in the
336    /// [`Example` section from `Rtc`](struct.Rtc.html#example).
337    pub fn read(&mut self, offset: u16, data: &mut [u8; 4]) {
338        let v = if (AMBA_ID_LOW..=AMBA_ID_HIGH).contains(&offset) {
339            let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
340            u32::from(AMBA_IDS[index])
341        } else {
342            match offset {
343                RTCDR => self.get_rtc_value(),
344                RTCMR => {
345                    // Read the match register.
346                    // TODO: Implement the match register functionality.
347                    self.mr
348                }
349                RTCLR => self.lr,
350                RTCCR => 1, // RTC is always enabled.
351                RTCIMSC => self.imsc,
352                RTCRIS => self.ris,
353                RTCMIS => self.ris & self.imsc,
354                _ => {
355                    // RTCICR is write only.  For reads of this register or
356                    // an invalid offset, call the invalid_read method of the
357                    // events struct and return.
358                    self.events.invalid_read();
359                    return;
360                }
361            }
362        };
363
364        *data = v.to_le_bytes();
365    }
366}
367
368#[cfg(test)]
369mod tests {
370    use super::*;
371
372    use std::sync::atomic::AtomicU64;
373    use std::sync::Arc;
374    use std::thread;
375    use std::time::Duration;
376
377    use vmm_sys_util::metric::Metric;
378
379    #[derive(Default)]
380    struct ExampleRtcMetrics {
381        invalid_read_count: AtomicU64,
382        invalid_write_count: AtomicU64,
383    }
384
385    impl RtcEvents for ExampleRtcMetrics {
386        fn invalid_read(&self) {
387            self.invalid_read_count.inc();
388            // We can also log a message here, or as part of any of the other methods.
389        }
390
391        fn invalid_write(&self) {
392            self.invalid_write_count.inc();
393        }
394    }
395
396    #[test]
397    fn test_regression_year_1970() {
398        // This is a regression test for: https://github.com/rust-vmm/vm-superio/issues/47.
399        // The problem is that the time in the guest would show up as in the 1970s.
400        let mut rtc = Rtc::new();
401        let expected_time = get_current_time();
402
403        let mut actual_time = [0u8; 4];
404        rtc.read(RTCDR, &mut actual_time);
405        // Check that the difference between the current time, and the time read from the
406        // RTC device is never bigger than one second. This should hold true irrespective of
407        // scheduling.
408        assert!(u32::from_le_bytes(actual_time) - expected_time <= 1);
409    }
410
411    #[test]
412    fn test_data_register() {
413        // Verify we can read the Data Register, but not write to it,
414        // and that the Data Register RTC count increments over time.
415        // This also tests that the invalid write metric is incremented for
416        // writes to RTCDR.
417        let metrics = Arc::new(ExampleRtcMetrics::default());
418        let mut rtc = Rtc::with_events(metrics);
419        let mut data = [0; 4];
420
421        // Check metrics are equal to 0 at the beginning.
422        assert_eq!(rtc.events.invalid_read_count.count(), 0);
423        assert_eq!(rtc.events.invalid_write_count.count(), 0);
424
425        // Read the data register.
426        rtc.read(RTCDR, &mut data);
427        let first_read = u32::from_le_bytes(data);
428
429        // Sleep for 1.5 seconds to let the counter tick.
430        let delay = Duration::from_millis(1500);
431        thread::sleep(delay);
432
433        // Read the data register again.
434        rtc.read(RTCDR, &mut data);
435        let second_read = u32::from_le_bytes(data);
436
437        // The second time should be greater than the first
438        assert!(second_read > first_read);
439
440        // Sleep for 1.5 seconds to let the counter tick.
441        let delay = Duration::from_millis(1500);
442        thread::sleep(delay);
443
444        // Writing the data register should have no effect.
445        data = 0u32.to_le_bytes();
446        rtc.write(RTCDR, &data);
447
448        // Invalid write should increment. All others should not change.
449        assert_eq!(rtc.events.invalid_read_count.count(), 0);
450        assert_eq!(rtc.events.invalid_write_count.count(), 1);
451
452        // Read the data register again.
453        rtc.read(RTCDR, &mut data);
454        let third_read = u32::from_le_bytes(data);
455
456        // The third time should be greater than the second.
457        assert!(third_read > second_read);
458
459        // Confirm metrics are unchanged.
460        assert_eq!(rtc.events.invalid_read_count.count(), 0);
461        assert_eq!(rtc.events.invalid_write_count.count(), 1);
462    }
463
464    #[test]
465    fn test_match_register() {
466        // Test reading and writing to the match register.
467        // TODO: Implement the alarm functionality and confirm an interrupt
468        // is raised when the match register is set.
469        let mut rtc = Rtc::new();
470        let mut data: [u8; 4];
471
472        // Write to the match register.
473        data = 123u32.to_le_bytes();
474        rtc.write(RTCMR, &data);
475
476        // Read the value back out of the match register and confirm it was
477        // correctly written.
478        rtc.read(RTCMR, &mut data);
479        assert_eq!(123, u32::from_le_bytes(data));
480    }
481
482    #[test]
483    fn test_load_register() {
484        // Read and write to the load register to confirm we can both
485        // set the RTC value forward and backward.
486        // This also tests the default Rtc constructor.
487        let mut rtc: Rtc<NoEvents> = Default::default();
488        let mut data = [0; 4];
489
490        // Get the RTC value with a load register of 0 (the initial value).
491        rtc.read(RTCDR, &mut data);
492        let old_val = u32::from_le_bytes(data);
493
494        // Increment LR and verify that the value was updated.
495        let lr = get_current_time() + 100;
496        data = lr.to_le_bytes();
497        rtc.write(RTCLR, &data);
498
499        // Read the load register and verify it matches the value just loaded.
500        rtc.read(RTCLR, &mut data);
501        assert_eq!(lr, u32::from_le_bytes(data));
502
503        // Read the data register and verify it matches the value just loaded.
504        // Note that this assumes less than 1 second has elapsed between
505        // setting RTCLR and this read (based on the RTC counter
506        // tick rate being 1Hz).
507        rtc.read(RTCDR, &mut data);
508        assert_eq!(lr, u32::from_le_bytes(data));
509
510        // Confirm that the new RTC value is greater than the old
511        let new_val = u32::from_le_bytes(data);
512        assert!(new_val > old_val);
513
514        // Set the LR in the past, and check that the RTC value is updated.
515        let lr = get_current_time() - 100;
516        data = lr.to_le_bytes();
517        rtc.write(RTCLR, &data);
518
519        rtc.read(RTCDR, &mut data);
520        let rtc_value = u32::from_le_bytes(data);
521        assert!(rtc_value < get_current_time());
522
523        // Checking that setting the maximum possible value for the LR does
524        // not cause overflows.
525        let lr = u32::MAX;
526        data = lr.to_le_bytes();
527        rtc.write(RTCLR, &data);
528        rtc.read(RTCDR, &mut data);
529        assert!(rtc.offset > -(u32::MAX as i64) && rtc.offset < u32::MAX as i64);
530        // We're checking that this is not 0 because that's the value we're
531        // setting in case the DR value does not fit in an u32.
532        assert_ne!(u32::from_le_bytes(data), 0);
533
534        // Reset the RTC value to 0 and confirm it was reset.
535        let lr = 0u32;
536        data = lr.to_le_bytes();
537        rtc.write(RTCLR, &data);
538
539        // Read the data register and verify it has been reset.
540        rtc.read(RTCDR, &mut data);
541        assert_eq!(lr, u32::from_le_bytes(data));
542    }
543
544    #[test]
545    fn test_rtc_value_overflow() {
546        // Verify that the RTC value will wrap on overflow instead of panic.
547        let mut rtc = Rtc::new();
548        let mut data: [u8; 4];
549
550        // Write u32::MAX to the load register
551        let lr_max = u32::MAX;
552        data = lr_max.to_le_bytes();
553        rtc.write(RTCLR, &data);
554
555        // Read the load register and verify it matches the value just loaded.
556        rtc.read(RTCLR, &mut data);
557        assert_eq!(lr_max, u32::from_le_bytes(data));
558
559        // Read the data register and verify it matches the value just loaded.
560        // Note that this assumes less than 1 second has elapsed between
561        // setting RTCLR and this read (based on the RTC counter
562        // tick rate being 1Hz).
563        rtc.read(RTCDR, &mut data);
564        assert_eq!(lr_max, u32::from_le_bytes(data));
565
566        // Sleep for 1.5 seconds to let the counter tick. This should
567        // cause the RTC value to overflow and wrap.
568        let delay = Duration::from_millis(1500);
569        thread::sleep(delay);
570
571        // Read the data register and verify it has wrapped around.
572        rtc.read(RTCDR, &mut data);
573        assert!(lr_max > u32::from_le_bytes(data));
574    }
575
576    #[test]
577    fn test_interrupt_mask_set_clear_register() {
578        // Test setting and clearing the interrupt mask bit.
579        let mut rtc = Rtc::new();
580        let mut data: [u8; 4];
581
582        // Manually set the raw interrupt.
583        rtc.ris = 1;
584
585        // Set the mask bit.
586        data = 1u32.to_le_bytes();
587        rtc.write(RTCIMSC, &data);
588
589        // Confirm the mask bit is set.
590        rtc.read(RTCIMSC, &mut data);
591        assert_eq!(1, u32::from_le_bytes(data));
592
593        // Confirm the raw and masked interrupts are set.
594        rtc.read(RTCRIS, &mut data);
595        assert_eq!(1, u32::from_le_bytes(data));
596        rtc.read(RTCMIS, &mut data);
597        assert_eq!(1, u32::from_le_bytes(data));
598
599        // Clear the mask bit.
600        data = 0u32.to_le_bytes();
601        rtc.write(RTCIMSC, &data);
602
603        // Confirm the mask bit is cleared.
604        rtc.read(RTCIMSC, &mut data);
605        assert_eq!(0, u32::from_le_bytes(data));
606
607        // Confirm the raw interrupt is set and the masked
608        // interrupt is not.
609        rtc.read(RTCRIS, &mut data);
610        assert_eq!(1, u32::from_le_bytes(data));
611        rtc.read(RTCMIS, &mut data);
612        assert_eq!(0, u32::from_le_bytes(data));
613    }
614
615    #[test]
616    fn test_interrupt_clear_register() {
617        // Test clearing the interrupt. This also tests
618        // that the invalid read and write metrics are incremented.
619        let metrics = Arc::new(ExampleRtcMetrics::default());
620        let mut rtc = Rtc::with_events(metrics);
621        let mut data = [0; 4];
622
623        // Check metrics are equal to 0 at the beginning.
624        assert_eq!(rtc.events.invalid_read_count.count(), 0);
625        assert_eq!(rtc.events.invalid_write_count.count(), 0);
626
627        // Manually set the raw interrupt and interrupt mask.
628        rtc.ris = 1;
629        rtc.imsc = 1;
630
631        // Confirm the raw and masked interrupts are set.
632        rtc.read(RTCRIS, &mut data);
633        assert_eq!(1, u32::from_le_bytes(data));
634        rtc.read(RTCMIS, &mut data);
635        assert_eq!(1, u32::from_le_bytes(data));
636
637        // Write to the interrupt clear register.
638        data = 1u32.to_le_bytes();
639        rtc.write(RTCICR, &data);
640
641        // Metrics should not change.
642        assert_eq!(rtc.events.invalid_read_count.count(), 0);
643        assert_eq!(rtc.events.invalid_write_count.count(), 0);
644
645        // Confirm the raw and masked interrupts are cleared.
646        rtc.read(RTCRIS, &mut data);
647        assert_eq!(0, u32::from_le_bytes(data));
648        rtc.read(RTCMIS, &mut data);
649        assert_eq!(0, u32::from_le_bytes(data));
650
651        // Confirm reading from RTCICR has no effect.
652        data = 123u32.to_le_bytes();
653        rtc.read(RTCICR, &mut data);
654        let v = u32::from_le_bytes(data);
655        assert_eq!(v, 123);
656
657        // Invalid read should increment.  All others should not change.
658        assert_eq!(rtc.events.invalid_read_count.count(), 1);
659        assert_eq!(rtc.events.invalid_write_count.count(), 0);
660    }
661
662    #[test]
663    fn test_control_register() {
664        // Writing 1 to the Control Register should reset the RTC value.
665        // Writing 0 should have no effect.
666        let mut rtc = Rtc::new();
667        let mut data: [u8; 4];
668
669        // Let's move the guest time in the future.
670        let lr = get_current_time() + 100;
671        data = lr.to_le_bytes();
672        rtc.write(RTCLR, &data);
673
674        // Get the RTC value.
675        rtc.read(RTCDR, &mut data);
676        let old_val = u32::from_le_bytes(data);
677
678        // Reset the RTC value by writing 1 to RTCCR.
679        data = 1u32.to_le_bytes();
680        rtc.write(RTCCR, &data);
681
682        // Get the RTC value.
683        rtc.read(RTCDR, &mut data);
684        let new_val = u32::from_le_bytes(data);
685
686        // The new value should be less than the old value.
687        assert!(new_val < old_val);
688
689        // Attempt to clear the control register should have no effect on
690        // either the RTCCR value or the RTC value.
691        data = 0u32.to_le_bytes();
692        rtc.write(RTCCR, &data);
693
694        // Read the RTCCR value and confirm it's still 1.
695        rtc.read(RTCCR, &mut data);
696        let v = u32::from_le_bytes(data);
697        assert_eq!(v, 1);
698
699        // Sleep for 1.5 seconds to let the counter tick.
700        let delay = Duration::from_millis(1500);
701        thread::sleep(delay);
702
703        // Read the RTC value and confirm it has incremented.
704        let old_val = new_val;
705        rtc.read(RTCDR, &mut data);
706        let new_val = u32::from_le_bytes(data);
707        assert!(new_val > old_val);
708    }
709
710    #[test]
711    fn test_raw_interrupt_status_register() {
712        // Writing to the Raw Interrupt Status Register should have no effect,
713        // and reading should return the value of RTCRIS.
714        let mut rtc = Rtc::new();
715        let mut data = [0; 4];
716
717        // Set the raw interrupt for testing.
718        rtc.ris = 1u32;
719
720        // Read the current value of RTCRIS.
721        rtc.read(RTCRIS, &mut data);
722        assert_eq!(u32::from_le_bytes(data), 1);
723
724        // Attempt to write to RTCRIS.
725        data = 0u32.to_le_bytes();
726        rtc.write(RTCRIS, &data);
727
728        // Read the current value of RTCRIS and confirm it's unchanged.
729        rtc.read(RTCRIS, &mut data);
730        assert_eq!(u32::from_le_bytes(data), 1);
731    }
732
733    #[test]
734    fn test_mask_interrupt_status_register() {
735        // Writing to the Masked Interrupt Status Register should have no effect,
736        // and reading should return the value of RTCRIS & RTCIMSC.
737        let mut rtc = Rtc::new();
738        let mut data = [0; 4];
739
740        // Set the raw interrupt for testing.
741        rtc.ris = 1u32;
742
743        // Confirm the mask bit is not set.
744        rtc.read(RTCIMSC, &mut data);
745        assert_eq!(0, u32::from_le_bytes(data));
746
747        // Read the current value of RTCMIS. Since the interrupt mask is
748        // initially 0, the interrupt should not be masked and reading RTCMIS
749        // should return 0.
750        rtc.read(RTCMIS, &mut data);
751        assert_eq!(u32::from_le_bytes(data), 0);
752
753        // Set the mask bit.
754        data = 1u32.to_le_bytes();
755        rtc.write(RTCIMSC, &data);
756
757        // Read the current value of RTCMIS. Since the interrupt mask is
758        // now set, the masked interrupt should be set.
759        rtc.read(RTCMIS, &mut data);
760        assert_eq!(u32::from_le_bytes(data), 1);
761
762        // Attempt to write to RTCMIS should have no effect.
763        data = 0u32.to_le_bytes();
764        rtc.write(RTCMIS, &data);
765
766        // Read the current value of RTCMIS and confirm it's unchanged.
767        rtc.read(RTCMIS, &mut data);
768        assert_eq!(u32::from_le_bytes(data), 1);
769    }
770
771    #[test]
772    fn test_read_only_register_addresses() {
773        let mut rtc = Rtc::new();
774        let mut data = [0; 4];
775
776        // Read the current value of AMBA_ID_LOW.
777        rtc.read(AMBA_ID_LOW, &mut data);
778        assert_eq!(data[0], AMBA_IDS[0]);
779
780        // Attempts to write to read-only registers (AMBA_ID_LOW in this case)
781        // should have no effect.
782        data = 123u32.to_le_bytes();
783        rtc.write(AMBA_ID_LOW, &data);
784
785        // Reread the current value of AMBA_ID_LOW and confirm it's unchanged.
786        rtc.read(AMBA_ID_LOW, &mut data);
787        assert_eq!(data[0], AMBA_IDS[0]);
788
789        // Reading from the AMBA_ID registers should succeed.
790        // Becuase we compute the index of the AMBA_IDS array by a logical bit
791        // shift of (offset - AMBA_ID_LOW) >> 2, we want to make sure that
792        // we correctly align down to a 4-byte register boundary, and that we
793        // don't overflow (we shouldn't, since offset provided to read()
794        // is unsigned).
795
796        // Verify that we can read from AMBA_ID_LOW and that the logical shift
797        // doesn't overflow.
798        data = [0; 4];
799        rtc.read(AMBA_ID_LOW, &mut data);
800        assert_eq!(data[0], AMBA_IDS[0]);
801
802        // Verify that attempts to read from AMBA_ID_LOW + 5 align down to
803        // AMBA_ID_LOW + 4, corresponding to AMBA_IDS[1].
804        data = [0; 4];
805        rtc.read(AMBA_ID_LOW + 5, &mut data);
806        assert_eq!(data[0], AMBA_IDS[1]);
807    }
808
809    #[test]
810    fn test_invalid_write_offset() {
811        // Test that writing to an invalid register offset has no effect
812        // on the RTC value (as read from the data register), and confirm
813        // the invalid write metric increments.
814        let metrics = Arc::new(ExampleRtcMetrics::default());
815        let mut rtc = Rtc::with_events(metrics);
816        let mut data = [0; 4];
817
818        // Check metrics are equal to 0 at the beginning.
819        assert_eq!(rtc.events.invalid_read_count.count(), 0);
820        assert_eq!(rtc.events.invalid_write_count.count(), 0);
821
822        // First test: Write to an address outside the expected range of
823        // register memory.
824
825        // Read the data register.
826        rtc.read(RTCDR, &mut data);
827        let first_read = u32::from_le_bytes(data);
828
829        // Attempt to write to an address outside the expected range of
830        // register memory.
831        data = 123u32.to_le_bytes();
832        rtc.write(AMBA_ID_HIGH + 4, &data);
833
834        // Invalid write should increment.  All others should not change.
835        assert_eq!(rtc.events.invalid_read_count.count(), 0);
836        assert_eq!(rtc.events.invalid_write_count.count(), 1);
837
838        // Read the data register again.
839        rtc.read(RTCDR, &mut data);
840        let second_read = u32::from_le_bytes(data);
841
842        // RTCDR should be unchanged.
843        // Note that this assumes less than 1 second has elapsed between
844        // the first and second read of RTCDR (based on the RTC counter
845        // tick rate being 1Hz).
846        assert_eq!(second_read, first_read);
847
848        // Second test: Attempt to write to a register address similar to the
849        // load register, but not actually valid.
850
851        // Read the data register.
852        rtc.read(RTCDR, &mut data);
853        let first_read = u32::from_le_bytes(data);
854
855        // Attempt to write to an invalid register address close to the load
856        // register's address.
857        data = 123u32.to_le_bytes();
858        rtc.write(RTCLR + 1, &data);
859
860        // Invalid write should increment again.  All others should not change.
861        assert_eq!(rtc.events.invalid_read_count.count(), 0);
862        assert_eq!(rtc.events.invalid_write_count.count(), 2);
863
864        // Read the data register again.
865        rtc.read(RTCDR, &mut data);
866        let second_read = u32::from_le_bytes(data);
867
868        // RTCDR should be unchanged
869        // Note that this assumes less than 1 second has elapsed between
870        // the first and second read of RTCDR (based on the RTC counter
871        // tick rate being 1Hz).
872        assert_eq!(second_read, first_read);
873
874        // Confirm neither metric has changed.
875        assert_eq!(rtc.events.invalid_read_count.count(), 0);
876        assert_eq!(rtc.events.invalid_write_count.count(), 2);
877    }
878
879    #[test]
880    fn test_invalid_read_offset() {
881        // Test that reading from an invalid register offset has no effect,
882        // and confirm the invalid read metric increments.
883        let metrics = Arc::new(ExampleRtcMetrics::default());
884        let mut rtc = Rtc::with_events(metrics);
885        let mut data: [u8; 4];
886
887        // Check metrics are equal to 0 at the beginning.
888        assert_eq!(rtc.events.invalid_read_count.count(), 0);
889        assert_eq!(rtc.events.invalid_write_count.count(), 0);
890
891        // Reading from a non-existent register should have no effect.
892        data = 123u32.to_le_bytes();
893        rtc.read(AMBA_ID_HIGH + 4, &mut data);
894        assert_eq!(123, u32::from_le_bytes(data));
895
896        // Invalid read should increment. All others should not change.
897        assert_eq!(rtc.events.invalid_read_count.count(), 1);
898        assert_eq!(rtc.events.invalid_write_count.count(), 0);
899
900        // Just to prove that AMBA_ID_HIGH + 4 doesn't contain 123...
901        data = 321u32.to_le_bytes();
902        rtc.read(AMBA_ID_HIGH + 4, &mut data);
903        assert_eq!(321, u32::from_le_bytes(data));
904
905        // Invalid read should increment again. All others should not change.
906        assert_eq!(rtc.events.invalid_read_count.count(), 2);
907        assert_eq!(rtc.events.invalid_write_count.count(), 0);
908    }
909
910    #[test]
911    fn test_state() {
912        let metrics = Arc::new(ExampleRtcMetrics::default());
913        let mut rtc = Rtc::with_events(metrics);
914        let mut data = [0; 4];
915
916        // Get the RTC value with a load register of 0 (the initial value).
917        rtc.read(RTCDR, &mut data);
918        let first_read = u32::from_le_bytes(data);
919
920        // Increment LR and verify that the value was updated.
921        let lr = get_current_time() + 100;
922        data = lr.to_le_bytes();
923        rtc.write(RTCLR, &data);
924
925        let state = rtc.state();
926        rtc.read(RTCLR, &mut data);
927        assert_eq!(state.lr.to_le_bytes(), data);
928
929        // Do an invalid `write` in order to increment a metric.
930        let mut data2 = 123u32.to_le_bytes();
931        rtc.write(AMBA_ID_HIGH + 4, &data2);
932        assert_eq!(rtc.events.invalid_write_count.count(), 1);
933
934        let metrics = Arc::new(ExampleRtcMetrics::default());
935        let mut rtc_from_state = Rtc::from_state(&state, metrics.clone());
936        let state_after_restore = rtc_from_state.state();
937
938        // Check that the old and the new state are identical.
939        assert_eq!(state, state_after_restore);
940
941        // Read the data register again.
942        rtc.read(RTCDR, &mut data);
943        let second_read = u32::from_le_bytes(data);
944        // The RTC values should be different.
945        assert!(second_read > first_read);
946
947        // Reading from the LR register should return the same value as before saving the state.
948        rtc_from_state.read(RTCLR, &mut data2);
949        assert_eq!(data, data2);
950
951        // Check that the restored `Rtc` doesn't keep the state of the old `metrics` object.
952        assert_eq!(rtc_from_state.events.invalid_write_count.count(), 0);
953
954        // Let's increment again a metric, and this time save the state of events as well (separate
955        // from the base state).
956        // Do an invalid `write` in order to increment a metric.
957        let data3 = 123u32.to_le_bytes();
958        rtc_from_state.write(AMBA_ID_HIGH + 4, &data3);
959        assert_eq!(rtc_from_state.events.invalid_write_count.count(), 1);
960
961        let state2 = rtc_from_state.state();
962        // Mimic saving the metrics for the sake of the example.
963        let saved_metrics = metrics;
964        let rtc = Rtc::from_state(&state2, saved_metrics);
965
966        // Check that the restored `Rtc` keeps the state of the old `metrics` object.
967        assert_eq!(rtc.events.invalid_write_count.count(), 1);
968    }
969
970    #[test]
971    fn test_overflow_offset() {
972        // Test that an invalid offset (too big) does not cause an overflow.
973        let rtc_state = RtcState {
974            lr: 65535,
975            offset: 9223372036854710636,
976            mr: 0,
977            imsc: 0,
978            ris: 0,
979        };
980        let mut rtc = Rtc::from_state(&rtc_state, NoEvents);
981        let mut data = [0u8; 4];
982        rtc.read(RTCDR, &mut data);
983    }
984}