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
|
||||
|
||||
use core::arch::asm;
|
||||
use core::ptr::addr_of_mut;
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
use intbits::Bits;
|
||||
use lazy_static::lazy_static;
|
||||
@ -77,7 +77,19 @@ lazy_static! {
|
||||
let sel_u_cs = gdt.append(Descriptor::user_code_segment());
|
||||
// DO NOT REORDER
|
||||
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 {
|
||||
sel_kernel_code: sel_k_cs,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
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 lazy_static::lazy_static;
|
||||
use x86_64::PhysAddr;
|
||||
@ -19,18 +19,47 @@ pub fn get_lapic_addr() -> PhysAddr {
|
||||
lazy_static! {
|
||||
pub static ref IDT: InterruptDescriptorTable = {
|
||||
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 {
|
||||
idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
||||
idt.page_fault.set_handler_fn(page_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
||||
idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code);
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault)
|
||||
.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
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
#[allow(dead_code)]
|
||||
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)]
|
||||
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!(
|
||||
"Fault: Page fault with {}, error code 0b{:b}",
|
||||
match addr {
|
||||
match page_fault_addr {
|
||||
Ok(addr_inner) => format!("address 0x{:x}", addr_inner),
|
||||
Err(_) => "invalid virtual address".into(),
|
||||
},
|
||||
@ -60,7 +90,10 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau
|
||||
| errcode.contains(PageFaultErrorCode::MALFORMED_TABLE)
|
||||
{
|
||||
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 {
|
||||
log_error!("Page Fault, trying to recover...");
|
||||
todo!("Page fault handler (kernel mode)")
|
||||
@ -71,7 +104,7 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau
|
||||
#[allow(dead_code)]
|
||||
extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) {
|
||||
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.code_segment.index(),
|
||||
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::{
|
||||
arch::{
|
||||
asm::ltr, x86_64::{
|
||||
gdt::SELECTORS, interrupts::IDT,
|
||||
},
|
||||
}, log::{LOGGER, LogLevel}, log_info, memory::alloc::format,
|
||||
asm::ltr,
|
||||
x86_64::{gdt::SELECTORS, interrupts::IDT},
|
||||
},
|
||||
log::{LOGGER, LogLevel},
|
||||
log_info,
|
||||
memory::alloc::format,
|
||||
};
|
||||
|
||||
pub fn init() -> Result<(), ()> {
|
||||
// Ensure GDT exists
|
||||
SELECTORS.gdt.load();
|
||||
log_info!("GDT loaded!");
|
||||
// Load IDT
|
||||
IDT.load();
|
||||
log_info!("IDT loaded!");
|
||||
// Ensure GDT exists
|
||||
SELECTORS.gdt.load();
|
||||
log_info!("GDT loaded!");
|
||||
x86_64::registers::model_specific::Star::write(
|
||||
SELECTORS.sel_user_code,
|
||||
SELECTORS.sel_user_stack,
|
||||
@ -22,12 +24,17 @@ pub fn init() -> Result<(), ()> {
|
||||
SELECTORS.sel_kernel_stack,
|
||||
)
|
||||
.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.0);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn jump_to_usermode(sp: VirtAddr, ip: VirtAddr) -> ! {
|
||||
log_info!("Jumping to usermode...");
|
||||
unsafe {
|
||||
InterruptStackFrameValue::new(
|
||||
ip,
|
||||
|
||||
@ -16,27 +16,18 @@ mod panic;
|
||||
mod process;
|
||||
mod util;
|
||||
|
||||
use core::ptr::addr_of;
|
||||
|
||||
use arch::x86_64::serial::SerialPort;
|
||||
use boot::{BASE_REVISION, params, *};
|
||||
use boot::{BASE_REVISION, params};
|
||||
use constants::*;
|
||||
use log::*;
|
||||
use memory::alloc::{boxed::Box, format, vec};
|
||||
use params::*;
|
||||
|
||||
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 x86_64::VirtAddr;
|
||||
|
||||
use crate::{
|
||||
arch::x86_64::cpuid::{CPUID, virt_supported},
|
||||
boot::modules::MODULE_RESPONSE,
|
||||
memory::paging::active_root_table,
|
||||
};
|
||||
use crate::{arch::x86_64::gdt::SELECTORS, boot::modules::MODULE_RESPONSE};
|
||||
|
||||
lazy_static! {
|
||||
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_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!");
|
||||
|
||||
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();
|
||||
|
||||
memory::log_memory();
|
||||
memory::log_address();
|
||||
|
||||
if let Some(string) = CPUID.get_processor_brand_string() {
|
||||
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
|
||||
);
|
||||
|
||||
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());
|
||||
if let Some(modules_list) = *MODULE_RESPONSE
|
||||
&& modules_list.modules()[0].path().ends_with("/userboot.bin")
|
||||
{
|
||||
@ -180,7 +106,8 @@ unsafe extern "C" fn main() -> ! {
|
||||
// TODO: remap userboot as user pages
|
||||
|
||||
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 {
|
||||
panic!("Userboot not found, cannot boot!");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user