xref: /cloud-hypervisor/devices/src/legacy/rtc_pl031.rs (revision 3ce0fef7fd546467398c914dbc74d8542e45cf6f)
1 // Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
2 // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 //! ARM PL031 Real Time Clock
6 //!
7 //! This module implements a PL031 Real Time Clock (RTC) that provides to provides long time base counter.
8 //! This is achieved by generating an interrupt signal after counting for a programmed number of cycles of
9 //! a real-time clock input.
10 //!
11 use crate::{read_le_u32, write_le_u32};
12 use std::fmt;
13 use std::sync::{Arc, Barrier};
14 use std::time::Instant;
15 use std::{io, result};
16 use vm_device::interrupt::InterruptSourceGroup;
17 use vm_device::BusDevice;
18 
19 // As you can see in https://static.docs.arm.com/ddi0224/c/real_time_clock_pl031_r1p3_technical_reference_manual_DDI0224C.pdf
20 // at section 3.2 Summary of RTC registers, the total size occupied by this device is 0x000 -> 0xFFC + 4 = 0x1000.
21 // From 0x0 to 0x1C we have following registers:
22 const RTCDR: u64 = 0x0; // Data Register.
23 const RTCMR: u64 = 0x4; // Match Register.
24 const RTCLR: u64 = 0x8; // Load Register.
25 const RTCCR: u64 = 0xc; // Control Register.
26 const RTCIMSC: u64 = 0x10; // Interrupt Mask Set or Clear Register.
27 const RTCRIS: u64 = 0x14; // Raw Interrupt Status.
28 const RTCMIS: u64 = 0x18; // Masked Interrupt Status.
29 const RTCICR: u64 = 0x1c; // Interrupt Clear Register.
30                           // From 0x020 to 0xFDC => reserved space.
31                           // From 0xFE0 to 0x1000 => Peripheral and PrimeCell Identification Registers which are Read Only registers.
32                           // AMBA standard devices have CIDs (Cell IDs) and PIDs (Peripheral IDs). The linux kernel will look for these in order to assert the identity
33                           // of these devices (i.e look at the `amba_device_try_add` function).
34                           // We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
35 const PL031_ID: [u8; 8] = [0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
36 // We are only interested in the margins.
37 const AMBA_ID_LOW: u64 = 0xFE0;
38 const AMBA_ID_HIGH: u64 = 0x1000;
39 /// Constant to convert seconds to nanoseconds.
40 pub const NANOS_PER_SECOND: u64 = 1_000_000_000;
41 
42 #[derive(Debug)]
43 pub enum Error {
44     BadWriteOffset(u64),
45     InterruptFailure(io::Error),
46 }
47 
48 impl fmt::Display for Error {
49     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50         match self {
51             Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {offset}"),
52             Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {e}"),
53         }
54     }
55 }
56 
57 type Result<T> = result::Result<T, Error>;
58 
59 /// Wrapper over `libc::clockid_t` to specify Linux Kernel clock source.
60 pub enum ClockType {
61     /// Equivalent to `libc::CLOCK_MONOTONIC`.
62     Monotonic,
63     /// Equivalent to `libc::CLOCK_REALTIME`.
64     Real,
65     /// Equivalent to `libc::CLOCK_PROCESS_CPUTIME_ID`.
66     ProcessCpu,
67     /// Equivalent to `libc::CLOCK_THREAD_CPUTIME_ID`.
68     ThreadCpu,
69 }
70 
71 impl From<ClockType> for libc::clockid_t {
72     fn from(ct: ClockType) -> libc::clockid_t {
73         match ct {
74             ClockType::Monotonic => libc::CLOCK_MONOTONIC,
75             ClockType::Real => libc::CLOCK_REALTIME,
76             ClockType::ProcessCpu => libc::CLOCK_PROCESS_CPUTIME_ID,
77             ClockType::ThreadCpu => libc::CLOCK_THREAD_CPUTIME_ID,
78         }
79     }
80 }
81 
82 /// Structure representing the date in local time with nanosecond precision.
83 pub struct LocalTime {
84     /// Seconds in current minute.
85     sec: i32,
86     /// Minutes in current hour.
87     min: i32,
88     /// Hours in current day, 24H format.
89     hour: i32,
90     /// Days in current month.
91     mday: i32,
92     /// Months in current year.
93     mon: i32,
94     /// Years passed since 1900 BC.
95     year: i32,
96     /// Nanoseconds in current second.
97     nsec: i64,
98 }
99 
100 impl LocalTime {
101     /// Returns the [LocalTime](struct.LocalTime.html) structure for the calling moment.
102     #[cfg(test)]
103     pub fn now() -> LocalTime {
104         let mut timespec = libc::timespec {
105             tv_sec: 0,
106             tv_nsec: 0,
107         };
108         let mut tm: libc::tm = libc::tm {
109             tm_sec: 0,
110             tm_min: 0,
111             tm_hour: 0,
112             tm_mday: 0,
113             tm_mon: 0,
114             tm_year: 0,
115             tm_wday: 0,
116             tm_yday: 0,
117             tm_isdst: 0,
118             tm_gmtoff: 0,
119             tm_zone: std::ptr::null(),
120         };
121 
122         // SAFETY: the parameters are valid.
123         unsafe {
124             libc::clock_gettime(libc::CLOCK_REALTIME, &mut timespec);
125             libc::localtime_r(&timespec.tv_sec, &mut tm);
126         }
127 
128         LocalTime {
129             sec: tm.tm_sec,
130             min: tm.tm_min,
131             hour: tm.tm_hour,
132             mday: tm.tm_mday,
133             mon: tm.tm_mon,
134             year: tm.tm_year,
135             nsec: timespec.tv_nsec,
136         }
137     }
138 }
139 
140 impl fmt::Display for LocalTime {
141     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142         write!(
143             f,
144             "{}-{:02}-{:02}T{:02}:{:02}:{:02}.{:09}",
145             self.year + 1900,
146             self.mon + 1,
147             self.mday,
148             self.hour,
149             self.min,
150             self.sec,
151             self.nsec
152         )
153     }
154 }
155 
156 /// Holds a micro-second resolution timestamp with both the real time and cpu time.
157 #[derive(Clone)]
158 pub struct TimestampUs {
159     /// Real time in microseconds.
160     pub time_us: u64,
161     /// Cpu time in microseconds.
162     pub cputime_us: u64,
163 }
164 
165 impl Default for TimestampUs {
166     fn default() -> TimestampUs {
167         TimestampUs {
168             time_us: get_time(ClockType::Monotonic) / 1000,
169             cputime_us: get_time(ClockType::ProcessCpu) / 1000,
170         }
171     }
172 }
173 
174 /// Returns a timestamp in nanoseconds based on the provided clock type.
175 ///
176 /// # Arguments
177 ///
178 /// * `clock_type` - Identifier of the Linux Kernel clock on which to act.
179 pub fn get_time(clock_type: ClockType) -> u64 {
180     let mut time_struct = libc::timespec {
181         tv_sec: 0,
182         tv_nsec: 0,
183     };
184     // SAFETY: the parameters are valid.
185     unsafe { libc::clock_gettime(clock_type.into(), &mut time_struct) };
186     seconds_to_nanoseconds(time_struct.tv_sec).unwrap() as u64 + (time_struct.tv_nsec as u64)
187 }
188 
189 /// Converts a timestamp in seconds to an equivalent one in nanoseconds.
190 /// Returns `None` if the conversion overflows.
191 ///
192 /// # Arguments
193 ///
194 /// * `value` - Timestamp in seconds.
195 pub fn seconds_to_nanoseconds(value: i64) -> Option<i64> {
196     value.checked_mul(NANOS_PER_SECOND as i64)
197 }
198 
199 /// A RTC device following the PL031 specification..
200 pub struct Rtc {
201     previous_now: Instant,
202     tick_offset: i64,
203     // This is used for implementing the RTC alarm. However, in Firecracker we do not need it.
204     match_value: u32,
205     // Writes to this register load an update value into the RTC.
206     load: u32,
207     imsc: u32,
208     ris: u32,
209     interrupt: Arc<dyn InterruptSourceGroup>,
210 }
211 
212 impl Rtc {
213     /// Constructs an AMBA PL031 RTC device.
214     pub fn new(interrupt: Arc<dyn InterruptSourceGroup>) -> Self {
215         Self {
216             // This is used only for duration measuring purposes.
217             previous_now: Instant::now(),
218             tick_offset: get_time(ClockType::Real) as i64,
219             match_value: 0,
220             load: 0,
221             imsc: 0,
222             ris: 0,
223             interrupt,
224         }
225     }
226 
227     fn trigger_interrupt(&mut self) -> Result<()> {
228         self.interrupt.trigger(0).map_err(Error::InterruptFailure)?;
229         Ok(())
230     }
231 
232     fn get_time(&self) -> u32 {
233         let ts = (self.tick_offset as i128)
234             + (Instant::now().duration_since(self.previous_now).as_nanos() as i128);
235         (ts / NANOS_PER_SECOND as i128) as u32
236     }
237 
238     fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
239         match offset {
240             RTCMR => {
241                 // The MR register is used for implementing the RTC alarm. A real time clock alarm is
242                 // a feature that can be used to allow a computer to 'wake up' after shut down to execute
243                 // tasks every day or on a certain day. It can sometimes be found in the 'Power Management'
244                 // section of a motherboard's BIOS setup. This is functionality that extends beyond
245                 // Firecracker intended use. However, we increment a metric just in case.
246                 self.match_value = val;
247             }
248             RTCLR => {
249                 self.load = val;
250                 self.previous_now = Instant::now();
251                 // If the unwrap fails, then the internal value of the clock has been corrupted and
252                 // we want to terminate the execution of the process.
253                 self.tick_offset = seconds_to_nanoseconds(i64::from(val)).unwrap();
254             }
255             RTCIMSC => {
256                 self.imsc = val & 1;
257                 self.trigger_interrupt()?;
258             }
259             RTCICR => {
260                 // As per above mentioned doc, the interrupt is cleared by writing any data value to
261                 // the Interrupt Clear Register.
262                 self.ris = 0;
263                 self.trigger_interrupt()?;
264             }
265             RTCCR => (), // ignore attempts to turn off the timer.
266             o => {
267                 return Err(Error::BadWriteOffset(o));
268             }
269         }
270         Ok(())
271     }
272 }
273 
274 impl BusDevice for Rtc {
275     fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
276         let mut read_ok = true;
277 
278         let v = if (AMBA_ID_LOW..AMBA_ID_HIGH).contains(&offset) {
279             let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
280             u32::from(PL031_ID[index])
281         } else {
282             match offset {
283                 RTCDR => self.get_time(),
284                 RTCMR => {
285                     // Even though we are not implementing RTC alarm we return the last value
286                     self.match_value
287                 }
288                 RTCLR => self.load,
289                 RTCCR => 1, // RTC is always enabled.
290                 RTCIMSC => self.imsc,
291                 RTCRIS => self.ris,
292                 RTCMIS => self.ris & self.imsc,
293                 _ => {
294                     read_ok = false;
295                     0
296                 }
297             }
298         };
299         if read_ok && data.len() <= 4 {
300             write_le_u32(data, v);
301         } else {
302             warn!(
303                 "Invalid RTC PL031 read: offset {}, data length {}",
304                 offset,
305                 data.len()
306             );
307         }
308     }
309 
310     fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
311         if data.len() <= 4 {
312             let v = read_le_u32(data);
313             if let Err(e) = self.handle_write(offset, v) {
314                 warn!("Failed to write to RTC PL031 device: {}", e);
315             }
316         } else {
317             warn!(
318                 "Invalid RTC PL031 write: offset {}, data length {}",
319                 offset,
320                 data.len()
321             );
322         }
323 
324         None
325     }
326 }
327 
328 #[cfg(test)]
329 mod tests {
330     use super::*;
331     use crate::{
332         read_be_u16, read_be_u32, read_le_i32, read_le_u16, read_le_u32, read_le_u64, write_be_u16,
333         write_be_u32, write_le_i32, write_le_u16, write_le_u32, write_le_u64,
334     };
335     use std::sync::Arc;
336     use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
337     use vmm_sys_util::eventfd::EventFd;
338 
339     const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
340 
341     #[test]
342     fn test_get_time() {
343         for _ in 0..1000 {
344             assert!(get_time(ClockType::Monotonic) <= get_time(ClockType::Monotonic));
345         }
346 
347         for _ in 0..1000 {
348             assert!(get_time(ClockType::ProcessCpu) <= get_time(ClockType::ProcessCpu));
349         }
350 
351         for _ in 0..1000 {
352             assert!(get_time(ClockType::ThreadCpu) <= get_time(ClockType::ThreadCpu));
353         }
354 
355         assert_ne!(get_time(ClockType::Real), 0);
356     }
357 
358     #[test]
359     fn test_local_time_display() {
360         let local_time = LocalTime {
361             sec: 30,
362             min: 15,
363             hour: 10,
364             mday: 4,
365             mon: 6,
366             year: 119,
367             nsec: 123_456_789,
368         };
369         assert_eq!(
370             String::from("2019-07-04T10:15:30.123456789"),
371             local_time.to_string()
372         );
373 
374         let local_time = LocalTime {
375             sec: 5,
376             min: 5,
377             hour: 5,
378             mday: 23,
379             mon: 7,
380             year: 44,
381             nsec: 123,
382         };
383         assert_eq!(
384             String::from("1944-08-23T05:05:05.000000123"),
385             local_time.to_string()
386         );
387 
388         let local_time = LocalTime::now();
389         assert!(local_time.mon >= 0 && local_time.mon <= 11);
390     }
391 
392     #[test]
393     fn test_seconds_to_nanoseconds() {
394         assert_eq!(
395             seconds_to_nanoseconds(100).unwrap() as u64,
396             100 * NANOS_PER_SECOND
397         );
398 
399         assert!(seconds_to_nanoseconds(9_223_372_037).is_none());
400     }
401 
402     struct TestInterrupt {
403         event_fd: EventFd,
404     }
405 
406     impl InterruptSourceGroup for TestInterrupt {
407         fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> {
408             self.event_fd.write(1)
409         }
410 
411         fn update(
412             &self,
413             _index: InterruptIndex,
414             _config: InterruptSourceConfig,
415             _masked: bool,
416             _set_gsi: bool,
417         ) -> result::Result<(), std::io::Error> {
418             Ok(())
419         }
420 
421         fn set_gsi(&self) -> result::Result<(), std::io::Error> {
422             Ok(())
423         }
424 
425         fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> {
426             Some(self.event_fd.try_clone().unwrap())
427         }
428     }
429 
430     impl TestInterrupt {
431         fn new(event_fd: EventFd) -> Self {
432             TestInterrupt { event_fd }
433         }
434     }
435 
436     #[test]
437     fn test_rtc_read_write_and_event() {
438         let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
439 
440         let mut rtc = Rtc::new(Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
441         let mut data = [0; 4];
442 
443         // Read and write to the MR register.
444         write_le_u32(&mut data, 123);
445         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCMR, &data);
446         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCMR, &mut data);
447         let v = read_le_u32(&data);
448         assert_eq!(v, 123);
449 
450         // Read and write to the LR register.
451         let v = get_time(ClockType::Real);
452         write_le_u32(&mut data, (v / NANOS_PER_SECOND) as u32);
453         let previous_now_before = rtc.previous_now;
454         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCLR, &data);
455 
456         assert!(rtc.previous_now > previous_now_before);
457 
458         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCLR, &mut data);
459         let v_read = read_le_u32(&data);
460         assert_eq!((v / NANOS_PER_SECOND) as u32, v_read);
461 
462         // Read and write to IMSC register.
463         // Test with non zero value.
464         let non_zero = 1;
465         write_le_u32(&mut data, non_zero);
466         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data);
467         // The interrupt line should be on.
468         assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() == 1);
469         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
470         let v = read_le_u32(&data);
471         assert_eq!(non_zero & 1, v);
472 
473         // Now test with 0.
474         write_le_u32(&mut data, 0);
475         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data);
476         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data);
477         let v = read_le_u32(&data);
478         assert_eq!(0, v);
479 
480         // Read and write to the ICR register.
481         write_le_u32(&mut data, 1);
482         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCICR, &data);
483         // The interrupt line should be on.
484         assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() > 1);
485         let v_before = read_le_u32(&data);
486 
487         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data);
488         let v = read_le_u32(&data);
489         // ICR is a  write only register. Data received should stay equal to data sent.
490         assert_eq!(v, v_before);
491 
492         // Attempts to turn off the RTC should not go through.
493         write_le_u32(&mut data, 0);
494         rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCCR, &data);
495         rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCCR, &mut data);
496         let v = read_le_u32(&data);
497         assert_eq!(v, 1);
498 
499         // Attempts to write beyond the writable space. Using here the space used to read
500         // the CID and PID from.
501         write_le_u32(&mut data, 0);
502         rtc.write(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &data);
503         // However, reading from the AMBA_ID_LOW should succeed upon read.
504 
505         let mut data = [0; 4];
506         rtc.read(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &mut data);
507         let index = AMBA_ID_LOW + 3;
508         assert_eq!(data[0], PL031_ID[((index - AMBA_ID_LOW) >> 2) as usize]);
509     }
510 
511     macro_rules! byte_order_test_read_write {
512         ($test_name: ident, $write_fn_name: ident, $read_fn_name: ident, $is_be: expr, $data_type: ty) => {
513             #[test]
514             fn $test_name() {
515                 let test_cases = [
516                     (
517                         0x0123_4567_89AB_CDEF as u64,
518                         [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef],
519                     ),
520                     (
521                         0x0000_0000_0000_0000 as u64,
522                         [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
523                     ),
524                     (
525                         0x1923_2345_ABF3_CCD4 as u64,
526                         [0x19, 0x23, 0x23, 0x45, 0xAB, 0xF3, 0xCC, 0xD4],
527                     ),
528                     (
529                         0x0FF0_0FF0_0FF0_0FF0 as u64,
530                         [0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0],
531                     ),
532                     (
533                         0xFFFF_FFFF_FFFF_FFFF as u64,
534                         [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
535                     ),
536                     (
537                         0x89AB_12D4_C2D2_09BB as u64,
538                         [0x89, 0xAB, 0x12, 0xD4, 0xC2, 0xD2, 0x09, 0xBB],
539                     ),
540                 ];
541 
542                 let type_size = std::mem::size_of::<$data_type>();
543                 for (test_val, v_arr) in &test_cases {
544                     let v = *test_val as $data_type;
545                     let cmp_iter: Box<dyn Iterator<Item = _>> = if $is_be {
546                         Box::new(v_arr[(8 - type_size)..].iter())
547                     } else {
548                         Box::new(v_arr.iter().rev())
549                     };
550                     // test write
551                     let mut write_arr = vec![Default::default(); type_size];
552                     $write_fn_name(&mut write_arr, v);
553                     for (cmp, cur) in cmp_iter.zip(write_arr.iter()) {
554                         assert_eq!(*cmp, *cur as u8)
555                     }
556                     // test read
557                     let read_val = $read_fn_name(&write_arr);
558                     assert_eq!(v, read_val);
559                 }
560             }
561         };
562     }
563 
564     byte_order_test_read_write!(test_le_u16, write_le_u16, read_le_u16, false, u16);
565     byte_order_test_read_write!(test_le_u32, write_le_u32, read_le_u32, false, u32);
566     byte_order_test_read_write!(test_le_u64, write_le_u64, read_le_u64, false, u64);
567     byte_order_test_read_write!(test_le_i32, write_le_i32, read_le_i32, false, i32);
568     byte_order_test_read_write!(test_be_u16, write_be_u16, read_be_u16, true, u16);
569     byte_order_test_read_write!(test_be_u32, write_be_u32, read_be_u32, true, u32);
570 }
571