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}