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_u64, write_be_u16, 333 write_be_u32, write_le_i32, write_le_u16, write_le_u64, 334 }; 335 use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig}; 336 use vmm_sys_util::eventfd::EventFd; 337 338 const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000; 339 340 #[test] 341 fn test_get_time() { 342 for _ in 0..1000 { 343 assert!(get_time(ClockType::Monotonic) <= get_time(ClockType::Monotonic)); 344 } 345 346 for _ in 0..1000 { 347 assert!(get_time(ClockType::ProcessCpu) <= get_time(ClockType::ProcessCpu)); 348 } 349 350 for _ in 0..1000 { 351 assert!(get_time(ClockType::ThreadCpu) <= get_time(ClockType::ThreadCpu)); 352 } 353 354 assert_ne!(get_time(ClockType::Real), 0); 355 } 356 357 #[test] 358 fn test_local_time_display() { 359 let local_time = LocalTime { 360 sec: 30, 361 min: 15, 362 hour: 10, 363 mday: 4, 364 mon: 6, 365 year: 119, 366 nsec: 123_456_789, 367 }; 368 assert_eq!( 369 String::from("2019-07-04T10:15:30.123456789"), 370 local_time.to_string() 371 ); 372 373 let local_time = LocalTime { 374 sec: 5, 375 min: 5, 376 hour: 5, 377 mday: 23, 378 mon: 7, 379 year: 44, 380 nsec: 123, 381 }; 382 assert_eq!( 383 String::from("1944-08-23T05:05:05.000000123"), 384 local_time.to_string() 385 ); 386 387 let local_time = LocalTime::now(); 388 assert!(local_time.mon >= 0 && local_time.mon <= 11); 389 } 390 391 #[test] 392 fn test_seconds_to_nanoseconds() { 393 assert_eq!( 394 seconds_to_nanoseconds(100).unwrap() as u64, 395 100 * NANOS_PER_SECOND 396 ); 397 398 assert!(seconds_to_nanoseconds(9_223_372_037).is_none()); 399 } 400 401 struct TestInterrupt { 402 event_fd: EventFd, 403 } 404 405 impl InterruptSourceGroup for TestInterrupt { 406 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 407 self.event_fd.write(1) 408 } 409 410 fn update( 411 &self, 412 _index: InterruptIndex, 413 _config: InterruptSourceConfig, 414 _masked: bool, 415 _set_gsi: bool, 416 ) -> result::Result<(), std::io::Error> { 417 Ok(()) 418 } 419 420 fn set_gsi(&self) -> result::Result<(), std::io::Error> { 421 Ok(()) 422 } 423 424 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 425 Some(self.event_fd.try_clone().unwrap()) 426 } 427 } 428 429 impl TestInterrupt { 430 fn new(event_fd: EventFd) -> Self { 431 TestInterrupt { event_fd } 432 } 433 } 434 435 #[test] 436 fn test_rtc_read_write_and_event() { 437 let intr_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap(); 438 439 let mut rtc = Rtc::new(Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap()))); 440 let mut data = [0; 4]; 441 442 // Read and write to the MR register. 443 write_le_u32(&mut data, 123); 444 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCMR, &data); 445 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCMR, &mut data); 446 let v = read_le_u32(&data); 447 assert_eq!(v, 123); 448 449 // Read and write to the LR register. 450 let v = get_time(ClockType::Real); 451 write_le_u32(&mut data, (v / NANOS_PER_SECOND) as u32); 452 let previous_now_before = rtc.previous_now; 453 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCLR, &data); 454 455 assert!(rtc.previous_now > previous_now_before); 456 457 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCLR, &mut data); 458 let v_read = read_le_u32(&data); 459 assert_eq!((v / NANOS_PER_SECOND) as u32, v_read); 460 461 // Read and write to IMSC register. 462 // Test with non zero value. 463 let non_zero = 1; 464 write_le_u32(&mut data, non_zero); 465 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data); 466 // The interrupt line should be on. 467 assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() == 1); 468 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data); 469 let v = read_le_u32(&data); 470 assert_eq!(non_zero & 1, v); 471 472 // Now test with 0. 473 write_le_u32(&mut data, 0); 474 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &data); 475 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCIMSC, &mut data); 476 let v = read_le_u32(&data); 477 assert_eq!(0, v); 478 479 // Read and write to the ICR register. 480 write_le_u32(&mut data, 1); 481 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCICR, &data); 482 // The interrupt line should be on. 483 assert!(rtc.interrupt.notifier(0).unwrap().read().unwrap() > 1); 484 let v_before = read_le_u32(&data); 485 486 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCICR, &mut data); 487 let v = read_le_u32(&data); 488 // ICR is a write only register. Data received should stay equal to data sent. 489 assert_eq!(v, v_before); 490 491 // Attempts to turn off the RTC should not go through. 492 write_le_u32(&mut data, 0); 493 rtc.write(LEGACY_RTC_MAPPED_IO_START, RTCCR, &data); 494 rtc.read(LEGACY_RTC_MAPPED_IO_START, RTCCR, &mut data); 495 let v = read_le_u32(&data); 496 assert_eq!(v, 1); 497 498 // Attempts to write beyond the writable space. Using here the space used to read 499 // the CID and PID from. 500 write_le_u32(&mut data, 0); 501 rtc.write(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &data); 502 // However, reading from the AMBA_ID_LOW should succeed upon read. 503 504 let mut data = [0; 4]; 505 rtc.read(LEGACY_RTC_MAPPED_IO_START, AMBA_ID_LOW, &mut data); 506 let index = AMBA_ID_LOW + 3; 507 assert_eq!(data[0], PL031_ID[((index - AMBA_ID_LOW) >> 2) as usize]); 508 } 509 510 macro_rules! byte_order_test_read_write { 511 ($test_name: ident, $write_fn_name: ident, $read_fn_name: ident, $is_be: expr, $data_type: ty) => { 512 #[test] 513 fn $test_name() { 514 let test_cases = [ 515 ( 516 0x0123_4567_89AB_CDEF as u64, 517 [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef], 518 ), 519 ( 520 0x0000_0000_0000_0000 as u64, 521 [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 522 ), 523 ( 524 0x1923_2345_ABF3_CCD4 as u64, 525 [0x19, 0x23, 0x23, 0x45, 0xAB, 0xF3, 0xCC, 0xD4], 526 ), 527 ( 528 0x0FF0_0FF0_0FF0_0FF0 as u64, 529 [0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0], 530 ), 531 ( 532 0xFFFF_FFFF_FFFF_FFFF as u64, 533 [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], 534 ), 535 ( 536 0x89AB_12D4_C2D2_09BB as u64, 537 [0x89, 0xAB, 0x12, 0xD4, 0xC2, 0xD2, 0x09, 0xBB], 538 ), 539 ]; 540 541 let type_size = std::mem::size_of::<$data_type>(); 542 for (test_val, v_arr) in &test_cases { 543 let v = *test_val as $data_type; 544 let cmp_iter: Box<dyn Iterator<Item = _>> = if $is_be { 545 Box::new(v_arr[(8 - type_size)..].iter()) 546 } else { 547 Box::new(v_arr.iter().rev()) 548 }; 549 // test write 550 let mut write_arr = vec![Default::default(); type_size]; 551 $write_fn_name(&mut write_arr, v); 552 for (cmp, cur) in cmp_iter.zip(write_arr.iter()) { 553 assert_eq!(*cmp, *cur as u8) 554 } 555 // test read 556 let read_val = $read_fn_name(&write_arr); 557 assert_eq!(v, read_val); 558 } 559 } 560 }; 561 } 562 563 byte_order_test_read_write!(test_le_u16, write_le_u16, read_le_u16, false, u16); 564 byte_order_test_read_write!(test_le_u32, write_le_u32, read_le_u32, false, u32); 565 byte_order_test_read_write!(test_le_u64, write_le_u64, read_le_u64, false, u64); 566 byte_order_test_read_write!(test_le_i32, write_le_i32, read_le_i32, false, i32); 567 byte_order_test_read_write!(test_be_u16, write_be_u16, read_be_u16, true, u16); 568 byte_order_test_read_write!(test_be_u32, write_be_u32, read_be_u32, true, u32); 569 } 570