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");
|
info!("Interrupts enabled");
|
||||||
|
|
||||||
|
serial::disable_screen_output();
|
||||||
|
|
||||||
let mut vcpu = vmm::get_vcpu(&mut bitmap_table).unwrap();
|
let mut vcpu = vmm::get_vcpu(&mut bitmap_table).unwrap();
|
||||||
loop {
|
loop {
|
||||||
let result = vcpu.run(&mut bitmap_table);
|
let result = vcpu.run(&mut bitmap_table);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use core::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use spin::Mutex;
|
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) {
|
pub fn _print(args: ::core::fmt::Arguments) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use x86_64::instructions::interrupts;
|
use x86_64::instructions::interrupts;
|
||||||
@ -23,6 +35,9 @@ pub fn _print(args: ::core::fmt::Arguments) {
|
|||||||
.write_fmt(args)
|
.write_fmt(args)
|
||||||
.expect("Printing to serial failed");
|
.expect("Printing to serial failed");
|
||||||
|
|
||||||
|
if !OUTPUT_TO_SCREEN.load(core::sync::atomic::Ordering::Relaxed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut fb = FRAME_BUFFER.lock();
|
let mut fb = FRAME_BUFFER.lock();
|
||||||
let fb = fb.as_mut();
|
let fb = fb.as_mut();
|
||||||
|
|
||||||
|
@ -12,13 +12,18 @@ pub trait VCpu {
|
|||||||
fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
|
fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<Self, &'static str>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
fn is_supported() -> bool
|
fn is_supported() -> bool
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
frame_allocator: &mut dyn FrameAllocator<Size4KiB>,
|
frame_allocator: &mut dyn FrameAllocator<Size4KiB>,
|
||||||
) -> Result<(), &'static str>;
|
) -> 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(
|
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;
|
use core::arch::asm;
|
||||||
|
|
||||||
pub fn read_msr(msr: u32) -> u64 {
|
pub fn read_msr(msr: u32) -> u64 {
|
||||||
|
@ -2,8 +2,7 @@ use core::arch::naked_asm;
|
|||||||
|
|
||||||
use raw_cpuid::cpuid;
|
use raw_cpuid::cpuid;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
registers::control::Cr4Flags,
|
structures::paging::{FrameAllocator, Size4KiB},
|
||||||
structures::paging::{frame, FrameAllocator, Size4KiB},
|
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ impl IntelVCpu {
|
|||||||
|
|
||||||
match exit_reason {
|
match exit_reason {
|
||||||
VmxExitReason::HLT => {
|
VmxExitReason::HLT => {
|
||||||
info!("VM hlt");
|
//info!("VM hlt");
|
||||||
}
|
}
|
||||||
VmxExitReason::EPT_VIOLATION => {
|
VmxExitReason::EPT_VIOLATION => {
|
||||||
let guest_address = vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL)?;
|
let guest_address = vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL)?;
|
||||||
@ -91,7 +90,6 @@ impl IntelVCpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn vmentry(&mut self) -> Result<(), InstructionError> {
|
fn vmentry(&mut self) -> Result<(), InstructionError> {
|
||||||
info!("VMEntry");
|
|
||||||
let success = {
|
let success = {
|
||||||
let result: u16;
|
let result: u16;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -99,7 +97,6 @@ impl IntelVCpu {
|
|||||||
};
|
};
|
||||||
result == 0
|
result == 0
|
||||||
};
|
};
|
||||||
info!("VMEntry result: {}", success);
|
|
||||||
|
|
||||||
if !self.launch_done && success {
|
if !self.launch_done && success {
|
||||||
self.launch_done = true;
|
self.launch_done = true;
|
||||||
|
Reference in New Issue
Block a user