Overhaul linker script

pull/110/head
Andre Richter 3 years ago
parent fa4a2de331
commit 223989adb9
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -102,7 +102,6 @@ objdump: $(KERNEL_ELF)
$(call colorecho, "\nLaunching objdump")
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -3,15 +3,26 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code
***********************************************************************************************/
.text :
{
*(.text._start) *(.text*)
}
/DISCARD/ : { *(.comment*) }
KEEP(*(.text._start))
*(.text*)
} :segment_rx
}

@ -103,6 +103,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -9,8 +9,7 @@
## Notable additions
- More sections in linker script:
- `.rodata`, `.data`
- `.bss`
- `.rodata`, `.got`, `.data`, `.bss`
- `_start()`:
- Halt core if core != `core0`.
- `core0` jumps to the `runtime_init()` Rust function.
@ -37,6 +36,19 @@ diff -uNr 01_wait_forever/Cargo.toml 02_runtime_init/Cargo.toml
default = []
bsp_rpi3 = []
diff -uNr 01_wait_forever/Makefile 02_runtime_init/Makefile
--- 01_wait_forever/Makefile
+++ 02_runtime_init/Makefile
@@ -102,6 +102,8 @@
$(call colorecho, "\nLaunching objdump")
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
+ --section .rodata \
+ --section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)
diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.S 02_runtime_init/src/_arch/aarch64/cpu/boot.S
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.S
+++ 02_runtime_init/src/_arch/aarch64/cpu/boot.S
@ -97,33 +109,45 @@ diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.rs 02_runtime_init/src/_arch/aar
diff -uNr 01_wait_forever/src/bsp/raspberrypi/link.ld 02_runtime_init/src/bsp/raspberrypi/link.ld
--- 01_wait_forever/src/bsp/raspberrypi/link.ld
+++ 02_runtime_init/src/bsp/raspberrypi/link.ld
@@ -13,5 +13,27 @@
*(.text._start) *(.text*)
}
@@ -11,6 +11,7 @@
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
+ segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
+ .rodata :
+ {
+ *(.rodata*)
+ }
SECTIONS
@@ -18,11 +19,30 @@
. = __rpi_load_addr;
/***********************************************************************************************
- * Code
+ * Code + RO Data + Global Offset Table
***********************************************************************************************/
.text :
{
KEEP(*(.text._start))
*(.text*)
} :segment_rx
+
+ .data :
+ {
+ *(.data*)
+ }
+ .rodata : ALIGN(8) { *(.rodata*) } :segment_rx
+ .got : ALIGN(8) { *(.got) } :segment_rx
+
+ /***********************************************************************************************
+ * Data + BSS
+ ***********************************************************************************************/
+ .data : { *(.data*) } :segment_rw
+
+ /* Section is zeroed in u64 chunks, align start and end to 8 bytes */
+ .bss ALIGN(8):
+ .bss : ALIGN(8)
+ {
+ __bss_start = .;
+ *(.bss*);
+ . = ALIGN(8);
+
+ /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
+ . += 8;
+ . += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
+ __bss_end_inclusive = . - 8;
+ }
+
/DISCARD/ : { *(.comment*) }
+ } :NONE
}
diff -uNr 01_wait_forever/src/bsp/raspberrypi/memory.rs 02_runtime_init/src/bsp/raspberrypi/memory.rs

@ -3,37 +3,46 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -103,6 +103,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -3,37 +3,46 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -103,6 +103,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -167,20 +167,43 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/cpu.rs 04_zero_overhead_abstr
+/// Used by `arch` code to find the early boot core.
+pub const BOOT_CORE_ID: usize = 0;
diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/link.ld 04_zero_overhead_abstraction/src/bsp/raspberrypi/link.ld
--- 03_hacky_hello_world/src/bsp/raspberrypi/link.ld
+++ 04_zero_overhead_abstraction/src/bsp/raspberrypi/link.ld
@@ -21,6 +21,7 @@
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
+ __rx_start = .;
.text :
{
KEEP(*(.text._start))
diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/memory.rs 04_zero_overhead_abstraction/src/bsp/raspberrypi/memory.rs
--- 03_hacky_hello_world/src/bsp/raspberrypi/memory.rs
+++ 04_zero_overhead_abstraction/src/bsp/raspberrypi/memory.rs
@@ -17,9 +17,25 @@
@@ -12,14 +12,36 @@
// Symbols from the linker script.
extern "Rust" {
+ static __rx_start: UnsafeCell<()>;
+
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
//--------------------------------------------------------------------------------------------------
+// Public Definitions
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// The board's memory map.
+#[rustfmt::skip]
+pub(super) mod map {
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+/// Start address of the Read+Execute (RX) range.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn rx_start() -> usize {
+ unsafe { __rx_start.get() as usize }
+}
+
+//--------------------------------------------------------------------------------------------------
@ -190,7 +213,7 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/memory.rs 04_zero_overhead_ab
+/// Exclusive end address of the boot core's stack.
+#[inline(always)]
+pub fn boot_core_stack_end() -> usize {
+ map::BOOT_CORE_STACK_END
+ rx_start()
+}
+
/// Return the inclusive range spanning the .bss section.

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,18 +12,24 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Code
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -33,7 +39,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -103,6 +103,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,18 +12,24 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
// Private Code
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -33,7 +39,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -122,6 +122,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -1110,10 +1110,16 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/driver.rs 06_drivers_gpio_uart/src
diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
--- 05_safe_globals/src/bsp/raspberrypi/memory.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
@@ -24,6 +24,29 @@
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
@@ -19,6 +19,38 @@
}
//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// The board's physical memory map.
+#[rustfmt::skip]
+pub(super) mod map {
+
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
@ -1137,10 +1143,13 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_START: usize = START + UART_OFFSET;
+ }
}
+}
+
+//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
diff -uNr 05_safe_globals/src/bsp/raspberrypi.rs 06_drivers_gpio_uart/src/bsp/raspberrypi.rs
--- 05_safe_globals/src/bsp/raspberrypi.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi.rs

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,6 +12,8 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
@ -20,10 +22,9 @@ extern "Rust" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -49,6 +50,20 @@ pub(super) mod map {
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
@ -56,7 +71,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -165,14 +165,6 @@ diff -uNr 06_drivers_gpio_uart/Makefile 07_uart_chainloader/Makefile
clippy:
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)
@@ -122,6 +129,7 @@
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
+ --section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)
diff -uNr 06_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.rs 07_uart_chainloader/src/_arch/aarch64/cpu/boot.rs
--- 06_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.rs
@ -276,77 +268,82 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 0
diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/link.ld 07_uart_chainloader/src/bsp/raspberrypi/link.ld
--- 06_drivers_gpio_uart/src/bsp/raspberrypi/link.ld
+++ 07_uart_chainloader/src/bsp/raspberrypi/link.ld
@@ -5,12 +5,15 @@
@@ -16,12 +16,13 @@
SECTIONS
{
- /* Set current address to the value from which the RPi starts execution */
- . = 0x80000;
- . = __rpi_load_addr;
+ /* Set the link address to 32 MiB */
+ . = 0x2000000;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
- __rx_start = .;
+ __binary_start = .;
.text :
{
- *(.text._start) *(.text*)
+ *(.text._start)
+ KEEP(*(.text.runtime_init))
+ *(.text*);
}
.rodata :
@@ -35,5 +38,16 @@
KEEP(*(.text._start))
@@ -46,4 +47,10 @@
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
+ .got :
+ {
+ *(.got*)
+ }
} :NONE
+
+ /* Fill up to 8 byte, b/c relocating the binary is done in u64 chunks */
+ . = ALIGN(8);
+ __binary_end_inclusive = . - 8;
+
+ __runtime_init_reloc = runtime_init;
+
/DISCARD/ : { *(.comment*) }
}
diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
--- 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
+++ 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
@@ -12,6 +12,9 @@
@@ -12,10 +12,12 @@
// Symbols from the linker script.
extern "Rust" {
- static __rx_start: UnsafeCell<()>;
-
+ static __binary_start: UnsafeCell<u64>;
+ static __binary_end_inclusive: UnsafeCell<u64>;
+ static __runtime_init_reloc: UnsafeCell<u64>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
+ static __binary_end_inclusive: UnsafeCell<u64>;
+
+ static __runtime_init_reloc: UnsafeCell<u64>;
}
@@ -23,10 +26,12 @@
/// The board's memory map.
//--------------------------------------------------------------------------------------------------
@@ -25,9 +27,12 @@
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+
+ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
+
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
@@ -59,13 +64,35 @@
map::BOOT_CORE_STACK_END
@@ -51,36 +56,44 @@
}
-/// Return the inclusive range spanning the .bss section.
//--------------------------------------------------------------------------------------------------
-// Private Code
+// Public Code
//--------------------------------------------------------------------------------------------------
-/// Start address of the Read+Execute (RX) range.
+/// Exclusive end address of the boot core's stack.
+#[inline(always)]
+pub fn boot_core_stack_end() -> usize {
+ map::BOOT_CORE_STACK_END
+}
+
+/// The address on which the Raspberry firmware loads every binary by default.
+#[inline(always)]
+pub fn board_default_load_addr() -> *const u64 {
@ -354,21 +351,33 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader
+}
+
+/// Return the inclusive range spanning the relocated kernel binary.
+///
+/// # Safety
+///
///
/// # Safety
///
-/// - Value is provided by the linker script and must be trusted as-is.
-#[inline(always)]
-fn rx_start() -> usize {
- unsafe { __rx_start.get() as usize }
+/// - Values are provided by the linker script and must be trusted as-is.
+/// - The linker-provided addresses must be u64 aligned.
+pub fn relocated_binary_range_inclusive() -> RangeInclusive<*mut u64> {
+ unsafe { RangeInclusive::new(__binary_start.get(), __binary_end_inclusive.get()) }
+}
+
}
-//--------------------------------------------------------------------------------------------------
-// Public Code
-//--------------------------------------------------------------------------------------------------
-
-/// Exclusive end address of the boot core's stack.
+/// The relocated address of function `runtime_init()`.
+#[inline(always)]
#[inline(always)]
-pub fn boot_core_stack_end() -> usize {
- rx_start()
+pub fn relocated_runtime_init_addr() -> *const u64 {
+ unsafe { __runtime_init_reloc.get() as _ }
+}
+
}
-/// Return the inclusive range spanning the .bss section.
+/// Return the inclusive range spanning the relocated .bss section.
///
/// # Safety
@ -498,7 +507,7 @@ diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs
diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate.rs
--- 06_drivers_gpio_uart/src/relocate.rs
+++ 07_uart_chainloader/src/relocate.rs
@@ -0,0 +1,51 @@
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
@ -537,16 +546,14 @@ diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate.
+ current_binary_start_addr = current_binary_start_addr.offset(1);
+ }
+
+ // The following function calls form a hack to achieve an "absolute jump" to
+ // `runtime_init::runtime_init()` by forcing an indirection through the global offset table
+ // (GOT), so that execution continues from the relocated binary.
+ //
+ // Without this, the address of `runtime_init()` would be calculated as a relative offset from
+ // the current program counter, since we are compiling as `position independent code`. This
+ // would cause us to keep executing from the address to which the firmware loaded us, instead of
+ // the relocated position.
+ // The following function calls realize an "absolute jump" to `runtime_init::runtime_init()` by
+ // forcing an indirection through the global offset table (GOT), so that execution continues
+ // from the relocated binary.
+ //
+ // There likely is a more elegant way to do this.
+ // Without the indirection through the assembly, the address of `runtime_init()` would be
+ // calculated as a relative offset from the current program counter, since we are compiling as
+ // `position independent code`. This would cause us to keep executing from the address to which
+ // the firmware loaded us, instead of the relocated position.
+ let relocated_runtime_init_addr = bsp::memory::relocated_runtime_init_addr() as usize;
+ cpu::branch_to_raw_addr(relocated_runtime_init_addr)
+}

@ -3,51 +3,54 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set the link address to 32 MiB */
. = 0x2000000;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__binary_start = .;
.text :
{
*(.text._start)
KEEP(*(.text.runtime_init))
*(.text*);
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
.got :
{
*(.got*)
}
} :NONE
/* Fill up to 8 byte, b/c relocating the binary is done in u64 chunks */
. = ALIGN(8);
__binary_end_inclusive = . - 8;
__runtime_init_reloc = runtime_init;
/DISCARD/ : { *(.comment*) }
}

@ -13,17 +13,18 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __binary_start: UnsafeCell<u64>;
static __binary_end_inclusive: UnsafeCell<u64>;
static __runtime_init_reloc: UnsafeCell<u64>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __binary_end_inclusive: UnsafeCell<u64>;
static __runtime_init_reloc: UnsafeCell<u64>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;

@ -36,16 +36,14 @@ pub unsafe fn relocate_self() -> ! {
current_binary_start_addr = current_binary_start_addr.offset(1);
}
// The following function calls form a hack to achieve an "absolute jump" to
// `runtime_init::runtime_init()` by forcing an indirection through the global offset table
// (GOT), so that execution continues from the relocated binary.
// The following function calls realize an "absolute jump" to `runtime_init::runtime_init()` by
// forcing an indirection through the global offset table (GOT), so that execution continues
// from the relocated binary.
//
// Without this, the address of `runtime_init()` would be calculated as a relative offset from
// the current program counter, since we are compiling as `position independent code`. This
// would cause us to keep executing from the address to which the firmware loaded us, instead of
// the relocated position.
//
// There likely is a more elegant way to do this.
// Without the indirection through the assembly, the address of `runtime_init()` would be
// calculated as a relative offset from the current program counter, since we are compiling as
// `position independent code`. This would cause us to keep executing from the address to which
// the firmware loaded us, instead of the relocated position.
let relocated_runtime_init_addr = bsp::memory::relocated_runtime_init_addr() as usize;
cpu::branch_to_raw_addr(relocated_runtime_init_addr)
}

@ -122,6 +122,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -96,14 +96,6 @@ diff -uNr 07_uart_chainloader/Makefile 08_timestamps/Makefile
clippy:
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)
@@ -129,7 +122,6 @@
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
- --section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)
diff -uNr 07_uart_chainloader/src/_arch/aarch64/cpu/boot.rs 08_timestamps/src/_arch/aarch64/cpu/boot.rs
--- 07_uart_chainloader/src/_arch/aarch64/cpu/boot.rs
@ -369,65 +361,60 @@ diff -uNr 07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 08
diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/link.ld 08_timestamps/src/bsp/raspberrypi/link.ld
--- 07_uart_chainloader/src/bsp/raspberrypi/link.ld
+++ 08_timestamps/src/bsp/raspberrypi/link.ld
@@ -5,15 +5,12 @@
@@ -16,13 +16,12 @@
SECTIONS
{
- /* Set the link address to 32 MiB */
- . = 0x2000000;
+ /* Set current address to the value from which the RPi starts execution */
+ . = 0x80000;
+ . = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
- __binary_start = .;
+ __rx_start = .;
.text :
{
- *(.text._start)
- KEEP(*(.text.runtime_init))
- *(.text*);
+ *(.text._start) *(.text*)
}
.rodata :
@@ -38,16 +35,5 @@
KEEP(*(.text._start))
@@ -47,10 +46,4 @@
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
- .got :
- {
- *(.got*)
- }
} :NONE
-
- /* Fill up to 8 byte, b/c relocating the binary is done in u64 chunks */
- . = ALIGN(8);
- __binary_end_inclusive = . - 8;
-
- __runtime_init_reloc = runtime_init;
-
/DISCARD/ : { *(.comment*) }
}
diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bsp/raspberrypi/memory.rs
--- 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
+++ 08_timestamps/src/bsp/raspberrypi/memory.rs
@@ -12,9 +12,6 @@
@@ -12,12 +12,10 @@
// Symbols from the linker script.
extern "Rust" {
- static __binary_start: UnsafeCell<u64>;
- static __binary_end_inclusive: UnsafeCell<u64>;
- static __runtime_init_reloc: UnsafeCell<u64>;
+ static __rx_start: UnsafeCell<()>;
+
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
- static __binary_end_inclusive: UnsafeCell<u64>;
-
- static __runtime_init_reloc: UnsafeCell<u64>;
}
@@ -26,12 +23,10 @@
/// The board's memory map.
//--------------------------------------------------------------------------------------------------
@@ -27,12 +25,9 @@
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
- pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
-
- pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
@ -435,10 +422,20 @@ diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bs
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
@@ -64,35 +59,13 @@
map::BOOT_CORE_STACK_END
@@ -56,44 +51,36 @@
}
//--------------------------------------------------------------------------------------------------
-// Public Code
+// Private Code
//--------------------------------------------------------------------------------------------------
-/// Exclusive end address of the boot core's stack.
-#[inline(always)]
-pub fn boot_core_stack_end() -> usize {
- map::BOOT_CORE_STACK_END
-}
-
-/// The address on which the Raspberry firmware loads every binary by default.
-#[inline(always)]
-pub fn board_default_load_addr() -> *const u64 {
@ -446,21 +443,33 @@ diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bs
-}
-
-/// Return the inclusive range spanning the relocated kernel binary.
-///
-/// # Safety
-///
+/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
-/// - Values are provided by the linker script and must be trusted as-is.
-/// - The linker-provided addresses must be u64 aligned.
-pub fn relocated_binary_range_inclusive() -> RangeInclusive<*mut u64> {
- unsafe { RangeInclusive::new(__binary_start.get(), __binary_end_inclusive.get()) }
-}
-
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn rx_start() -> usize {
+ unsafe { __rx_start.get() as usize }
}
-/// The relocated address of function `runtime_init()`.
-#[inline(always)]
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Exclusive end address of the boot core's stack.
#[inline(always)]
-pub fn relocated_runtime_init_addr() -> *const u64 {
- unsafe { __runtime_init_reloc.get() as _ }
-}
-
+pub fn boot_core_stack_end() -> usize {
+ rx_start()
}
-/// Return the inclusive range spanning the relocated .bss section.
+/// Return the inclusive range spanning the .bss section.
///
@ -674,7 +683,7 @@ diff -uNr 07_uart_chainloader/src/print.rs 08_timestamps/src/print.rs
diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
--- 07_uart_chainloader/src/relocate.rs
+++ 08_timestamps/src/relocate.rs
@@ -1,51 +0,0 @@
@@ -1,49 +0,0 @@
-// SPDX-License-Identifier: MIT OR Apache-2.0
-//
-// Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
@ -713,16 +722,14 @@ diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
- current_binary_start_addr = current_binary_start_addr.offset(1);
- }
-
- // The following function calls form a hack to achieve an "absolute jump" to
- // `runtime_init::runtime_init()` by forcing an indirection through the global offset table
- // (GOT), so that execution continues from the relocated binary.
- //
- // Without this, the address of `runtime_init()` would be calculated as a relative offset from
- // the current program counter, since we are compiling as `position independent code`. This
- // would cause us to keep executing from the address to which the firmware loaded us, instead of
- // the relocated position.
- // The following function calls realize an "absolute jump" to `runtime_init::runtime_init()` by
- // forcing an indirection through the global offset table (GOT), so that execution continues
- // from the relocated binary.
- //
- // There likely is a more elegant way to do this.
- // Without the indirection through the assembly, the address of `runtime_init()` would be
- // calculated as a relative offset from the current program counter, since we are compiling as
- // `position independent code`. This would cause us to keep executing from the address to which
- // the firmware loaded us, instead of the relocated position.
- let relocated_runtime_init_addr = bsp::memory::relocated_runtime_init_addr() as usize;
- cpu::branch_to_raw_addr(relocated_runtime_init_addr)
-}

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,6 +12,8 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
@ -20,10 +22,9 @@ extern "Rust" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -49,6 +50,20 @@ pub(super) mod map {
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
@ -56,7 +71,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -147,6 +147,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,6 +12,8 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
@ -20,10 +22,9 @@ extern "Rust" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -49,6 +50,20 @@ pub(super) mod map {
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
@ -56,7 +71,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -147,6 +147,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -136,7 +136,7 @@ Finally, we set the stack pointer for `SP_EL1` and call `ERET`:
```rust
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
SP_EL1.set(bsp::cpu::BOOT_CORE_STACK_START);
SP_EL1.set(bsp::memory::boot_core_stack_end() as u64);
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,6 +12,8 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
@ -20,10 +22,9 @@ extern "Rust" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -49,6 +50,20 @@ pub(super) mod map {
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
@ -56,7 +71,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -147,6 +147,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -224,10 +224,16 @@ enables caching for data and instructions.
### `link.ld`
We need to align the `ro` section to `64 KiB` so that it doesn't overlap with the next section that
needs read/write attributes. This blows up the binary in size, but is a small price to pay
considering that it reduces the amount of static paging entries significantly, when compared to the
classical `4 KiB` granule.
We need to align the `rx` segment to `64 KiB` so that it doesn't overlap with the next section that
needs read/write attributes instead of read/execute attributes:
```ld.s
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
```
This blows up the binary in size, but is a small price to pay considering that it reduces the amount
of static paging entries significantly, when compared to the classical `4 KiB` granule.
## Address translation examples
@ -807,23 +813,16 @@ diff -uNr 10_privilege_level/src/_arch/aarch64/memory/mmu.rs 11_virtual_mem_part
diff -uNr 10_privilege_level/src/bsp/raspberrypi/link.ld 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/link.ld
--- 10_privilege_level/src/bsp/raspberrypi/link.ld
+++ 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/link.ld
@@ -8,6 +8,7 @@
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
+ __ro_start = .;
.text :
{
*(.text._start) *(.text*)
@@ -17,6 +18,8 @@
{
*(.rodata*)
}
+ . = ALIGN(65536); /* Fill up to 64 KiB */
+ __ro_end = .;
@@ -31,6 +31,9 @@
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
+ . = ALIGN(64K); /* Align to page boundary */
+ __rx_end_exclusive = .;
+
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory/mmu.rs
--- 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs
@ -857,7 +856,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_mem_pa
+ [
+ TranslationDescriptor {
+ name: "Kernel code and RO data",
+ virtual_range: ro_range_inclusive,
+ virtual_range: rx_range_inclusive,
+ physical_range_translation: Translation::Identity,
+ attribute_fields: AttributeFields {
+ mem_attributes: MemAttributes::CacheableDRAM,
@ -892,10 +891,10 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_mem_pa
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+fn ro_range_inclusive() -> RangeInclusive<usize> {
+fn rx_range_inclusive() -> RangeInclusive<usize> {
+ // Notice the subtraction to turn the exclusive end into an inclusive end.
+ #[allow(clippy::range_minus_one)]
+ RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
+ RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
+}
+
+fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
@ -928,17 +927,16 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_mem_part1_
use core::{cell::UnsafeCell, ops::RangeInclusive};
//--------------------------------------------------------------------------------------------------
@@ -14,6 +16,8 @@
@@ -13,6 +15,7 @@
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
+ static __rx_end_exclusive: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
+ static __ro_start: UnsafeCell<()>;
+ static __ro_end: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
@@ -23,6 +27,21 @@
/// The board's memory map.
@@ -25,6 +28,20 @@
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
+ /// The inclusive end address of the memory map.
@ -955,11 +953,10 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_mem_part1_
+ /// physical address that is not backed by any DRAM (e.g. accessing an address close to 4 GiB on
+ /// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
+ pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
+
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
@@ -36,6 +55,7 @@
pub const UART_OFFSET: usize = 0x0020_1000;
@@ -37,6 +54,7 @@
pub const START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
@ -967,7 +964,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_mem_part1_
}
/// Physical devices.
@@ -46,10 +66,35 @@
@@ -47,6 +65,7 @@
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
@ -975,35 +972,24 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_mem_part1_
}
}
//--------------------------------------------------------------------------------------------------
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// Start address of the Read-Only (RO) range.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn ro_start() -> usize {
+ unsafe { __ro_start.get() as usize }
+}
+
+/// Size of the Read-Only (RO) range of the kernel binary.
@@ -64,6 +83,16 @@
unsafe { __rx_start.get() as usize }
}
+/// Exclusive end address of the Read+Execute (RX) range.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn ro_end() -> usize {
+ unsafe { __ro_end.get() as usize }
+fn rx_end_exclusive() -> usize {
+ unsafe { __rx_end_exclusive.get() as usize }
+}
+
+//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
diff -uNr 10_privilege_level/src/bsp.rs 11_virtual_mem_part1_identity_mapping/src/bsp.rs
--- 10_privilege_level/src/bsp.rs
+++ 11_virtual_mem_part1_identity_mapping/src/bsp.rs

@ -3,40 +3,50 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
__ro_start = .;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
. = ALIGN(65536); /* Fill up to 64 KiB */
__ro_end = .;
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -14,17 +14,18 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
static __ro_end: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
/// The inclusive end address of the memory map.
@ -42,8 +43,6 @@ pub(super) mod map {
/// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -74,24 +73,24 @@ pub(super) mod map {
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { __ro_start.get() as usize }
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
/// Exclusive end address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { __ro_end.get() as usize }
fn rx_end_exclusive() -> usize {
unsafe { __rx_end_exclusive.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -101,7 +100,7 @@ fn ro_end() -> usize {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -26,7 +26,7 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
[
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: ro_range_inclusive,
virtual_range: rx_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
@ -61,10 +61,10 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
fn rx_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
}
fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {

@ -147,6 +147,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -238,7 +238,7 @@ because `Rust` has no stable convention ([yet](https://github.com/rust-lang/rfcs
Next, we craft the exception vector table:
```asm
.section .exception_vectors, "ax", @progbits
.section .text
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
.align 11
@ -324,7 +324,7 @@ The actual handlers referenced from the assembly can now branch to it for the ti
```rust
#[no_mangle]
unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
unsafe extern "C" fn current_elx_irq(e: &mut ExceptionContext) {
default_exception_handler(e);
}
```
@ -480,7 +480,7 @@ General purpose register:
diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs 12_exceptions_part1_groundwork/src/_arch/aarch64/exception.rs
--- 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs
+++ 12_exceptions_part1_groundwork/src/_arch/aarch64/exception.rs
@@ -11,7 +11,230 @@
@@ -11,7 +11,224 @@
//!
//! crate::exception::arch_exception
@ -541,18 +541,18 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs 1
+//------------------------------------------------------------------------------
+
+#[no_mangle]
+unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
+ default_exception_handler(e);
+unsafe extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
+ panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
+}
+
+#[no_mangle]
+unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext) {
+ default_exception_handler(e);
+unsafe extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
+ panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
+}
+
+#[no_mangle]
+unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext) {
+ default_exception_handler(e);
+unsafe extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
+ panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
+}
+
+//------------------------------------------------------------------------------
@ -646,9 +646,7 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs 1
+ writeln!(f, " - {}", ec_translation)?;
+
+ // Raw print of instruction specific syndrome.
+ write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
+
+ Ok(())
+ write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))
+ }
+}
+
@ -681,9 +679,7 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs 1
+
+ write!(f, " Illegal Execution State (IL): {}",
+ to_flag_str(self.0.is_set(SPSR_EL1::IL))
+ )?;
+
+ Ok(())
+ )
+ }
+}
+
@ -704,15 +700,13 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs 1
+ for (i, reg) in self.gpr.iter().enumerate() {
+ write!(f, " x{: <2}: {: >#018x}{}", i, reg, alternating(i))?;
+ }
+ write!(f, " lr : {:#018x}", self.lr)?;
+
+ Ok(())
+ write!(f, " lr : {:#018x}", self.lr)
+ }
+}
//--------------------------------------------------------------------------------------------------
// Public Code
@@ -28,3 +251,23 @@
@@ -28,3 +245,23 @@
_ => (PrivilegeLevel::Unknown, "Unknown"),
}
}
@ -793,7 +787,7 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.S 12
+//--------------------------------------------------------------------------------------------------
+// The exception vector table.
+//--------------------------------------------------------------------------------------------------
+.section .exception_vectors, "ax", @progbits
+.section .text
+
+// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
+.align 11
@ -880,22 +874,6 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.S 12
+
+ eret
diff -uNr 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/link.ld 12_exceptions_part1_groundwork/src/bsp/raspberrypi/link.ld
--- 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/link.ld
+++ 12_exceptions_part1_groundwork/src/bsp/raspberrypi/link.ld
@@ -14,6 +14,11 @@
*(.text._start) *(.text*)
}
+ .exception_vectors :
+ {
+ *(.exception_vectors*)
+ }
+
.rodata :
{
*(.rodata*)
diff -uNr 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory/mmu.rs 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs
--- 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory/mmu.rs
+++ 12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs
@ -926,7 +904,7 @@ diff -uNr 11_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory/mmu.r
virtual_range: mmio_range_inclusive,
physical_range_translation: Translation::Identity,
@@ -67,11 +57,6 @@
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
}
-fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {

@ -50,7 +50,7 @@
//--------------------------------------------------------------------------------------------------
// The exception vector table.
//--------------------------------------------------------------------------------------------------
.section .exception_vectors, "ax", @progbits
.section .text
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
.align 11

@ -67,18 +67,18 @@ fn default_exception_handler(e: &ExceptionContext) {
//------------------------------------------------------------------------------
#[no_mangle]
unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
//------------------------------------------------------------------------------
@ -172,9 +172,7 @@ impl fmt::Display for EsrEL1 {
writeln!(f, " - {}", ec_translation)?;
// Raw print of instruction specific syndrome.
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
Ok(())
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))
}
}
@ -207,9 +205,7 @@ impl fmt::Display for SpsrEL1 {
write!(f, " Illegal Execution State (IL): {}",
to_flag_str(self.0.is_set(SPSR_EL1::IL))
)?;
Ok(())
)
}
}
@ -230,9 +226,7 @@ impl fmt::Display for ExceptionContext {
for (i, reg) in self.gpr.iter().enumerate() {
write!(f, " x{: <2}: {: >#018x}{}", i, reg, alternating(i))?;
}
write!(f, " lr : {:#018x}", self.lr)?;
Ok(())
write!(f, " lr : {:#018x}", self.lr)
}
}

@ -3,45 +3,50 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
__ro_start = .;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.exception_vectors :
{
*(.exception_vectors*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.rodata :
{
*(.rodata*)
}
. = ALIGN(65536); /* Fill up to 64 KiB */
__ro_end = .;
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -14,17 +14,18 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
static __ro_end: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
/// The inclusive end address of the memory map.
@ -42,8 +43,6 @@ pub(super) mod map {
/// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -74,24 +73,24 @@ pub(super) mod map {
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { __ro_start.get() as usize }
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
/// Exclusive end address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { __ro_end.get() as usize }
fn rx_end_exclusive() -> usize {
unsafe { __rx_end_exclusive.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -101,7 +100,7 @@ fn ro_end() -> usize {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -26,7 +26,7 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
[
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: ro_range_inclusive,
virtual_range: rx_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
@ -51,10 +51,10 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
fn rx_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {

@ -179,6 +179,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -50,7 +50,7 @@
//--------------------------------------------------------------------------------------------------
// The exception vector table.
//--------------------------------------------------------------------------------------------------
.section .exception_vectors, "ax", @progbits
.section .text
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
.align 11

@ -67,18 +67,18 @@ fn default_exception_handler(e: &ExceptionContext) {
//------------------------------------------------------------------------------
#[no_mangle]
unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
//------------------------------------------------------------------------------
@ -162,9 +162,7 @@ impl fmt::Display for EsrEL1 {
writeln!(f, " - {}", ec_translation)?;
// Raw print of instruction specific syndrome.
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
Ok(())
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))
}
}
@ -197,9 +195,7 @@ impl fmt::Display for SpsrEL1 {
write!(f, " Illegal Execution State (IL): {}",
to_flag_str(self.0.is_set(SPSR_EL1::IL))
)?;
Ok(())
)
}
}
@ -220,9 +216,7 @@ impl fmt::Display for ExceptionContext {
for (i, reg) in self.gpr.iter().enumerate() {
write!(f, " x{: <2}: {: >#018x}{}", i, reg, alternating(i))?;
}
write!(f, " lr : {:#018x}", self.lr)?;
Ok(())
write!(f, " lr : {:#018x}", self.lr)
}
}

@ -3,45 +3,50 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
__ro_start = .;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.exception_vectors :
{
*(.exception_vectors*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.rodata :
{
*(.rodata*)
}
. = ALIGN(65536); /* Fill up to 64 KiB */
__ro_end = .;
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -14,17 +14,18 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
static __ro_end: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
/// The inclusive end address of the memory map.
@ -42,8 +43,6 @@ pub(super) mod map {
/// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -74,24 +73,24 @@ pub(super) mod map {
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { __ro_start.get() as usize }
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
/// Exclusive end address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { __ro_end.get() as usize }
fn rx_end_exclusive() -> usize {
unsafe { __rx_end_exclusive.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -101,7 +100,7 @@ fn ro_end() -> usize {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -26,7 +26,7 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
[
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: ro_range_inclusive,
virtual_range: rx_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
@ -51,10 +51,10 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
fn rx_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {

@ -179,6 +179,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -2056,7 +2056,7 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/exception.rs 14_exceptions_p
diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
--- 13_integrated_testing/src/bsp/raspberrypi/memory.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
@@ -52,10 +52,12 @@
@@ -51,10 +51,12 @@
pub mod mmio {
use super::*;
@ -2073,7 +2073,7 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part
}
/// Physical devices.
@@ -66,6 +68,8 @@
@@ -65,6 +67,8 @@
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;

@ -50,7 +50,7 @@
//--------------------------------------------------------------------------------------------------
// The exception vector table.
//--------------------------------------------------------------------------------------------------
.section .exception_vectors, "ax", @progbits
.section .text
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
.align 11

@ -68,18 +68,18 @@ fn default_exception_handler(e: &ExceptionContext) {
//------------------------------------------------------------------------------
#[no_mangle]
unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
//------------------------------------------------------------------------------
@ -166,9 +166,7 @@ impl fmt::Display for EsrEL1 {
writeln!(f, " - {}", ec_translation)?;
// Raw print of instruction specific syndrome.
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
Ok(())
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))
}
}
@ -201,9 +199,7 @@ impl fmt::Display for SpsrEL1 {
write!(f, " Illegal Execution State (IL): {}",
to_flag_str(self.0.is_set(SPSR_EL1::IL))
)?;
Ok(())
)
}
}
@ -224,9 +220,7 @@ impl fmt::Display for ExceptionContext {
for (i, reg) in self.gpr.iter().enumerate() {
write!(f, " x{: <2}: {: >#018x}{}", i, reg, alternating(i))?;
}
write!(f, " lr : {:#018x}", self.lr)?;
Ok(())
write!(f, " lr : {:#018x}", self.lr)
}
}

@ -3,45 +3,50 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
__ro_start = .;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.exception_vectors :
{
*(.exception_vectors*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.rodata :
{
*(.rodata*)
}
. = ALIGN(65536); /* Fill up to 64 KiB */
__ro_end = .;
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -14,17 +14,18 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
static __ro_end: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
/// The inclusive end address of the memory map.
@ -42,8 +43,6 @@ pub(super) mod map {
/// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -78,24 +77,24 @@ pub(super) mod map {
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_start() -> usize {
unsafe { __ro_start.get() as usize }
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
/// Size of the Read-Only (RO) range of the kernel binary.
/// Exclusive end address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_end() -> usize {
unsafe { __ro_end.get() as usize }
fn rx_end_exclusive() -> usize {
unsafe { __rx_end_exclusive.get() as usize }
}
//--------------------------------------------------------------------------------------------------
@ -105,7 +104,7 @@ fn ro_end() -> usize {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

@ -26,7 +26,7 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
[
TranslationDescriptor {
name: "Kernel code and RO data",
virtual_range: ro_range_inclusive,
virtual_range: rx_range_inclusive,
physical_range_translation: Translation::Identity,
attribute_fields: AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
@ -51,10 +51,10 @@ pub static LAYOUT: KernelVirtualLayout<NUM_MEM_RANGES> = KernelVirtualLayout::ne
// Private Code
//--------------------------------------------------------------------------------------------------
fn ro_range_inclusive() -> RangeInclusive<usize> {
fn rx_range_inclusive() -> RangeInclusive<usize> {
// Notice the subtraction to turn the exclusive end into an inclusive end.
#[allow(clippy::range_minus_one)]
RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
}
fn mmio_range_inclusive() -> RangeInclusive<usize> {

@ -179,6 +179,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

@ -276,6 +276,13 @@ unsafe fn init(&self) -> Result<(), &'static str> {
There's a couple of changes not covered in this tutorial text, but the reader should ideally skim
through them:
- [`src/bsp/raspberrypi/memory.rs`](src/bsp/raspberrypi/memory.rs) and
[`src/bsp/raspberrypi/link.ld`](src/bsp/raspberrypi/link.ld) changed the location of the boot
core's stack. It is now located after the data segment, and separated by an unmapped `guard page`.
There is also supporting code in
[`src/_arch/aarch64/exception.rs`](src/_arch/aarch64/exception.rs) that runs on data aborts and
checks if the fault address lies within the `stack guard page`. This can be an indication that a
kernel stack overflow happened.
- [`src/memory/mmu/types.rs`](src/memory/mmu/types.rs) introduces a couple of supporting types, like
`Page<ATYPE>`.
- [`src/memory/mmu/mapping_record.rs`](src/memory/mmu/mapping_record.rs) provides the generic kernel
@ -309,18 +316,18 @@ Minipush 1.0
[MP] ⏩ Pushing 67 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now
[ 0.786819] Booting on: Raspberry Pi 3
[ 0.787092] MMU online:
[ 0.787384] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.789128] Virtual Physical Size Attr Entity
[ 0.790873] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.792618] 0x0000_0000_0007_0000..0x0000_0000_0007_ffff --> 0x00_0007_0000..0x00_0007_ffff | 64 KiB | C RW XN | Kernel boot-core stack
[ 0.794221] 0x0000_0000_0008_0000..0x0000_0000_0008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
[ 0.795835] 0x0000_0000_0009_0000..0x0000_0000_001b_ffff --> 0x00_0009_0000..0x00_001b_ffff | 1 MiB | C RW XN | Kernel data and bss
[ 0.797406] 0x0000_0001_f000_0000..0x0000_0001_f000_ffff --> 0x00_3f20_0000..0x00_3f20_ffff | 64 KiB | Dev RW XN | BCM GPIO
[ 0.798857] | BCM PL011 UART
[ 0.800374] 0x0000_0001_f001_0000..0x0000_0001_f001_ffff --> 0x00_3f00_0000..0x00_3f00_ffff | 64 KiB | Dev RW XN | BCM Peripheral Interrupt Controller
[ 0.802117] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.789721] Booting on: Raspberry Pi 3
[ 0.789994] MMU online:
[ 0.790286] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.792030] Virtual Physical Size Attr Entity
[ 0.793774] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.795520] 0x0000_0000_0008_0000..0x0000_0000_0008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
[ 0.797134] 0x0000_0000_0009_0000..0x0000_0000_001b_ffff --> 0x00_0009_0000..0x00_001b_ffff | 1 MiB | C RW XN | Kernel data and bss
[ 0.798704] 0x0000_0000_001d_0000..0x0000_0000_0024_ffff --> 0x00_001d_0000..0x00_0024_ffff | 512 KiB | C RW XN | Kernel boot-core stack
[ 0.800307] 0x0000_0001_f000_0000..0x0000_0001_f000_ffff --> 0x00_3f20_0000..0x00_3f20_ffff | 64 KiB | Dev RW XN | BCM GPIO
[ 0.801759] | BCM PL011 UART
[ 0.803276] 0x0000_0001_f001_0000..0x0000_0001_f001_ffff --> 0x00_3f00_0000..0x00_3f00_ffff | 64 KiB | Dev RW XN | BCM Peripheral Interrupt Controller
[ 0.805020] -------------------------------------------------------------------------------------------------------------------------------------------
```
Raspberry Pi 4:
@ -344,19 +351,19 @@ Minipush 1.0
[MP] ⏩ Pushing 74 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now
[ 0.853908] Booting on: Raspberry Pi 4
[ 0.854007] MMU online:
[ 0.854299] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.856043] Virtual Physical Size Attr Entity
[ 0.857788] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.859533] 0x0000_0000_0007_0000..0x0000_0000_0007_ffff --> 0x00_0007_0000..0x00_0007_ffff | 64 KiB | C RW XN | Kernel boot-core stack
[ 0.861137] 0x0000_0000_0008_0000..0x0000_0000_0008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
[ 0.862750] 0x0000_0000_0009_0000..0x0000_0000_001b_ffff --> 0x00_0009_0000..0x00_001b_ffff | 1 MiB | C RW XN | Kernel data and bss
[ 0.864321] 0x0000_0001_f000_0000..0x0000_0001_f000_ffff --> 0x00_fe20_0000..0x00_fe20_ffff | 64 KiB | Dev RW XN | BCM GPIO
[ 0.865772] | BCM PL011 UART
[ 0.867289] 0x0000_0001_f001_0000..0x0000_0001_f001_ffff --> 0x00_ff84_0000..0x00_ff84_ffff | 64 KiB | Dev RW XN | GICD
[ 0.868697] | GICC
[ 0.870105] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.870371] Booting on: Raspberry Pi 4
[ 0.870470] MMU online:
[ 0.870763] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.872507] Virtual Physical Size Attr Entity
[ 0.874251] -------------------------------------------------------------------------------------------------------------------------------------------
[ 0.875996] 0x0000_0000_0008_0000..0x0000_0000_0008_ffff --> 0x00_0008_0000..0x00_0008_ffff | 64 KiB | C RO X | Kernel code and RO data
[ 0.877611] 0x0000_0000_0009_0000..0x0000_0000_001b_ffff --> 0x00_0009_0000..0x00_001b_ffff | 1 MiB | C RW XN | Kernel data and bss
[ 0.879181] 0x0000_0000_001d_0000..0x0000_0000_0024_ffff --> 0x00_001d_0000..0x00_0024_ffff | 512 KiB | C RW XN | Kernel boot-core stack
[ 0.880784] 0x0000_0001_f000_0000..0x0000_0001_f000_ffff --> 0x00_fe20_0000..0x00_fe20_ffff | 64 KiB | Dev RW XN | BCM GPIO
[ 0.882235] | BCM PL011 UART
[ 0.883752] 0x0000_0001_f001_0000..0x0000_0001_f001_ffff --> 0x00_ff84_0000..0x00_ff84_ffff | 64 KiB | Dev RW XN | GICD
[ 0.885160] | GICC
[ 0.886569] -------------------------------------------------------------------------------------------------------------------------------------------
```
## Diff to previous
@ -375,6 +382,55 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/cpu/boot.rs 15_v
// Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
asm::eret()
diff -uNr 14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/exception.rs 15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/exception.rs
--- 14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/exception.rs
+++ 15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/exception.rs
@@ -11,7 +11,11 @@
//!
//! crate::exception::arch_exception
-use crate::{bsp, exception};
+use crate::{
+ bsp::{self},
+ exception,
+ memory::Address,
+};
use core::{cell::UnsafeCell, fmt};
use cortex_a::{barrier, regs::*};
use register::InMemoryRegister;
@@ -50,6 +54,20 @@
// Private Code
//--------------------------------------------------------------------------------------------------
+/// Check if additional context can be derived from a data abort.
+fn inspect_data_abort(f: &mut fmt::Formatter) -> fmt::Result {
+ let fault_addr = Address::new(FAR_EL1.get() as usize);
+
+ if bsp::memory::mmu::virt_boot_core_stack_guard_page_desc().contains(fault_addr) {
+ writeln!(
+ f,
+ "\n\n >> Attempted to access the guard page of the kernel's boot core stack <<"
+ )?;
+ }
+
+ Ok(())
+}
+
/// Prints verbose information about the exception and then panics.
fn default_exception_handler(e: &ExceptionContext) {
panic!(
@@ -166,7 +184,9 @@
writeln!(f, " - {}", ec_translation)?;
// Raw print of instruction specific syndrome.
- write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))
+ write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
+
+ inspect_data_abort(f)
}
}
diff -uNr 14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/translation_table.rs 15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/memory/mmu/translation_table.rs
--- 14_exceptions_part2_peripheral_IRQs/src/_arch/aarch64/memory/mmu/translation_table.rs
+++ 15_virtual_mem_part2_mmio_remap/src/_arch/aarch64/memory/mmu/translation_table.rs
@ -1413,23 +1469,41 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/driver.rs 15_v
diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/link.ld 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/link.ld
--- 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/link.ld
+++ 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/link.ld
@@ -42,6 +42,11 @@
. += 8;
@@ -37,6 +37,7 @@
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
+ __rw_start = .;
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
@@ -49,4 +50,21 @@
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
+ . = ALIGN(65536);
+ __data_end = .;
+
+ __ro_size = __ro_end - __ro_start;
+ __data_size = __data_end - __ro_end;
/DISCARD/ : { *(.comment*) }
} :NONE
+
+ . = ALIGN(64K); /* Align to page boundary */
+ __rw_end_exclusive = .;
+
+ /***********************************************************************************************
+ * Guard Page between boot core stack and data
+ ***********************************************************************************************/
+ __boot_core_stack_guard_page_start = .;
+ . += 64K;
+ __boot_core_stack_guard_page_end_exclusive = .;
+
+ /***********************************************************************************************
+ * Boot Core Stack
+ ***********************************************************************************************/
+ __boot_core_stack_start = .;
+ . += 512K;
+ __boot_core_stack_end_exclusive = .;
}
diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory/mmu.rs
--- 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
+++ 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory/mmu.rs
@@ -4,70 +4,157 @@
@@ -4,70 +4,164 @@
//! BSP Memory Management Unit.
@ -1465,16 +1539,16 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
+/// The translation granule chosen by this BSP. This will be used everywhere else in the kernel to
+/// derive respective data structures and their sizes. For example, the `crate::memory::mmu::Page`.
+pub type KernelGranule = TranslationGranule<{ 64 * 1024 }>;
-const NUM_MEM_RANGES: usize = 2;
+
+/// The kernel's virtual address space defined by this BSP.
+pub type KernelVirtAddrSpace = AddressSpace<{ 8 * 1024 * 1024 * 1024 }>;
-/// The virtual memory layout.
-const NUM_MEM_RANGES: usize = 2;
+//--------------------------------------------------------------------------------------------------
+// Global instances
+//--------------------------------------------------------------------------------------------------
+
-/// The virtual memory layout.
+/// The kernel translation tables.
///
-/// The layout must contain only special ranges, aka anything that is _not_ normal cacheable DRAM.
@ -1484,7 +1558,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
- [
- TranslationDescriptor {
- name: "Kernel code and RO data",
- virtual_range: ro_range_inclusive,
- virtual_range: rx_range_inclusive,
- physical_range_translation: Translation::Identity,
- attribute_fields: AttributeFields {
- mem_attributes: MemAttributes::CacheableDRAM,
@ -1515,10 +1589,10 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
// Private Code
//--------------------------------------------------------------------------------------------------
-fn ro_range_inclusive() -> RangeInclusive<usize> {
-fn rx_range_inclusive() -> RangeInclusive<usize> {
- // Notice the subtraction to turn the exclusive end into an inclusive end.
- #[allow(clippy::range_minus_one)]
- RangeInclusive::new(super::ro_start(), super::ro_end() - 1)
- RangeInclusive::new(super::rx_start(), super::rx_end_exclusive() - 1)
+/// Helper function for calculating the number of pages the given parameter spans.
+const fn size_to_num_pages(size: usize) -> usize {
+ assert!(size > 0);
@ -1527,44 +1601,44 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
+ size >> KernelGranule::SHIFT
+}
+
+/// The boot core's stack.
+fn virt_stack_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::boot_core_stack_size());
+/// The Read+Execute (RX) pages of the kernel binary.
+fn virt_rx_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::rx_size());
+
+ PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
+ PageSliceDescriptor::from_addr(super::virt_rx_start(), num_pages)
+}
+
+/// The Read-Only (RO) pages of the kernel binary.
+fn virt_ro_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::ro_size());
+/// The Read+Write (RW) pages of the kernel binary.
+fn virt_rw_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::rw_size());
+
+ PageSliceDescriptor::from_addr(super::virt_ro_start(), num_pages)
+ PageSliceDescriptor::from_addr(super::virt_rw_start(), num_pages)
+}
+
+/// The data pages of the kernel binary.
+fn virt_data_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::data_size());
+/// The boot core's stack.
+fn virt_boot_core_stack_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::boot_core_stack_size());
+
+ PageSliceDescriptor::from_addr(super::virt_data_start(), num_pages)
+ PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
+}
+
+// The binary is still identity mapped, so we don't need to convert in the following.
+
+/// The boot core's stack.
+fn phys_stack_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_stack_page_desc().into()
+}
+
+/// The Read-Only (RO) pages of the kernel binary.
+fn phys_ro_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_ro_page_desc().into()
+/// The Read+Execute (RX) pages of the kernel binary.
+fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_rx_page_desc().into()
}
-fn mmio_range_inclusive() -> RangeInclusive<usize> {
- RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
+/// The data pages of the kernel binary.
+fn phys_data_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_data_page_desc().into()
+/// The Read+Write (RW) pages of the kernel binary.
+fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_rw_page_desc().into()
+}
+
+/// The boot core's stack.
+fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
+ virt_boot_core_stack_page_desc().into()
}
//--------------------------------------------------------------------------------------------------
@ -1579,6 +1653,13 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
+ &KERNEL_TABLES
+}
+
+/// The boot core's stack guard page.
+pub fn virt_boot_core_stack_guard_page_desc() -> PageSliceDescriptor<Virtual> {
+ let num_pages = size_to_num_pages(super::boot_core_stack_guard_page_size());
+
+ PageSliceDescriptor::from_addr(super::virt_boot_core_stack_guard_page_start(), num_pages)
+}
+
+/// Pointer to the last page of the physical address space.
+pub fn phys_addr_space_end_page() -> *const Page<Physical> {
+ common::align_down(
@ -1594,31 +1675,31 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
+/// - Any miscalculation or attribute error will likely be fatal. Needs careful manual checking.
+pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
+ generic_mmu::kernel_map_pages_at(
+ "Kernel boot-core stack",
+ &virt_stack_page_desc(),
+ &phys_stack_page_desc(),
+ "Kernel code and RO data",
+ &virt_rx_page_desc(),
+ &phys_rx_page_desc(),
+ &AttributeFields {
+ mem_attributes: MemAttributes::CacheableDRAM,
+ acc_perms: AccessPermissions::ReadWrite,
+ execute_never: true,
+ acc_perms: AccessPermissions::ReadOnly,
+ execute_never: false,
+ },
+ )?;
+
+ generic_mmu::kernel_map_pages_at(
+ "Kernel code and RO data",
+ &virt_ro_page_desc(),
+ &phys_ro_page_desc(),
+ "Kernel data and bss",
+ &virt_rw_page_desc(),
+ &phys_rw_page_desc(),
+ &AttributeFields {
+ mem_attributes: MemAttributes::CacheableDRAM,
+ acc_perms: AccessPermissions::ReadOnly,
+ execute_never: false,
+ acc_perms: AccessPermissions::ReadWrite,
+ execute_never: true,
+ },
+ )?;
+
+ generic_mmu::kernel_map_pages_at(
+ "Kernel data and bss",
+ &virt_data_page_desc(),
+ &phys_data_page_desc(),
+ "Kernel boot-core stack",
+ &virt_boot_core_stack_page_desc(),
+ &phys_boot_core_stack_page_desc(),
+ &AttributeFields {
+ mem_attributes: MemAttributes::CacheableDRAM,
+ acc_perms: AccessPermissions::ReadWrite,
@ -1630,7 +1711,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
}
//--------------------------------------------------------------------------------------------------
@@ -82,14 +169,12 @@
@@ -82,14 +176,18 @@
/// Check alignment of the kernel's virtual memory layout sections.
#[kernel_test]
fn virt_mem_layout_sections_are_64KiB_aligned() {
@ -1639,7 +1720,13 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
- for i in LAYOUT.inner().iter() {
- let start: usize = *(i.virtual_range)().start();
- let end: usize = *(i.virtual_range)().end() + 1;
+ for i in [virt_stack_page_desc, virt_ro_page_desc, virt_data_page_desc].iter() {
+ for i in [
+ virt_rx_page_desc,
+ virt_rw_page_desc,
+ virt_boot_core_stack_page_desc,
+ ]
+ .iter()
+ {
+ let start: usize = i().start_addr().into_usize();
+ let end: usize = i().end_addr().into_usize();
@ -1650,7 +1737,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
assert!(end >= start);
}
}
@@ -97,18 +182,28 @@
@@ -97,18 +195,28 @@
/// Ensure the kernel's virtual memory layout is free of overlaps.
#[kernel_test]
fn virt_mem_layout_has_no_overlaps() {
@ -1666,9 +1753,9 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
- assert!(!second_range().contains(first_range().start()));
- assert!(!second_range().contains(first_range().end()));
+ let layout = [
+ virt_stack_page_desc(),
+ virt_ro_page_desc(),
+ virt_data_page_desc(),
+ virt_rx_page_desc(),
+ virt_rw_page_desc(),
+ virt_boot_core_stack_page_desc(),
+ ];
+
+ for (i, first_range) in layout.iter().enumerate() {
@ -1694,7 +1781,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs
diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory.rs
--- 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
+++ 15_virtual_mem_part2_mmio_remap/src/bsp/raspberrypi/memory.rs
@@ -3,9 +3,41 @@
@@ -3,9 +3,40 @@
// Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
//! BSP Memory Management.
@ -1703,31 +1790,30 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
+//! copies the binary to 0x8_0000:
+//!
+//! +---------------------------------------------+
+//! | | 0x0
+//! | Unmapped |
+//! | | 0x6_FFFF
+//! +---------------------------------------------+
+//! | BOOT_CORE_STACK_START | 0x7_0000
+//! | | ^
+//! | ... | | Stack growth direction
+//! | | |
+//! | BOOT_CORE_STACK_END_INCLUSIVE | 0x7_FFFF
+//! +---------------------------------------------+
+//! | RO_START == BOOT_CORE_STACK_END | 0x8_0000
+//! | |
+//! | Unmapped |
+//! | |
+//! +---------------------------------------------+
+//! | | rx_start @ 0x8_0000
+//! | .text |
+//! | .exception_vectors |
+//! | .rodata |
+//! | |
+//! | RO_END_INCLUSIVE | 0x8_0000 + __ro_size - 1
+//! | .got |
+//! | | rx_end_inclusive
+//! +---------------------------------------------+
+//! | RO_END == DATA_START | 0x8_0000 + __ro_size
+//! | |
+//! | | rw_start == ro_end
+//! | .data |
+//! | .bss |
+//! | | rw_end_inclusive
+//! +---------------------------------------------+
+//! | | rw_end
+//! | Unmapped Boot-core Stack Guard Page |
+//! | |
+//! | DATA_END_INCLUSIVE | 0x8_0000 + __ro_size + __data_size - 1
+//! +---------------------------------------------+
+//! | | boot_core_stack_start ^
+//! | | | stack
+//! | Boot-core Stack | | growth
+//! | | | direction
+//! | | boot_core_stack_end_inclusive |
+//! +---------------------------------------------+
pub mod mmu;
@ -1736,21 +1822,25 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
use core::{cell::UnsafeCell, ops::RangeInclusive};
//--------------------------------------------------------------------------------------------------
@@ -17,47 +49,39 @@
@@ -17,8 +48,16 @@
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
+ static __rw_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
- static __ro_end: UnsafeCell<()>;
+ static __ro_size: UnsafeCell<()>;
+ static __data_size: UnsafeCell<()>;
+ static __rw_end_exclusive: UnsafeCell<()>;
+
+ static __boot_core_stack_start: UnsafeCell<()>;
+ static __boot_core_stack_end_exclusive: UnsafeCell<()>;
+
+ static __boot_core_stack_guard_page_start: UnsafeCell<()>;
+ static __boot_core_stack_guard_page_end_exclusive: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------
-/// The board's memory map.
+/// The board's physical memory map.
@@ -28,35 +67,26 @@
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
- /// The inclusive end address of the memory map.
@ -1767,13 +1857,10 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
- /// physical address that is not backed by any DRAM (e.g. accessing an address close to 4 GiB on
- /// an RPi3 that comes with 1 GiB of RAM). This would result in a crash or other kind of error.
- pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
+ use super::*;
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
-
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const BOOT_CORE_STACK_SIZE: usize = 0x1_0000;
+ use super::*;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
@ -1802,7 +1889,7 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
}
/// Physical devices.
@@ -65,13 +89,22 @@
@@ -64,13 +94,22 @@
pub mod mmio {
use super::*;
@ -1831,53 +1918,72 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
}
//--------------------------------------------------------------------------------------------------
@@ -84,8 +117,8 @@
@@ -83,18 +122,69 @@
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
-fn ro_start() -> usize {
- unsafe { __ro_start.get() as usize }
+fn virt_ro_start() -> Address<Virtual> {
+ Address::new(unsafe { __ro_start.get() as usize })
-fn rx_start() -> usize {
- unsafe { __rx_start.get() as usize }
+fn virt_rx_start() -> Address<Virtual> {
+ Address::new(unsafe { __rx_start.get() as usize })
}
/// Size of the Read-Only (RO) range of the kernel binary.
@@ -94,8 +127,42 @@
-/// Exclusive end address of the Read+Execute (RX) range.
+/// Size of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
-fn ro_end() -> usize {
- unsafe { __ro_end.get() as usize }
+fn ro_size() -> usize {
+ unsafe { __ro_size.get() as usize }
-fn rx_end_exclusive() -> usize {
- unsafe { __rx_end_exclusive.get() as usize }
+fn rx_size() -> usize {
+ unsafe { (__rx_end_exclusive.get() as usize) - (__rx_start.get() as usize) }
+}
+
+/// Start address of the data range.
+/// Start address of the Read+Write (RW) range.
+#[inline(always)]
+fn virt_data_start() -> Address<Virtual> {
+ virt_ro_start() + ro_size()
+fn virt_rw_start() -> Address<Virtual> {
+ Address::new(unsafe { __rw_start.get() as usize })
+}
+
+/// Size of the data range.
+/// Size of the Read+Write (RW) range.
+///
+/// # Safety
+///
+/// - Value is provided by the linker script and must be trusted as-is.
+#[inline(always)]
+fn data_size() -> usize {
+ unsafe { __data_size.get() as usize }
+fn rw_size() -> usize {
+ unsafe { (__rw_end_exclusive.get() as usize) - (__rw_start.get() as usize) }
+}
+
+/// Start address of the boot core's stack.
+#[inline(always)]
+fn virt_boot_core_stack_start() -> Address<Virtual> {
+ virt_ro_start() - map::BOOT_CORE_STACK_SIZE
+ Address::new(unsafe { __boot_core_stack_start.get() as usize })
+}
+
+/// Size of the boot core's stack.
+#[inline(always)]
+fn boot_core_stack_size() -> usize {
+ map::BOOT_CORE_STACK_SIZE
+ unsafe {
+ (__boot_core_stack_end_exclusive.get() as usize) - (__boot_core_stack_start.get() as usize)
+ }
+}
+
+/// Start address of the boot core's stack guard page.
+#[inline(always)]
+fn virt_boot_core_stack_guard_page_start() -> Address<Virtual> {
+ Address::new(unsafe { __boot_core_stack_guard_page_start.get() as usize })
+}
+
+/// Size of the boot core's stack guard page.
+#[inline(always)]
+fn boot_core_stack_guard_page_size() -> usize {
+ unsafe {
+ (__boot_core_stack_guard_page_end_exclusive.get() as usize)
+ - (__boot_core_stack_guard_page_start.get() as usize)
+ }
+}
+
+/// Exclusive end address of the physical address space.
@ -1887,12 +1993,12 @@ diff -uNr 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs 15_v
}
//--------------------------------------------------------------------------------------------------
@@ -104,8 +171,10 @@
@@ -103,8 +193,10 @@
/// Exclusive end address of the boot core's stack.
#[inline(always)]
-pub fn boot_core_stack_end() -> usize {
- map::BOOT_CORE_STACK_END
- rx_start()
+pub fn phys_boot_core_stack_end() -> Address<Physical> {
+ // The binary is still identity mapped, so we don't need to convert here.
+ let end = virt_boot_core_stack_start().into_usize() + boot_core_stack_size();

@ -50,7 +50,7 @@
//--------------------------------------------------------------------------------------------------
// The exception vector table.
//--------------------------------------------------------------------------------------------------
.section .exception_vectors, "ax", @progbits
.section .text
// Align by 2^11 bytes, as demanded by ARMv8-A. Same as ALIGN(2048) in an ld script.
.align 11

@ -11,7 +11,11 @@
//!
//! crate::exception::arch_exception
use crate::{bsp, exception};
use crate::{
bsp::{self},
exception,
memory::Address,
};
use core::{cell::UnsafeCell, fmt};
use cortex_a::{barrier, regs::*};
use register::InMemoryRegister;
@ -50,6 +54,20 @@ struct EsrEL1;
// Private Code
//--------------------------------------------------------------------------------------------------
/// Check if additional context can be derived from a data abort.
fn inspect_data_abort(f: &mut fmt::Formatter) -> fmt::Result {
let fault_addr = Address::new(FAR_EL1.get() as usize);
if bsp::memory::mmu::virt_boot_core_stack_guard_page_desc().contains(fault_addr) {
writeln!(
f,
"\n\n >> Attempted to access the guard page of the kernel's boot core stack <<"
)?;
}
Ok(())
}
/// Prints verbose information about the exception and then panics.
fn default_exception_handler(e: &ExceptionContext) {
panic!(
@ -68,18 +86,18 @@ fn default_exception_handler(e: &ExceptionContext) {
//------------------------------------------------------------------------------
#[no_mangle]
unsafe extern "C" fn current_el0_synchronous(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_irq(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
#[no_mangle]
unsafe extern "C" fn current_el0_serror(e: &mut ExceptionContext) {
default_exception_handler(e);
unsafe extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
panic!("Should not be here. Use of SP_EL0 in EL1 is not supported.")
}
//------------------------------------------------------------------------------
@ -168,7 +186,7 @@ impl fmt::Display for EsrEL1 {
// Raw print of instruction specific syndrome.
write!(f, " Instr Specific Syndrome (ISS): {:#x}", esr_el1.read(ESR_EL1::ISS))?;
Ok(())
inspect_data_abort(f)
}
}
@ -201,9 +219,7 @@ impl fmt::Display for SpsrEL1 {
write!(f, " Illegal Execution State (IL): {}",
to_flag_str(self.0.is_set(SPSR_EL1::IL))
)?;
Ok(())
)
}
}
@ -224,9 +240,7 @@ impl fmt::Display for ExceptionContext {
for (i, reg) in self.gpr.iter().enumerate() {
write!(f, " x{: <2}: {: >#018x}{}", i, reg, alternating(i))?;
}
write!(f, " lr : {:#018x}", self.lr)?;
Ok(())
write!(f, " lr : {:#018x}", self.lr)
}
}

@ -3,50 +3,68 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
__ro_start = .;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.exception_vectors :
{
*(.exception_vectors*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.rodata :
{
*(.rodata*)
}
. = ALIGN(65536); /* Fill up to 64 KiB */
__ro_end = .;
. = ALIGN(64K); /* Align to page boundary */
__rx_end_exclusive = .;
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
__rw_start = .;
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
. = ALIGN(65536);
__data_end = .;
} :NONE
. = ALIGN(64K); /* Align to page boundary */
__rw_end_exclusive = .;
__ro_size = __ro_end - __ro_start;
__data_size = __data_end - __ro_end;
/***********************************************************************************************
* Guard Page between boot core stack and data
***********************************************************************************************/
__boot_core_stack_guard_page_start = .;
. += 64K;
__boot_core_stack_guard_page_end_exclusive = .;
/DISCARD/ : { *(.comment*) }
/***********************************************************************************************
* Boot Core Stack
***********************************************************************************************/
__boot_core_stack_start = .;
. += 512K;
__boot_core_stack_end_exclusive = .;
}

@ -8,31 +8,30 @@
//! copies the binary to 0x8_0000:
//!
//! +---------------------------------------------+
//! | | 0x0
//! | Unmapped |
//! | | 0x6_FFFF
//! +---------------------------------------------+
//! | BOOT_CORE_STACK_START | 0x7_0000
//! | | ^
//! | ... | | Stack growth direction
//! | | |
//! | BOOT_CORE_STACK_END_INCLUSIVE | 0x7_FFFF
//! +---------------------------------------------+
//! | RO_START == BOOT_CORE_STACK_END | 0x8_0000
//! | |
//! | Unmapped |
//! | |
//! +---------------------------------------------+
//! | | rx_start @ 0x8_0000
//! | .text |
//! | .exception_vectors |
//! | .rodata |
//! | |
//! | RO_END_INCLUSIVE | 0x8_0000 + __ro_size - 1
//! | .got |
//! | | rx_end_inclusive
//! +---------------------------------------------+
//! | RO_END == DATA_START | 0x8_0000 + __ro_size
//! | |
//! | | rw_start == rx_end
//! | .data |
//! | .bss |
//! | | rw_end_inclusive
//! +---------------------------------------------+
//! | | rw_end
//! | Unmapped Boot-core Stack Guard Page |
//! | |
//! | DATA_END_INCLUSIVE | 0x8_0000 + __ro_size + __data_size - 1
//! +---------------------------------------------+
//! | | boot_core_stack_start ^
//! | | | stack
//! | Boot-core Stack | | growth
//! | | | direction
//! | | boot_core_stack_end_inclusive |
//! +---------------------------------------------+
pub mod mmu;
@ -46,11 +45,19 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __rx_end_exclusive: UnsafeCell<()>;
static __rw_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
static __ro_start: UnsafeCell<()>;
static __ro_size: UnsafeCell<()>;
static __data_size: UnsafeCell<()>;
static __rw_end_exclusive: UnsafeCell<()>;
static __boot_core_stack_start: UnsafeCell<()>;
static __boot_core_stack_end_exclusive: UnsafeCell<()>;
static __boot_core_stack_guard_page_start: UnsafeCell<()>;
static __boot_core_stack_guard_page_end_exclusive: UnsafeCell<()>;
}
//--------------------------------------------------------------------------------------------------
@ -62,8 +69,6 @@ extern "Rust" {
pub(super) mod map {
use super::*;
pub const BOOT_CORE_STACK_SIZE: usize = 0x1_0000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
pub mod mmio {
@ -111,52 +116,69 @@ pub(super) mod map {
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read-Only (RO) range.
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn virt_ro_start() -> Address<Virtual> {
Address::new(unsafe { __ro_start.get() as usize })
fn virt_rx_start() -> Address<Virtual> {
Address::new(unsafe { __rx_start.get() as usize })
}
/// Size of the Read-Only (RO) range of the kernel binary.
/// Size of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn ro_size() -> usize {
unsafe { __ro_size.get() as usize }
fn rx_size() -> usize {
unsafe { (__rx_end_exclusive.get() as usize) - (__rx_start.get() as usize) }
}
/// Start address of the data range.
/// Start address of the Read+Write (RW) range.
#[inline(always)]
fn virt_data_start() -> Address<Virtual> {
virt_ro_start() + ro_size()
fn virt_rw_start() -> Address<Virtual> {
Address::new(unsafe { __rw_start.get() as usize })
}
/// Size of the data range.
/// Size of the Read+Write (RW) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn data_size() -> usize {
unsafe { __data_size.get() as usize }
fn rw_size() -> usize {
unsafe { (__rw_end_exclusive.get() as usize) - (__rw_start.get() as usize) }
}
/// Start address of the boot core's stack.
#[inline(always)]
fn virt_boot_core_stack_start() -> Address<Virtual> {
virt_ro_start() - map::BOOT_CORE_STACK_SIZE
Address::new(unsafe { __boot_core_stack_start.get() as usize })
}
/// Size of the boot core's stack.
#[inline(always)]
fn boot_core_stack_size() -> usize {
map::BOOT_CORE_STACK_SIZE
unsafe {
(__boot_core_stack_end_exclusive.get() as usize) - (__boot_core_stack_start.get() as usize)
}
}
/// Start address of the boot core's stack guard page.
#[inline(always)]
fn virt_boot_core_stack_guard_page_start() -> Address<Virtual> {
Address::new(unsafe { __boot_core_stack_guard_page_start.get() as usize })
}
/// Size of the boot core's stack guard page.
#[inline(always)]
fn boot_core_stack_guard_page_size() -> usize {
unsafe {
(__boot_core_stack_guard_page_end_exclusive.get() as usize)
- (__boot_core_stack_guard_page_start.get() as usize)
}
}
/// Exclusive end address of the physical address space.

@ -60,42 +60,42 @@ const fn size_to_num_pages(size: usize) -> usize {
size >> KernelGranule::SHIFT
}
/// The boot core's stack.
fn virt_stack_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::boot_core_stack_size());
/// The Read+Execute (RX) pages of the kernel binary.
fn virt_rx_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::rx_size());
PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
PageSliceDescriptor::from_addr(super::virt_rx_start(), num_pages)
}
/// The Read-Only (RO) pages of the kernel binary.
fn virt_ro_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::ro_size());
/// The Read+Write (RW) pages of the kernel binary.
fn virt_rw_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::rw_size());
PageSliceDescriptor::from_addr(super::virt_ro_start(), num_pages)
PageSliceDescriptor::from_addr(super::virt_rw_start(), num_pages)
}
/// The data pages of the kernel binary.
fn virt_data_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::data_size());
/// The boot core's stack.
fn virt_boot_core_stack_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::boot_core_stack_size());
PageSliceDescriptor::from_addr(super::virt_data_start(), num_pages)
PageSliceDescriptor::from_addr(super::virt_boot_core_stack_start(), num_pages)
}
// The binary is still identity mapped, so we don't need to convert in the following.
/// The boot core's stack.
fn phys_stack_page_desc() -> PageSliceDescriptor<Physical> {
virt_stack_page_desc().into()
/// The Read+Execute (RX) pages of the kernel binary.
fn phys_rx_page_desc() -> PageSliceDescriptor<Physical> {
virt_rx_page_desc().into()
}
/// The Read-Only (RO) pages of the kernel binary.
fn phys_ro_page_desc() -> PageSliceDescriptor<Physical> {
virt_ro_page_desc().into()
/// The Read+Write (RW) pages of the kernel binary.
fn phys_rw_page_desc() -> PageSliceDescriptor<Physical> {
virt_rw_page_desc().into()
}
/// The data pages of the kernel binary.
fn phys_data_page_desc() -> PageSliceDescriptor<Physical> {
virt_data_page_desc().into()
/// The boot core's stack.
fn phys_boot_core_stack_page_desc() -> PageSliceDescriptor<Physical> {
virt_boot_core_stack_page_desc().into()
}
//--------------------------------------------------------------------------------------------------
@ -107,6 +107,13 @@ pub fn kernel_translation_tables() -> &'static InitStateLock<KernelTranslationTa
&KERNEL_TABLES
}
/// The boot core's stack guard page.
pub fn virt_boot_core_stack_guard_page_desc() -> PageSliceDescriptor<Virtual> {
let num_pages = size_to_num_pages(super::boot_core_stack_guard_page_size());
PageSliceDescriptor::from_addr(super::virt_boot_core_stack_guard_page_start(), num_pages)
}
/// Pointer to the last page of the physical address space.
pub fn phys_addr_space_end_page() -> *const Page<Physical> {
common::align_down(
@ -122,31 +129,31 @@ pub fn phys_addr_space_end_page() -> *const Page<Physical> {
/// - Any miscalculation or attribute error will likely be fatal. Needs careful manual checking.
pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
generic_mmu::kernel_map_pages_at(
"Kernel boot-core stack",
&virt_stack_page_desc(),
&phys_stack_page_desc(),
"Kernel code and RO data",
&virt_rx_page_desc(),
&phys_rx_page_desc(),
&AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadWrite,
execute_never: true,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
},
)?;
generic_mmu::kernel_map_pages_at(
"Kernel code and RO data",
&virt_ro_page_desc(),
&phys_ro_page_desc(),
"Kernel data and bss",
&virt_rw_page_desc(),
&phys_rw_page_desc(),
&AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadOnly,
execute_never: false,
acc_perms: AccessPermissions::ReadWrite,
execute_never: true,
},
)?;
generic_mmu::kernel_map_pages_at(
"Kernel data and bss",
&virt_data_page_desc(),
&phys_data_page_desc(),
"Kernel boot-core stack",
&virt_boot_core_stack_page_desc(),
&phys_boot_core_stack_page_desc(),
&AttributeFields {
mem_attributes: MemAttributes::CacheableDRAM,
acc_perms: AccessPermissions::ReadWrite,
@ -169,7 +176,13 @@ mod tests {
/// Check alignment of the kernel's virtual memory layout sections.
#[kernel_test]
fn virt_mem_layout_sections_are_64KiB_aligned() {
for i in [virt_stack_page_desc, virt_ro_page_desc, virt_data_page_desc].iter() {
for i in [
virt_rx_page_desc,
virt_rw_page_desc,
virt_boot_core_stack_page_desc,
]
.iter()
{
let start: usize = i().start_addr().into_usize();
let end: usize = i().end_addr().into_usize();
@ -183,9 +196,9 @@ mod tests {
#[kernel_test]
fn virt_mem_layout_has_no_overlaps() {
let layout = [
virt_stack_page_desc(),
virt_ro_page_desc(),
virt_data_page_desc(),
virt_rx_page_desc(),
virt_rw_page_desc(),
virt_boot_core_stack_page_desc(),
];
for (i, first_range) in layout.iter().enumerate() {

@ -122,6 +122,7 @@ objdump: $(KERNEL_ELF)
@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
--section .text \
--section .rodata \
--section .got \
$(KERNEL_ELF) | rustfilt
nm: $(KERNEL_ELF)

Binary file not shown.

Binary file not shown.

@ -3,37 +3,47 @@
* Copyright (c) 2018-2021 Andre Richter <andre.o.richter@gmail.com>
*/
/* The address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_load_addr = 0x80000;
ENTRY(__rpi_load_addr)
PHDRS
{
segment_rx PT_LOAD FLAGS(5); /* 5 == RX */
segment_rw PT_LOAD FLAGS(6); /* 6 == RW */
}
SECTIONS
{
/* Set current address to the value from which the RPi starts execution */
. = 0x80000;
. = __rpi_load_addr;
/***********************************************************************************************
* Code + RO Data + Global Offset Table
***********************************************************************************************/
__rx_start = .;
.text :
{
*(.text._start) *(.text*)
}
KEEP(*(.text._start))
*(.text*)
} :segment_rx
.rodata :
{
*(.rodata*)
}
.rodata : ALIGN(8) { *(.rodata*) } :segment_rx
.got : ALIGN(8) { *(.got) } :segment_rx
.data :
{
*(.data*)
}
/***********************************************************************************************
* Data + BSS
***********************************************************************************************/
.data : { *(.data*) } :segment_rw
/* Section is zeroed in u64 chunks, align start and end to 8 bytes */
.bss ALIGN(8):
.bss : ALIGN(8)
{
__bss_start = .;
*(.bss*);
. = ALIGN(8);
/* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
. += 8;
. += 8; /* Fill for the bss == 0 case, so that __bss_start <= __bss_end_inclusive holds */
__bss_end_inclusive = . - 8;
}
/DISCARD/ : { *(.comment*) }
} :NONE
}

@ -12,6 +12,8 @@ use core::{cell::UnsafeCell, ops::RangeInclusive};
// Symbols from the linker script.
extern "Rust" {
static __rx_start: UnsafeCell<()>;
static __bss_start: UnsafeCell<u64>;
static __bss_end_inclusive: UnsafeCell<u64>;
}
@ -20,10 +22,9 @@ extern "Rust" {
// Public Definitions
//--------------------------------------------------------------------------------------------------
/// The board's memory map.
/// The board's physical memory map.
#[rustfmt::skip]
pub(super) mod map {
pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000;
@ -49,6 +50,20 @@ pub(super) mod map {
}
}
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
/// Start address of the Read+Execute (RX) range.
///
/// # Safety
///
/// - Value is provided by the linker script and must be trusted as-is.
#[inline(always)]
fn rx_start() -> usize {
unsafe { __rx_start.get() as usize }
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
@ -56,7 +71,7 @@ pub(super) mod map {
/// Exclusive end address of the boot core's stack.
#[inline(always)]
pub fn boot_core_stack_end() -> usize {
map::BOOT_CORE_STACK_END
rx_start()
}
/// Return the inclusive range spanning the .bss section.

Loading…
Cancel
Save