Skip to content

Commit

Permalink
add support for Raspberry Pi
Browse files Browse the repository at this point in the history
  • Loading branch information
Miochyann committed Feb 23, 2024
1 parent c28a269 commit 7230aed
Show file tree
Hide file tree
Showing 13 changed files with 623 additions and 0 deletions.
46 changes: 46 additions & 0 deletions modules/ruxhal/src/platform/aarch64_raspi/mem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::mem::*;
use page_table_entry::{aarch64::A64PTE, GenericPTE, MappingFlags};

/// Returns platform-specific memory regions.
pub(crate) fn platform_regions() -> impl Iterator<Item = MemRegion> {
core::iter::once(MemRegion {
paddr: 0x0.into(),
size: 0x1000,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
name: "spintable",
})
.chain(crate::mem::default_free_regions())
.chain(crate::mem::default_mmio_regions())
}

pub(crate) unsafe fn init_boot_page_table(
boot_pt_l0: &mut [A64PTE; 512],
boot_pt_l1: &mut [A64PTE; 512],
) {
// 0x0000_0000_0000 ~ 0x0080_0000_0000, table
boot_pt_l0[0] = A64PTE::new_table(PhysAddr::from(boot_pt_l1.as_ptr() as usize));
// 0x0000_0000_0000..0x0000_4000_0000, 1G block, device memory
boot_pt_l1[0] = A64PTE::new_page(
PhysAddr::from(0),
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE,
true,
);
// 0x0000_4000_0000..0x0000_8000_0000, 1G block, normal memory
boot_pt_l1[1] = A64PTE::new_page(
PhysAddr::from(0x4000_0000),
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE,
true,
);
// 0x0000_8000_0000..0x0000_C000_0000, 1G block, normal memory
boot_pt_l1[2] = A64PTE::new_page(
PhysAddr::from(0x8000_0000),
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::EXECUTE,
true,
);
// 0x0000_C000_0000..0x0001_0000_0000, 1G block, DEVICE memory
boot_pt_l1[3] = A64PTE::new_page(
PhysAddr::from(0xc000_0000),
MappingFlags::READ | MappingFlags::WRITE | MappingFlags::DEVICE,
true,
);
}
69 changes: 69 additions & 0 deletions modules/ruxhal/src/platform/aarch64_raspi/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
pub mod mem;

#[cfg(feature = "smp")]
pub mod mp;

#[cfg(feature = "irq")]
pub mod irq {
pub use crate::platform::aarch64_common::gic::*;
}

pub mod console {
pub use crate::platform::aarch64_common::pl011::*;
}

pub mod time {
pub use crate::platform::aarch64_common::generic_timer::*;
}

pub mod misc {
pub fn terminate() -> ! {
info!("Shutting down...");
loop {
crate::arch::halt();
}
}
}

extern "C" {
fn exception_vector_base();
fn rust_main(cpu_id: usize, dtb: usize);
#[cfg(feature = "smp")]
fn rust_main_secondary(cpu_id: usize);
}

pub(crate) unsafe extern "C" fn rust_entry(cpu_id: usize, dtb: usize) {
crate::mem::clear_bss();
crate::arch::set_exception_vector_base(exception_vector_base as usize);
crate::arch::write_page_table_root0(0.into()); // disable low address access
crate::cpu::init_primary(cpu_id);
super::aarch64_common::pl011::init_early();
super::aarch64_common::generic_timer::init_early();
rust_main(cpu_id, dtb);
}

#[cfg(feature = "smp")]
pub(crate) unsafe extern "C" fn rust_entry_secondary(cpu_id: usize) {
crate::arch::set_exception_vector_base(exception_vector_base as usize);
crate::arch::write_page_table_root0(0.into()); // disable low address access
crate::cpu::init_secondary(cpu_id);
rust_main_secondary(cpu_id);
}

/// Initializes the platform devices for the primary CPU.
///
/// For example, the interrupt controller and the timer.
pub fn platform_init() {
#[cfg(feature = "irq")]
super::aarch64_common::gic::init_primary();
super::aarch64_common::generic_timer::init_percpu();
super::aarch64_common::pl011::init();
}

/// Initializes the platform devices for secondary CPUs.
#[cfg(feature = "smp")]
pub fn platform_init_secondary() {
#[cfg(feature = "irq")]
super::aarch64_common::gic::init_secondary();
super::aarch64_common::generic_timer::init_percpu();
}
49 changes: 49 additions & 0 deletions modules/ruxhal/src/platform/aarch64_raspi/mp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::mem::{phys_to_virt, virt_to_phys, PhysAddr, VirtAddr};

static mut SECONDARY_STACK_TOP: usize = 0;

extern "C" {
fn _start_secondary();
}

#[naked]
#[link_section = ".text.boot"]
unsafe extern "C" fn modify_stack_and_start() {
core::arch::asm!("
ldr x21, ={secondary_boot_stack} // the secondary CPU hasn't set the TTBR1
mov x8, {phys_virt_offset} // minus the offset to get the phys addr of the boot stack
sub x21, x21, x8
ldr x21, [x21]
mov x0, x21 // x0 will be set to SP in the beginning of _start_secondary
b _start_secondary",
secondary_boot_stack = sym SECONDARY_STACK_TOP,
phys_virt_offset = const axconfig::PHYS_VIRT_OFFSET,
options(noreturn)
);
}

pub static CPU_SPIN_TABLE: [PhysAddr; 4] = [
PhysAddr::from(0xd8),
PhysAddr::from(0xe0),
PhysAddr::from(0xe8),
PhysAddr::from(0xf0),
];

/// Starts the given secondary CPU with its boot stack.
pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) {
let entry_paddr = virt_to_phys(VirtAddr::from(modify_stack_and_start as usize)).as_usize();
unsafe {
// set the boot code address of the given secondary CPU
let spintable_vaddr = phys_to_virt(CPU_SPIN_TABLE[cpu_id]);
let release_ptr = spintable_vaddr.as_mut_ptr() as *mut usize;
release_ptr.write_volatile(entry_paddr);
crate::arch::flush_dcache_line(spintable_vaddr);

// set the boot stack of the given secondary CPU
SECONDARY_STACK_TOP = stack_top.as_usize();
crate::arch::flush_dcache_line(VirtAddr::from(
(&SECONDARY_STACK_TOP as *const usize) as usize,
));
}
aarch64_cpu::asm::sev();
}
3 changes: 3 additions & 0 deletions modules/ruxhal/src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-qemu-virt"))] {
mod aarch64_qemu_virt;
pub use self::aarch64_qemu_virt::*;
} else if #[cfg(all(target_arch = "aarch64", platform_family = "aarch64-raspi"))] {
mod aarch64_raspi;
pub use self::aarch64_raspi::*;
} else {
mod dummy;
pub use self::dummy::*;
Expand Down
31 changes: 31 additions & 0 deletions platforms/aarch64-raspi4.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Architecture identifier.
arch = "aarch64"
# Platform identifier.
platform = "aarch64-raspi4"
# Platform family.
family = "aarch64-raspi"

# Base address of the whole physical memory.
phys-memory-base = "0x0"
# Size of the whole physical memory.
phys-memory-size = "0xFC00_0000" # 3G 960M
# Base physical address of the kernel image.
kernel-base-paddr = "0x8_0000"
# Base virtual address of the kernel image.
kernel-base-vaddr = "0xffff_0000_0008_0000"
# Linear mapping offset, for quick conversions between physical and virtual
# addresses.
phys-virt-offset = "0xffff_0000_0000_0000"
# MMIO regions with format (`base_paddr`, `size`).
mmio-regions = [
["0xFE20_1000", "0x1000"], # PL011 UART
["0xFF84_1000", "0x8000"], # GICv2
]
virtio-mmio-regions = []
# UART Address
uart-paddr = "0xFE20_1000"
uart-irq = "0x79"

# GIC Address
gicc-paddr = "0xFF84_2000"
gicd-paddr = "0xFF84_1000"
94 changes: 94 additions & 0 deletions scripts/make/raspi4.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
include tools/raspi4/common/docker.mk
include tools/raspi4/common/format.mk
include tools/raspi4/common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi4.
BSP ?= rpi4

# Default to a serial device name that is common in Linux.
DEV_SERIAL ?= /dev/ttyACM0

##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi4)
TARGET = aarch64-unknown-none-softfloat
KERNEL_BIN := $(OUT_BIN)
OBJDUMP_BINARY = aarch64-none-elf-objdump
NM_BINARY = aarch64-none-elf-nm
READELF_BINARY = aarch64-none-elf-readelf
OPENOCD_ARG = -f /openocd/tcl/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /openocd/rpi4.cfg
JTAG_BOOT_IMAGE = tools/raspi4/X1_JTAG_boot/jtag_boot_rpi4.img
RUSTC_MISC_ARGS = -C target-cpu=cortex-a72
endif

EXEC_MINIPUSH = ruby tools/raspi4/common/serial/minipush.rb

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i
DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/tools/raspi4/common:/work/common
DOCKER_ARG_DIR_JTAG = -v $(shell pwd)/tools/raspi4/X1_JTAG_boot:/work/X1_JTAG_boot
DOCKER_ARG_DEV = --privileged -v /dev:/dev
DOCKER_ARG_NET = --network host

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_GDB = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_NET) $(DOCKER_IMAGE)

# Dockerize commands, which require USB device passthrough, only on Linux.
ifeq ($(shell uname -s),Linux)
DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV)
DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)
DOCKER_JTAGBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_ARG_DIR_JTAG) $(DOCKER_IMAGE)
DOCKER_OPENOCD = $(DOCKER_CMD_DEV) $(DOCKER_ARG_NET) $(DOCKER_IMAGE)
else
DOCKER_OPENOCD = echo "Not yet supported on non-Linux systems."; \#
endif

##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all chainboot

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Push the kernel to the real HW target
##------------------------------------------------------------------------------
chainboot: $(KERNEL_BIN)
@$(DOCKER_CHAINBOOT) $(EXEC_MINIPUSH) $(DEV_SERIAL) $(KERNEL_BIN)


##--------------------------------------------------------------------------------------------------
## Debugging targets
##--------------------------------------------------------------------------------------------------
.PHONY: jtagboot openocd gdb gdb-opt0

##------------------------------------------------------------------------------
## Push the JTAG boot image to the real HW target
##------------------------------------------------------------------------------
jtagboot: $(KERNEL_BIN)
@$(DOCKER_JTAGBOOT) $(EXEC_MINIPUSH) $(DEV_SERIAL) $(JTAG_BOOT_IMAGE)

##------------------------------------------------------------------------------
## Start OpenOCD session
##------------------------------------------------------------------------------
openocd:
$(call color_header, "Launching OpenOCD")
@$(DOCKER_OPENOCD) openocd $(OPENOCD_ARG)

##------------------------------------------------------------------------------
## Start GDB session
##------------------------------------------------------------------------------
gdb: RUSTC_MISC_ARGS += -C debuginfo=2
gdb: $(KERNEL_ELF)
$(call color_header, "Launching GDB")
@$(DOCKER_GDB) gdb-multiarch -q $(KERNEL_ELF)
5 changes: 5 additions & 0 deletions tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
deptool/Cargo.lock
deptool/target
deptool/output.txt
bwbench_client/target
bwbench_client/Cargo.lock
1 change: 1 addition & 0 deletions tools/raspi4/common/docker.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DOCKER_IMAGE := rustembedded/osdev-utils:2021.12
12 changes: 12 additions & 0 deletions tools/raspi4/common/format.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
define color_header
@tput setaf 6 2> /dev/null || true
@printf '\n%s\n' $(1)
@tput sgr0 2> /dev/null || true
endef

define color_progress_prefix
@tput setaf 2 2> /dev/null || true
@tput bold 2 2> /dev/null || true
@printf '%12s ' $(1)
@tput sgr0 2> /dev/null || true
endef
9 changes: 9 additions & 0 deletions tools/raspi4/common/operating_system.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ifeq ($(shell uname -s),Linux)
DU_ARGUMENTS = --block-size=1024 --apparent-size
else ifeq ($(shell uname -s),Darwin)
DU_ARGUMENTS = -k -A
endif

define disk_usage_KiB
@printf '%s KiB\n' `du $(DU_ARGUMENTS) $(1) | cut -f1`
endef
Loading

0 comments on commit 7230aed

Please sign in to comment.