mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
Add power management watchdog,
rework interrupts
This commit is contained in:
@@ -15,7 +15,7 @@ extern crate alloc;
|
||||
|
||||
#[repr(C, align(16))]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct HeapHeader {
|
||||
struct HeapHeader {
|
||||
next: Option<*mut HeapHeader>,
|
||||
before: Option<*mut HeapHeader>,
|
||||
size: usize,
|
||||
@@ -26,9 +26,9 @@ const HEAP_HEADER_SIZE: usize = size_of::<HeapHeader>();
|
||||
const MIN_BLOCK_SIZE: usize = 16;
|
||||
|
||||
pub struct Heap {
|
||||
pub start_address: *mut HeapHeader,
|
||||
pub end_address: *mut HeapHeader,
|
||||
pub raw_size: usize,
|
||||
start_address: *mut HeapHeader,
|
||||
end_address: *mut HeapHeader,
|
||||
raw_size: usize,
|
||||
}
|
||||
impl Heap {
|
||||
pub const fn empty() -> Self {
|
||||
@@ -72,7 +72,7 @@ impl Heap {
|
||||
Ok(current)
|
||||
}
|
||||
|
||||
pub fn malloc(&self, mut size: usize) -> Result<*mut u8, NovaError> {
|
||||
fn malloc(&self, mut size: usize) -> Result<*mut u8, NovaError> {
|
||||
if size == 0 {
|
||||
return Err(NovaError::EmptyHeapSegmentNotAllowed);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ impl Heap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn free(&self, pointer: *mut u8) -> Result<(), NovaError> {
|
||||
fn free(&self, pointer: *mut u8) -> Result<(), NovaError> {
|
||||
let mut segment = Self::get_header_ref_from_data_pointer(pointer);
|
||||
unsafe {
|
||||
// IF prev is free:
|
||||
|
||||
9
link.ld
9
link.ld
@@ -27,7 +27,7 @@ SECTIONS {
|
||||
KEEP(*(.vector_table))
|
||||
}
|
||||
|
||||
.heap 0x8000000 : ALIGN(16)
|
||||
.heap : ALIGN(16)
|
||||
{
|
||||
__heap_start = .;
|
||||
. += 0x10000; #10kB
|
||||
@@ -41,6 +41,13 @@ SECTIONS {
|
||||
__stack_end = .;
|
||||
}
|
||||
|
||||
.stack_el0 : ALIGN(16)
|
||||
{
|
||||
__stack_start_el0 = .;
|
||||
. += 0x10000; #10kB stack
|
||||
__stack_end_el0 = .;
|
||||
}
|
||||
|
||||
|
||||
_end = .;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use core::{
|
||||
arch::asm,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
use crate::{
|
||||
get_current_el,
|
||||
irq_interrupt::daif::unmask_irq,
|
||||
mmio_read, mmio_write,
|
||||
peripherals::gpio::{blink_gpio, SpecificGpio},
|
||||
timer::sleep_s,
|
||||
peripherals::gpio::{read_gpio_event_detect_status, reset_gpio_event_detect_status},
|
||||
};
|
||||
|
||||
const INTERRUPT_BASE: u32 = 0x3F00_B000;
|
||||
@@ -14,9 +12,6 @@ const IRQ_PENDING_BASE: u32 = INTERRUPT_BASE + 0x204;
|
||||
const ENABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x210;
|
||||
const DISABLE_IRQ_BASE: u32 = INTERRUPT_BASE + 0x21C;
|
||||
|
||||
// GPIO
|
||||
const GPEDS_BASE: u32 = 0x3F20_0040;
|
||||
|
||||
#[repr(u32)]
|
||||
pub enum IRQState {
|
||||
AuxInt = 29,
|
||||
@@ -34,22 +29,97 @@ pub enum IRQState {
|
||||
UartInt = 57,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn irq_handler() {
|
||||
handle_gpio_interrupt();
|
||||
/// Representation of the ESR_ELx registers
|
||||
///
|
||||
/// Reference: D1.10.4
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[allow(dead_code)]
|
||||
struct EsrElX {
|
||||
ec: u32,
|
||||
il: u32,
|
||||
iss: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn synchronous_interrupt() {
|
||||
loop {
|
||||
println!("Sync Exception");
|
||||
blink_gpio(SpecificGpio::OnboardLed as u8, 100);
|
||||
esr_uart_dump();
|
||||
sleep_s(200);
|
||||
impl From<u32> for EsrElX {
|
||||
fn from(value: u32) -> Self {
|
||||
Self {
|
||||
ec: value >> 26,
|
||||
il: (value >> 25) & 0b1,
|
||||
iss: value & 0x1FFFFFF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn esr_uart_dump() {
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rust_irq_handler() {
|
||||
daif::mask_all();
|
||||
handle_gpio_interrupt();
|
||||
let source_el = get_exception_return_exception_level() >> 2;
|
||||
println!("Source EL: {}", source_el);
|
||||
println!("Current EL: {}", get_current_el());
|
||||
println!("Return register address: {:#x}", get_elr_el1());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rust_synchronous_interrupt_no_el_change() {
|
||||
daif::mask_all();
|
||||
|
||||
let source_el = get_exception_return_exception_level() >> 2;
|
||||
println!("--------Sync Exception in EL{}--------", source_el);
|
||||
println!("No EL change");
|
||||
println!("Current EL: {}", get_current_el());
|
||||
println!("{:?}", EsrElX::from(get_esr_el1()));
|
||||
println!("Return register address: {:#x}", get_elr_el1());
|
||||
println!("-------------------------------------");
|
||||
}
|
||||
|
||||
/// Synchronous Exception Handler
|
||||
///
|
||||
/// Lower Exception level, where the implemented level
|
||||
/// immediately lower than the target level is using
|
||||
/// AArch64.
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rust_synchronous_interrupt_imm_lower_aarch64() {
|
||||
daif::mask_all();
|
||||
|
||||
let source_el = get_exception_return_exception_level() >> 2;
|
||||
println!("--------Sync Exception in EL{}--------", source_el);
|
||||
println!("Exception escalated to EL {}", get_current_el());
|
||||
println!("Current EL: {}", get_current_el());
|
||||
let esr = EsrElX::from(get_esr_el1());
|
||||
println!("{:?}", EsrElX::from(esr));
|
||||
println!("Return register address: {:#x}", get_elr_el1());
|
||||
|
||||
match esr.ec {
|
||||
0b100100 => {
|
||||
println!("Cause: Data Abort from a lower Exception level");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("-------------------------------------");
|
||||
|
||||
set_return_to_kernel_main();
|
||||
}
|
||||
|
||||
fn set_return_to_kernel_main() {
|
||||
unsafe {
|
||||
asm!("ldr x0, =kernel_main", "msr ELR_EL1, x0");
|
||||
asm!("mov x0, #(0b0101)", "msr SPSR_EL1, x0");
|
||||
}
|
||||
}
|
||||
|
||||
fn get_exception_return_exception_level() -> u32 {
|
||||
let spsr: u32;
|
||||
unsafe {
|
||||
asm!("mrs {0:x}, SPSR_EL1", out(reg) spsr);
|
||||
}
|
||||
spsr & 0b1111
|
||||
}
|
||||
|
||||
/// Read the syndrome information that caused an exception
|
||||
///
|
||||
/// ESR = Exception Syndrome Register
|
||||
fn get_esr_el1() -> u32 {
|
||||
let esr: u32;
|
||||
unsafe {
|
||||
asm!(
|
||||
@@ -57,20 +127,21 @@ fn esr_uart_dump() {
|
||||
esr = out(reg) esr
|
||||
);
|
||||
}
|
||||
for i in (0..32).rev() {
|
||||
if ((esr >> i) & 1) == 0 {
|
||||
print!("0");
|
||||
} else {
|
||||
print!("1");
|
||||
}
|
||||
if i % 4 == 0 && i > 0 {
|
||||
print!("_");
|
||||
}
|
||||
esr
|
||||
}
|
||||
|
||||
if i == 26 || i == 25 || i == 0 {
|
||||
print!("\n\r");
|
||||
}
|
||||
/// Read the return address
|
||||
///
|
||||
/// ELR = Exception Link Registers
|
||||
fn get_elr_el1() -> u32 {
|
||||
let elr: u32;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {esr:x}, ELR_EL1",
|
||||
esr = out(reg) elr
|
||||
);
|
||||
}
|
||||
elr
|
||||
}
|
||||
|
||||
fn handle_gpio_interrupt() {
|
||||
@@ -81,32 +152,16 @@ fn handle_gpio_interrupt() {
|
||||
if val {
|
||||
#[allow(clippy::single_match)]
|
||||
match i {
|
||||
26 => print!("Button Pressed"),
|
||||
26 => {
|
||||
println!("Button Pressed");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Reset GPIO Interrupt handler by writing a 1
|
||||
reset_gpio_event_detect_status(i);
|
||||
}
|
||||
}
|
||||
enable_irq();
|
||||
}
|
||||
|
||||
/// Get current interrupt status of a GPIO pin
|
||||
pub fn read_gpio_event_detect_status(id: u32) -> bool {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
let val = mmio_read(register) >> register_offset;
|
||||
(val & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Resets current interrupt status of a GPIO pin
|
||||
pub fn reset_gpio_event_detect_status(id: u32) {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
mmio_write(register, 0b1 << register_offset);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unmask_irq();
|
||||
}
|
||||
|
||||
/// Enables IRQ Source
|
||||
@@ -147,16 +202,26 @@ pub fn read_irq_pending(state: IRQState) -> bool {
|
||||
((mmio_read(register) >> register_offset) & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Clears the IRQ DAIF Mask
|
||||
///
|
||||
/// Enables IRQ interrupts
|
||||
pub fn enable_irq() {
|
||||
unsafe { asm!("msr DAIFClr, #0x2") }
|
||||
}
|
||||
pub mod daif {
|
||||
use core::arch::asm;
|
||||
|
||||
/// Clears the IRQ DAIF Mask
|
||||
///
|
||||
/// Disable IRQ interrupts
|
||||
pub fn disable_irq() {
|
||||
unsafe { asm!("msr DAIFSet, #0x2") }
|
||||
#[inline(always)]
|
||||
pub fn mask_all() {
|
||||
unsafe { asm!("msr DAIFSet, #0xf", options(nomem, nostack)) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn unmask_all() {
|
||||
unsafe { asm!("msr DAIFClr, #0xf", options(nomem, nostack)) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn mask_irq() {
|
||||
unsafe { asm!("msr DAIFSet, #0x2", options(nomem, nostack)) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn unmask_irq() {
|
||||
unsafe { asm!("msr DAIFClr, #0x2", options(nomem, nostack)) }
|
||||
}
|
||||
}
|
||||
|
||||
16
src/lib.rs
16
src/lib.rs
@@ -1,12 +1,15 @@
|
||||
#![no_std]
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
use core::{
|
||||
arch::asm,
|
||||
panic::PanicInfo,
|
||||
ptr::{read_volatile, write_volatile},
|
||||
};
|
||||
|
||||
use heap::Heap;
|
||||
|
||||
pub static PERIPHERAL_BASE: u32 = 0x3F00_0000;
|
||||
|
||||
unsafe extern "C" {
|
||||
unsafe static mut __heap_start: u8;
|
||||
unsafe static mut __heap_end: u8;
|
||||
@@ -53,6 +56,7 @@ pub mod configuration;
|
||||
pub mod framebuffer;
|
||||
pub mod irq_interrupt;
|
||||
pub mod mailbox;
|
||||
pub mod power_management;
|
||||
pub mod timer;
|
||||
|
||||
pub fn mmio_read(address: u32) -> u32 {
|
||||
@@ -62,3 +66,15 @@ pub fn mmio_read(address: u32) -> u32 {
|
||||
pub fn mmio_write(address: u32, data: u32) {
|
||||
unsafe { write_volatile(address as *mut u32, data) }
|
||||
}
|
||||
|
||||
pub fn get_current_el() -> u64 {
|
||||
let el: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {el}, CurrentEL",
|
||||
el = out(reg) el,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
el >> 2
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ macro_rules! max {
|
||||
#[macro_export]
|
||||
macro_rules! mailbox_command {
|
||||
($name:ident, $tag:expr, $request_len:expr,$response_len:expr) => {
|
||||
/// More information at: https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
|
||||
/// More information at: <https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface>
|
||||
pub fn $name(
|
||||
request_data: [u32; $request_len / 4],
|
||||
) -> Result<[u32; $response_len / 4], NovaError> {
|
||||
@@ -59,10 +59,10 @@ macro_rules! mailbox_command {
|
||||
};
|
||||
}
|
||||
|
||||
mailbox_command!(mb_read_soc_temp, 0x0003_0006, 4, 8);
|
||||
mailbox_command!(read_soc_temp, 0x0003_0006, 4, 8);
|
||||
|
||||
// Framebuffer
|
||||
mailbox_command!(mb_get_display_resolution, 0x0004_0003, 0, 8);
|
||||
mailbox_command!(get_display_resolution, 0x0004_0003, 0, 8);
|
||||
|
||||
pub fn read_mailbox(channel: u32) -> u32 {
|
||||
// Wait until mailbox is not empty
|
||||
|
||||
45
src/main.rs
45
src/main.rs
@@ -13,9 +13,9 @@ extern crate alloc;
|
||||
use alloc::boxed::Box;
|
||||
use nova::{
|
||||
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
||||
init_heap,
|
||||
irq_interrupt::enable_irq_source,
|
||||
mailbox::mb_read_soc_temp,
|
||||
get_current_el, init_heap,
|
||||
irq_interrupt::{daif, enable_irq_source},
|
||||
mailbox,
|
||||
peripherals::{
|
||||
gpio::{
|
||||
blink_gpio, gpio_pull_up, set_falling_edge_detect, set_gpio_function, GPIOFunction,
|
||||
@@ -24,13 +24,13 @@ use nova::{
|
||||
uart::uart_init,
|
||||
},
|
||||
print, println,
|
||||
timer::{delay_nops, sleep_us},
|
||||
};
|
||||
|
||||
global_asm!(include_str!("vector.S"));
|
||||
|
||||
extern "C" {
|
||||
fn el2_to_el1();
|
||||
fn el1_to_el0();
|
||||
static mut __bss_start: u32;
|
||||
static mut __bss_end: u32;
|
||||
}
|
||||
@@ -57,12 +57,11 @@ pub extern "C" fn main() -> ! {
|
||||
// Set ACT Led to Outout
|
||||
let _ = set_gpio_function(21, GPIOFunction::Output);
|
||||
|
||||
// Delay so clock speed can stabilize
|
||||
delay_nops(50000);
|
||||
println!("Hello World!");
|
||||
println!("Exception level: {}", get_current_el());
|
||||
|
||||
unsafe {
|
||||
asm!("mrs x0, SCTLR_EL1");
|
||||
asm!("mrs x0, SCTLR_EL1",);
|
||||
el2_to_el1();
|
||||
}
|
||||
|
||||
@@ -80,14 +79,22 @@ unsafe fn zero_bss() {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kernel_main() -> ! {
|
||||
println!("EL: {}", get_current_el());
|
||||
println!("Kernel Main");
|
||||
println!("Exception Level: {}", get_current_el());
|
||||
daif::unmask_all();
|
||||
|
||||
unsafe {
|
||||
init_heap();
|
||||
heap_test();
|
||||
el1_to_el0();
|
||||
};
|
||||
|
||||
sleep_us(500_000);
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn el0() -> ! {
|
||||
println!("Jumped into EL0");
|
||||
|
||||
// Set GPIO 26 to Input
|
||||
enable_irq_source(nova::irq_interrupt::IRQState::GpioInt0); //26 is on the first GPIO bank
|
||||
@@ -106,34 +113,20 @@ pub extern "C" fn kernel_main() -> ! {
|
||||
fb.draw_function(cos, 100, 101, RED);
|
||||
|
||||
loop {
|
||||
let temp = mb_read_soc_temp([0]).unwrap();
|
||||
let temp = mailbox::read_soc_temp([0]).unwrap();
|
||||
println!("{} °C", temp[1] / 1000);
|
||||
|
||||
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn heap_test() {
|
||||
let b = Box::new([1, 2, 3, 4]);
|
||||
println!("{:?}", b);
|
||||
}
|
||||
}
|
||||
|
||||
fn cos(x: u32) -> f64 {
|
||||
libm::cos(x as f64 * 0.1) * 20.0
|
||||
}
|
||||
|
||||
fn get_current_el() -> u64 {
|
||||
let el: u64;
|
||||
unsafe {
|
||||
asm!(
|
||||
"mrs {el}, CurrentEL",
|
||||
el = out(reg) el,
|
||||
options(nomem, nostack, preserves_flags)
|
||||
);
|
||||
}
|
||||
el >> 2
|
||||
}
|
||||
|
||||
fn enable_uart() {
|
||||
uart_init();
|
||||
// Set GPIO Pins to UART
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use core::result::Result;
|
||||
use core::result::Result::Ok;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
|
||||
use crate::timer::{delay_nops, sleep_ms};
|
||||
use crate::{mmio_read, mmio_write};
|
||||
@@ -8,10 +9,11 @@ const GPFSEL_BASE: u32 = 0x3F20_0000;
|
||||
const GPSET_BASE: u32 = 0x3F20_001C;
|
||||
const GPCLR_BASE: u32 = 0x3F20_0028;
|
||||
const GPLEV_BASE: u32 = 0x3F20_0034;
|
||||
const GPEDS_BASE: u32 = 0x3F20_0040;
|
||||
const GPFEN_BASE: u32 = 0x3F20_0058;
|
||||
const GPPUD: u32 = 0x3F20_0094;
|
||||
const GPPUDCLK_BASE: u32 = 0x3F20_0098;
|
||||
const GPREN_BASE: u32 = 0x3F20_004C;
|
||||
const GPFEN_BASE: u32 = 0x3F20_0058;
|
||||
|
||||
#[repr(u8)]
|
||||
pub enum SpecificGpio {
|
||||
@@ -48,7 +50,8 @@ pub fn set_gpio_function(gpio: u8, state: GPIOFunction) -> Result<(), &'static s
|
||||
|
||||
/// Set the GPIO to high
|
||||
///
|
||||
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`
|
||||
/// Should be used when GPIO function is set to `OUTPUT` via `set_gpio_function`,
|
||||
/// otherwise setting is ignored
|
||||
pub fn gpio_high(gpio: u8) -> Result<(), &'static str> {
|
||||
let register_index = gpio / 32;
|
||||
let register_offset = gpio % 32;
|
||||
@@ -119,7 +122,7 @@ fn gpio_pull_up_down(gpio: u8, val: u32) {
|
||||
mmio_write(register_addr, 0);
|
||||
}
|
||||
|
||||
/// Get the current status if falling edge detection is set
|
||||
/// Get the current status of the falling edge detection
|
||||
pub fn read_falling_edge_detect(gpio: u8) -> bool {
|
||||
let register_addr = GPFEN_BASE + 4 * (gpio as u32 / 32);
|
||||
let register_offset = gpio % 32;
|
||||
@@ -128,7 +131,7 @@ pub fn read_falling_edge_detect(gpio: u8) -> bool {
|
||||
((current >> register_offset) & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Get the current status if falling edge detection is set
|
||||
/// Get the current status of the rising edge detection
|
||||
pub fn read_rising_edge_detect(gpio: u8) -> bool {
|
||||
let register_addr = GPREN_BASE + 4 * (gpio as u32 / 32);
|
||||
let register_offset = gpio % 32;
|
||||
@@ -170,6 +173,29 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) {
|
||||
mmio_write(register_addr, new_val);
|
||||
}
|
||||
|
||||
/// Returns with the interrupt status of an GPIO.
|
||||
///
|
||||
/// GPEDS register is used to record level and edge events on the GPIO pins.
|
||||
/// When an event is triggered by the GPIO, the corresponding bit will be set to 1.
|
||||
pub fn read_gpio_event_detect_status(id: u32) -> bool {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
let val = mmio_read(register) >> register_offset;
|
||||
(val & 0b1) != 0
|
||||
}
|
||||
|
||||
/// Resets current interrupt status of a GPIO pin.
|
||||
pub fn reset_gpio_event_detect_status(id: u32) {
|
||||
let register = GPEDS_BASE + (id / 32) * 4;
|
||||
let register_offset = id % 32;
|
||||
|
||||
mmio_write(register, 0b1 << register_offset);
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
// TODO: GPHEN,GPLEN,GPAREN,GPAFEN
|
||||
|
||||
pub fn blink_gpio(gpio: u8, duration_ms: u64) {
|
||||
let _ = gpio_high(gpio);
|
||||
|
||||
|
||||
27
src/power_management.rs
Normal file
27
src/power_management.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use core::ptr::{read_volatile, write_volatile};
|
||||
|
||||
use crate::PERIPHERAL_BASE;
|
||||
|
||||
/// Power Management Base
|
||||
static PM_BASE: u32 = PERIPHERAL_BASE + 0x10_0000;
|
||||
static PM_RSTC: u32 = PM_BASE + 0x1c;
|
||||
static PM_WDOG: u32 = PM_BASE + 0x24;
|
||||
|
||||
static PM_PASSWORD: u32 = 0x5a000000;
|
||||
static PM_WDOG_TIMER_MASK: u32 = 0x000fffff;
|
||||
static PM_RSTC_WRCFG_CLR: u32 = 0xffffffcf;
|
||||
static PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020;
|
||||
|
||||
pub fn reboot_system() {
|
||||
unsafe {
|
||||
let pm_rstc_val = read_volatile(PM_RSTC as *mut u32);
|
||||
// (31:16) bits -> password
|
||||
// (11:0) bits -> value
|
||||
write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | (1 & PM_WDOG_TIMER_MASK));
|
||||
write_volatile(
|
||||
PM_RSTC as *mut u32,
|
||||
PM_PASSWORD | (pm_rstc_val & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET,
|
||||
);
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
125
src/vector.S
125
src/vector.S
@@ -14,11 +14,14 @@ vector_table:
|
||||
ventry .
|
||||
ventry .
|
||||
|
||||
ventry synchronous_interrupt // Synchronous Exception 0x200
|
||||
ventry synchronous_interrupt_no_el_change // Synchronous Exception 0x200
|
||||
ventry irq_handler // IRQ(Interrupt Request) 0x280
|
||||
ventry .
|
||||
ventry .
|
||||
|
||||
ventry synchronous_interrupt_imm_lower_aarch64
|
||||
ventry irq_handler
|
||||
|
||||
|
||||
.align 4
|
||||
.global el2_to_el1
|
||||
@@ -31,7 +34,7 @@ el2_to_el1:
|
||||
mov x0, #(0b0101)
|
||||
msr SPSR_EL2, x0
|
||||
|
||||
// Set return address to ELR_EL2
|
||||
// Set return address to kernel_main
|
||||
ldr x0, =kernel_main
|
||||
msr ELR_EL2, x0
|
||||
|
||||
@@ -53,7 +56,121 @@ el2_to_el1:
|
||||
orr x0,x0, x1
|
||||
msr CPACR_EL1,x0
|
||||
|
||||
isb
|
||||
|
||||
// Return to EL1
|
||||
eret
|
||||
|
||||
.align 4
|
||||
.global el1_to_el0
|
||||
el1_to_el0:
|
||||
|
||||
// Set SPSR_EL1: return to EL0t
|
||||
mov x0, #(0b0000)
|
||||
msr SPSR_EL1, x0
|
||||
|
||||
// Set return address to el0
|
||||
ldr x0, =el0
|
||||
msr ELR_EL1, x0
|
||||
|
||||
// Set SP_EL1 to stack base
|
||||
ldr x0, =__stack_end_el0
|
||||
msr SP_EL0, x0
|
||||
|
||||
// Return to EL0
|
||||
eret
|
||||
|
||||
|
||||
.align 4
|
||||
irq_handler:
|
||||
sub sp, sp, #176
|
||||
stp x0, x1, [sp, #0]
|
||||
stp x2, x3, [sp, #16]
|
||||
stp x4, x5, [sp, #32]
|
||||
stp x6, x7, [sp, #48]
|
||||
stp x8, x9, [sp, #64]
|
||||
stp x10, x11, [sp, #80]
|
||||
stp x12, x13, [sp, #96]
|
||||
stp x14, x15, [sp, #112]
|
||||
stp x16, x17, [sp, #128]
|
||||
stp x18, x29, [sp, #144]
|
||||
stp x30, xzr, [sp, #160]
|
||||
|
||||
bl rust_irq_handler
|
||||
|
||||
ldp x0, x1, [sp, #0]
|
||||
ldp x2, x3, [sp, #16]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #48]
|
||||
ldp x8, x9, [sp, #64]
|
||||
ldp x10, x11, [sp, #80]
|
||||
ldp x12, x13, [sp, #96]
|
||||
ldp x14, x15, [sp, #112]
|
||||
ldp x16, x17, [sp, #128]
|
||||
ldp x18, x29, [sp, #144]
|
||||
ldp x30, xzr, [sp, #160]
|
||||
add sp, sp, #176
|
||||
|
||||
eret
|
||||
|
||||
.align 4
|
||||
synchronous_interrupt_imm_lower_aarch64:
|
||||
sub sp, sp, #176
|
||||
stp x0, x1, [sp, #0]
|
||||
stp x2, x3, [sp, #16]
|
||||
stp x4, x5, [sp, #32]
|
||||
stp x6, x7, [sp, #48]
|
||||
stp x8, x9, [sp, #64]
|
||||
stp x10, x11, [sp, #80]
|
||||
stp x12, x13, [sp, #96]
|
||||
stp x14, x15, [sp, #112]
|
||||
stp x16, x17, [sp, #128]
|
||||
stp x18, x29, [sp, #144]
|
||||
stp x30, xzr, [sp, #160]
|
||||
|
||||
bl rust_synchronous_interrupt_imm_lower_aarch64
|
||||
|
||||
ldp x0, x1, [sp, #0]
|
||||
ldp x2, x3, [sp, #16]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #48]
|
||||
ldp x8, x9, [sp, #64]
|
||||
ldp x10, x11, [sp, #80]
|
||||
ldp x12, x13, [sp, #96]
|
||||
ldp x14, x15, [sp, #112]
|
||||
ldp x16, x17, [sp, #128]
|
||||
ldp x18, x29, [sp, #144]
|
||||
ldp x30, xzr, [sp, #160]
|
||||
add sp, sp, #176
|
||||
|
||||
eret
|
||||
|
||||
.align 4
|
||||
synchronous_interrupt_no_el_change:
|
||||
sub sp, sp, #176
|
||||
stp x0, x1, [sp, #0]
|
||||
stp x2, x3, [sp, #16]
|
||||
stp x4, x5, [sp, #32]
|
||||
stp x6, x7, [sp, #48]
|
||||
stp x8, x9, [sp, #64]
|
||||
stp x10, x11, [sp, #80]
|
||||
stp x12, x13, [sp, #96]
|
||||
stp x14, x15, [sp, #112]
|
||||
stp x16, x17, [sp, #128]
|
||||
stp x18, x29, [sp, #144]
|
||||
stp x30, xzr, [sp, #160]
|
||||
|
||||
bl rust_synchronous_interrupt_no_el_change
|
||||
|
||||
ldp x0, x1, [sp, #0]
|
||||
ldp x2, x3, [sp, #16]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #48]
|
||||
ldp x8, x9, [sp, #64]
|
||||
ldp x10, x11, [sp, #80]
|
||||
ldp x12, x13, [sp, #96]
|
||||
ldp x14, x15, [sp, #112]
|
||||
ldp x16, x17, [sp, #128]
|
||||
ldp x18, x29, [sp, #144]
|
||||
ldp x30, xzr, [sp, #160]
|
||||
add sp, sp, #176
|
||||
|
||||
eret
|
||||
|
||||
@@ -15,7 +15,7 @@ REMOTE_DIR="$TFTP_PATH"
|
||||
|
||||
# BUILD
|
||||
echo "[*] Building kernel..."
|
||||
cargo build --release
|
||||
cargo build --release --target aarch64-unknown-none
|
||||
|
||||
# CONVERT TO IMG
|
||||
echo "[*] Convert kernel elf to img..."
|
||||
|
||||
Reference in New Issue
Block a user