xref: /aosp_15_r20/external/crosvm/devices/src/register_space/register.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2018 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::boxed::Box;
6 use std::cmp::max;
7 use std::cmp::min;
8 use std::cmp::Ord;
9 use std::cmp::Ordering;
10 use std::cmp::PartialOrd;
11 use std::mem::size_of;
12 use std::sync::Arc;
13 use std::sync::MutexGuard;
14 
15 use base::error;
16 use sync::Mutex;
17 use zerocopy::AsBytes;
18 use zerocopy::FromBytes;
19 
20 /// Type of offset in the register space.
21 pub type RegisterOffset = u64;
22 
23 /// This represents a range of memory in the register space starting.
24 /// Both from and to are inclusive.
25 #[derive(Debug, Eq, PartialEq, Copy, Clone)]
26 pub struct RegisterRange {
27     pub from: RegisterOffset,
28     pub to: RegisterOffset,
29 }
30 
31 impl Ord for RegisterRange {
cmp(&self, other: &RegisterRange) -> Ordering32     fn cmp(&self, other: &RegisterRange) -> Ordering {
33         self.from.cmp(&other.from)
34     }
35 }
36 
37 impl PartialOrd for RegisterRange {
partial_cmp(&self, other: &RegisterRange) -> Option<Ordering>38     fn partial_cmp(&self, other: &RegisterRange) -> Option<Ordering> {
39         Some(self.cmp(other))
40     }
41 }
42 
43 impl RegisterRange {
44     /// Return true if those range overlaps.
overlap_with(&self, other: &RegisterRange) -> bool45     pub fn overlap_with(&self, other: &RegisterRange) -> bool {
46         !(self.from > other.to || self.to < other.from)
47     }
48 
49     /// Get the overlapping part of two RegisterRange.
50     /// Return is Option(overlap_from, overlap_to).
51     /// For example, (4,7).overlap_range(5, 8) will be Some(5, 7).
overlap_range(&self, other: &RegisterRange) -> Option<RegisterRange>52     pub fn overlap_range(&self, other: &RegisterRange) -> Option<RegisterRange> {
53         if !self.overlap_with(other) {
54             return None;
55         }
56         Some(RegisterRange {
57             from: max(self.from, other.from),
58             to: min(self.to, other.to),
59         })
60     }
61 }
62 
63 /// RegisterValue trait should be satisfied by register value types.
64 pub trait RegisterValue:
65     'static
66     + Into<u64>
67     + Clone
68     + AsBytes
69     + FromBytes
70     + Send
71     + Sync
72     + Copy
73     + std::ops::BitOr<Self, Output = Self>
74     + std::ops::BitAnd<Self, Output = Self>
75     + std::ops::Not<Output = Self>
76     + std::fmt::LowerHex
77 {
78     // Get byte of the offset.
get_byte(&self, offset: usize) -> u879     fn get_byte(&self, offset: usize) -> u8 {
80         let val: u64 = (*self).into();
81         (val >> (offset * 8)) as u8
82     }
83     // Set masked bits.
set_bits(&mut self, mask: Self)84     fn set_bits(&mut self, mask: Self) {
85         *self = *self | mask;
86     }
87     // Clear masked bits.
clear_bits(&mut self, mask: Self)88     fn clear_bits(&mut self, mask: Self) {
89         *self = *self & (!mask);
90     }
91 }
92 impl RegisterValue for u8 {}
93 impl RegisterValue for u16 {}
94 impl RegisterValue for u32 {}
95 impl RegisterValue for u64 {}
96 
97 // Helper function to read a register. If the read range overlaps with value's range, it will load
98 // corresponding bytes into data.
read_reg_helper<T: RegisterValue>( val: T, val_range: RegisterRange, addr: RegisterOffset, data: &mut [u8], )99 fn read_reg_helper<T: RegisterValue>(
100     val: T,
101     val_range: RegisterRange,
102     addr: RegisterOffset,
103     data: &mut [u8],
104 ) {
105     let read_range = RegisterRange {
106         from: addr,
107         to: addr + data.len() as u64 - 1,
108     };
109 
110     let overlap = match val_range.overlap_range(&read_range) {
111         Some(overlap) => overlap,
112         None => {
113             error!("calling read_reg_helper with non overlapping range. mmio_register might have a bug");
114             return;
115         }
116     };
117     let val_start_idx = (overlap.from - val_range.from) as usize;
118     let read_start_idx = (overlap.from - read_range.from) as usize;
119     let total_size = (overlap.to - overlap.from) as usize + 1;
120     for i in 0..total_size {
121         data[read_start_idx + i] = val.get_byte(val_start_idx + i);
122     }
123 }
124 
125 /// Interface for register, as seen by guest driver.
126 pub trait RegisterInterface: Send {
127     /// Range of this register.
range(&self) -> RegisterRange128     fn range(&self) -> RegisterRange;
129     /// Handle read.
read(&self, addr: RegisterOffset, data: &mut [u8])130     fn read(&self, addr: RegisterOffset, data: &mut [u8]);
131     /// Handle write.
write(&self, _addr: RegisterOffset, _data: &[u8])132     fn write(&self, _addr: RegisterOffset, _data: &[u8]) {}
133     /// Reset this register to default value.
134     #[allow(dead_code)]
reset(&self)135     fn reset(&self) {}
136 }
137 
138 // Spec for hardware init Read Only Registers.
139 // The value of this register won't change.
140 pub struct StaticRegisterSpec<T: RegisterValue> {
141     pub offset: RegisterOffset,
142     pub value: T,
143 }
144 
145 /// A static register is a register inited by hardware. The value won't change in it's lifetime.
146 /// All functions implemented on this one is thread safe.
147 #[derive(Clone)]
148 pub struct StaticRegister<T>
149 where
150     T: RegisterValue,
151 {
152     spec: &'static StaticRegisterSpec<T>,
153 }
154 
155 impl<T> StaticRegister<T>
156 where
157     T: RegisterValue,
158 {
159     /// Create an new static register from spec.
new(spec: &'static StaticRegisterSpec<T>) -> StaticRegister<T>160     pub fn new(spec: &'static StaticRegisterSpec<T>) -> StaticRegister<T> {
161         StaticRegister { spec }
162     }
163 }
164 
165 impl<T> RegisterInterface for StaticRegister<T>
166 where
167     T: RegisterValue,
168 {
range(&self) -> RegisterRange169     fn range(&self) -> RegisterRange {
170         RegisterRange {
171             from: self.spec.offset,
172             to: self.spec.offset + (size_of::<T>() as u64) - 1,
173         }
174     }
175 
read(&self, addr: RegisterOffset, data: &mut [u8])176     fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
177         let val_range = self.range();
178         read_reg_helper(self.spec.value, val_range, addr, data);
179     }
180 }
181 
182 /// Macro helps to build a static register.
183 #[macro_export]
184 macro_rules! static_register {
185     (ty: $ty:ty,offset: $offset:expr,value: $value:expr,) => {{
186         use $crate::register_space::*;
187         static REG_SPEC: StaticRegisterSpec<$ty> = StaticRegisterSpec::<$ty> {
188             offset: $offset,
189             value: $value,
190         };
191         StaticRegister::new(&REG_SPEC)
192     }};
193 }
194 
195 /// Spec for a regular register. It specifies it's location on register space, guest writable mask
196 /// and guest write to clear mask.
197 pub struct RegisterSpec<T> {
198     pub name: String,
199     pub offset: RegisterOffset,
200     pub reset_value: T,
201     /// Only masked bits could be written by guest.
202     pub guest_writeable_mask: T,
203     /// When write 1 to bits masked, those bits will be cleared. See Xhci spec 5.1
204     /// for more details.
205     pub guest_write_1_to_clear_mask: T,
206 }
207 
208 struct RegisterInner<T: RegisterValue> {
209     spec: RegisterSpec<T>,
210     value: T,
211     write_cb: Option<Box<dyn Fn(T) -> T + Send>>,
212 }
213 
214 /// Register is a thread safe struct. It can be safely changed from any thread.
215 #[derive(Clone)]
216 pub struct Register<T: RegisterValue> {
217     inner: Arc<Mutex<RegisterInner<T>>>,
218 }
219 
220 impl<T: RegisterValue> Register<T> {
new(spec: RegisterSpec<T>, val: T) -> Self221     pub fn new(spec: RegisterSpec<T>, val: T) -> Self {
222         Register {
223             inner: Arc::new(Mutex::new(RegisterInner {
224                 spec,
225                 value: val,
226                 write_cb: None,
227             })),
228         }
229     }
230 
lock(&self) -> MutexGuard<RegisterInner<T>>231     fn lock(&self) -> MutexGuard<RegisterInner<T>> {
232         self.inner.lock()
233     }
234 }
235 
236 // All functions implemented on this one is thread safe.
237 impl<T: RegisterValue> RegisterInterface for Register<T> {
range(&self) -> RegisterRange238     fn range(&self) -> RegisterRange {
239         let locked = self.lock();
240         let spec = &locked.spec;
241         RegisterRange {
242             from: spec.offset,
243             to: spec.offset + (size_of::<T>() as u64) - 1,
244         }
245     }
246 
read(&self, addr: RegisterOffset, data: &mut [u8])247     fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
248         let val_range = self.range();
249         let value = self.lock().value;
250         read_reg_helper(value, val_range, addr, data);
251     }
252 
write(&self, addr: RegisterOffset, data: &[u8])253     fn write(&self, addr: RegisterOffset, data: &[u8]) {
254         let my_range = self.range();
255         let write_range = RegisterRange {
256             from: addr,
257             to: addr + data.len() as u64 - 1,
258         };
259 
260         let overlap = match my_range.overlap_range(&write_range) {
261             Some(range) => range,
262             None => {
263                 error!("write should not be invoked on this register");
264                 return;
265             }
266         };
267         let my_start_idx = (overlap.from - my_range.from) as usize;
268         let write_start_idx = (overlap.from - write_range.from) as usize;
269         let total_size = (overlap.to - overlap.from) as usize + 1;
270 
271         let mut reg_value: T = self.lock().value;
272         let value: &mut [u8] = reg_value.as_bytes_mut();
273         for i in 0..total_size {
274             value[my_start_idx + i] = self.apply_write_masks_to_byte(
275                 value[my_start_idx + i],
276                 data[write_start_idx + i],
277                 my_start_idx + i,
278             );
279         }
280 
281         // A single u64 register is done by write to lower 32 bit and then higher 32 bit. Callback
282         // should only be invoked when higher is written.
283         if my_range.to != overlap.to {
284             self.lock().value = reg_value;
285             return;
286         }
287 
288         // Taking the callback out of register when executing it. This prevent dead lock if
289         // callback want to read current register value.
290         // Note that the only source of callback comes from mmio writing, which is synchronized.
291         let cb = {
292             let mut inner = self.lock();
293             match inner.write_cb.take() {
294                 Some(cb) => cb,
295                 None => {
296                     // Write value if there is no callback.
297                     inner.value = reg_value;
298                     return;
299                 }
300             }
301         };
302         // Callback is invoked without holding any lock.
303         let value = cb(reg_value);
304         let mut inner = self.lock();
305         inner.value = value;
306         inner.write_cb = Some(cb);
307     }
308 
reset(&self)309     fn reset(&self) {
310         let mut locked = self.lock();
311         locked.value = locked.spec.reset_value;
312     }
313 }
314 
315 impl<T: RegisterValue> Register<T> {
316     /// Get current value of this register.
get_value(&self) -> T317     pub fn get_value(&self) -> T {
318         self.lock().value
319     }
320 
321     /// This function apply "write 1 to clear mask" and "guest writeable mask".
322     /// All write operations should go through this, the result of this function
323     /// is the new state of correspoding byte.
apply_write_masks_to_byte(&self, old_byte: u8, write_byte: u8, offset: usize) -> u8324     pub fn apply_write_masks_to_byte(&self, old_byte: u8, write_byte: u8, offset: usize) -> u8 {
325         let locked = self.lock();
326         let spec = &locked.spec;
327         let guest_write_1_to_clear_mask: u64 = spec.guest_write_1_to_clear_mask.into();
328         let guest_writeable_mask: u64 = spec.guest_writeable_mask.into();
329         // Mask with w1c mask.
330         let w1c_mask = (guest_write_1_to_clear_mask >> (offset * 8)) as u8;
331         let val = (!w1c_mask & write_byte) | (w1c_mask & old_byte & !write_byte);
332         // Mask with writable mask.
333         let w_mask = (guest_writeable_mask >> (offset * 8)) as u8;
334         (old_byte & (!w_mask)) | (val & w_mask)
335     }
336 
337     /// Set a callback. It will be invoked when write happens.
set_write_cb<C: 'static + Fn(T) -> T + Send>(&self, callback: C)338     pub fn set_write_cb<C: 'static + Fn(T) -> T + Send>(&self, callback: C) {
339         self.lock().write_cb = Some(Box::new(callback));
340     }
341 
342     /// Set value from device side. Callback won't be invoked.
set_value(&self, val: T)343     pub fn set_value(&self, val: T) {
344         self.lock().value = val;
345     }
346 
347     /// Set masked bits.
set_bits(&self, mask: T)348     pub fn set_bits(&self, mask: T) {
349         self.lock().value.set_bits(mask);
350     }
351 
352     /// Clear masked bits.
clear_bits(&self, mask: T)353     pub fn clear_bits(&self, mask: T) {
354         self.lock().value.clear_bits(mask);
355     }
356 }
357 
358 #[macro_export]
359 macro_rules! register {
360     (
361         name: $name:tt,
362         ty: $ty:ty,
363         offset: $offset:expr,
364         reset_value: $rv:expr,
365         guest_writeable_mask: $mask:expr,
366         guest_write_1_to_clear_mask: $w1tcm:expr,
367     ) => {{
368         use $crate::register_space::*;
369         let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
370             name: String::from($name),
371             offset: $offset,
372             reset_value: $rv,
373             guest_writeable_mask: $mask,
374             guest_write_1_to_clear_mask: $w1tcm,
375         };
376         Register::<$ty>::new(spec, $rv)
377     }};
378     (name: $name:tt, ty: $ty:ty,offset: $offset:expr,reset_value: $rv:expr,) => {{
379         use $crate::register_space::*;
380         let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
381             name: String::from($name),
382             offset: $offset,
383             reset_value: $rv,
384             guest_writeable_mask: !0,
385             guest_write_1_to_clear_mask: 0,
386         };
387         Register::<$ty>::new(spec, $rv)
388     }};
389 }
390 
391 #[macro_export]
392 macro_rules! register_array {
393     (
394         name: $name:tt,
395         ty:
396         $ty:ty,cnt:
397         $cnt:expr,base_offset:
398         $base_offset:expr,stride:
399         $stride:expr,reset_value:
400         $rv:expr,guest_writeable_mask:
401         $gwm:expr,guest_write_1_to_clear_mask:
402         $gw1tcm:expr,
403     ) => {{
404         use $crate::register_space::*;
405         let mut v: Vec<Register<$ty>> = Vec::new();
406         for i in 0..$cnt {
407             let offset = $base_offset + ($stride * i) as RegisterOffset;
408             let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
409                 name: format!("{}-{}", $name, i),
410                 offset,
411                 reset_value: $rv,
412                 guest_writeable_mask: $gwm,
413                 guest_write_1_to_clear_mask: $gw1tcm,
414             };
415             v.push(Register::<$ty>::new(spec, $rv));
416         }
417         v
418     }};
419 }
420 
421 #[cfg(test)]
422 mod tests {
423     use super::*;
424 
425     static REG_SPEC0: StaticRegisterSpec<u8> = StaticRegisterSpec::<u8> {
426         offset: 3,
427         value: 32,
428     };
429 
430     static REG_SPEC1: StaticRegisterSpec<u16> = StaticRegisterSpec::<u16> {
431         offset: 3,
432         value: 32,
433     };
434 
435     #[test]
static_register_basic_test_u8()436     fn static_register_basic_test_u8() {
437         let r = StaticRegister::<u8> { spec: &REG_SPEC0 };
438         let mut data: [u8; 4] = [0, 0, 0, 0];
439         assert_eq!(r.range().from, 3);
440         assert_eq!(r.range().to, 3);
441         r.read(0, &mut data);
442         assert_eq!(data, [0, 0, 0, 32]);
443         r.read(2, &mut data);
444         assert_eq!(data, [0, 32, 0, 32]);
445     }
446 
447     #[test]
static_register_basic_test_u16()448     fn static_register_basic_test_u16() {
449         let r = StaticRegister::<u16> { spec: &REG_SPEC1 };
450         let mut data: [u8; 4] = [0, 0, 0, 0];
451         assert_eq!(r.range().from, 3);
452         assert_eq!(r.range().to, 4);
453         r.read(0, &mut data);
454         assert_eq!(data, [0, 0, 0, 32]);
455         r.read(2, &mut data);
456         assert_eq!(data, [0, 32, 0, 32]);
457     }
458 
459     #[test]
static_register_interface_test()460     fn static_register_interface_test() {
461         let r: Box<dyn RegisterInterface> = Box::new(static_register! {
462             ty: u8,
463             offset: 3,
464             value: 32,
465         });
466         let mut data: [u8; 4] = [0, 0, 0, 0];
467         assert_eq!(r.range().from, 3);
468         assert_eq!(r.range().to, 3);
469         r.read(0, &mut data);
470         assert_eq!(data, [0, 0, 0, 32]);
471         r.read(2, &mut data);
472         assert_eq!(data, [0, 32, 0, 32]);
473     }
474 
475     #[test]
register_basic_rw_test()476     fn register_basic_rw_test() {
477         let r = register! {
478             name: "",
479             ty: u8,
480             offset: 3,
481             reset_value: 0xf1,
482             guest_writeable_mask: 0xff,
483             guest_write_1_to_clear_mask: 0x0,
484         };
485         let mut data: [u8; 4] = [0, 0, 0, 0];
486         assert_eq!(r.range().from, 3);
487         assert_eq!(r.range().to, 3);
488         r.read(0, &mut data);
489         assert_eq!(data, [0, 0, 0, 0xf1]);
490         r.read(2, &mut data);
491         assert_eq!(data, [0, 0xf1, 0, 0xf1]);
492         data = [0, 0, 0, 0xab];
493         r.write(0, &data);
494         assert_eq!(r.get_value(), 0xab);
495         r.reset();
496         assert_eq!(r.get_value(), 0xf1);
497         r.set_value(0xcc);
498         assert_eq!(r.get_value(), 0xcc);
499     }
500 
501     #[test]
register_basic_writeable_mask_test()502     fn register_basic_writeable_mask_test() {
503         let r = register! {
504             name: "",
505             ty: u8,
506             offset: 3,
507             reset_value: 0x0,
508             guest_writeable_mask: 0xf,
509             guest_write_1_to_clear_mask: 0x0,
510         };
511         let mut data: [u8; 4] = [0, 0, 0, 0];
512         assert_eq!(r.range().from, 3);
513         assert_eq!(r.range().to, 3);
514         r.read(0, &mut data);
515         assert_eq!(data, [0, 0, 0, 0]);
516         data = [0, 0, 0, 0xab];
517         r.write(0, &data);
518         assert_eq!(r.get_value(), 0x0b);
519         r.reset();
520         assert_eq!(r.get_value(), 0x0);
521         r.set_value(0xcc);
522         assert_eq!(r.get_value(), 0xcc);
523     }
524 
525     #[test]
register_basic_write_1_to_clear_mask_test()526     fn register_basic_write_1_to_clear_mask_test() {
527         let r = register! {
528             name: "",
529             ty: u8,
530             offset: 3,
531             reset_value: 0xf1,
532             guest_writeable_mask: 0xff,
533             guest_write_1_to_clear_mask: 0xf0,
534         };
535         let mut data: [u8; 4] = [0, 0, 0, 0];
536         assert_eq!(r.range().from, 3);
537         assert_eq!(r.range().to, 3);
538         r.read(0, &mut data);
539         assert_eq!(data, [0, 0, 0, 0xf1]);
540         data = [0, 0, 0, 0xfa];
541         r.write(0, &data);
542         assert_eq!(r.get_value(), 0x0a);
543         r.reset();
544         assert_eq!(r.get_value(), 0xf1);
545         r.set_value(0xcc);
546         assert_eq!(r.get_value(), 0xcc);
547     }
548 
549     #[test]
register_basic_write_1_to_clear_mask_test_u32()550     fn register_basic_write_1_to_clear_mask_test_u32() {
551         let r = register! {
552             name: "",
553             ty: u32,
554             offset: 0,
555             reset_value: 0xfff1,
556             guest_writeable_mask: 0xff,
557             guest_write_1_to_clear_mask: 0xf0,
558         };
559         let mut data: [u8; 4] = [0, 0, 0, 0];
560         assert_eq!(r.range().from, 0);
561         assert_eq!(r.range().to, 3);
562         r.read(0, &mut data);
563         assert_eq!(data, [0xf1, 0xff, 0, 0]);
564         data = [0xfa, 0, 0, 0];
565         r.write(0, &data);
566         assert_eq!(r.get_value(), 0xff0a);
567         r.reset();
568         assert_eq!(r.get_value(), 0xfff1);
569         r.set_value(0xcc);
570         assert_eq!(r.get_value(), 0xcc);
571     }
572 
573     #[test]
register_callback_test()574     fn register_callback_test() {
575         let state = Arc::new(Mutex::new(0u8));
576         let r = register! {
577             name: "",
578             ty: u8,
579             offset: 3,
580             reset_value: 0xf1,
581             guest_writeable_mask: 0xff,
582             guest_write_1_to_clear_mask: 0xf0,
583         };
584 
585         let s2 = state.clone();
586         r.set_write_cb(move |val: u8| {
587             *s2.lock() = val;
588             val
589         });
590         let data: [u8; 4] = [0, 0, 0, 0xff];
591         r.write(0, &data);
592         assert_eq!(*state.lock(), 0xf);
593         r.set_value(0xab);
594         assert_eq!(*state.lock(), 0xf);
595         let data: [u8; 1] = [0xfc];
596         r.write(3, &data);
597         assert_eq!(*state.lock(), 0xc);
598     }
599 }
600