need to push this shit before I murder someone
This commit is contained in:
parent
749a0d6bec
commit
088a7e3fc8
@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use core::ptr::addr_of_mut;
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
|
||||||
use intbits::Bits;
|
use intbits::Bits;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -77,7 +77,19 @@ lazy_static! {
|
|||||||
let sel_u_cs = gdt.append(Descriptor::user_code_segment());
|
let sel_u_cs = gdt.append(Descriptor::user_code_segment());
|
||||||
// DO NOT REORDER
|
// DO NOT REORDER
|
||||||
let sel_tss = gdt.append(
|
let sel_tss = gdt.append(
|
||||||
Descriptor::tss_segment(&TSS).set_flags(DescriptorFlags::from_bits_retain(0b1010))
|
{
|
||||||
|
let tss_addr = addr_of!(TSS) as u128;
|
||||||
|
let tss_size = size_of_val(&TSS) as u128;
|
||||||
|
let mut tss_descriptor: u128 = 0;
|
||||||
|
tss_descriptor.set_bits(0..=15, tss_size.bits(0..=15)); // Limit bits 0..=15
|
||||||
|
tss_descriptor.set_bits(48..=51, tss_size.bits(16..=19)); // Limit bits 16..=19
|
||||||
|
tss_descriptor.set_bits(16..=39, tss_addr.bits(0..=24)); // Base bits 0..=24
|
||||||
|
tss_descriptor.set_bits(56..=95, tss_addr.bits(25..=63)); // Base bits 25..=63
|
||||||
|
tss_descriptor.set_bits(40..=47, 0b10110001);
|
||||||
|
tss_descriptor.set_bits(52..=55, 0b1010);
|
||||||
|
log_info!("TSS descriptor (calculated manually): 0x{:032x}", tss_descriptor);
|
||||||
|
Descriptor::SystemSegment(tss_descriptor.bits(64..=127) as u64, tss_descriptor.bits(0..=63) as u64)
|
||||||
|
}
|
||||||
);
|
);
|
||||||
Selectors {
|
Selectors {
|
||||||
sel_kernel_code: sel_k_cs,
|
sel_kernel_code: sel_k_cs,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use crate::arch::x86_64::gdt::SELECTORS;
|
use crate::arch::x86_64::gdt::SELECTORS;
|
||||||
use crate::{LOGGER, format, log_info, log_trace};
|
use crate::{LOGGER, SERIAL_3F8, format, log_info, log_trace};
|
||||||
use crate::{LogLevel, log_error};
|
use crate::{LogLevel, log_error};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use x86_64::PhysAddr;
|
use x86_64::PhysAddr;
|
||||||
@ -19,18 +19,47 @@ pub fn get_lapic_addr() -> PhysAddr {
|
|||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDT: InterruptDescriptorTable = {
|
pub static ref IDT: InterruptDescriptorTable = {
|
||||||
let mut idt = InterruptDescriptorTable::new();
|
let mut idt = InterruptDescriptorTable::new();
|
||||||
// TODO: Rewrite using our own x86 interrupt wrapper
|
|
||||||
// code. The x86_interrupt ABI is always breaking, and this
|
|
||||||
// approach will fall apart once multiarch support is re-added.
|
|
||||||
unsafe {
|
unsafe {
|
||||||
idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
idt.double_fault
|
||||||
idt.page_fault.set_handler_fn(page_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
.set_handler_fn(double_fault)
|
||||||
idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
.set_code_selector(SELECTORS.sel_kernel_code)
|
||||||
|
.set_privilege_level(x86_64::PrivilegeLevel::Ring3)
|
||||||
|
.set_present(true);
|
||||||
|
idt.page_fault
|
||||||
|
.set_handler_fn(page_fault)
|
||||||
|
.set_code_selector(SELECTORS.sel_kernel_code)
|
||||||
|
.set_privilege_level(x86_64::PrivilegeLevel::Ring3)
|
||||||
|
.set_present(true);
|
||||||
|
idt.general_protection_fault
|
||||||
|
.set_handler_fn(gen_prot_fault)
|
||||||
|
.set_code_selector(SELECTORS.sel_kernel_code)
|
||||||
|
.set_privilege_level(x86_64::PrivilegeLevel::Ring3)
|
||||||
|
.set_present(true);
|
||||||
|
idt.divide_error
|
||||||
|
.set_handler_fn(div_zero)
|
||||||
|
.set_code_selector(SELECTORS.sel_kernel_code)
|
||||||
|
.set_privilege_level(x86_64::PrivilegeLevel::Ring3)
|
||||||
|
.set_present(true);
|
||||||
|
idt.breakpoint
|
||||||
|
.set_handler_fn(debug)
|
||||||
|
.set_code_selector(SELECTORS.sel_kernel_code)
|
||||||
|
.set_privilege_level(x86_64::PrivilegeLevel::Ring3)
|
||||||
|
.set_present(true);
|
||||||
}
|
}
|
||||||
idt
|
idt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn div_zero(info: InterruptStackFrame) {
|
||||||
|
log_error!("Divide by zero error: 0x{:x}, {:?}", info.instruction_pointer, info.code_segment.rpl());
|
||||||
|
unsafe { info.iretq() }
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "x86-interrupt" fn debug(info: InterruptStackFrame) {
|
||||||
|
log_error!("Debug");
|
||||||
|
unsafe { info.iretq() }
|
||||||
|
}
|
||||||
|
|
||||||
// Must do this to avoid unused function warning
|
// Must do this to avoid unused function warning
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
|
extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
|
||||||
@ -40,10 +69,11 @@ extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFaultErrorCode) {
|
extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFaultErrorCode) {
|
||||||
let addr = x86_64::registers::control::Cr2::read();
|
SERIAL_3F8.lock().log_writeln("Page fault, baby!");
|
||||||
|
let page_fault_addr = x86_64::registers::control::Cr2::read();
|
||||||
log_trace!(
|
log_trace!(
|
||||||
"Fault: Page fault with {}, error code 0b{:b}",
|
"Fault: Page fault with {}, error code 0b{:b}",
|
||||||
match addr {
|
match page_fault_addr {
|
||||||
Ok(addr_inner) => format!("address 0x{:x}", addr_inner),
|
Ok(addr_inner) => format!("address 0x{:x}", addr_inner),
|
||||||
Err(_) => "invalid virtual address".into(),
|
Err(_) => "invalid virtual address".into(),
|
||||||
},
|
},
|
||||||
@ -60,7 +90,10 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau
|
|||||||
| errcode.contains(PageFaultErrorCode::MALFORMED_TABLE)
|
| errcode.contains(PageFaultErrorCode::MALFORMED_TABLE)
|
||||||
{
|
{
|
||||||
let info_formatted = format!("{info:#?}");
|
let info_formatted = format!("{info:#?}");
|
||||||
crate::interrupt::page_fault_fatal(addr.unwrap().as_u64() as usize, info_formatted)
|
crate::interrupt::page_fault_fatal(
|
||||||
|
page_fault_addr.unwrap().as_u64() as usize,
|
||||||
|
info_formatted,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
log_error!("Page Fault, trying to recover...");
|
log_error!("Page Fault, trying to recover...");
|
||||||
todo!("Page fault handler (kernel mode)")
|
todo!("Page fault handler (kernel mode)")
|
||||||
@ -71,7 +104,7 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) {
|
extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) {
|
||||||
crate::interrupt::gen_prot_fault(format!(
|
crate::interrupt::gen_prot_fault(format!(
|
||||||
"RIP 0x{:x}, CS {} ({:?}), error: 0x{:x}",
|
"RIP 0x{:x}, CS {} (RPL {:?}), error: 0x{:x}",
|
||||||
info.instruction_pointer,
|
info.instruction_pointer,
|
||||||
info.code_segment.index(),
|
info.code_segment.index(),
|
||||||
info.code_segment.rpl(),
|
info.code_segment.rpl(),
|
||||||
|
|||||||
@ -1,20 +1,22 @@
|
|||||||
use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStackFrameValue};
|
use x86_64::{VirtAddr, registers::{rflags::RFlags, segmentation::Segment}, structures::idt::InterruptStackFrameValue};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{
|
arch::{
|
||||||
asm::ltr, x86_64::{
|
asm::ltr,
|
||||||
gdt::SELECTORS, interrupts::IDT,
|
x86_64::{gdt::SELECTORS, interrupts::IDT},
|
||||||
},
|
},
|
||||||
}, log::{LOGGER, LogLevel}, log_info, memory::alloc::format,
|
log::{LOGGER, LogLevel},
|
||||||
|
log_info,
|
||||||
|
memory::alloc::format,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init() -> Result<(), ()> {
|
pub fn init() -> Result<(), ()> {
|
||||||
// Ensure GDT exists
|
|
||||||
SELECTORS.gdt.load();
|
|
||||||
log_info!("GDT loaded!");
|
|
||||||
// Load IDT
|
// Load IDT
|
||||||
IDT.load();
|
IDT.load();
|
||||||
log_info!("IDT loaded!");
|
log_info!("IDT loaded!");
|
||||||
|
// Ensure GDT exists
|
||||||
|
SELECTORS.gdt.load();
|
||||||
|
log_info!("GDT loaded!");
|
||||||
x86_64::registers::model_specific::Star::write(
|
x86_64::registers::model_specific::Star::write(
|
||||||
SELECTORS.sel_user_code,
|
SELECTORS.sel_user_code,
|
||||||
SELECTORS.sel_user_stack,
|
SELECTORS.sel_user_stack,
|
||||||
@ -22,12 +24,17 @@ pub fn init() -> Result<(), ()> {
|
|||||||
SELECTORS.sel_kernel_stack,
|
SELECTORS.sel_kernel_stack,
|
||||||
)
|
)
|
||||||
.expect("Segment order in GDT is bad");
|
.expect("Segment order in GDT is bad");
|
||||||
|
unsafe {
|
||||||
|
x86_64::registers::segmentation::CS::set_reg(SELECTORS.sel_kernel_code);
|
||||||
|
x86_64::registers::segmentation::SS::set_reg(SELECTORS.sel_kernel_stack);
|
||||||
|
}
|
||||||
//ltr(SELECTORS.sel_tss.index()) // THIS WILL CAUSE A GPF, YOU STUPID WHORE
|
//ltr(SELECTORS.sel_tss.index()) // THIS WILL CAUSE A GPF, YOU STUPID WHORE
|
||||||
ltr(SELECTORS.sel_tss.0);
|
ltr(SELECTORS.sel_tss.0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jump_to_usermode(sp: VirtAddr, ip: VirtAddr) -> ! {
|
pub fn jump_to_usermode(sp: VirtAddr, ip: VirtAddr) -> ! {
|
||||||
|
log_info!("Jumping to usermode...");
|
||||||
unsafe {
|
unsafe {
|
||||||
InterruptStackFrameValue::new(
|
InterruptStackFrameValue::new(
|
||||||
ip,
|
ip,
|
||||||
|
|||||||
@ -16,27 +16,18 @@ mod panic;
|
|||||||
mod process;
|
mod process;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use core::ptr::addr_of;
|
|
||||||
|
|
||||||
use arch::x86_64::serial::SerialPort;
|
use arch::x86_64::serial::SerialPort;
|
||||||
use boot::{BASE_REVISION, params, *};
|
use boot::{BASE_REVISION, params};
|
||||||
use constants::*;
|
use constants::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use memory::alloc::{boxed::Box, format, vec};
|
use memory::alloc::{boxed::Box, format, vec};
|
||||||
use params::*;
|
use params::*;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use limine::firmware::{
|
|
||||||
FIRMWARE_TYPE_EFI32, FIRMWARE_TYPE_EFI64, FIRMWARE_TYPE_SBI, FIRMWARE_TYPE_X86BIOS,
|
|
||||||
};
|
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
use x86_64::VirtAddr;
|
use x86_64::VirtAddr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{arch::x86_64::gdt::SELECTORS, boot::modules::MODULE_RESPONSE};
|
||||||
arch::x86_64::cpuid::{CPUID, virt_supported},
|
|
||||||
boot::modules::MODULE_RESPONSE,
|
|
||||||
memory::paging::active_root_table,
|
|
||||||
};
|
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref SERIAL_3F8: Mutex<SerialPort> = Mutex::new(
|
pub static ref SERIAL_3F8: Mutex<SerialPort> = Mutex::new(
|
||||||
@ -100,78 +91,13 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
.log_writeln("\tWelcome to the Gila microkernel!\n");
|
.log_writeln("\tWelcome to the Gila microkernel!\n");
|
||||||
log_info!("Booting gila version {}", kernel_version_string());
|
log_info!("Booting gila version {}", kernel_version_string());
|
||||||
|
|
||||||
match boot::FIRMWARE_TYPE_REQUEST.response() {
|
|
||||||
Some(resp) => log_info!(
|
|
||||||
"Firmware type: {}",
|
|
||||||
match resp.firmware_type {
|
|
||||||
FIRMWARE_TYPE_SBI => "SBI",
|
|
||||||
FIRMWARE_TYPE_EFI32 => "UEFI (32-bit)",
|
|
||||||
FIRMWARE_TYPE_EFI64 => "UEFI (64-bit)",
|
|
||||||
FIRMWARE_TYPE_X86BIOS => "x86 BIOS",
|
|
||||||
_ => "Unknown",
|
|
||||||
}
|
|
||||||
),
|
|
||||||
None => log_warning!("Firmware type: No response"),
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info!("Trans rights!");
|
log_info!("Trans rights!");
|
||||||
|
|
||||||
if let Some(framebuffer_response) = FRAMEBUFFER_REQUEST.response() {
|
|
||||||
let fb = framebuffer_response.framebuffers_rev1().unwrap()[0];
|
|
||||||
log_info!("Framebuffer response received");
|
|
||||||
for mode in fb.modes() {
|
|
||||||
log_trace!(
|
|
||||||
"Mode: {}x{}, {} bits per pixel",
|
|
||||||
mode.width,
|
|
||||||
mode.height,
|
|
||||||
mode.bpp
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log_info!("Framebuffer response absent, graphics disabled",);
|
|
||||||
}
|
|
||||||
|
|
||||||
let smp_response = MP_REQUEST.response();
|
|
||||||
match smp_response {
|
|
||||||
None => log_info!("Multiprocessing response not received"),
|
|
||||||
Some(resp) => {
|
|
||||||
log_info!("Multiprocessing response received");
|
|
||||||
log_info!("{} CPUs found", resp.cpus().len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let rsdp_response = RSDP_REQUEST.response();
|
|
||||||
match rsdp_response {
|
|
||||||
None => log_info!("RDSP response not received"),
|
|
||||||
Some(resp) => {
|
|
||||||
log_info!("RSDP response received");
|
|
||||||
log_trace!("RSDP address: 0x{:x}", resp.address as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boot::modules::log_modules();
|
boot::modules::log_modules();
|
||||||
|
|
||||||
memory::log_memory();
|
memory::log_memory();
|
||||||
memory::log_address();
|
memory::log_address();
|
||||||
|
|
||||||
if let Some(string) = CPUID.get_processor_brand_string() {
|
log_info!("TSS descriptor: 0x{:08x} {:08x}", SELECTORS.gdt.entries()[SELECTORS.sel_tss.index() as usize + 1].raw(), SELECTORS.gdt.entries()[SELECTORS.sel_tss.index() as usize].raw());
|
||||||
log_info!("CPU brand string: {}", string.as_str());
|
|
||||||
}
|
|
||||||
if let Some(string) = CPUID.get_vendor_info() {
|
|
||||||
log_info!("CPU vendor: {}", string.as_str());
|
|
||||||
}
|
|
||||||
if let Some(string) = CPUID.get_hypervisor_info() {
|
|
||||||
log_info!("Hypervisor: {:?}", string.identify());
|
|
||||||
}
|
|
||||||
log_info!("Virtualization provider: {:?}", virt_supported());
|
|
||||||
|
|
||||||
let root_ptable_info = unsafe { active_root_table() };
|
|
||||||
log_info!(
|
|
||||||
"Root page table is Level {} at 0x{:x}",
|
|
||||||
root_ptable_info.1,
|
|
||||||
addr_of!(*root_ptable_info.0) as usize
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(modules_list) = *MODULE_RESPONSE
|
if let Some(modules_list) = *MODULE_RESPONSE
|
||||||
&& modules_list.modules()[0].path().ends_with("/userboot.bin")
|
&& modules_list.modules()[0].path().ends_with("/userboot.bin")
|
||||||
{
|
{
|
||||||
@ -180,7 +106,8 @@ unsafe extern "C" fn main() -> ! {
|
|||||||
// TODO: remap userboot as user pages
|
// TODO: remap userboot as user pages
|
||||||
|
|
||||||
let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]);
|
let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]);
|
||||||
arch::startup::jump_to_usermode(VirtAddr::new(0xfffffff800000000), start_addr)
|
log_trace!("Userboot start address: 0x{:x}", start_addr);
|
||||||
|
arch::startup::jump_to_usermode(VirtAddr::new(0xffffffff80000000), start_addr)
|
||||||
} else {
|
} else {
|
||||||
panic!("Userboot not found, cannot boot!");
|
panic!("Userboot not found, cannot boot!");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user