x86_64: initial booting capability
This commit is contained in:
parent
7fa347aa20
commit
e2381ee25a
@ -18,9 +18,13 @@ linked_list_allocator = "0.10.5"
|
||||
spinning_top = "0.2.5"
|
||||
static_assertions = "1.1.0"
|
||||
tock-registers = "0.8.1"
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
[dependencies.elf]
|
||||
version = "0.7.2"
|
||||
git = "https://git.alnyan.me/yggdrasil/yggdrasil-elf.git"
|
||||
default-features = false
|
||||
features = ["no_std_stream"]
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
yboot-proto = { git = "https://git.alnyan.me/yggdrasil/yboot-proto.git" }
|
||||
|
100
src/arch/mod.rs
100
src/arch/mod.rs
@ -1,48 +1,60 @@
|
||||
//! Provides architecture/platform-specific implementation details
|
||||
pub mod aarch64;
|
||||
|
||||
pub use aarch64::plat_qemu::{QemuPlatform as PlatformImpl, PLATFORM};
|
||||
pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE};
|
||||
use abi::error::Error;
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
/// Describes messages sent from some CPU to others
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u64)]
|
||||
pub enum CpuMessage {
|
||||
/// Indicates that the sender CPU entered kernel panic and wants other CPUs to follow
|
||||
Panic,
|
||||
}
|
||||
|
||||
/// Interface for an architecture-specific facilities
|
||||
pub trait Architecture {
|
||||
/// Address, to which "zero" address is mapped in the virtual address space
|
||||
const KERNEL_VIRT_OFFSET: usize;
|
||||
|
||||
/// Initializes the memory management unit and sets up virtual memory management.
|
||||
/// `bsp` flag is provided to make sure mapping tables are only initialized once in a SMP
|
||||
/// system.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe to call if the MMU has already been initialized.
|
||||
unsafe fn init_mmu(&self, bsp: bool);
|
||||
|
||||
/// Allocates a virtual mapping for the specified physical memory region
|
||||
fn map_device_pages(&self, phys: usize, count: usize) -> Result<usize, Error>;
|
||||
|
||||
// Architecture intrinsics
|
||||
|
||||
/// Suspends CPU until an interrupt is received
|
||||
fn wait_for_interrupt();
|
||||
|
||||
/// Sets the local CPU's interrupt mask.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Enabling interrupts may lead to unexpected behavior unless the context explicitly expects
|
||||
/// them.
|
||||
unsafe fn set_interrupt_mask(mask: bool);
|
||||
|
||||
/// Returns the local CPU's interrupt mask
|
||||
fn interrupt_mask() -> bool;
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "aarch64")] {
|
||||
pub mod aarch64;
|
||||
|
||||
pub use aarch64::plat_qemu::{QemuPlatform as PlatformImpl, PLATFORM};
|
||||
pub use aarch64::{AArch64 as ArchitectureImpl, ARCHITECTURE};
|
||||
use abi::error::Error;
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
/// Describes messages sent from some CPU to others
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u64)]
|
||||
pub enum CpuMessage {
|
||||
/// Indicates that the sender CPU entered kernel panic and wants other CPUs to follow
|
||||
Panic,
|
||||
}
|
||||
|
||||
/// Interface for an architecture-specific facilities
|
||||
pub trait Architecture {
|
||||
/// Address, to which "zero" address is mapped in the virtual address space
|
||||
const KERNEL_VIRT_OFFSET: usize;
|
||||
|
||||
/// Initializes the memory management unit and sets up virtual memory management.
|
||||
/// `bsp` flag is provided to make sure mapping tables are only initialized once in a SMP
|
||||
/// system.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe to call if the MMU has already been initialized.
|
||||
unsafe fn init_mmu(&self, bsp: bool);
|
||||
|
||||
/// Allocates a virtual mapping for the specified physical memory region
|
||||
fn map_device_pages(&self, phys: usize, count: usize) -> Result<usize, Error>;
|
||||
|
||||
// Architecture intrinsics
|
||||
|
||||
/// Suspends CPU until an interrupt is received
|
||||
fn wait_for_interrupt();
|
||||
|
||||
/// Sets the local CPU's interrupt mask.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Enabling interrupts may lead to unexpected behavior unless the context explicitly expects
|
||||
/// them.
|
||||
unsafe fn set_interrupt_mask(mask: bool);
|
||||
|
||||
/// Returns the local CPU's interrupt mask
|
||||
fn interrupt_mask() -> bool;
|
||||
}
|
||||
} else if #[cfg(target_arch = "x86_64")] {
|
||||
pub mod x86_64;
|
||||
} else {
|
||||
compile_error!("Architecture is not supported");
|
||||
}
|
||||
}
|
||||
|
0
src/arch/x86_64/entry.S
Normal file
0
src/arch/x86_64/entry.S
Normal file
73
src/arch/x86_64/mod.rs
Normal file
73
src/arch/x86_64/mod.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use core::arch::global_asm;
|
||||
|
||||
use yboot_proto::{
|
||||
v1::FramebufferOption, LoadProtocolHeader, LoadProtocolV1, KERNEL_MAGIC, LOADER_MAGIC,
|
||||
PROTOCOL_VERSION_1,
|
||||
};
|
||||
|
||||
pub const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
||||
const BOOT_STACK_SIZE: usize = 65536;
|
||||
|
||||
#[repr(C, align(0x20))]
|
||||
struct BootStack {
|
||||
data: [u8; BOOT_STACK_SIZE],
|
||||
}
|
||||
|
||||
#[link_section = ".bss"]
|
||||
static mut BSP_STACK: BootStack = BootStack {
|
||||
data: [0; BOOT_STACK_SIZE],
|
||||
};
|
||||
|
||||
#[used]
|
||||
#[link_section = ".data.yboot"]
|
||||
static mut YBOOT_DATA: LoadProtocolV1 = LoadProtocolV1 {
|
||||
header: LoadProtocolHeader {
|
||||
kernel_magic: KERNEL_MAGIC,
|
||||
version: PROTOCOL_VERSION_1,
|
||||
},
|
||||
kernel_virt_offset: KERNEL_VIRT_OFFSET as _,
|
||||
|
||||
opt_framebuffer: FramebufferOption {
|
||||
req_width: 1024,
|
||||
req_height: 768,
|
||||
|
||||
res_width: 0,
|
||||
res_height: 0,
|
||||
res_stride: 0,
|
||||
res_address: 0,
|
||||
},
|
||||
};
|
||||
|
||||
extern "C" fn __x86_64_upper_entry() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
r#"
|
||||
.global __x86_64_entry
|
||||
|
||||
.section .text.entry
|
||||
__x86_64_entry:
|
||||
mov ${yboot_loader_magic}, %edi
|
||||
cmp %edi, %eax
|
||||
je 2f
|
||||
|
||||
// (Currently) unsupported bootloader
|
||||
1:
|
||||
cli
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
2:
|
||||
// yboot entry method
|
||||
movabsq ${stack_bottom} + {stack_size}, %rax
|
||||
movabsq ${entry}, %rcx
|
||||
mov %rax, %rsp
|
||||
jmp *%rcx
|
||||
"#,
|
||||
yboot_loader_magic = const LOADER_MAGIC,
|
||||
stack_size = const BOOT_STACK_SIZE,
|
||||
stack_bottom = sym BSP_STACK,
|
||||
entry = sym __x86_64_upper_entry,
|
||||
options(att_syntax)
|
||||
);
|
0
src/arch/x86_64/tables.rs
Normal file
0
src/arch/x86_64/tables.rs
Normal file
183
src/main.rs
183
src/main.rs
@ -7,102 +7,107 @@
|
||||
const_trait_impl,
|
||||
maybe_uninit_slice,
|
||||
arbitrary_self_types,
|
||||
let_chains,
|
||||
linked_list_cursors
|
||||
const_mut_refs,
|
||||
let_chains
|
||||
)]
|
||||
#![allow(clippy::new_without_default)]
|
||||
#![warn(missing_docs)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate yggdrasil_abi as abi;
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::{FileMode, OpenOptions, RawFd},
|
||||
process::ExitCode,
|
||||
};
|
||||
use fs::{devfs, FileBlockAllocator, INITRD_DATA};
|
||||
use memfs::MemoryFilesystem;
|
||||
use task::process::Process;
|
||||
use vfs::{Filesystem, IoContext, VnodeRef};
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
pub mod debug;
|
||||
// extern crate yggdrasil_abi as abi;
|
||||
//
|
||||
// use abi::{
|
||||
// error::Error,
|
||||
// io::{FileMode, OpenOptions, RawFd},
|
||||
// process::ExitCode,
|
||||
// };
|
||||
// use fs::{devfs, FileBlockAllocator, INITRD_DATA};
|
||||
// use memfs::MemoryFilesystem;
|
||||
// use task::process::Process;
|
||||
// use vfs::{Filesystem, IoContext, VnodeRef};
|
||||
//
|
||||
// extern crate alloc;
|
||||
//
|
||||
// #[macro_use]
|
||||
// pub mod debug;
|
||||
#[macro_use]
|
||||
pub mod arch;
|
||||
|
||||
pub mod device;
|
||||
pub mod fs;
|
||||
pub mod mem;
|
||||
pub mod panic;
|
||||
pub mod proc;
|
||||
pub mod sync;
|
||||
pub mod syscall;
|
||||
pub mod task;
|
||||
pub mod util;
|
||||
|
||||
fn setup_root() -> Result<VnodeRef, Error> {
|
||||
let initrd_data = INITRD_DATA.get();
|
||||
let fs = MemoryFilesystem::<FileBlockAllocator>::from_slice(initrd_data.data).unwrap();
|
||||
fs.root()
|
||||
}
|
||||
|
||||
/// Entry point for common kernel code.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This function is meant to be used as a kernel-space process after all the platform-specific
|
||||
/// initialization has finished.
|
||||
pub fn kernel_main() {
|
||||
// use crate::{debug::LogLevel, mem::phys};
|
||||
// use crate::task::tasklet::{self, TaskFlow};
|
||||
// use core::time::Duration;
|
||||
|
||||
// Schedule a tasklet to print memory usage stats every 10 seconds
|
||||
// tasklet::add_periodic("mem-stats", Duration::from_secs(3), || {
|
||||
// let phys_mem = phys::PHYSICAL_MEMORY.get().lock();
|
||||
// let stats = phys_mem.stats();
|
||||
// stats.dump(LogLevel::Debug);
|
||||
|
||||
// TaskFlow::Continue
|
||||
// });
|
||||
|
||||
let root = match setup_root() {
|
||||
Ok(root) => root,
|
||||
Err(err) => {
|
||||
warnln!("Could not setup root from initrd: {:?}", err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let ioctx = IoContext::new(root);
|
||||
let node = ioctx.find(None, "/init", true, true).unwrap();
|
||||
let file = node.open(OpenOptions::READ, FileMode::empty()).unwrap();
|
||||
|
||||
let devfs = devfs::root();
|
||||
let console = ioctx
|
||||
.find(Some(devfs.clone()), "ttyS0", true, true)
|
||||
.unwrap();
|
||||
let stdin = console.open(OpenOptions::READ, FileMode::empty()).unwrap();
|
||||
let stdout = console.open(OpenOptions::WRITE, FileMode::empty()).unwrap();
|
||||
let stderr = stdout.clone();
|
||||
|
||||
{
|
||||
let user_init = proc::exec::load_elf(file, &["/init", "xxx"]).unwrap();
|
||||
let mut io = user_init.io.lock();
|
||||
io.set_ioctx(ioctx);
|
||||
io.set_file(RawFd::STDIN, stdin).unwrap();
|
||||
io.set_file(RawFd::STDOUT, stdout).unwrap();
|
||||
io.set_file(RawFd::STDERR, stderr).unwrap();
|
||||
drop(io);
|
||||
|
||||
user_init.set_session_terminal(console);
|
||||
|
||||
user_init.enqueue_somewhere();
|
||||
}
|
||||
|
||||
Process::current().exit(ExitCode::SUCCESS);
|
||||
#[panic_handler]
|
||||
fn panic_handler(_pi: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
//
|
||||
// pub mod device;
|
||||
// pub mod fs;
|
||||
// pub mod mem;
|
||||
// pub mod panic;
|
||||
// pub mod proc;
|
||||
// pub mod sync;
|
||||
// pub mod syscall;
|
||||
// pub mod task;
|
||||
// pub mod util;
|
||||
//
|
||||
// fn setup_root() -> Result<VnodeRef, Error> {
|
||||
// let initrd_data = INITRD_DATA.get();
|
||||
// let fs = MemoryFilesystem::<FileBlockAllocator>::from_slice(initrd_data.data).unwrap();
|
||||
// fs.root()
|
||||
// }
|
||||
//
|
||||
// /// Entry point for common kernel code.
|
||||
// ///
|
||||
// /// # Note
|
||||
// ///
|
||||
// /// This function is meant to be used as a kernel-space process after all the platform-specific
|
||||
// /// initialization has finished.
|
||||
// pub fn kernel_main() {
|
||||
// // use crate::{debug::LogLevel, mem::phys};
|
||||
// // use crate::task::tasklet::{self, TaskFlow};
|
||||
// // use core::time::Duration;
|
||||
//
|
||||
// // Schedule a tasklet to print memory usage stats every 10 seconds
|
||||
// // tasklet::add_periodic("mem-stats", Duration::from_secs(3), || {
|
||||
// // let phys_mem = phys::PHYSICAL_MEMORY.get().lock();
|
||||
// // let stats = phys_mem.stats();
|
||||
// // stats.dump(LogLevel::Debug);
|
||||
//
|
||||
// // TaskFlow::Continue
|
||||
// // });
|
||||
//
|
||||
// let root = match setup_root() {
|
||||
// Ok(root) => root,
|
||||
// Err(err) => {
|
||||
// warnln!("Could not setup root from initrd: {:?}", err);
|
||||
// return;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let ioctx = IoContext::new(root);
|
||||
// let node = ioctx.find(None, "/init", true, true).unwrap();
|
||||
// let file = node.open(OpenOptions::READ, FileMode::empty()).unwrap();
|
||||
//
|
||||
// let devfs = devfs::root();
|
||||
// let console = ioctx
|
||||
// .find(Some(devfs.clone()), "ttyS0", true, true)
|
||||
// .unwrap();
|
||||
// let stdin = console.open(OpenOptions::READ, FileMode::empty()).unwrap();
|
||||
// let stdout = console.open(OpenOptions::WRITE, FileMode::empty()).unwrap();
|
||||
// let stderr = stdout.clone();
|
||||
//
|
||||
// {
|
||||
// let user_init = proc::exec::load_elf(file, &["/init", "xxx"]).unwrap();
|
||||
// let mut io = user_init.io.lock();
|
||||
// io.set_ioctx(ioctx);
|
||||
// io.set_file(RawFd::STDIN, stdin).unwrap();
|
||||
// io.set_file(RawFd::STDOUT, stdout).unwrap();
|
||||
// io.set_file(RawFd::STDERR, stderr).unwrap();
|
||||
// drop(io);
|
||||
//
|
||||
// user_init.set_session_terminal(console);
|
||||
//
|
||||
// user_init.enqueue_somewhere();
|
||||
// }
|
||||
//
|
||||
// Process::current().exit(ExitCode::SUCCESS);
|
||||
// }
|
||||
|
Loading…
x
Reference in New Issue
Block a user