linux
This commit is contained in:
BIN
nel_os_kernel/bzImage
Normal file
BIN
nel_os_kernel/bzImage
Normal file
Binary file not shown.
BIN
nel_os_kernel/rootfs-n.cpio.gz
Normal file
BIN
nel_os_kernel/rootfs-n.cpio.gz
Normal file
Binary file not shown.
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(
|
||||
|
291
nel_os_kernel/src/vmm/x86_64/common/linux.rs
Normal file
291
nel_os_kernel/src/vmm/x86_64/common/linux.rs
Normal 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,
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
pub mod linux;
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
pub fn read_msr(msr: u32) -> u64 {
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user