mirror of
https://github.com/iceHtwoO/novaOS.git
synced 2026-04-16 20:22:26 +00:00
feat: start application via application_manager
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ settings.json
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.venv
|
.venv
|
||||||
.nvimlog
|
.nvimlog
|
||||||
|
__pycache__
|
||||||
|
.pytest_cache
|
||||||
|
|
||||||
|
|||||||
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@@ -66,6 +66,16 @@
|
|||||||
"preLaunchTask": "Run QEMU",
|
"preLaunchTask": "Run QEMU",
|
||||||
"stopOnEntry": true,
|
"stopOnEntry": true,
|
||||||
"processCreateCommands": ["gdb-remote localhost:1234"]
|
"processCreateCommands": ["gdb-remote localhost:1234"]
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "NVIM LLDB",
|
||||||
|
"type": "codelldb",
|
||||||
|
"request": "attach",
|
||||||
|
"program": "${workspaceFolder}/target/aarch64-unknown-none/debug/nova",
|
||||||
|
"preLaunchTask": "Run QEMU",
|
||||||
|
"stopOnEntry": true,
|
||||||
|
"processCreateCommands": ["gdb-remote localhost:1234"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
25
Cargo.lock
generated
25
Cargo.lock
generated
@@ -40,6 +40,15 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.29"
|
version = "0.4.29"
|
||||||
@@ -55,6 +64,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"nova_error",
|
"nova_error",
|
||||||
"paste",
|
"paste",
|
||||||
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -129,6 +139,21 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.111"
|
version = "2.0.111"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ heap = {path = "workspace/heap"}
|
|||||||
nova_error = {path = "workspace/nova_error"}
|
nova_error = {path = "workspace/nova_error"}
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
|
spin = "0.10.0"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ pub enum PhysSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(align(4096))]
|
#[repr(align(4096))]
|
||||||
pub struct PageTable([TableEntry; TABLE_ENTRY_COUNT]);
|
pub struct PageTable(pub [TableEntry; TABLE_ENTRY_COUNT]);
|
||||||
|
|
||||||
impl Iterator for PageTable {
|
impl Iterator for PageTable {
|
||||||
type Item = VirtAddr;
|
type Item = VirtAddr;
|
||||||
@@ -204,7 +204,6 @@ fn map_range_dynamic(
|
|||||||
(virt, _) = virt.overflowing_add(GRANULARITY);
|
(virt, _) = virt.overflowing_add(GRANULARITY);
|
||||||
remaining -= GRANULARITY;
|
remaining -= GRANULARITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +223,7 @@ pub fn alloc_page(
|
|||||||
|
|
||||||
/// Allocate a singe page in one block.
|
/// Allocate a singe page in one block.
|
||||||
pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result<VirtAddr, NovaError> {
|
pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result<VirtAddr, NovaError> {
|
||||||
if !start.is_multiple_of(GRANULARITY) {
|
if !start.is_multiple_of(LEVEL2_BLOCK_SIZE) {
|
||||||
return Err(NovaError::Misalignment);
|
return Err(NovaError::Misalignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,8 +237,8 @@ pub fn find_free_kerne_page_in_block(start: VirtAddr) -> Result<VirtAddr, NovaEr
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(virt_addr) = table.next() {
|
if let Some(offset) = table.next() {
|
||||||
return Ok(virt_addr);
|
return Ok(start + (offset * GRANULARITY));
|
||||||
}
|
}
|
||||||
Err(NovaError::OutOfMeomory)
|
Err(NovaError::OutOfMeomory)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aarch64::mmu::{
|
aarch64::mmu::{
|
||||||
find_free_kerne_page_in_block, map_page, physical_mapping::reserve_page, TableEntry,
|
find_free_kerne_page_in_block, map_page, physical_mapping::reserve_page, PageTable,
|
||||||
NORMAL_MEM, TRANSLATIONTABLE_TTBR1, WRITABLE,
|
TableEntry, VirtAddr, NORMAL_MEM, TRANSLATIONTABLE_TTBR0, TRANSLATIONTABLE_TTBR1, WRITABLE,
|
||||||
},
|
},
|
||||||
configuration::memory_mapping::APPLICATION_TRANSLATION_TABLE_VA,
|
configuration::memory_mapping::{APPLICATION_TRANSLATION_TABLE_VA, EL0_STACK_TOP},
|
||||||
};
|
};
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::arch::asm;
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
pub table_ptr: *mut TableEntry,
|
pub table_ptr: *mut TableEntry,
|
||||||
}
|
pub start_addr: usize,
|
||||||
|
|
||||||
impl Default for Application {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application {
|
impl Application {
|
||||||
pub fn new() -> Self {
|
pub fn new(start_addr: VirtAddr) -> Self {
|
||||||
let physical_addr = reserve_page();
|
let physical_addr = reserve_page();
|
||||||
let virtual_address =
|
let virtual_address =
|
||||||
find_free_kerne_page_in_block(APPLICATION_TRANSLATION_TABLE_VA).unwrap();
|
find_free_kerne_page_in_block(APPLICATION_TRANSLATION_TABLE_VA).unwrap();
|
||||||
@@ -31,14 +28,55 @@ impl Application {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// TODO: Temporary fix, while kernel and app share some memory regions
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
|
unsafe {
|
||||||
|
let table = &mut *(virtual_address as *mut PageTable);
|
||||||
|
table.0 = TRANSLATIONTABLE_TTBR0.0;
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
table_ptr: physical_addr as *mut TableEntry,
|
table_ptr: physical_addr as *mut TableEntry,
|
||||||
|
start_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn start(&self) {
|
||||||
|
unsafe {
|
||||||
|
asm!("msr ELR_EL1, {}", in(reg) self.start_addr);
|
||||||
|
asm!("msr SPSR_EL1, {0:x}", in(reg) 0);
|
||||||
|
asm!("msr SP_EL0, {0:x}", in(reg) EL0_STACK_TOP);
|
||||||
|
asm!("msr TTBR0_EL1, {}", in(reg) self.table_ptr as usize);
|
||||||
|
asm!("eret");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static mut APPLICATION_LIST: Option<Vec<Application>> = None;
|
struct AppManager {
|
||||||
|
apps: Option<Vec<Application>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppManager {
|
||||||
|
const fn new() -> Self {
|
||||||
|
Self { apps: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for AppManager {}
|
||||||
|
|
||||||
|
static APP_MANAGER: Mutex<AppManager> = Mutex::new(AppManager::new());
|
||||||
|
|
||||||
pub fn initialize_app_manager() {
|
pub fn initialize_app_manager() {
|
||||||
unsafe { APPLICATION_LIST = Some(Vec::new()) }
|
let mut guard = APP_MANAGER.lock();
|
||||||
|
guard.apps = Some(Vec::new());
|
||||||
|
}
|
||||||
|
pub fn add_app(app: Application) {
|
||||||
|
if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() {
|
||||||
|
app_list.push(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_app(index: usize) {
|
||||||
|
if let Some(app_list) = APP_MANAGER.lock().apps.as_mut() {
|
||||||
|
app_list[index].start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/config.S
22
src/config.S
@@ -78,25 +78,3 @@ configure_mmu_el1:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.align 4
|
|
||||||
.global el1_to_el0
|
|
||||||
el1_to_el0:
|
|
||||||
mov x8, x0
|
|
||||||
// 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
|
|
||||||
adrp x0, EL0_STACK_TOP
|
|
||||||
ldr x1, [x0, :lo12:EL0_STACK_TOP]
|
|
||||||
msr SP_EL0, x1
|
|
||||||
|
|
||||||
isb
|
|
||||||
|
|
||||||
mov x0, x8
|
|
||||||
// Return to EL0
|
|
||||||
eret
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ pub const EL0_STACK_SIZE: usize = LEVEL2_BLOCK_SIZE * 2;
|
|||||||
pub const MAILBOX_VIRTUAL_ADDRESS: VirtAddr = 0xFFFF_FF81_FFFF_E000;
|
pub const MAILBOX_VIRTUAL_ADDRESS: VirtAddr = 0xFFFF_FF81_FFFF_E000;
|
||||||
pub static mut MAILBOX_PHYSICAL_ADDRESS: Option<PhysAddr> = None;
|
pub static mut MAILBOX_PHYSICAL_ADDRESS: Option<PhysAddr> = None;
|
||||||
|
|
||||||
|
// TODO: Currently limited to 512 applications, more than enough, but has to be kept
|
||||||
|
// in mind
|
||||||
pub const APPLICATION_TRANSLATION_TABLE_VA: VirtAddr = 0xFFFF_FF81_FE00_0000;
|
pub const APPLICATION_TRANSLATION_TABLE_VA: VirtAddr = 0xFFFF_FF81_FE00_0000;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ extern crate alloc;
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use nova::{
|
use nova::{
|
||||||
aarch64::registers::{daif, read_id_aa64mmfr0_el1},
|
aarch64::registers::{daif, read_id_aa64mmfr0_el1},
|
||||||
|
application_manager::{add_app, Application},
|
||||||
configuration::memory_mapping::initialize_mmu_translation_tables,
|
configuration::memory_mapping::initialize_mmu_translation_tables,
|
||||||
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
framebuffer::{FrameBuffer, BLUE, GREEN, RED},
|
||||||
get_current_el, init_logger,
|
get_current_el, init_logger,
|
||||||
@@ -77,7 +78,6 @@ pub extern "C" fn main() -> ! {
|
|||||||
unsafe {
|
unsafe {
|
||||||
el2_to_el1();
|
el2_to_el1();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::empty_loop)]
|
#[allow(clippy::empty_loop)]
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
@@ -104,6 +104,9 @@ pub extern "C" fn kernel_main() {
|
|||||||
|
|
||||||
enable_irq_source(IRQSource::UartInt);
|
enable_irq_source(IRQSource::UartInt);
|
||||||
|
|
||||||
|
let app = Application::new(el0 as *const () as usize);
|
||||||
|
add_app(app);
|
||||||
|
|
||||||
kernel_loop();
|
kernel_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use core::arch::asm;
|
|||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
application_manager::start_app,
|
||||||
interrupt_handlers::irq::{register_interrupt_handler, IRQSource},
|
interrupt_handlers::irq::{register_interrupt_handler, IRQSource},
|
||||||
peripherals::uart::read_uart_data,
|
peripherals::uart::read_uart_data,
|
||||||
pi3::mailbox::read_soc_temp,
|
pi3::mailbox::read_soc_temp,
|
||||||
@@ -15,10 +16,6 @@ pub struct Terminal {
|
|||||||
input: String,
|
input: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn el1_to_el0();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Terminal {
|
impl Default for Terminal {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
@@ -48,7 +45,7 @@ impl Terminal {
|
|||||||
"el0" => unsafe {
|
"el0" => unsafe {
|
||||||
let i = 69;
|
let i = 69;
|
||||||
asm!("", in("x0") i);
|
asm!("", in("x0") i);
|
||||||
el1_to_el0();
|
start_app(0);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unknown command: \"{}\"", self.input);
|
println!("Unknown command: \"{}\"", self.input);
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ qemu-system-aarch64 \
|
|||||||
-cpu cortex-a53 \
|
-cpu cortex-a53 \
|
||||||
-serial stdio \
|
-serial stdio \
|
||||||
-sd ../sd.img \
|
-sd ../sd.img \
|
||||||
-kernel ../target/aarch64-unknown-none/debug/kernel8.img \
|
-kernel ../target/aarch64-unknown-none/debug/kernel8.img -S -s
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fn test_heap_allocation() {
|
|||||||
assert_eq!(actual_alloc_size % MIN_BLOCK_SIZE, 0);
|
assert_eq!(actual_alloc_size % MIN_BLOCK_SIZE, 0);
|
||||||
|
|
||||||
// Verify section is occupied
|
// Verify section is occupied
|
||||||
assert!((*malloc_header).free == false);
|
assert!(!(*malloc_header).free);
|
||||||
|
|
||||||
// Verify next header has been created
|
// Verify next header has been created
|
||||||
let next = (*malloc_header).next.unwrap();
|
let next = (*malloc_header).next.unwrap();
|
||||||
@@ -55,7 +55,7 @@ fn test_full_heap() {
|
|||||||
let malloc = heap.malloc(malloc_size).unwrap();
|
let malloc = heap.malloc(malloc_size).unwrap();
|
||||||
let malloc_header = Heap::get_header_ref_from_data_pointer(malloc);
|
let malloc_header = Heap::get_header_ref_from_data_pointer(malloc);
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_eq!((*malloc_header).free, false);
|
assert!(!(*malloc_header).free);
|
||||||
assert!((*malloc_header).next.is_none());
|
assert!((*malloc_header).next.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ fn test_freeing_root() {
|
|||||||
let malloc = heap.malloc(malloc_size).unwrap();
|
let malloc = heap.malloc(malloc_size).unwrap();
|
||||||
let malloc_header = Heap::get_header_ref_from_data_pointer(malloc);
|
let malloc_header = Heap::get_header_ref_from_data_pointer(malloc);
|
||||||
unsafe {
|
unsafe {
|
||||||
assert_eq!((*malloc_header).free, false);
|
assert!(!(*malloc_header).free);
|
||||||
assert!((*malloc_header).size >= malloc_size);
|
assert!((*malloc_header).size >= malloc_size);
|
||||||
assert!((*root_header).next.is_some());
|
assert!((*root_header).next.is_some());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user