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: {0}")] 49 InterruptFailure(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 { 67 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. 82 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. 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. 117 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 130 fn trigger_interrupt(&mut self) -> Result<()> { 131 self.interrupt.trigger(0).map_err(Error::InterruptFailure)?; 132 Ok(()) 133 } 134 135 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 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 { 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 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 { 255 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 { 293 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] 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] 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] 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 { 374 fn trigger(&self, _index: InterruptIndex) -> result::Result<(), std::io::Error> { 375 self.event_fd.write(1) 376 } 377 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 388 fn set_gsi(&self) -> result::Result<(), std::io::Error> { 389 Ok(()) 390 } 391 392 fn notifier(&self, _index: InterruptIndex) -> Option<EventFd> { 393 Some(self.event_fd.try_clone().unwrap()) 394 } 395 } 396 397 impl TestInterrupt { 398 fn new(event_fd: EventFd) -> Self { 399 TestInterrupt { event_fd } 400 } 401 } 402 403 #[test] 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