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