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(×pec.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 ) -> result::Result<(), std::io::Error> { 417 Ok(()) 418 } 419 420 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 421 Some(self.event_fd.try_clone().unwrap()) 422 } 423 } 424 425 impl TestInterrupt { 426 fn new(event_fd: EventFd) -> Self { 427 TestInterrupt { event_fd } 428 } 429 } 430 431 #[test] 432 fn test_rtc_read_write_and_event() { 433 let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); 434 435 let mut rtc = Rtc::new(Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); 436 let mut data = [0; 4]; 437 438 // Read and write to the MR register. 439 write_le_u32(&mut data, 123); 440 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCMR, &data); 441 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCMR, &mut data); 442 let v = read_le_u32(&data); 443 assert_eq!(v, 123); 444 445 // Read and write to the LR register. 446 let v = get_time(ClockType::Real); 447 write_le_u32(&mut data, (v / NANOS_PER_SECOND) as u32); 448 let previous_now_before = rtc.previous_now; 449 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCLR, &data); 450 451 assert!(rtc.previous_now > previous_now_before); 452 453 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCLR, &mut data); 454 let v_read = read_le_u32(&data); 455 assert_eq!((v / NANOS_PER_SECOND) as u32, v_read); 456 457 // Read and write to IMSC register. 458 // Test with non zero value. 459 let non_zero = 1; 460 write_le_u32(&mut data, non_zero); 461 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data); 462 // The interrupt line should be on. 463 assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() == 1); 464 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data); 465 let v = read_le_u32(&data); 466 assert_eq!(non_zero & 1, v); 467 468 // Now test with 0. 469 write_le_u32(&mut data, 0); 470 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data); 471 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data); 472 let v = read_le_u32(&data); 473 assert_eq!(0, v); 474 475 // Read and write to the ICR register. 476 write_le_u32(&mut data, 1); 477 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCICR, &data); 478 // The interrupt line should be on. 479 assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() > 1); 480 let v_before = read_le_u32(&data); 481 482 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data); 483 let v = read_le_u32(&data); 484 // ICR is a write only register. Data received should stay equal to data sent. 485 assert_eq!(v, v_before); 486 487 // Attempts to turn off the RTC should not go through. 488 write_le_u32(&mut data, 0); 489 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCCR, &data); 490 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCCR, &mut data); 491 let v = read_le_u32(&data); 492 assert_eq!(v, 1); 493 494 // Attempts to write beyond the writable space. Using here the space used to read 495 // the CID and PID from. 496 write_le_u32(&mut data, 0); 497 rtc.write(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &data); 498 // However, reading from the AMBA_ID_LOW should succeed upon read. 499 500 let mut data = [0; 4]; 501 rtc.read(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &mut data); 502 let index = AMBA_ID_LOW + 3; 503 assert_eq!(data[0], PL031_ID[((index - AMBA_ID_LOW) >> 2) as usize]); 504 } 505 506 macro_rules! byte_order_test_read_write { 507 ($test_name: ident, $write_fn_name: ident, $read_fn_name: ident, $is_be: expr, $data_type: ty) => { 508 #[test] 509 fn $test_name() { 510 let test_cases = [ 511 ( 512 0x0123_4567_89AB_CDEF as u64, 513 [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef], 514 ), 515 ( 516 0x0000_0000_0000_0000 as u64, 517 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 518 ), 519 ( 520 0x1923_2345_ABF3_CCD4 as u64, 521 [0x19, 0x23, 0x23, 0x45, 0xAB, 0xF3, 0xCC, 0xD4], 522 ), 523 ( 524 0x0FF0_0FF0_0FF0_0FF0 as u64, 525 [0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0], 526 ), 527 ( 528 0xFFFF_FFFF_FFFF_FFFF as u64, 529 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], 530 ), 531 ( 532 0x89AB_12D4_C2D2_09BB as u64, 533 [0x89, 0xAB, 0x12, 0xD4, 0xC2, 0xD2, 0x09, 0xBB], 534 ), 535 ]; 536 537 let type_size = std::mem::size_of::<$data_type>(); 538 for (test_val, v_arr) in &test_cases { 539 let v = *test_val as $data_type; 540 let cmp_iter: Box<dyn Iterator<Item = _>> = if $is_be { 541 Box::new(v_arr[(8 - type_size)..].iter()) 542 } else { 543 Box::new(v_arr.iter().rev()) 544 }; 545 // test write 546 let mut write_arr = vec![Default::default(); type_size]; 547 $write_fn_name(&mut write_arr, v); 548 for (cmp, cur) in cmp_iter.zip(write_arr.iter()) { 549 assert_eq!(*cmp, *cur as u8) 550 } 551 // test read 552 let read_val = $read_fn_name(&write_arr); 553 assert_eq!(v, read_val); 554 } 555 } 556 }; 557 } 558 559 byte_order_test_read_write!(test_le_u16, write_le_u16, read_le_u16, false, u16); 560 byte_order_test_read_write!(test_le_u32, write_le_u32, read_le_u32, false, u32); 561 byte_order_test_read_write!(test_le_u64, write_le_u64, read_le_u64, false, u64); 562 byte_order_test_read_write!(test_le_i32, write_le_i32, read_le_i32, false, i32); 563 byte_order_test_read_write!(test_be_u16, write_be_u16, read_be_u16, true, u16); 564 byte_order_test_read_write!(test_be_u32, write_be_u32, read_be_u32, true, u32); 565 } 566