Skip to content

Commit 1496e00

Browse files
committed
Refactor tutorial 13
1 parent c758875 commit 1496e00

Some content is hidden

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

50 files changed

+1310
-2012
lines changed

Diff for: 13_integrated_testing/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ name = "00_interface_sanity_console"
4444
harness = false
4545

4646
[[test]]
47-
name = "02_arch_exception_handling"
47+
name = "02_arch_exception_handling_sync_page_fault"
4848
harness = false

Diff for: 13_integrated_testing/Makefile

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ifeq ($(BSP),rpi3)
2222
QEMU_TEST_ARGS = $(QEMU_RELEASE_ARGS) -semihosting
2323
OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi3.cfg
2424
JTAG_BOOT_IMAGE = jtag_boot_rpi3.img
25-
LINKER_FILE = src/bsp/rpi/link.ld
25+
LINKER_FILE = src/bsp/raspberrypi/link.ld
2626
RUSTC_MISC_ARGS = -C target-cpu=cortex-a53
2727
else ifeq ($(BSP),rpi4)
2828
TARGET = aarch64-unknown-none-softfloat
@@ -33,7 +33,7 @@ else ifeq ($(BSP),rpi4)
3333
# QEMU_TEST_ARGS = $(QEMU_RELEASE_ARGS) -semihosting
3434
OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi4.cfg
3535
JTAG_BOOT_IMAGE = jtag_boot_rpi4.img
36-
LINKER_FILE = src/bsp/rpi/link.ld
36+
LINKER_FILE = src/bsp/raspberrypi/link.ld
3737
RUSTC_MISC_ARGS = -C target-cpu=cortex-a72
3838
endif
3939

@@ -89,8 +89,7 @@ $(OUTPUT): $(CARGO_OUTPUT)
8989
$(OBJCOPY_CMD) $< $(OUTPUT)
9090

9191
doc:
92-
cargo xdoc --target=$(TARGET) --features bsp_$(BSP) --document-private-items
93-
xdg-open target/$(TARGET)/doc/libkernel/index.html
92+
cargo xdoc --target=$(TARGET) --features bsp_$(BSP) --document-private-items --open
9493

9594
ifeq ($(QEMU_MACHINE_TYPE),)
9695
qemu:

Diff for: 13_integrated_testing/README.md

+77-1,181
Large diffs are not rendered by default.

Diff for: 13_integrated_testing/kernel

32 Bytes
Binary file not shown.

Diff for: 13_integrated_testing/kernel8.img

0 Bytes
Binary file not shown.

Diff for: 13_integrated_testing/src/arch/aarch64.rs renamed to 13_integrated_testing/src/_arch/aarch64/cpu.rs

+20-80
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,27 @@
22
//
33
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
44

5-
//! AArch64.
5+
//! Architectural processor code.
66
7-
mod exception;
8-
mod mmu;
9-
pub mod sync;
10-
mod time;
11-
12-
use crate::{bsp, interface};
7+
use crate::{bsp, cpu};
138
use cortex_a::{asm, regs::*};
149

10+
//--------------------------------------------------------------------------------------------------
11+
// Boot Code
12+
//--------------------------------------------------------------------------------------------------
13+
1514
/// The entry of the `kernel` binary.
1615
///
1716
/// The function must be named `_start`, because the linker is looking for this exact name.
1817
///
1918
/// # Safety
2019
///
2120
/// - Linker script must ensure to place this function at `0x80_000`.
21+
#[naked]
2222
#[no_mangle]
2323
pub unsafe extern "C" fn _start() -> ! {
24-
const CORE_MASK: u64 = 0x3;
25-
2624
// Expect the boot core to start in EL2.
27-
if (bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK)
25+
if (bsp::cpu::BOOT_CORE_ID == cpu::smp::core_id())
2826
&& (CurrentEL.get() == CurrentEL::EL::EL2.value)
2927
{
3028
el2_to_el1_transition()
@@ -39,9 +37,12 @@ pub unsafe extern "C" fn _start() -> ! {
3937
/// # Safety
4038
///
4139
/// - The HW state of EL1 must be prepared in a sound way.
42-
/// - Exception return from EL2 must must continue execution in EL1 with ´runtime_init::init()`.
40+
/// - Exception return from EL2 must must continue execution in EL1 with
41+
/// `runtime_init::runtime_init()`.
4342
#[inline(always)]
4443
unsafe fn el2_to_el1_transition() -> ! {
44+
use crate::runtime_init;
45+
4546
// Enable timer counter registers for EL1.
4647
CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET);
4748

@@ -53,7 +54,7 @@ unsafe fn el2_to_el1_transition() -> ! {
5354

5455
// Set up a simulated exception return.
5556
//
56-
// First, fake a saved program status, where all interrupts were masked and SP_EL1 was used as a
57+
// First, fake a saved program status where all interrupts were masked and SP_EL1 was used as a
5758
// stack pointer.
5859
SPSR_EL2.write(
5960
SPSR_EL2::D::Masked
@@ -63,99 +64,38 @@ unsafe fn el2_to_el1_transition() -> ! {
6364
+ SPSR_EL2::M::EL1h,
6465
);
6566

66-
// Second, let the link register point to init().
67-
ELR_EL2.set(crate::runtime_init::runtime_init as *const () as u64);
67+
// Second, let the link register point to runtime_init().
68+
ELR_EL2.set(runtime_init::runtime_init as *const () as u64);
6869

6970
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
70-
SP_EL1.set(bsp::BOOT_CORE_STACK_START);
71+
SP_EL1.set(bsp::cpu::BOOT_CORE_STACK_START);
7172

72-
// Use `eret` to "return" to EL1. This will result in execution of `reset()` in EL1.
73+
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
7374
asm::eret()
7475
}
7576

7677
//--------------------------------------------------------------------------------------------------
77-
// Global instances
78-
//--------------------------------------------------------------------------------------------------
79-
80-
static TIMER: time::Timer = time::Timer;
81-
static MMU: mmu::MMU = mmu::MMU;
82-
83-
//--------------------------------------------------------------------------------------------------
84-
// Implementation of the kernel's architecture abstraction code
78+
// Public Code
8579
//--------------------------------------------------------------------------------------------------
8680

8781
pub use asm::nop;
8882

8983
/// Spin for `n` cycles.
84+
#[inline(always)]
9085
pub fn spin_for_cycles(n: usize) {
9186
for _ in 0..n {
9287
asm::nop();
9388
}
9489
}
9590

96-
/// Return a reference to a `interface::time::TimeKeeper` implementation.
97-
pub fn timer() -> &'static impl interface::time::Timer {
98-
&TIMER
99-
}
100-
101-
/// Pause execution on the calling CPU core.
91+
/// Pause execution on the core.
10292
#[inline(always)]
10393
pub fn wait_forever() -> ! {
10494
loop {
10595
asm::wfe()
10696
}
10797
}
10898

109-
/// Enable exception handling.
110-
///
111-
/// # Safety
112-
///
113-
/// - Changes the HW state of the processing element.
114-
pub unsafe fn enable_exception_handling() {
115-
exception::set_vbar_el1();
116-
}
117-
118-
/// Return a reference to an `interface::mm::MMU` implementation.
119-
pub fn mmu() -> &'static impl interface::mm::MMU {
120-
&MMU
121-
}
122-
123-
/// Information about the HW state.
124-
pub mod state {
125-
use crate::arch::PrivilegeLevel;
126-
use cortex_a::regs::*;
127-
128-
/// The processing element's current privilege level.
129-
pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
130-
let el = CurrentEL.read_as_enum(CurrentEL::EL);
131-
match el {
132-
Some(CurrentEL::EL::Value::EL2) => (PrivilegeLevel::Hypervisor, "EL2"),
133-
Some(CurrentEL::EL::Value::EL1) => (PrivilegeLevel::Kernel, "EL1"),
134-
Some(CurrentEL::EL::Value::EL0) => (PrivilegeLevel::User, "EL0"),
135-
_ => (PrivilegeLevel::Unknown, "Unknown"),
136-
}
137-
}
138-
139-
/// Print the AArch64 exceptions status.
140-
#[rustfmt::skip]
141-
pub fn print_exception_state() {
142-
use super::{
143-
exception,
144-
exception::{Debug, SError, FIQ, IRQ},
145-
};
146-
use crate::info;
147-
148-
let to_mask_str = |x| -> _ {
149-
if x { "Masked" } else { "Unmasked" }
150-
};
151-
152-
info!(" Debug: {}", to_mask_str(exception::is_masked::<Debug>()));
153-
info!(" SError: {}", to_mask_str(exception::is_masked::<SError>()));
154-
info!(" IRQ: {}", to_mask_str(exception::is_masked::<IRQ>()));
155-
info!(" FIQ: {}", to_mask_str(exception::is_masked::<FIQ>()));
156-
}
157-
}
158-
15999
//--------------------------------------------------------------------------------------------------
160100
// Testing
161101
//--------------------------------------------------------------------------------------------------

Diff for: 13_integrated_testing/src/_arch/aarch64/cpu/smp.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
4+
5+
//! Architectural symmetric multiprocessing.
6+
7+
use cortex_a::regs::*;
8+
9+
//--------------------------------------------------------------------------------------------------
10+
// Public Code
11+
//--------------------------------------------------------------------------------------------------
12+
13+
/// Return the executing core's id.
14+
#[inline(always)]
15+
pub fn core_id<T>() -> T
16+
where
17+
T: From<u8>,
18+
{
19+
const CORE_MASK: u64 = 0b11;
20+
21+
T::from((MPIDR_EL1.get() & CORE_MASK) as u8)
22+
}

Diff for: 13_integrated_testing/src/arch/aarch64/exception.S renamed to 13_integrated_testing/src/_arch/aarch64/exception.S

+11-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//
33
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
44

5-
/// Call the function provided by parameter `\handler` after saving exception context. Provide the
6-
/// context as the first parameter to '\handler'.
5+
/// Call the function provided by parameter `\handler` after saving the exception context. Provide
6+
/// the context as the first parameter to '\handler'.
77
.macro CALL_WITH_CONTEXT handler
88
// Make room on the stack for the exception context.
99
sub sp, sp, #16 * 17
@@ -52,16 +52,19 @@
5252
//--------------------------------------------------------------------------------------------------
5353
.section .exception_vectors, "ax", @progbits
5454

55-
// Align by 2^11 bytes, as demanded by the AArch64 spec. Same as ALIGN(2048) in an ld script.
55+
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
5656
.align 11
5757

5858
// Export a symbol for the Rust code to use.
5959
__exception_vector_start:
6060

6161
// Current exception level with SP_EL0.
62+
//
6263
// .org sets the offset relative to section start.
6364
//
64-
// It must be ensured that `CALL_WITH_CONTEXT` <= 0x80 bytes.
65+
// # Safety
66+
//
67+
// - It must be ensured that `CALL_WITH_CONTEXT` <= 0x80 bytes.
6568
.org 0x000
6669
CALL_WITH_CONTEXT current_el0_synchronous
6770
.org 0x080
@@ -81,7 +84,7 @@ __exception_vector_start:
8184
.org 0x380
8285
CALL_WITH_CONTEXT current_elx_serror
8386

84-
// Lower exception level, aarch64
87+
// Lower exception level, AArch64
8588
.org 0x400
8689
CALL_WITH_CONTEXT lower_aarch64_synchronous
8790
.org 0x480
@@ -91,7 +94,7 @@ __exception_vector_start:
9194
.org 0x580
9295
CALL_WITH_CONTEXT lower_aarch64_serror
9396

94-
// Lower exception level, aarch32
97+
// Lower exception level, AArch32
9598
.org 0x600
9699
CALL_WITH_CONTEXT lower_aarch32_synchronous
97100
.org 0x680
@@ -105,6 +108,8 @@ __exception_vector_start:
105108
//--------------------------------------------------------------------------------------------------
106109
// Helper functions
107110
//--------------------------------------------------------------------------------------------------
111+
.section .text
112+
108113
__exception_restore_context:
109114
ldr w19, [sp, #16 * 16]
110115
ldp lr, x20, [sp, #16 * 15]

0 commit comments

Comments
 (0)