Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/register_space/register.rs
5394 views
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::FromBytes;
18
use zerocopy::IntoBytes;
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 {
32
fn cmp(&self, other: &RegisterRange) -> Ordering {
33
self.from.cmp(&other.from)
34
}
35
}
36
37
impl PartialOrd for RegisterRange {
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.
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.
64
pub 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
}
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.
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.
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.
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.
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
{
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]
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
pending_value: Option<T>,
212
write_cb: Option<Box<dyn Fn(T) -> T + Send>>,
213
}
214
215
impl<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)]
246
pub struct Register<T: RegisterValue> {
247
inner: Arc<Mutex<RegisterInner<T>>>,
248
}
249
250
impl<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.
268
impl<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
349
impl<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]
393
macro_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]
426
macro_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)]
456
mod 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
}
634
635