pl031.rs0.00%
1
// Copyright 2025 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
//! Emulated PL031 Real Time Clock (RTC) device.16
//! See: https://developer.arm.com/documentation/ddi0224/c17
18
use std::time::{SystemTime, UNIX_EPOCH};19
20
use parking_lot::Mutex;21
22
use crate::device::{self, MmioDev, Pause};23
use crate::mem::emulated::{Action, Mmio};24
use crate::{bitflags, mem};25
26
const RTC_DR: u64 = 0x000;27
const RTC_MR: u64 = 0x004;28
const RTC_LR: u64 = 0x008;29
const RTC_CR: u64 = 0x00C;30
const RTC_IMSC: u64 = 0x010;31
const RTC_RIS: u64 = 0x014;32
const RTC_MIS: u64 = 0x018;33
const RTC_ICR: u64 = 0x01C;34
35
const RTC_PERIPH_ID0: u64 = 0xFE0;36
const RTC_PERIPH_ID1: u64 = 0xFE4;37
const RTC_PERIPH_ID2: u64 = 0xFE8;38
const RTC_PERIPH_ID3: u64 = 0xFEC;39
const RTC_PCELL_ID0: u64 = 0xFF0;40
const RTC_PCELL_ID1: u64 = 0xFF4;41
const RTC_PCELL_ID2: u64 = 0xFF8;42
const RTC_PCELL_ID3: u64 = 0xFFC;43
44
const PERIPH_ID: [u8; 4] = [0x31, 0x10, 0x04, 0x00];45
const PCELL_ID: [u8; 4] = [0x0d, 0xf0, 0x05, 0xb1];46
47
bitflags! {48
#[derive(Default)]49
struct Interrupt(u32) {50
RTCINTR = 1 << 0;51
}52
}53
54
#[derive(Debug, Default)]55
struct Pl031Reg {56
mr: u32,57
lr: u32,58
offset: u32,59
}60
61
#[derive(Debug)]62
pub struct Pl031 {63
name: Box<str>,64
reg: Mutex<Pl031Reg>,65
}66
67
impl Pl031 {68
pub fn new(base_addr: u64) -> Self {69
Self {70
name: Box::from(format!("pl031@{base_addr:x}")),71
reg: Mutex::new(Pl031Reg::default()),72
}73
}74
75
fn now() -> u32 {76
match SystemTime::now().duration_since(UNIX_EPOCH) {77
Ok(duration) => duration.as_secs() as u32,78
Err(_) => {79
log::error!("System clock is before UNIX_EPOCH. PL031 won't work!");80
081
}82
}83
}84
}85
86
impl Mmio for Pl031 {87
fn size(&self) -> u64 {88
0x100089
}90
91
fn read(&self, offset: u64, _size: u8) -> mem::Result<u64> {92
let reg = self.reg.lock();93
let val = match offset {94
RTC_DR => reg.offset.wrapping_add(Self::now()),95
RTC_MR => reg.mr,96
RTC_LR => reg.lr,97
RTC_CR => 1, // RTC is always enabled98
RTC_IMSC | RTC_RIS | RTC_MIS => 0, // Interrupts are not supported99
RTC_PERIPH_ID0 => PERIPH_ID[0] as u32,100
RTC_PERIPH_ID1 => PERIPH_ID[1] as u32,101
RTC_PERIPH_ID2 => PERIPH_ID[2] as u32,102
RTC_PERIPH_ID3 => PERIPH_ID[3] as u32,103
RTC_PCELL_ID0 => PCELL_ID[0] as u32,104
RTC_PCELL_ID1 => PCELL_ID[1] as u32,105
RTC_PCELL_ID2 => PCELL_ID[2] as u32,106
RTC_PCELL_ID3 => PCELL_ID[3] as u32,107
_ => {108
log::warn!("{}: read from unknown offset {offset:#x}", self.name);109
0110
}111
};112
log::trace!("{}: read {val:#x} from offset {offset:#x}", self.name);113
Ok(val as u64)114
}115
116
fn write(&self, offset: u64, _size: u8, val: u64) -> mem::Result<Action> {117
let mut reg = self.reg.lock();118
let val = val as u32;119
match offset {120
RTC_MR => reg.mr = val,121
RTC_LR => {122
reg.offset = val.wrapping_sub(Self::now());123
reg.lr = val;124
}125
RTC_CR => {} // RTC is always enabled126
RTC_IMSC => {127
// Interrupt is alwasy masked128
if Interrupt::from_bits_retain(val).contains(Interrupt::RTCINTR) {129
log::warn!("{}: guest tries to unmask interrupt", self.name);130
}131
}132
RTC_ICR => {} // Interrupts are not supported133
_ => {134
log::warn!(135
"{}: write {val:#x} to unknown offset {offset:#x}",136
self.name,137
);138
}139
};140
log::trace!("{}: write {val:#x} to offset {offset:#x}", self.name);141
Ok(Action::None)142
}143
}144
145
impl Pause for Pl031 {146
fn pause(&self) -> device::Result<()> {147
Ok(())148
}149
150
fn resume(&self) -> device::Result<()> {151
Ok(())152
}153
}154
155
impl MmioDev for Pl031 {}156