This commit is contained in:
Masato Imai
2025-08-10 10:20:36 +00:00
parent e897aa8da8
commit 78973adc59
8 changed files with 317 additions and 5 deletions

BIN
nel_os_kernel/bzImage Normal file

Binary file not shown.

Binary file not shown.

View File

@ -157,6 +157,8 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
info!("Interrupts enabled");
serial::disable_screen_output();
let mut vcpu = vmm::get_vcpu(&mut bitmap_table).unwrap();
loop {
let result = vcpu.run(&mut bitmap_table);

View File

@ -1,3 +1,5 @@
use core::sync::atomic::AtomicBool;
use alloc::format;
use lazy_static::lazy_static;
use spin::Mutex;
@ -13,6 +15,16 @@ lazy_static! {
};
}
static OUTPUT_TO_SCREEN: AtomicBool = AtomicBool::new(true);
pub fn disable_screen_output() {
OUTPUT_TO_SCREEN.store(false, core::sync::atomic::Ordering::Relaxed);
}
pub fn enable_screen_output() {
OUTPUT_TO_SCREEN.store(true, core::sync::atomic::Ordering::Relaxed);
}
pub fn _print(args: ::core::fmt::Arguments) {
use core::fmt::Write;
use x86_64::instructions::interrupts;
@ -23,6 +35,9 @@ pub fn _print(args: ::core::fmt::Arguments) {
.write_fmt(args)
.expect("Printing to serial failed");
if !OUTPUT_TO_SCREEN.load(core::sync::atomic::Ordering::Relaxed) {
return;
}
let mut fb = FRAME_BUFFER.lock();
let fb = fb.as_mut();

View File

@ -12,13 +12,18 @@ pub trait VCpu {
fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
where
Self: Sized;
fn is_supported() -> bool
where
Self: Sized;
fn run(
&mut self,
frame_allocator: &mut dyn FrameAllocator<Size4KiB>,
) -> Result<(), &'static str>;
fn write_memory(&mut self, addr: u64, data: u8) -> Result<(), &'static str>;
fn read_memory(&mut self, addr: u64) -> Result<u8, &'static str>;
}
pub fn get_vcpu(

View File

@ -0,0 +1,291 @@
use core::ptr::read_unaligned;
pub const BZIMAGE: &'static [u8] = include_bytes!("../../../../bzImage");
pub const INITRD: &'static [u8] = include_bytes!("../../../../rootfs-n.cpio.gz");
pub const LAYOUT_BOOTPARAM: u64 = 0x0001_0000;
pub const LAYOUT_CMDLINE: u64 = 0x0002_0000;
pub const LAYOUT_KERNEL_BASE: u64 = 0x0010_0000;
pub const LAYOUT_INITRD: u64 = 0x0800_0000;
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct BootParams {
pub _screen_info: [u8; 0x40],
pub _apm_bios_info: [u8; 0x14],
pub _pad2: [u8; 4],
pub tboot_addr: u64,
pub ist_info: [u8; 0x10],
pub _pad3: [u8; 0x10],
pub hd0_info: [u8; 0x10],
pub hd1_info: [u8; 0x10],
pub _sys_desc_table: [u8; 0x10],
pub _olpc_ofw_header: [u8; 0x10],
pub _pad4: [u8; 0x80],
pub _edid_info: [u8; 0x80],
pub _efi_info: [u8; 0x20],
pub alt_mem_k: u32,
pub scratch: u32,
pub e820_entries: u8,
pub eddbuf_entries: u8,
pub edd_mbr_sig_buf_entries: u8,
pub kbd_status: u8,
pub _pad6: [u8; 5],
pub hdr: SetupHeader,
pub _pad7: [u8; 0x290 - SetupHeader::HEADER_OFFSET - size_of::<SetupHeader>()],
pub _edd_mbr_sig_buffer: [u32; 0x10],
pub e820_map: [E820Entry; Self::E820MAX],
pub _unimplemented: [u8; 0x330],
}
impl BootParams {
pub const E820MAX: usize = 128;
pub fn new() -> Self {
let params = Self {
_screen_info: [0; 0x40],
_apm_bios_info: [0; 0x14],
_pad2: [0; 4],
tboot_addr: 0,
ist_info: [0; 0x10],
_pad3: [0; 0x10],
hd0_info: [0; 0x10],
hd1_info: [0; 0x10],
_sys_desc_table: [0; 0x10],
_olpc_ofw_header: [0; 0x10],
_pad4: [0; 0x80],
_edid_info: [0; 0x80],
_efi_info: [0; 0x20],
alt_mem_k: 0,
scratch: 0,
e820_entries: 0,
eddbuf_entries: 0,
edd_mbr_sig_buf_entries: 0,
kbd_status: 0,
_pad6: [0; 5],
hdr: SetupHeader::default(),
_pad7: [0; 0x290 - SetupHeader::HEADER_OFFSET - size_of::<SetupHeader>()],
_edd_mbr_sig_buffer: [0; 0x10],
e820_map: [E820Entry {
addr: 0,
size: 0,
type_: E820Type::Ram as u32,
}; Self::E820MAX],
_unimplemented: [0; 0x330],
};
params
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, &'static str> {
let hdr = SetupHeader::from_bytes(bytes)?;
let mut bp = BootParams::new();
bp.hdr = hdr;
Ok(bp)
}
pub fn add_e820_entry(&mut self, addr: u64, size: u64, type_: E820Type) {
self.e820_map[self.e820_entries as usize].addr = addr;
self.e820_map[self.e820_entries as usize].size = size;
self.e820_map[self.e820_entries as usize].type_ = type_ as u32;
self.e820_entries += 1;
}
}
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, Default)]
pub struct SetupHeader {
pub setup_sects: u8,
pub root_flags: u16,
pub syssize: u32,
pub ram_size: u16,
pub vid_mode: u16,
pub root_dev: u16,
pub boot_flag: u16,
pub jump: u16,
pub header: u32,
pub version: u16,
pub realmode_switch: u32,
pub start_sys_seg: u16,
pub kernel_version: u16,
pub type_of_loader: u8,
pub loadflags: LoadflagBitfield,
pub setup_move_size: u16,
pub code32_start: u32,
pub ramdisk_image: u32,
pub ramdisk_size: u32,
pub bootsect_kludge: u32,
pub heap_end_ptr: u16,
pub ext_loader_ver: u8,
pub ext_loader_type: u8,
pub cmd_line_ptr: u32,
pub initrd_addr_max: u32,
pub kernel_alignment: u32,
pub relocatable_kernel: u8,
pub min_alignment: u8,
pub xloadflags: u16,
pub cmdline_size: u32,
pub hardware_subarch: u32,
pub hardware_subarch_data: u64,
pub payload_offset: u32,
pub payload_length: u32,
pub setup_data: u64,
pub pref_address: u64,
pub init_size: u32,
pub handover_offset: u32,
pub kernel_info_offset: u32,
}
impl SetupHeader {
pub const HEADER_OFFSET: usize = 0x1F1;
pub fn from_bytes(bytes: &[u8]) -> Result<Self, &'static str> {
if bytes.len() < Self::HEADER_OFFSET + size_of::<Self>() {
return Err("バイト配列が小さすぎます");
}
let mut hdr = unsafe {
let header_ptr = bytes.as_ptr().add(Self::HEADER_OFFSET) as *const Self;
read_unaligned(header_ptr)
};
if hdr.setup_sects == 0 {
hdr.setup_sects = 4;
}
Ok(hdr)
}
pub fn get_protected_code_offset(&self) -> usize {
(self.setup_sects as usize + 1) * 512
}
}
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, Default)]
pub struct LoadflagBitfield {
raw: u8,
}
impl LoadflagBitfield {
pub fn loaded_high(&self) -> bool {
(self.raw & 0x01) != 0
}
pub fn set_loaded_high(&mut self, loaded_high: bool) {
if loaded_high {
self.raw |= 0x01;
} else {
self.raw &= !0x01;
}
}
pub fn kaslr_flag(&self) -> bool {
(self.raw & 0x02) != 0
}
pub fn quiet_flag(&self) -> bool {
(self.raw & 0x20) != 0
}
pub fn keep_segments(&self) -> bool {
(self.raw & 0x40) != 0
}
pub fn set_keep_segments(&mut self, keep_segments: bool) {
if keep_segments {
self.raw |= 0x40;
} else {
self.raw &= !0x40;
}
}
pub fn can_use_heap(&self) -> bool {
(self.raw & 0x80) != 0
}
pub fn set_can_use_heap(&mut self, can_use_heap: bool) {
if can_use_heap {
self.raw |= 0x80;
} else {
self.raw &= !0x80;
}
}
pub fn new(
loaded_high: bool,
kaslr_flag: bool,
quiet_flag: bool,
keep_segments: bool,
can_use_heap: bool,
) -> Self {
let mut raw = 0u8;
if loaded_high {
raw |= 0x01;
}
if kaslr_flag {
raw |= 0x02;
}
if quiet_flag {
raw |= 0x20;
}
if keep_segments {
raw |= 0x40;
}
if can_use_heap {
raw |= 0x80;
}
Self { raw }
}
pub fn to_u8(&self) -> u8 {
self.raw
}
}
#[repr(C, packed)]
#[derive(Debug, Clone, Copy)]
pub struct E820Entry {
addr: u64,
size: u64,
type_: u32,
}
impl E820Entry {
pub fn get_addr(&self) -> u64 {
self.addr
}
pub fn get_size(&self) -> u64 {
self.size
}
pub fn get_type(&self) -> Result<E820Type, &'static str> {
match self.type_ {
1 => Ok(E820Type::Ram),
2 => Ok(E820Type::Reserved),
3 => Ok(E820Type::Acpi),
4 => Ok(E820Type::Nvs),
5 => Ok(E820Type::Unusable),
_ => Err("不明なE820タイプ"),
}
}
pub fn new(addr: u64, size: u64, type_: E820Type) -> Self {
Self {
addr,
size,
type_: type_ as u32,
}
}
}
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum E820Type {
Ram = 1,
Reserved = 2,
Acpi = 3,
Nvs = 4,
Unusable = 5,
}

View File

@ -1,3 +1,5 @@
pub mod linux;
use core::arch::asm;
pub fn read_msr(msr: u32) -> u64 {

View File

@ -2,8 +2,7 @@ use core::arch::naked_asm;
use raw_cpuid::cpuid;
use x86_64::{
registers::control::Cr4Flags,
structures::paging::{frame, FrameAllocator, Size4KiB},
structures::paging::{FrameAllocator, Size4KiB},
VirtAddr,
};
@ -74,7 +73,7 @@ impl IntelVCpu {
match exit_reason {
VmxExitReason::HLT => {
info!("VM hlt");
//info!("VM hlt");
}
VmxExitReason::EPT_VIOLATION => {
let guest_address = vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL)?;
@ -91,7 +90,6 @@ impl IntelVCpu {
}
fn vmentry(&mut self) -> Result<(), InstructionError> {
info!("VMEntry");
let success = {
let result: u16;
unsafe {
@ -99,7 +97,6 @@ impl IntelVCpu {
};
result == 0
};
info!("VMEntry result: {}", success);
if !self.launch_done && success {
self.launch_done = true;