x86_64: initial booting capability

This commit is contained in:
Mark Poliakov 2023-07-28 14:26:39 +03:00
parent 7fa347aa20
commit e2381ee25a
6 changed files with 227 additions and 133 deletions

View File

@ -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" }

View File

@ -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
View File

73
src/arch/x86_64/mod.rs Normal file
View 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)
);

View File

View File

@ -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);
// }