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