Skip to content

Commit 3ba794a

Browse files
committed
Dedicated EL2 examples.
* Adds more Hyp register details. * A bunch of fixes to the docs * Makes sure CI actually runs these and the SMP examples
1 parent a7d4d1c commit 3ba794a

72 files changed

Lines changed: 2579 additions & 150 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,50 @@ jobs:
406406
export PATH=/opt/qemu/bin:$PATH
407407
just test-qemu-v8r
408408
409+
# Run some SMP programs in QEMU 9 for Armv8-R
410+
# These tests build with nightly as pinned by the rust-toolchain.toml file, because they include Tier 3 targets
411+
test-qemu-v8r-smp:
412+
runs-on: ubuntu-24.04
413+
needs: [build-all]
414+
steps:
415+
- name: Checkout
416+
uses: actions/checkout@v4
417+
- name: Install Just
418+
uses: taiki-e/install-action@just
419+
- name: Install Dependencies
420+
run: |
421+
sudo apt-get -y update
422+
sudo apt-get -y install libpixman-1-0 libfdt1 libglib2.0-0t64
423+
- name: Install custom QEMU into /opt
424+
run: |
425+
curl -sSL https://github.com/jonathanpallant/qemu9-for-ubuntu-2404/releases/download/qemu-9.2.3%2Bbuild0/qemu-9.2.3-ubuntu-24.04.tar.gz | sudo tar xvzf - -C /
426+
- name: Run tests in QEMU
427+
run: |
428+
export PATH=/opt/qemu/bin:$PATH
429+
just test-qemu-v8r-smp
430+
431+
# Run some EL2 programs in QEMU 9 for Armv8-R
432+
# These tests build with nightly as pinned by the rust-toolchain.toml file, because they include Tier 3 targets
433+
test-qemu-v8r-el2:
434+
runs-on: ubuntu-24.04
435+
needs: [build-all]
436+
steps:
437+
- name: Checkout
438+
uses: actions/checkout@v4
439+
- name: Install Just
440+
uses: taiki-e/install-action@just
441+
- name: Install Dependencies
442+
run: |
443+
sudo apt-get -y update
444+
sudo apt-get -y install libpixman-1-0 libfdt1 libglib2.0-0t64
445+
- name: Install custom QEMU into /opt
446+
run: |
447+
curl -sSL https://github.com/jonathanpallant/qemu9-for-ubuntu-2404/releases/download/qemu-9.2.3%2Bbuild0/qemu-9.2.3-ubuntu-24.04.tar.gz | sudo tar xvzf - -C /
448+
- name: Run tests in QEMU
449+
run: |
450+
export PATH=/opt/qemu/bin:$PATH
451+
just test-qemu-v8r-el2
452+
409453
# Gather all the above QEMU jobs together for the purposes of getting an overall pass-fail
410454
test-qemu-all:
411455
runs-on: ubuntu-24.04
@@ -417,6 +461,8 @@ jobs:
417461
test-qemu-v7a,
418462
test-qemu-v7r,
419463
test-qemu-v8r,
464+
test-qemu-v8r-smp,
465+
test-qemu-v8r-el2,
420466
]
421467
steps:
422468
- run: /bin/true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ examples/mps3-an536/target
33
examples/mps3-an536/target-d32
44
examples/mps3-an536-smp/target
55
examples/mps3-an536-smp/target-d32
6+
examples/mps3-an536-el2/target
7+
examples/mps3-an536-el2/target-d32
68
examples/versatileab/target
79
examples/versatileab/target-d32
810
Cargo.lock

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
"examples/versatileab/Cargo.toml",
1212
"examples/mps3-an536/Cargo.toml",
1313
"examples/mps3-an536-smp/Cargo.toml",
14+
"examples/mps3-an536-el2/Cargo.toml"
1415
]
1516
}

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ exclude = [
44
"examples/versatileab",
55
"examples/mps3-an536",
66
"examples/mps3-an536-smp",
7+
"examples/mps3-an536-el2",
78
]
89
members = [
910
"aarch32-cpu",

aarch32-cpu/src/generic_timer/el2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{El1PhysicalTimer, El1VirtualTimer, GenericTimer};
88
pub struct El2PhysicalTimer(El1PhysicalTimer);
99

1010
impl El2PhysicalTimer {
11-
/// Create an EL1 Generic Timer handle
11+
/// Create an EL2 Physical Timer handle
1212
///
1313
/// # Safety
1414
///
@@ -79,7 +79,7 @@ impl GenericTimer for El2PhysicalTimer {
7979
pub struct El2VirtualTimer(El1VirtualTimer);
8080

8181
impl El2VirtualTimer {
82-
/// Create an EL1 Generic Timer handle
82+
/// Create an EL2 Generic Timer handle
8383
///
8484
/// # Safety
8585
///

aarch32-cpu/src/register/armv8r/hcptr.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,22 @@
33
use crate::register::{SysReg, SysRegRead, SysRegWrite};
44

55
/// HCPTR (*Hyp Architectural Feature Trap Register*)
6-
#[derive(Debug, Copy, Clone)]
7-
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6+
#[bitbybit::bitfield(u32, debug, defmt_fields(feature = "defmt"))]
87
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9-
pub struct Hcptr(pub u32);
8+
pub struct Hcptr {
9+
/// TCPAC - Traps EL1 accesses to the CPACR to Hyp mode
10+
#[bit(31, rw)]
11+
tcpac: bool,
12+
/// TTA - Traps System register accesses to all implemented trace registers to Hyp mode
13+
#[bit(20, rw)]
14+
tta: bool,
15+
/// TASE - Traps execution of Advanced SIMD instructions to Hyp mode when the value of HCPTR.TCP10 is 0.
16+
#[bit(15, rw)]
17+
tase: bool,
18+
/// TCP - Trap accesses to Advanced SIMD and floating-point functionality to Hyp mode
19+
#[bit(10, rw)]
20+
tcp: bool,
21+
}
1022

1123
impl SysReg for Hcptr {
1224
const CP: u32 = 15;
@@ -22,7 +34,18 @@ impl Hcptr {
2234
#[inline]
2335
/// Reads HCPTR (*Hyp Architectural Feature Trap Register*)
2436
pub fn read() -> Hcptr {
25-
unsafe { Self(<Self as SysRegRead>::read_raw()) }
37+
unsafe { Self::new_with_raw_value(<Self as SysRegRead>::read_raw()) }
38+
}
39+
40+
/// Modify HCPTR (*Hyp Architectural Feature Trap Register*)
41+
#[inline]
42+
pub fn modify<F>(f: F)
43+
where
44+
F: FnOnce(&mut Self),
45+
{
46+
let mut value = Self::read();
47+
f(&mut value);
48+
Self::write(value);
2649
}
2750
}
2851

@@ -31,13 +54,9 @@ impl crate::register::SysRegWrite for Hcptr {}
3154
impl Hcptr {
3255
#[inline]
3356
/// Writes HCPTR (*Hyp Architectural Feature Trap Register*)
34-
///
35-
/// # Safety
36-
///
37-
/// Ensure that this value is appropriate for this register
38-
pub unsafe fn write(value: Self) {
57+
pub fn write(value: Self) {
3958
unsafe {
40-
<Self as SysRegWrite>::write_raw(value.0);
59+
<Self as SysRegWrite>::write_raw(value.raw_value());
4160
}
4261
}
4362
}

aarch32-cpu/src/register/armv8r/hcr.rs

Lines changed: 112 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,106 @@
33
use crate::register::{SysReg, SysRegRead, SysRegWrite};
44

55
/// HCR (*Hyp Configuration Register*)
6-
#[derive(Debug, Copy, Clone)]
6+
#[bitbybit::bitfield(u32, debug, defmt_fields(feature = "defmt"))]
7+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8+
pub struct Hcr {
9+
/// TCPAC - Traps EL1 accesses to the CPACR to Hyp mode
10+
#[bit(31, rw)]
11+
tcpac: bool,
12+
/// TRVM - Trap Reads of Memory controls
13+
#[bit(30, rw)]
14+
trvm: bool,
15+
/// HCD - HVC instruction disable
16+
#[bit(29, rw)]
17+
hcd: bool,
18+
/// TGE - Trap General Exceptions from EL0
19+
#[bit(27, rw)]
20+
tge: bool,
21+
/// TVM - Trap Memory controls
22+
#[bit(26, rw)]
23+
tvm: bool,
24+
/// TPU - Trap cache maintenance instructions that operate to the Point of Unification
25+
#[bit(24, rw)]
26+
tpu: bool,
27+
/// TPC - Trap data or unified cache maintenance instructions that operate to the Point of Coherency
28+
#[bit(23, rw)]
29+
tpc: bool,
30+
/// TSW - Trap data or unified cache maintenance instructions that operate by Set/Way
31+
#[bit(22, rw)]
32+
tsw: bool,
33+
/// TAC - Trap Auxiliary Control Registers
34+
#[bit(21, rw)]
35+
tac: bool,
36+
/// TIDCP - Trap IMPLEMENTATION DEFINED functionality
37+
#[bit(20, rw)]
38+
tidcp: bool,
39+
/// TID3 - Trap ID group 3
40+
#[bit(18, rw)]
41+
tid3: bool,
42+
/// TID2 - Trap ID group 2
43+
#[bit(17, rw)]
44+
tid2: bool,
45+
/// TID1 - Trap ID group 1
46+
#[bit(16, rw)]
47+
tid1: bool,
48+
/// TID0 - Trap ID group 0
49+
#[bit(15, rw)]
50+
tid0: bool,
51+
/// TWE - Traps EL0 and EL1 execution of WFE instructions to Hyp mode
52+
#[bit(14, rw)]
53+
twe: bool,
54+
/// TWI - Traps EL0 and EL1 execution of WFI instructions to Hyp mode
55+
#[bit(13, rw)]
56+
twi: bool,
57+
/// DC - Default Cacheability
58+
#[bit(12, rw)]
59+
dc: bool,
60+
/// BSU - Barrier Shareability upgrade.
61+
#[bits(10..=11, rw)]
62+
bsu: Bsu,
63+
/// FB - Force broadcast
64+
#[bit(9, rw)]
65+
fb: bool,
66+
/// VA - Virtual SError interrupt exception
67+
#[bit(8, rw)]
68+
va: bool,
69+
/// VI - Virtual IRQ exception
70+
#[bit(7, rw)]
71+
vi: bool,
72+
/// VF - Virtual FIQ exception
73+
#[bit(6, rw)]
74+
vf: bool,
75+
/// AMO - SError interrupt Mask Override
76+
#[bit(5, rw)]
77+
amo: bool,
78+
/// IMO - IRQ Mask Override
79+
#[bit(4, rw)]
80+
imo: bool,
81+
/// FMO - FIQ Mask Override
82+
#[bit(3, rw)]
83+
fmo: bool,
84+
/// SWIO - Set/Way Invalidation Override
85+
#[bit(1, rw)]
86+
swio: bool,
87+
/// VM - Virtualization enable
88+
#[bit(0, rw)]
89+
vm: bool,
90+
}
91+
92+
/// Barrier Shareability upgrade
93+
///
94+
/// This field determines the minimum Shareability domain that is applied to any
95+
/// barrier instruction executed from EL1 or EL0
96+
#[bitbybit::bitenum(u2, exhaustive = true)]
797
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
898
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9-
pub struct Hcr(pub u32);
99+
#[derive(Debug, PartialEq, Eq)]
100+
pub enum Bsu {
101+
NoEffect = 0b00,
102+
InnerShareable = 0b01,
103+
OuterShareable = 0b10,
104+
FullSystem = 0b11,
105+
}
10106

11107
impl SysReg for Hcr {
12108
const CP: u32 = 15;
@@ -22,7 +118,7 @@ impl Hcr {
22118
#[inline]
23119
/// Reads HCR (*Hyp Configuration Register*)
24120
pub fn read() -> Hcr {
25-
unsafe { Self(<Self as SysRegRead>::read_raw()) }
121+
unsafe { Self::new_with_raw_value(<Self as SysRegRead>::read_raw()) }
26122
}
27123
}
28124

@@ -31,13 +127,20 @@ impl crate::register::SysRegWrite for Hcr {}
31127
impl Hcr {
32128
#[inline]
33129
/// Writes HCR (*Hyp Configuration Register*)
34-
///
35-
/// # Safety
36-
///
37-
/// Ensure that this value is appropriate for this register
38-
pub unsafe fn write(value: Self) {
130+
pub fn write(value: Self) {
39131
unsafe {
40-
<Self as SysRegWrite>::write_raw(value.0);
132+
<Self as SysRegWrite>::write_raw(value.raw_value());
41133
}
42134
}
135+
136+
#[inline]
137+
/// Modify HCR (*Hyp Configuration Register*)
138+
pub fn modify<F>(f: F)
139+
where
140+
F: FnOnce(&mut Self),
141+
{
142+
let mut value = Self::read();
143+
f(&mut value);
144+
Self::write(value);
145+
}
43146
}

0 commit comments

Comments
 (0)