Skip to content

Commit ddf15c5

Browse files
Abstract the MCR and MRC operations.
1 parent ce7e6b1 commit ddf15c5

File tree

7 files changed

+160
-78
lines changed

7 files changed

+160
-78
lines changed

cortex-r/src/register/armv8r/cbar.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11
//! Code for the *Configuration Base Address Register*
22
3+
use crate::register::{SysReg, SysRegRead};
4+
35
/// The *Configuration Base Address Register* (CBAR)
46
#[derive(Clone, Copy, PartialEq, Eq)]
57
pub struct Cbar(u32);
68

9+
impl SysReg for Cbar {
10+
const CP: u32 = 15;
11+
const CRN: u32 = 15;
12+
const OP1: u32 = 1;
13+
const CRM: u32 = 3;
14+
const OP2: u32 = 0;
15+
}
16+
17+
impl SysRegRead for Cbar {}
18+
719
impl Cbar {
820
/// Reads the *Configuration Base Address Register*
921
#[inline]
1022
pub fn read() -> Cbar {
11-
let r: u32;
12-
#[cfg(target_arch = "arm")]
13-
unsafe {
14-
core::arch::asm!("mrc p15, 1, {}, c15, c3, 0", out(reg) r, options(nomem, nostack, preserves_flags));
15-
}
16-
#[cfg(not(target_arch = "arm"))]
17-
{
18-
r = 0;
19-
}
20-
Self(r)
23+
// Safety: this read has no side-effects
24+
unsafe { Self(<Self as SysRegRead>::read_raw()) }
2125
}
2226

2327
/// Get the periphbase address

cortex-r/src/register/armv8r/hactlr.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Code for managing the *Hyp Auxiliary Control Register*
22
3+
use crate::register::{SysReg, SysRegRead, SysRegWrite};
4+
35
/// The *Hyp Auxiliary Control Register* (HACTRL)
46
#[bitbybit::bitfield(u32)]
57
pub struct Hactlr {
@@ -33,31 +35,33 @@ pub struct Hactlr {
3335
cpuactlr: bool,
3436
}
3537

38+
impl SysReg for Hactlr {
39+
const CP: u32 = 15;
40+
const CRN: u32 = 1;
41+
const OP1: u32 = 4;
42+
const CRM: u32 = 0;
43+
const OP2: u32 = 1;
44+
}
45+
46+
impl SysRegRead for Hactlr {}
47+
48+
impl SysRegWrite for Hactlr {}
49+
3650
impl Hactlr {
3751
/// Reads the *Hyp Auxiliary Control Register*
3852
#[inline]
3953
pub fn read() -> Hactlr {
40-
let r: u32;
4154
// Safety: Reading this register has no side-effects and is atomic
42-
#[cfg(target_arch = "arm")]
43-
unsafe {
44-
core::arch::asm!("mrc p15, 4, {}, c1, c0, 1", out(reg) r, options(nomem, nostack, preserves_flags));
45-
}
46-
#[cfg(not(target_arch = "arm"))]
47-
{
48-
r = 0;
49-
}
50-
Self::new_with_raw_value(r)
55+
unsafe { Self::new_with_raw_value(<Self as SysRegRead>::read_raw()) }
5156
}
5257

5358
/// Write to the *Hyp Auxiliary Control Register*
5459
#[inline]
55-
pub fn write(_value: Self) {
60+
pub fn write(value: Self) {
5661
// Safety: Writing this register is atomic
57-
#[cfg(target_arch = "arm")]
5862
unsafe {
59-
core::arch::asm!("mcr p15, 4, {}, c1, c0, 1", in(reg) _value.raw_value(), options(nomem, nostack, preserves_flags));
60-
};
63+
<Self as SysRegWrite>::write_raw(value.raw_value());
64+
}
6165
}
6266

6367
/// Modify the *Hyp Auxiliary Control Register*

cortex-r/src/register/armv8r/hvbar.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Code for the *Hyp Vector Base Address Register*
22
3+
use crate::register::{SysReg, SysRegRead, SysRegWrite};
4+
35
/// The *Hyp Vector Base Address Register* (Hvbar)
46
///
57
/// There is no `modify` method because this register holds a single 32-bit address.
@@ -9,22 +11,24 @@
911
#[repr(transparent)]
1012
pub struct Hvbar(*mut u32);
1113

14+
impl SysReg for Hvbar {
15+
const CP: u32 = 15;
16+
const CRN: u32 = 12;
17+
const OP1: u32 = 4;
18+
const CRM: u32 = 0;
19+
const OP2: u32 = 0;
20+
}
21+
22+
impl SysRegRead for Hvbar {}
23+
24+
impl SysRegWrite for Hvbar {}
25+
1226
impl Hvbar {
1327
/// Reads the *Hyp Vector Base Address Register*
14-
///
15-
/// Will cause an exception unless you are in EL2.
1628
#[inline]
1729
pub fn read() -> Hvbar {
18-
let r: usize;
19-
#[cfg(target_arch = "arm")]
20-
unsafe {
21-
core::arch::asm!("mrc p15, 4, {}, c12, c0, 0", out(reg) r, options(nomem, nostack, preserves_flags));
22-
}
23-
#[cfg(not(target_arch = "arm"))]
24-
{
25-
r = 0;
26-
}
27-
Self(r as *mut u32)
30+
// Safety: Reading this register has no side-effects and is atomic
31+
unsafe { Self(<Self as SysRegRead>::read_raw() as *mut u32) }
2832
}
2933

3034
/// Write to the *Hyp Vector Base Address Register*
@@ -34,12 +38,11 @@ impl Hvbar {
3438
/// You must supply a correctly-aligned address of a valid Arm Cortex-R
3539
/// Vector Table.
3640
#[inline]
37-
pub fn write(_value: Self) {
41+
pub unsafe fn write(value: Self) {
3842
// Safety: Writing this register is atomic
39-
#[cfg(target_arch = "arm")]
4043
unsafe {
41-
core::arch::asm!("mcr p15, 0, {}, c12, c0, 0", in(reg) _value.0, options(nomem, nostack, preserves_flags));
42-
};
44+
<Self as SysRegWrite>::write_raw(value.0 as u32);
45+
}
4346
}
4447
}
4548

cortex-r/src/register/armv8r/vbar.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
//! Code for the *Vector Base Address Register*
22
3+
use crate::register::{SysReg, SysRegRead, SysRegWrite};
4+
35
/// The *Vector Base Address Register* (VBAR)
46
///
57
/// There is no `modify` method because this register holds a single 32-bit address.
68
#[derive(Clone, Copy, PartialEq, Eq)]
79
#[repr(transparent)]
810
pub struct Vbar(pub *mut u32);
911

12+
impl SysReg for Vbar {
13+
const CP: u32 = 15;
14+
const CRN: u32 = 12;
15+
const OP1: u32 = 0;
16+
const CRM: u32 = 0;
17+
const OP2: u32 = 0;
18+
}
19+
20+
impl SysRegRead for Vbar {}
21+
22+
impl SysRegWrite for Vbar {}
23+
1024
impl Vbar {
1125
/// Reads the *Vector Base Address Register*
1226
#[inline]
1327
pub fn read() -> Vbar {
14-
let r: usize;
15-
#[cfg(target_arch = "arm")]
16-
unsafe {
17-
core::arch::asm!("mrc p15, 0, {}, c12, c0, 0", out(reg) r, options(nomem, nostack, preserves_flags));
18-
}
19-
#[cfg(not(target_arch = "arm"))]
20-
{
21-
r = 0;
22-
}
23-
Self(r as *mut u32)
28+
// Safety: Reading this register has no side-effects and is atomic
29+
unsafe { Self(<Self as SysRegRead>::read_raw() as *mut u32) }
2430
}
2531

2632
/// Write to the *Vector Base Address Register*
@@ -30,12 +36,11 @@ impl Vbar {
3036
/// You must supply a correctly-aligned address of a valid Arm Cortex-R
3137
/// Vector Table.
3238
#[inline]
33-
pub unsafe fn write(_value: Self) {
39+
pub unsafe fn write(value: Self) {
3440
// Safety: Writing this register is atomic
35-
#[cfg(target_arch = "arm")]
3641
unsafe {
37-
core::arch::asm!("mcr p15, 0, {}, c12, c0, 0", in(reg) _value.0, options(nomem, nostack, preserves_flags));
38-
};
42+
<Self as SysRegWrite>::write_raw(value.0 as u32);
43+
}
3944
}
4045
}
4146

cortex-r/src/register/midr.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
use arbitrary_int::{u12, u4};
44

5+
use super::{SysReg, SysRegRead};
6+
57
/// The *Main ID Register* (MIDR)
68
#[bitbybit::bitfield(u32)]
79
pub struct Midr {
@@ -22,21 +24,22 @@ pub struct Midr {
2224
rev: u4,
2325
}
2426

27+
impl SysReg for Midr {
28+
const CP: u32 = 15;
29+
const CRN: u32 = 0;
30+
const OP1: u32 = 0;
31+
const CRM: u32 = 0;
32+
const OP2: u32 = 0;
33+
}
34+
35+
impl SysRegRead for Midr {}
36+
2537
impl Midr {
2638
/// Reads the *Main ID Register*
2739
#[inline]
2840
pub fn read() -> Midr {
29-
let r: u32;
3041
// Safety: Reading this register has no side-effects and is atomic
31-
#[cfg(target_arch = "arm")]
32-
unsafe {
33-
core::arch::asm!("mrc p15, 0, {}, c0, c0, 0", out(reg) r, options(nomem, nostack, preserves_flags));
34-
}
35-
#[cfg(not(target_arch = "arm"))]
36-
{
37-
r = 0;
38-
}
39-
Self::new_with_raw_value(r)
42+
unsafe { Self::new_with_raw_value(<Self as SysRegRead>::read_raw()) }
4043
}
4144
}
4245

cortex-r/src/register/mod.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,66 @@ mod armv8r;
1818
#[cfg(arm_architecture = "v8-r")]
1919
pub use armv8r::*;
2020

21+
/// Describes a System Register
22+
trait SysReg {
23+
/// Which Co-Processor (e.g. 15 for CP15) is this register in?
24+
const CP: u32;
25+
/// Which CRn argument (e.g. 0 for c0) accesses this register
26+
const CRN: u32;
27+
/// Which OP1 argument accesses this register
28+
const OP1: u32;
29+
/// Which CRm argument (e.g. 0 for c0) accesses this register
30+
const CRM: u32;
31+
/// Which OP2 argument accesses this register
32+
const OP2: u32;
33+
}
34+
35+
/// Readable System Registers
36+
trait SysRegRead: SysReg {
37+
#[inline]
38+
unsafe fn read_raw() -> u32 {
39+
let r: u32;
40+
#[cfg(target_arch = "arm")]
41+
unsafe {
42+
core::arch::asm!(
43+
"mrc p{cp}, {op1}, {reg}, c{crn}, c{crm}, {op2}",
44+
cp = const Self::CP,
45+
op1 = const Self::OP1,
46+
reg = out(reg) r,
47+
crn = const Self::CRN,
48+
crm = const Self::CRM,
49+
op2 = const Self::OP2,
50+
options(nomem, nostack, preserves_flags)
51+
);
52+
}
53+
#[cfg(not(target_arch = "arm"))]
54+
{
55+
r = 0;
56+
}
57+
r
58+
}
59+
}
60+
61+
/// Writable System Registers
62+
trait SysRegWrite: SysReg {
63+
#[inline]
64+
unsafe fn write_raw(_value: u32) {
65+
#[cfg(target_arch = "arm")]
66+
unsafe {
67+
core::arch::asm!(
68+
"mcr p{cp}, {op1}, {reg}, c{crn}, c{crm}, {op2}",
69+
cp = const Self::CP,
70+
op1 = const Self::OP1,
71+
reg = in(reg) _value,
72+
crn = const Self::CRN,
73+
crm = const Self::CRM,
74+
op2 = const Self::OP2,
75+
options(nomem, nostack, preserves_flags)
76+
);
77+
}
78+
}
79+
}
80+
2181
// TODO:
2282

2383
// Multiprocessor Affinity Register (MPIDR)

cortex-r/src/register/sctlr.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Code for managing the *System Control Register*
22
3+
use super::{SysReg, SysRegRead, SysRegWrite};
4+
35
/// The *System Control Register* (SCTLR)
46
#[bitbybit::bitfield(u32)]
57
pub struct Sctlr {
@@ -53,31 +55,32 @@ pub struct Sctlr {
5355
m: bool,
5456
}
5557

58+
impl SysReg for Sctlr {
59+
const CP: u32 = 15;
60+
const CRN: u32 = 1;
61+
const OP1: u32 = 0;
62+
const CRM: u32 = 0;
63+
const OP2: u32 = 0;
64+
}
65+
66+
impl SysRegRead for Sctlr {}
67+
68+
impl SysRegWrite for Sctlr {}
69+
5670
impl Sctlr {
5771
/// Reads the *System Control Register*
5872
#[inline]
5973
pub fn read() -> Self {
60-
let r: u32;
61-
// Safety: Reading this register has no side-effects and is atomic
62-
#[cfg(target_arch = "arm")]
63-
unsafe {
64-
core::arch::asm!("mrc p15, 0, {}, c1, c0, 0", out(reg) r, options(nomem, nostack, preserves_flags));
65-
}
66-
#[cfg(not(target_arch = "arm"))]
67-
{
68-
r = 0;
69-
}
70-
Self::new_with_raw_value(r)
74+
unsafe { Self::new_with_raw_value(<Self as SysRegRead>::read_raw()) }
7175
}
7276

7377
/// Write to the *System Control Register*
7478
#[inline]
7579
pub fn write(_value: Self) {
7680
// Safety: Writing this register is atomic
77-
#[cfg(target_arch = "arm")]
7881
unsafe {
79-
core::arch::asm!("mcr p15, 0, {}, c1, c0, 0", in(reg) _value.raw_value(), options(nomem, nostack, preserves_flags));
80-
};
82+
<Self as SysRegWrite>::write_raw(_value.raw_value());
83+
}
8184
}
8285

8386
/// Modify the *System Control Register*

0 commit comments

Comments
 (0)