1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::cell::RefCell;
6 use std::collections::BTreeMap;
7 use std::fs::File;
8 use std::fs::OpenOptions;
9 use std::os::unix::fs::FileExt;
10 use std::rc::Rc;
11
12 use anyhow::Context;
13 use arch::MsrAction;
14 use arch::MsrConfig;
15 use arch::MsrExitHandlerError;
16 use arch::MsrFilter;
17 use arch::MsrRWType;
18 use arch::MsrValueFrom;
19 use base::debug;
20 use base::error;
21 use remain::sorted;
22 use thiserror::Error as ThisError;
23
24 #[sorted]
25 #[derive(ThisError, Debug)]
26 pub enum Error {
27 #[error("Unable to open host msr file: {0}")]
28 HostMsrGetError(anyhow::Error),
29 #[error("Unable to get metadata of dev file for msr: {0}")]
30 HostMsrGetMetadataError(std::io::Error),
31 #[error("Unable to read host msr: {0}")]
32 HostMsrReadError(std::io::Error),
33 #[error("Unable to set permissions of dev file for msr: {0}")]
34 HostMsrSetPermsError(std::io::Error),
35 #[error("Unable to write host msr: {0}")]
36 HostMsrWriteError(std::io::Error),
37 #[error("Not set msr action parameter")]
38 InvalidAction,
39 }
40
41 pub type Result<T> = std::result::Result<T, Error>;
42
43 /// Wrap for userspace MSR file descriptor (/dev/cpu/*/msr).
44 pub struct MsrDevFile {
45 dev_msr: File,
46 }
47
48 impl MsrDevFile {
49 /// Create a new MSR file descriptor.
50 ///
51 /// "Passthrough" handler will create file descriptor with both read and write
52 /// permissions. MsrHandlers controls read/write with MsrRWType. This avoids
53 /// the corner case that some MSRs are read-only while other MSRs need write
54 /// permission.
55 /// "Emulate" handler will create read-only file descriptor. This read-only
56 /// descriptor will only be used once to initialize MSR value and "Emulate"
57 /// handler won't store its descriptor at MsrHandlers level.
new(cpu_id: usize, read_only: bool) -> Result<Self>58 fn new(cpu_id: usize, read_only: bool) -> Result<Self> {
59 let filename = format!("/dev/cpu/{}/msr", cpu_id);
60 let dev_msr = OpenOptions::new()
61 .read(true)
62 .write(!read_only)
63 .open(&filename)
64 .context(format!("Cannot open {}, are you root?", filename))
65 .map_err(Error::HostMsrGetError)?;
66 Ok(MsrDevFile { dev_msr })
67 }
68
read(&self, index: u32) -> Result<u64>69 fn read(&self, index: u32) -> Result<u64> {
70 let mut data = [0; 8];
71 self.dev_msr
72 .read_exact_at(&mut data, index.into())
73 .map_err(Error::HostMsrReadError)?;
74 Ok(u64::from_ne_bytes(data))
75 }
76
77 // In fact, only "passthrough" will write into MSR file.
write(&self, index: u32, data: u64) -> Result<()>78 fn write(&self, index: u32, data: u64) -> Result<()> {
79 self.dev_msr
80 .write_all_at(&data.to_ne_bytes(), index.into())
81 .map_err(Error::HostMsrWriteError)?;
82 Ok(())
83 }
84 }
85
86 /// Wrap for general RDMSR/WRMSR handling.
87 ///
88 /// Each specific handler needs to implement this trait.
89 pub trait MsrHandling {
read(&self) -> Result<u64>90 fn read(&self) -> Result<u64>;
91 // For "emulate" handler, it need to update MSR value which is stored in
92 // `msr_data` of MsrEmulate. So declare `self` as mutable.
write(&mut self, data: u64) -> Result<()>93 fn write(&mut self, data: u64) -> Result<()>;
94 }
95
96 type MsrFileType = Rc<RefCell<BTreeMap<usize /* vcpu */, Rc<MsrDevFile>>>>;
97
98 /// MsrPassthroughHandler - passthrough handler that will handle RDMSR/WRMSR
99 /// by reading/writing MSR file directly.
100 /// For RDMSR, this handler will give Guest the current MSR value on Host.
101 /// For WRMSR, this handler will directly pass the change desired by the Guest
102 /// to the host, and expect the change to take effect on the MSR of the host.
103 struct MsrPassthroughHandler {
104 /// MSR index.
105 index: u32,
106 /// MSR source CPU, CPU 0 or running CPU.
107 from: MsrValueFrom,
108 /// Reference of MSR file descriptors.
109 msr_file: MsrFileType,
110 }
111
112 impl MsrPassthroughHandler {
new(index: u32, msr_config: &MsrConfig, msr_file: MsrFileType) -> Result<Self>113 fn new(index: u32, msr_config: &MsrConfig, msr_file: MsrFileType) -> Result<Self> {
114 let pass = MsrPassthroughHandler {
115 index,
116 from: msr_config.from,
117 msr_file,
118 };
119 pass.get_msr_dev()?;
120 Ok(pass)
121 }
122
123 /// A helper interface to get MSR file descriptor.
get_msr_dev(&self) -> Result<Rc<MsrDevFile>>124 fn get_msr_dev(&self) -> Result<Rc<MsrDevFile>> {
125 let cpu_id = self.from.get_cpu_id();
126 // First, check if the descriptor is stored before.
127 if let Some(dev_msr) = self.msr_file.borrow().get(&cpu_id) {
128 return Ok(Rc::clone(dev_msr));
129 }
130
131 // If descriptor isn't found, create new one.
132 let new_dev_msr = Rc::new(MsrDevFile::new(cpu_id, false)?);
133 // Note: For MsrValueFrom::RWFromRunningCPU case, just store
134 // the new descriptor and don't remove the previous.
135 // This is for convenience, since the most decriptor number is
136 // same as Host CPU count.
137 self.msr_file
138 .borrow_mut()
139 .insert(cpu_id, Rc::clone(&new_dev_msr));
140 Ok(new_dev_msr)
141 }
142 }
143
144 impl MsrHandling for MsrPassthroughHandler {
read(&self) -> Result<u64>145 fn read(&self) -> Result<u64> {
146 let index = self.index;
147 self.get_msr_dev()?.read(index)
148 }
149
write(&mut self, data: u64) -> Result<()>150 fn write(&mut self, data: u64) -> Result<()> {
151 let index = self.index;
152 self.get_msr_dev()?.write(index, data)
153 }
154 }
155
156 /// MsrPassthroughHandler - emulate handler that will handle RDMSR/WRMSR
157 /// with a dummy MSR value other than access to real
158 /// MSR.
159 /// This Handler will initialize a value(`msr_data`) with the corresponding
160 /// Host MSR value, then handle the RDMSR/WRMSR based on this "value".
161 ///
162 /// For RDMSR, this handler will give Guest the stored `msr_data`.
163 /// For WRMSR, this handler will directly change `msr_data` without the
164 /// modification on real Host MSR. The change will not take effect on the
165 /// real MSR of Host.
166 ///
167 /// 'emulate' Handler is used in the case, that some driver need to control
168 /// MSR and user just wants to make WRMSR successful and doesn't care about
169 /// if WRMSR really works. This handlers make Guest's control of CPU not
170 /// affect the host
171 struct MsrEmulateHandler {
172 /// Only initialize msr_data with MSR source pCPU, and will not update
173 /// msr value changes on host cpu into msr_data.
174 msr_data: u64,
175 }
176
177 impl MsrEmulateHandler {
new(index: u32, msr_config: &MsrConfig, msr_file: &MsrFileType) -> Result<Self>178 fn new(index: u32, msr_config: &MsrConfig, msr_file: &MsrFileType) -> Result<Self> {
179 let cpu_id = msr_config.from.get_cpu_id();
180 let msr_data: u64 = if let Some(dev_msr) = msr_file.borrow().get(&cpu_id) {
181 dev_msr.read(index)?
182 } else {
183 // Don't allow to write. Only read the value to initialize
184 // `msr_data` and won't store in MsrHandlers level.
185 MsrDevFile::new(cpu_id, true)?.read(index)?
186 };
187
188 Ok(MsrEmulateHandler { msr_data })
189 }
190 }
191
192 impl MsrHandling for MsrEmulateHandler {
read(&self) -> Result<u64>193 fn read(&self) -> Result<u64> {
194 Ok(self.msr_data)
195 }
196
write(&mut self, data: u64) -> Result<()>197 fn write(&mut self, data: u64) -> Result<()> {
198 self.msr_data = data;
199 Ok(())
200 }
201 }
202
203 /// MSR handler configuration. Per-cpu.
204 #[derive(Default)]
205 pub struct MsrHandlers {
206 /// Store read/write permissions to control read/write brfore calling
207 /// MsrHandling trait.
208 pub handler: BTreeMap<u32, (MsrRWType, Rc<RefCell<Box<dyn MsrHandling>>>)>,
209 /// Store file descriptor here to avoid cache duplicate descriptors
210 /// for each MSR.
211 /// Only collect descriptor of 'passthrough' handler, since 'emulate'
212 /// uses descriptor only once during initialization.
213 pub msr_file: MsrFileType,
214 }
215
216 impl MsrHandlers {
new() -> Self217 pub fn new() -> Self {
218 MsrHandlers {
219 ..Default::default()
220 }
221 }
222
read(&self, index: u32) -> Option<u64>223 pub fn read(&self, index: u32) -> Option<u64> {
224 if let Some((rw_type, handler)) = self.handler.get(&index) {
225 // It's not error. This means user does't want to handle
226 // RDMSR. Just log it.
227 if matches!(rw_type, MsrRWType::WriteOnly) {
228 debug!("RDMSR is not allowed for msr: {:#x}", index);
229 return None;
230 }
231
232 match handler.borrow().read() {
233 Ok(data) => Some(data),
234 Err(e) => {
235 error!("MSR host read failed {:#x} {:?}", index, e);
236 None
237 }
238 }
239 } else {
240 None
241 }
242 }
243
write(&self, index: u32, data: u64) -> Option<()>244 pub fn write(&self, index: u32, data: u64) -> Option<()> {
245 if let Some((rw_type, handler)) = self.handler.get(&index) {
246 // It's not error. This means user does't want to handle
247 // WRMSR. Just log it.
248 if matches!(rw_type, MsrRWType::ReadOnly) {
249 debug!("WRMSR is not allowed for msr: {:#x}", index);
250 return None;
251 }
252
253 match handler.borrow_mut().write(data) {
254 Ok(_) => Some(()),
255 Err(e) => {
256 error!("MSR host write failed {:#x} {:?}", index, e);
257 None
258 }
259 }
260 } else {
261 None
262 }
263 }
264
add_handler( &mut self, index: u32, msr_config: MsrConfig, cpu_id: usize, ) -> std::result::Result<(), MsrExitHandlerError>265 pub fn add_handler(
266 &mut self,
267 index: u32,
268 msr_config: MsrConfig,
269 cpu_id: usize,
270 ) -> std::result::Result<(), MsrExitHandlerError> {
271 match msr_config.action {
272 MsrAction::MsrPassthrough => {
273 let msr_handler: Rc<RefCell<Box<dyn MsrHandling>>> =
274 match MsrPassthroughHandler::new(index, &msr_config, Rc::clone(&self.msr_file))
275 {
276 Ok(r) => Rc::new(RefCell::new(Box::new(r))),
277 Err(e) => {
278 error!(
279 "failed to create MSR passthrough handler for vcpu {}: {:#}",
280 cpu_id, e
281 );
282 return Err(MsrExitHandlerError::HandlerCreateFailed);
283 }
284 };
285 self.handler
286 .insert(index, (msr_config.rw_type, msr_handler));
287 }
288 MsrAction::MsrEmulate => {
289 let msr_handler: Rc<RefCell<Box<dyn MsrHandling>>> =
290 match MsrEmulateHandler::new(index, &msr_config, &self.msr_file) {
291 Ok(r) => Rc::new(RefCell::new(Box::new(r))),
292 Err(e) => {
293 error!(
294 "failed to create MSR emulate handler for vcpu {}: {:#}",
295 cpu_id, e
296 );
297 return Err(MsrExitHandlerError::HandlerCreateFailed);
298 }
299 };
300 self.handler
301 .insert(index, (msr_config.rw_type, msr_handler));
302 }
303 };
304 Ok(())
305 }
306 }
307
308 /// get override msr list
get_override_msr_list( msr_list: &BTreeMap<u32, MsrConfig>, ) -> ( Vec<u32>, Vec<u32>, )309 pub fn get_override_msr_list(
310 msr_list: &BTreeMap<u32, MsrConfig>,
311 ) -> (
312 Vec<u32>, /* read override */
313 Vec<u32>, /* write override */
314 ) {
315 let mut rd_msrs: Vec<u32> = Vec::new();
316 let mut wr_msrs: Vec<u32> = Vec::new();
317
318 for (index, config) in msr_list.iter() {
319 if config.filter == MsrFilter::Override {
320 match config.rw_type {
321 MsrRWType::ReadOnly => {
322 rd_msrs.push(*index);
323 }
324 MsrRWType::WriteOnly => {
325 wr_msrs.push(*index);
326 }
327 MsrRWType::ReadWrite => {
328 rd_msrs.push(*index);
329 wr_msrs.push(*index);
330 }
331 }
332 }
333 }
334 (rd_msrs, wr_msrs)
335 }
336