mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
feat: move EL0 stack to virtual space
This commit is contained in:
18
link.ld
18
link.ld
@@ -4,14 +4,15 @@ SECTIONS {
|
|||||||
.text ALIGN(4) : {
|
.text ALIGN(4) : {
|
||||||
KEEP(*(.text._start))
|
KEEP(*(.text._start))
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
|
. = ALIGN(4K);
|
||||||
|
__text_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rodata : {
|
.rodata : {
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
.data ALIGN(2M) : {
|
.data : {
|
||||||
_data = .;
|
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,10 @@ SECTIONS {
|
|||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. = ALIGN(2M);
|
||||||
|
|
||||||
|
__share_end = .;
|
||||||
|
|
||||||
.vector_table ALIGN(2K) : {
|
.vector_table ALIGN(2K) : {
|
||||||
KEEP(*(.vector_table))
|
KEEP(*(.vector_table))
|
||||||
}
|
}
|
||||||
@@ -36,15 +41,6 @@ SECTIONS {
|
|||||||
. = ALIGN(2M);
|
. = ALIGN(2M);
|
||||||
|
|
||||||
__kernel_end = .;
|
__kernel_end = .;
|
||||||
|
|
||||||
.stack_el0 : {
|
|
||||||
__stack_start_el0 = .;
|
|
||||||
. += 10K; #10kB stack
|
|
||||||
__stack_end_el0 = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
. = ALIGN(2M);
|
|
||||||
_end = .;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__bss_size = (__bss_end - __bss_start) >> 3;
|
__bss_size = (__bss_end - __bss_start) >> 3;
|
||||||
|
|||||||
@@ -8,13 +8,6 @@ use crate::{
|
|||||||
get_current_el,
|
get_current_el,
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe extern "C" {
|
|
||||||
static mut __translation_table_l2_start: u64;
|
|
||||||
static __stack_start_el0: u64;
|
|
||||||
static __kernel_end: u64;
|
|
||||||
static _data: u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BLOCK: u64 = 0b01;
|
const BLOCK: u64 = 0b01;
|
||||||
const TABLE: u64 = 0b11;
|
const TABLE: u64 = 0b11;
|
||||||
const PAGE: u64 = 0b11;
|
const PAGE: u64 = 0b11;
|
||||||
@@ -111,21 +104,21 @@ fn map_range_explicit(
|
|||||||
|
|
||||||
while virt % LEVEL2_BLOCK_SIZE != 0 {
|
while virt % LEVEL2_BLOCK_SIZE != 0 {
|
||||||
map_page(virt, phys, base, flags)?;
|
map_page(virt, phys, base, flags)?;
|
||||||
virt += GRANULARITY;
|
(virt, _) = virt.overflowing_add(GRANULARITY);
|
||||||
phys += GRANULARITY;
|
phys += GRANULARITY;
|
||||||
remaining -= GRANULARITY;
|
remaining -= GRANULARITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
while remaining >= LEVEL2_BLOCK_SIZE {
|
while remaining >= LEVEL2_BLOCK_SIZE {
|
||||||
map_l2_block(virt, phys, base, flags)?;
|
map_l2_block(virt, phys, base, flags)?;
|
||||||
virt += LEVEL2_BLOCK_SIZE;
|
(virt, _) = virt.overflowing_add(LEVEL2_BLOCK_SIZE);
|
||||||
phys += LEVEL2_BLOCK_SIZE;
|
phys += LEVEL2_BLOCK_SIZE;
|
||||||
remaining -= LEVEL2_BLOCK_SIZE;
|
remaining -= LEVEL2_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
while remaining > 0 {
|
while remaining > 0 {
|
||||||
map_page(virt, phys, base, flags)?;
|
map_page(virt, phys, base, flags)?;
|
||||||
virt += GRANULARITY;
|
(virt, _) = virt.overflowing_add(GRANULARITY);
|
||||||
phys += GRANULARITY;
|
phys += GRANULARITY;
|
||||||
remaining -= GRANULARITY;
|
remaining -= GRANULARITY;
|
||||||
}
|
}
|
||||||
@@ -143,13 +136,13 @@ fn map_range_dynamic(
|
|||||||
|
|
||||||
while remaining >= LEVEL2_BLOCK_SIZE {
|
while remaining >= LEVEL2_BLOCK_SIZE {
|
||||||
map_l2_block(virt, reserve_block(), base, flags)?;
|
map_l2_block(virt, reserve_block(), base, flags)?;
|
||||||
virt += LEVEL2_BLOCK_SIZE;
|
(virt, _) = virt.overflowing_add(LEVEL2_BLOCK_SIZE);
|
||||||
remaining -= LEVEL2_BLOCK_SIZE;
|
remaining -= LEVEL2_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
while remaining > 0 {
|
while remaining > 0 {
|
||||||
map_page(virt, reserve_page(), base, flags)?;
|
map_page(virt, reserve_page(), base, flags)?;
|
||||||
virt += GRANULARITY;
|
(virt, _) = virt.overflowing_add(GRANULARITY);
|
||||||
remaining -= GRANULARITY;
|
remaining -= GRANULARITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +179,7 @@ pub fn alloc_page_explicit(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_page(
|
pub fn map_page(
|
||||||
virtual_address: usize,
|
virtual_address: usize,
|
||||||
physical_address: usize,
|
physical_address: usize,
|
||||||
base_table_ptr: *mut PageTable,
|
base_table_ptr: *mut PageTable,
|
||||||
|
|||||||
@@ -87,8 +87,9 @@ el1_to_el0:
|
|||||||
msr ELR_EL1, x0
|
msr ELR_EL1, x0
|
||||||
|
|
||||||
// Set SP_EL1 to stack base
|
// Set SP_EL1 to stack base
|
||||||
ldr x0, =__stack_end_el0
|
adrp x0, EL0_STACK_TOP
|
||||||
msr SP_EL0, x0
|
ldr x1, [x0, :lo12:EL0_STACK_TOP]
|
||||||
|
msr SP_EL0, x1
|
||||||
|
|
||||||
isb
|
isb
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ pub static TCR_EL1_CONF: u64 = IPS | TG0 | TG1 | T0SZ | T1SZ | SH0 | SH1 | AS;
|
|||||||
pub mod mmu {
|
pub mod mmu {
|
||||||
use crate::{
|
use crate::{
|
||||||
aarch64::mmu::{
|
aarch64::mmu::{
|
||||||
alloc_block_l2_explicit, allocate_memory, map_l2_block, reserve_range, PhysSource,
|
alloc_block_l2_explicit, allocate_memory, map_l2_block, map_page, reserve_range,
|
||||||
DEVICE_MEM, EL0_ACCESSIBLE, KERNEL_VIRTUAL_MEM_SPACE, LEVEL1_BLOCK_SIZE,
|
PhysSource, DEVICE_MEM, EL0_ACCESSIBLE, GRANULARITY, KERNEL_VIRTUAL_MEM_SPACE,
|
||||||
LEVEL2_BLOCK_SIZE, NORMAL_MEM, PXN, READ_ONLY, STACK_START_ADDR,
|
LEVEL1_BLOCK_SIZE, LEVEL2_BLOCK_SIZE, NORMAL_MEM, PXN, READ_ONLY, STACK_START_ADDR,
|
||||||
TRANSLATIONTABLE_TTBR0, UXN, WRITABLE,
|
TRANSLATIONTABLE_TTBR0, UXN, WRITABLE,
|
||||||
},
|
},
|
||||||
PERIPHERAL_BASE,
|
PERIPHERAL_BASE,
|
||||||
@@ -45,22 +45,24 @@ pub mod mmu {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
static EL1_STACK_TOP: usize = STACK_START_ADDR | KERNEL_VIRTUAL_MEM_SPACE;
|
static EL1_STACK_TOP: usize = STACK_START_ADDR | KERNEL_VIRTUAL_MEM_SPACE;
|
||||||
const EL1_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2;
|
const EL1_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2;
|
||||||
|
#[no_mangle]
|
||||||
|
static EL0_STACK_TOP: usize = STACK_START_ADDR;
|
||||||
|
const EL0_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static _data: u64;
|
static __text_end: u64;
|
||||||
static _end: u64;
|
static __share_end: u64;
|
||||||
static __kernel_end: u64;
|
static __kernel_end: u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_mmu_translation_tables() {
|
pub fn initialize_mmu_translation_tables() {
|
||||||
let shared_segment_end = unsafe { &_data } as *const _ as usize;
|
let text_end = unsafe { &__text_end } as *const _ as usize;
|
||||||
|
let shared_segment_end = unsafe { &__share_end } as *const _ as usize;
|
||||||
let kernel_end = unsafe { &__kernel_end } as *const _ as usize;
|
let kernel_end = unsafe { &__kernel_end } as *const _ as usize;
|
||||||
let user_space_end = unsafe { &_end } as *const _ as usize;
|
|
||||||
|
|
||||||
reserve_range(0x0, user_space_end).unwrap();
|
reserve_range(0x0, kernel_end).unwrap();
|
||||||
|
|
||||||
for addr in (0..shared_segment_end).step_by(LEVEL2_BLOCK_SIZE) {
|
for addr in (0..text_end).step_by(GRANULARITY) {
|
||||||
map_l2_block(
|
map_page(
|
||||||
addr,
|
addr,
|
||||||
addr,
|
addr,
|
||||||
core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0),
|
core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0),
|
||||||
@@ -69,6 +71,16 @@ pub mod mmu {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for addr in (text_end..shared_segment_end).step_by(GRANULARITY) {
|
||||||
|
map_page(
|
||||||
|
addr,
|
||||||
|
addr,
|
||||||
|
core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0),
|
||||||
|
EL0_ACCESSIBLE | WRITABLE | NORMAL_MEM,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
for addr in (shared_segment_end..kernel_end).step_by(LEVEL2_BLOCK_SIZE) {
|
for addr in (shared_segment_end..kernel_end).step_by(LEVEL2_BLOCK_SIZE) {
|
||||||
map_l2_block(
|
map_l2_block(
|
||||||
addr,
|
addr,
|
||||||
@@ -79,16 +91,6 @@ pub mod mmu {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for addr in (kernel_end..user_space_end).step_by(LEVEL2_BLOCK_SIZE) {
|
|
||||||
map_l2_block(
|
|
||||||
addr,
|
|
||||||
addr,
|
|
||||||
core::ptr::addr_of_mut!(TRANSLATIONTABLE_TTBR0),
|
|
||||||
EL0_ACCESSIBLE | WRITABLE | PXN | NORMAL_MEM,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
for addr in (PERIPHERAL_BASE..LEVEL1_BLOCK_SIZE).step_by(LEVEL2_BLOCK_SIZE) {
|
for addr in (PERIPHERAL_BASE..LEVEL1_BLOCK_SIZE).step_by(LEVEL2_BLOCK_SIZE) {
|
||||||
alloc_block_l2_explicit(
|
alloc_block_l2_explicit(
|
||||||
addr,
|
addr,
|
||||||
@@ -99,6 +101,15 @@ pub mod mmu {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Frame Buffer memory range
|
||||||
|
allocate_memory(
|
||||||
|
0x3c100000,
|
||||||
|
1080 * 1920 * 4,
|
||||||
|
PhysSource::Explicit(0x3c100000),
|
||||||
|
NORMAL_MEM | PXN | UXN | WRITABLE | EL0_ACCESSIBLE,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
allocate_memory(
|
allocate_memory(
|
||||||
EL1_STACK_TOP - EL1_STACK_SIZE + 0x10,
|
EL1_STACK_TOP - EL1_STACK_SIZE + 0x10,
|
||||||
EL1_STACK_SIZE,
|
EL1_STACK_SIZE,
|
||||||
@@ -106,5 +117,13 @@ pub mod mmu {
|
|||||||
WRITABLE | NORMAL_MEM,
|
WRITABLE | NORMAL_MEM,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
allocate_memory(
|
||||||
|
EL0_STACK_TOP - EL0_STACK_SIZE + 0x10,
|
||||||
|
EL0_STACK_SIZE,
|
||||||
|
PhysSource::Any,
|
||||||
|
WRITABLE | EL0_ACCESSIBLE | NORMAL_MEM,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/main.rs
46
src/main.rs
@@ -11,10 +11,7 @@ extern crate alloc;
|
|||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use nova::{
|
use nova::{
|
||||||
aarch64::{
|
aarch64::registers::{daif, read_id_aa64mmfr0_el1},
|
||||||
mmu::{allocate_memory, PhysSource, EL0_ACCESSIBLE, NORMAL_MEM, PXN, UXN, WRITABLE},
|
|
||||||
registers::{daif, read_id_aa64mmfr0_el1},
|
|
||||||
},
|
|
||||||
configuration::mmu::initialize_mmu_translation_tables,
|
configuration::mmu::initialize_mmu_translation_tables,
|
||||||
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
||||||
get_current_el,
|
get_current_el,
|
||||||
@@ -26,13 +23,14 @@ use nova::{
|
|||||||
},
|
},
|
||||||
uart::uart_init,
|
uart::uart_init,
|
||||||
},
|
},
|
||||||
pi3::mailbox,
|
|
||||||
println,
|
println,
|
||||||
};
|
};
|
||||||
|
|
||||||
global_asm!(include_str!("vector.S"));
|
global_asm!(include_str!("vector.S"));
|
||||||
global_asm!(include_str!("config.S"));
|
global_asm!(include_str!("config.S"));
|
||||||
|
|
||||||
|
static mut FRAMEBUFFER: Option<FrameBuffer> = None;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn el2_to_el1();
|
fn el2_to_el1();
|
||||||
fn el1_to_el0();
|
fn el1_to_el0();
|
||||||
@@ -74,6 +72,8 @@ pub extern "C" fn main() -> ! {
|
|||||||
|
|
||||||
println!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1());
|
println!("Register: AA64MMFR0_EL1: {:064b}", read_id_aa64mmfr0_el1());
|
||||||
println!("Moving El2->EL1");
|
println!("Moving El2->EL1");
|
||||||
|
unsafe { FRAMEBUFFER = Some(FrameBuffer::default()) };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
el2_to_el1();
|
el2_to_el1();
|
||||||
}
|
}
|
||||||
@@ -100,15 +100,6 @@ pub extern "C" fn kernel_main() -> ! {
|
|||||||
}
|
}
|
||||||
println!("heap allocation test: {:?}", test_vector);
|
println!("heap allocation test: {:?}", test_vector);
|
||||||
|
|
||||||
// Frame Buffer memory range
|
|
||||||
// TODO: this is just temporary
|
|
||||||
allocate_memory(
|
|
||||||
0x3c100000,
|
|
||||||
1080 * 1920 * 4,
|
|
||||||
PhysSource::Explicit(0x3c100000),
|
|
||||||
NORMAL_MEM | PXN | UXN | WRITABLE | EL0_ACCESSIBLE,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
println!("Exception Level: {}", get_current_el());
|
println!("Exception Level: {}", get_current_el());
|
||||||
daif::unmask_all();
|
daif::unmask_all();
|
||||||
|
|
||||||
@@ -132,22 +123,25 @@ pub extern "C" fn el0() -> ! {
|
|||||||
|
|
||||||
enable_irq_source(IRQSource::UartInt);
|
enable_irq_source(IRQSource::UartInt);
|
||||||
|
|
||||||
let fb = FrameBuffer::default();
|
if let Some(fb) = unsafe { FRAMEBUFFER.as_mut() } {
|
||||||
|
for i in 0..1080 {
|
||||||
|
fb.draw_pixel(50, i, BLUE);
|
||||||
|
}
|
||||||
|
fb.draw_square(500, 500, 600, 700, RED);
|
||||||
|
fb.draw_square_fill(800, 800, 900, 900, GREEN);
|
||||||
|
fb.draw_square_fill(1000, 800, 1200, 700, BLUE);
|
||||||
|
fb.draw_square_fill(900, 100, 800, 150, RED | BLUE);
|
||||||
|
fb.draw_string("Hello World! :D\nTest next Line", 500, 5, 3, BLUE);
|
||||||
|
|
||||||
for i in 0..1080 {
|
fb.draw_function(cos, 0, 101, RED);
|
||||||
fb.draw_pixel(50, i, BLUE);
|
|
||||||
}
|
}
|
||||||
fb.draw_square(500, 500, 600, 700, RED);
|
|
||||||
fb.draw_square_fill(800, 800, 900, 900, GREEN);
|
|
||||||
fb.draw_square_fill(1000, 800, 1200, 700, BLUE);
|
|
||||||
fb.draw_square_fill(900, 100, 800, 150, RED | BLUE);
|
|
||||||
fb.draw_string("Hello World! :D\nTest next Line", 500, 5, 3, BLUE);
|
|
||||||
|
|
||||||
fb.draw_function(cos, 0, 101, RED);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let temp = mailbox::read_soc_temp([0]).unwrap();
|
// TODO: Mailbox requires a physical address. The stack is now in VA space causing an issue.
|
||||||
println!("{} °C", temp[1] / 1000);
|
// Fix with SVCs ?
|
||||||
|
|
||||||
|
// let temp = mailbox::read_soc_temp([0]).unwrap();
|
||||||
|
// println!("{} °C", temp[1] / 1000);
|
||||||
|
|
||||||
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
blink_gpio(SpecificGpio::OnboardLed as u8, 500);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user