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    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)]
216pub struct Register<T: RegisterValue> {
217    inner: Arc<Mutex<RegisterInner<T>>>,
218}
219
220impl<T: RegisterValue> Register<T> {
221    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
231    fn lock(&self) -> MutexGuard<RegisterInner<T>> {
232        self.inner.lock()
233    }
234}
235
236// All functions implemented on this one is thread safe.
237impl<T: RegisterValue> RegisterInterface for Register<T> {
238    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
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
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_mut_bytes();
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
309    fn reset(&self) {
310        let mut locked = self.lock();
311        locked.value = locked.spec.reset_value;
312    }
313}
314
315impl<T: RegisterValue> Register<T> {
316    /// Get current value of this register.
317    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.
324    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.
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.
343    pub fn set_value(&self, val: T) {
344        self.lock().value = val;
345    }
346
347    /// Set masked bits.
348    pub fn set_bits(&self, mask: T) {
349        self.lock().value.set_bits(mask);
350    }
351
352    /// Clear masked bits.
353    pub fn clear_bits(&self, mask: T) {
354        self.lock().value.clear_bits(mask);
355    }
356}
357
358#[macro_export]
359macro_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]
392macro_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)]
422mod 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]
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]
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]
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]
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]
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]
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]
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]
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}