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