devices/register_space/
register.rs

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
5use std::boxed::Box;
6use std::cmp::max;
7use std::cmp::min;
8use std::cmp::Ord;
9use std::cmp::Ordering;
10use std::cmp::PartialOrd;
11use std::mem::size_of;
12use std::sync::Arc;
13use std::sync::MutexGuard;
14
15use base::error;
16use sync::Mutex;
17use zerocopy::FromBytes;
18use zerocopy::IntoBytes;
19
20/// Type of offset in the register space.
21pub 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)]
26pub struct RegisterRange {
27    pub from: RegisterOffset,
28    pub to: RegisterOffset,
29}
30
31impl Ord for RegisterRange {
32    fn cmp(&self, other: &RegisterRange) -> Ordering {
33        self.from.cmp(&other.from)
34    }
35}
36
37impl PartialOrd for RegisterRange {
38    fn partial_cmp(&self, other: &RegisterRange) -> Option<Ordering> {
39        Some(self.cmp(other))
40    }
41}
42
43impl RegisterRange {
44    /// Return true if those range overlaps.
45    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).
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.
64pub trait RegisterValue:
65    'static
66    + Into<u64>
67    + Clone
68    + FromBytes
69    + IntoBytes
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.
79    fn get_byte(&self, offset: usize) -> u8 {
80        let val: u64 = (*self).into();
81        (val >> (offset * 8)) as u8
82    }
83    // Set masked bits.
84    fn set_bits(&mut self, mask: Self) {
85        *self = *self | mask;
86    }
87    // Clear masked bits.
88    fn clear_bits(&mut self, mask: Self) {
89        *self = *self & (!mask);
90    }
91}
92impl RegisterValue for u8 {}
93impl RegisterValue for u16 {}
94impl RegisterValue for u32 {}
95impl 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.
99fn 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.
126pub trait RegisterInterface: Send {
127    /// Range of this register.
128    fn range(&self) -> RegisterRange;
129    /// Handle read.
130    fn read(&self, addr: RegisterOffset, data: &mut [u8]);
131    /// Handle write.
132    fn write(&self, _addr: RegisterOffset, _data: &[u8]) {}
133    /// Reset this register to default value.
134    #[allow(dead_code)]
135    fn reset(&self) {}
136}
137
138// Spec for hardware init Read Only Registers.
139// The value of this register won't change.
140pub 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)]
148pub struct StaticRegister<T>
149where
150    T: RegisterValue,
151{
152    spec: &'static StaticRegisterSpec<T>,
153}
154
155impl<T> StaticRegister<T>
156where
157    T: RegisterValue,
158{
159    /// Create an new static register from spec.
160    pub fn new(spec: &'static StaticRegisterSpec<T>) -> StaticRegister<T> {
161        StaticRegister { spec }
162    }
163}
164
165impl<T> RegisterInterface for StaticRegister<T>
166where
167    T: RegisterValue,
168{
169    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
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]
184macro_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.
197pub 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
208struct RegisterInner<T: RegisterValue> {
209    spec: RegisterSpec<T>,
210    value: T,
211    pending_value: Option<T>,
212    write_cb: Option<Box<dyn Fn(T) -> T + Send>>,
213}
214
215impl<T: RegisterValue> RegisterInner<T> {
216    fn value(&self) -> T {
217        self.value
218    }
219
220    fn pending_value(&self) -> T {
221        match self.pending_value {
222            Some(pending_value) => pending_value,
223            None => self.value,
224        }
225    }
226
227    fn set(&mut self, value: T) {
228        self.pending_value = Some(value);
229    }
230
231    fn commit(&mut self) {
232        if let Some(value) = self.pending_value {
233            self.value = value;
234            self.pending_value = None;
235        }
236    }
237
238    fn set_and_commit(&mut self, value: T) {
239        self.set(value);
240        self.commit();
241    }
242}
243
244/// Register is a thread safe struct. It can be safely changed from any thread.
245#[derive(Clone)]
246pub struct Register<T: RegisterValue> {
247    inner: Arc<Mutex<RegisterInner<T>>>,
248}
249
250impl<T: RegisterValue> Register<T> {
251    pub fn new(spec: RegisterSpec<T>, val: T) -> Self {
252        Register {
253            inner: Arc::new(Mutex::new(RegisterInner {
254                spec,
255                value: val,
256                pending_value: None,
257                write_cb: None,
258            })),
259        }
260    }
261
262    fn lock(&self) -> MutexGuard<RegisterInner<T>> {
263        self.inner.lock()
264    }
265}
266
267// All functions implemented on this one is thread safe.
268impl<T: RegisterValue> RegisterInterface for Register<T> {
269    fn range(&self) -> RegisterRange {
270        let locked = self.lock();
271        let spec = &locked.spec;
272        RegisterRange {
273            from: spec.offset,
274            to: spec.offset + (size_of::<T>() as u64) - 1,
275        }
276    }
277
278    fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
279        let val_range = self.range();
280        let value = self.lock().value();
281        read_reg_helper(value, val_range, addr, data);
282    }
283
284    fn write(&self, addr: RegisterOffset, data: &[u8]) {
285        let my_range = self.range();
286        let write_range = RegisterRange {
287            from: addr,
288            to: addr + data.len() as u64 - 1,
289        };
290
291        let overlap = match my_range.overlap_range(&write_range) {
292            Some(range) => range,
293            None => {
294                error!("write should not be invoked on this register");
295                return;
296            }
297        };
298        let my_start_idx = (overlap.from - my_range.from) as usize;
299        let write_start_idx = (overlap.from - write_range.from) as usize;
300        let total_size = (overlap.to - overlap.from) as usize + 1;
301
302        let mut reg_value: T = self.lock().pending_value();
303        let value: &mut [u8] = reg_value.as_mut_bytes();
304        for i in 0..total_size {
305            value[my_start_idx + i] = self.apply_write_masks_to_byte(
306                value[my_start_idx + i],
307                data[write_start_idx + i],
308                my_start_idx + i,
309            );
310        }
311
312        // A single u64 register is done by write to lower 32 bit and then higher 32 bit. Callback
313        // should only be invoked when higher is written.
314        if my_range.to != overlap.to {
315            // The value of this register won't be updated until the higher 32 bit arrives, because
316            // the intermediate value should not be observed by any thread.
317            self.lock().set(reg_value);
318            return;
319        }
320
321        // Taking the callback out of register when executing it. This prevent dead lock if
322        // callback want to read current register value.
323        // Note that the only source of callback comes from mmio writing, which is synchronized.
324        let cb = {
325            let mut inner = self.lock();
326            match inner.write_cb.take() {
327                Some(cb) => cb,
328                None => {
329                    // Write value if there is no callback.
330                    inner.set_and_commit(reg_value);
331                    return;
332                }
333            }
334        };
335        // Callback is invoked without holding any lock.
336        let value = cb(reg_value);
337        let mut inner = self.lock();
338        inner.set_and_commit(value);
339        inner.write_cb = Some(cb);
340    }
341
342    fn reset(&self) {
343        let mut locked = self.lock();
344        let reset_value = locked.spec.reset_value;
345        locked.set_and_commit(reset_value);
346    }
347}
348
349impl<T: RegisterValue> Register<T> {
350    /// Get current value of this register.
351    pub fn get_value(&self) -> T {
352        self.lock().value
353    }
354
355    /// This function apply "write 1 to clear mask" and "guest writeable mask".
356    /// All write operations should go through this, the result of this function
357    /// is the new state of correspoding byte.
358    pub fn apply_write_masks_to_byte(&self, old_byte: u8, write_byte: u8, offset: usize) -> u8 {
359        let locked = self.lock();
360        let spec = &locked.spec;
361        let guest_write_1_to_clear_mask: u64 = spec.guest_write_1_to_clear_mask.into();
362        let guest_writeable_mask: u64 = spec.guest_writeable_mask.into();
363        // Mask with w1c mask.
364        let w1c_mask = (guest_write_1_to_clear_mask >> (offset * 8)) as u8;
365        let val = (!w1c_mask & write_byte) | (w1c_mask & old_byte & !write_byte);
366        // Mask with writable mask.
367        let w_mask = (guest_writeable_mask >> (offset * 8)) as u8;
368        (old_byte & (!w_mask)) | (val & w_mask)
369    }
370
371    /// Set a callback. It will be invoked when write happens.
372    pub fn set_write_cb<C: 'static + Fn(T) -> T + Send>(&self, callback: C) {
373        self.lock().write_cb = Some(Box::new(callback));
374    }
375
376    /// Set value from device side. Callback won't be invoked.
377    pub fn set_value(&self, val: T) {
378        self.lock().value = val;
379    }
380
381    /// Set masked bits.
382    pub fn set_bits(&self, mask: T) {
383        self.lock().value.set_bits(mask);
384    }
385
386    /// Clear masked bits.
387    pub fn clear_bits(&self, mask: T) {
388        self.lock().value.clear_bits(mask);
389    }
390}
391
392#[macro_export]
393macro_rules! register {
394    (
395        name: $name:tt,
396        ty: $ty:ty,
397        offset: $offset:expr,
398        reset_value: $rv:expr,
399        guest_writeable_mask: $mask:expr,
400        guest_write_1_to_clear_mask: $w1tcm:expr,
401    ) => {{
402        use $crate::register_space::*;
403        let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
404            name: String::from($name),
405            offset: $offset,
406            reset_value: $rv,
407            guest_writeable_mask: $mask,
408            guest_write_1_to_clear_mask: $w1tcm,
409        };
410        Register::<$ty>::new(spec, $rv)
411    }};
412    (name: $name:tt, ty: $ty:ty,offset: $offset:expr,reset_value: $rv:expr,) => {{
413        use $crate::register_space::*;
414        let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
415            name: String::from($name),
416            offset: $offset,
417            reset_value: $rv,
418            guest_writeable_mask: !0,
419            guest_write_1_to_clear_mask: 0,
420        };
421        Register::<$ty>::new(spec, $rv)
422    }};
423}
424
425#[macro_export]
426macro_rules! register_array {
427    (
428        name: $name:tt,
429        ty:
430        $ty:ty,cnt:
431        $cnt:expr,base_offset:
432        $base_offset:expr,stride:
433        $stride:expr,reset_value:
434        $rv:expr,guest_writeable_mask:
435        $gwm:expr,guest_write_1_to_clear_mask:
436        $gw1tcm:expr,
437    ) => {{
438        use $crate::register_space::*;
439        let mut v: Vec<Register<$ty>> = Vec::new();
440        for i in 0..$cnt {
441            let offset = $base_offset + ($stride * i) as RegisterOffset;
442            let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
443                name: format!("{}-{}", $name, i),
444                offset,
445                reset_value: $rv,
446                guest_writeable_mask: $gwm,
447                guest_write_1_to_clear_mask: $gw1tcm,
448            };
449            v.push(Register::<$ty>::new(spec, $rv));
450        }
451        v
452    }};
453}
454
455#[cfg(test)]
456mod tests {
457    use super::*;
458
459    static REG_SPEC0: StaticRegisterSpec<u8> = StaticRegisterSpec::<u8> {
460        offset: 3,
461        value: 32,
462    };
463
464    static REG_SPEC1: StaticRegisterSpec<u16> = StaticRegisterSpec::<u16> {
465        offset: 3,
466        value: 32,
467    };
468
469    #[test]
470    fn static_register_basic_test_u8() {
471        let r = StaticRegister::<u8> { spec: &REG_SPEC0 };
472        let mut data: [u8; 4] = [0, 0, 0, 0];
473        assert_eq!(r.range().from, 3);
474        assert_eq!(r.range().to, 3);
475        r.read(0, &mut data);
476        assert_eq!(data, [0, 0, 0, 32]);
477        r.read(2, &mut data);
478        assert_eq!(data, [0, 32, 0, 32]);
479    }
480
481    #[test]
482    fn static_register_basic_test_u16() {
483        let r = StaticRegister::<u16> { spec: &REG_SPEC1 };
484        let mut data: [u8; 4] = [0, 0, 0, 0];
485        assert_eq!(r.range().from, 3);
486        assert_eq!(r.range().to, 4);
487        r.read(0, &mut data);
488        assert_eq!(data, [0, 0, 0, 32]);
489        r.read(2, &mut data);
490        assert_eq!(data, [0, 32, 0, 32]);
491    }
492
493    #[test]
494    fn static_register_interface_test() {
495        let r: Box<dyn RegisterInterface> = Box::new(static_register! {
496            ty: u8,
497            offset: 3,
498            value: 32,
499        });
500        let mut data: [u8; 4] = [0, 0, 0, 0];
501        assert_eq!(r.range().from, 3);
502        assert_eq!(r.range().to, 3);
503        r.read(0, &mut data);
504        assert_eq!(data, [0, 0, 0, 32]);
505        r.read(2, &mut data);
506        assert_eq!(data, [0, 32, 0, 32]);
507    }
508
509    #[test]
510    fn register_basic_rw_test() {
511        let r = register! {
512            name: "",
513            ty: u8,
514            offset: 3,
515            reset_value: 0xf1,
516            guest_writeable_mask: 0xff,
517            guest_write_1_to_clear_mask: 0x0,
518        };
519        let mut data: [u8; 4] = [0, 0, 0, 0];
520        assert_eq!(r.range().from, 3);
521        assert_eq!(r.range().to, 3);
522        r.read(0, &mut data);
523        assert_eq!(data, [0, 0, 0, 0xf1]);
524        r.read(2, &mut data);
525        assert_eq!(data, [0, 0xf1, 0, 0xf1]);
526        data = [0, 0, 0, 0xab];
527        r.write(0, &data);
528        assert_eq!(r.get_value(), 0xab);
529        r.reset();
530        assert_eq!(r.get_value(), 0xf1);
531        r.set_value(0xcc);
532        assert_eq!(r.get_value(), 0xcc);
533    }
534
535    #[test]
536    fn register_basic_writeable_mask_test() {
537        let r = register! {
538            name: "",
539            ty: u8,
540            offset: 3,
541            reset_value: 0x0,
542            guest_writeable_mask: 0xf,
543            guest_write_1_to_clear_mask: 0x0,
544        };
545        let mut data: [u8; 4] = [0, 0, 0, 0];
546        assert_eq!(r.range().from, 3);
547        assert_eq!(r.range().to, 3);
548        r.read(0, &mut data);
549        assert_eq!(data, [0, 0, 0, 0]);
550        data = [0, 0, 0, 0xab];
551        r.write(0, &data);
552        assert_eq!(r.get_value(), 0x0b);
553        r.reset();
554        assert_eq!(r.get_value(), 0x0);
555        r.set_value(0xcc);
556        assert_eq!(r.get_value(), 0xcc);
557    }
558
559    #[test]
560    fn register_basic_write_1_to_clear_mask_test() {
561        let r = register! {
562            name: "",
563            ty: u8,
564            offset: 3,
565            reset_value: 0xf1,
566            guest_writeable_mask: 0xff,
567            guest_write_1_to_clear_mask: 0xf0,
568        };
569        let mut data: [u8; 4] = [0, 0, 0, 0];
570        assert_eq!(r.range().from, 3);
571        assert_eq!(r.range().to, 3);
572        r.read(0, &mut data);
573        assert_eq!(data, [0, 0, 0, 0xf1]);
574        data = [0, 0, 0, 0xfa];
575        r.write(0, &data);
576        assert_eq!(r.get_value(), 0x0a);
577        r.reset();
578        assert_eq!(r.get_value(), 0xf1);
579        r.set_value(0xcc);
580        assert_eq!(r.get_value(), 0xcc);
581    }
582
583    #[test]
584    fn register_basic_write_1_to_clear_mask_test_u32() {
585        let r = register! {
586            name: "",
587            ty: u32,
588            offset: 0,
589            reset_value: 0xfff1,
590            guest_writeable_mask: 0xff,
591            guest_write_1_to_clear_mask: 0xf0,
592        };
593        let mut data: [u8; 4] = [0, 0, 0, 0];
594        assert_eq!(r.range().from, 0);
595        assert_eq!(r.range().to, 3);
596        r.read(0, &mut data);
597        assert_eq!(data, [0xf1, 0xff, 0, 0]);
598        data = [0xfa, 0, 0, 0];
599        r.write(0, &data);
600        assert_eq!(r.get_value(), 0xff0a);
601        r.reset();
602        assert_eq!(r.get_value(), 0xfff1);
603        r.set_value(0xcc);
604        assert_eq!(r.get_value(), 0xcc);
605    }
606
607    #[test]
608    fn register_callback_test() {
609        let state = Arc::new(Mutex::new(0u8));
610        let r = register! {
611            name: "",
612            ty: u8,
613            offset: 3,
614            reset_value: 0xf1,
615            guest_writeable_mask: 0xff,
616            guest_write_1_to_clear_mask: 0xf0,
617        };
618
619        let s2 = state.clone();
620        r.set_write_cb(move |val: u8| {
621            *s2.lock() = val;
622            val
623        });
624        let data: [u8; 4] = [0, 0, 0, 0xff];
625        r.write(0, &data);
626        assert_eq!(*state.lock(), 0xf);
627        r.set_value(0xab);
628        assert_eq!(*state.lock(), 0xf);
629        let data: [u8; 1] = [0xfc];
630        r.write(3, &data);
631        assert_eq!(*state.lock(), 0xc);
632    }
633}