Use x86_64 crate for asm

This commit is contained in:
August 2025-09-28 23:04:00 -04:00
parent 4097ae0b53
commit f48426c59c
Signed by: shibedrill
GPG Key ID: 5FE0CB25945EFAA2
7 changed files with 58 additions and 168 deletions

View File

@ -1,125 +1,6 @@
// Copyright (c) 2025 shibedrill // Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
#![allow(clippy::missing_safety_doc)]
#![allow(dead_code)]
use core::arch::asm;
pub fn read_cr0() -> u64 {
let cr0: u64;
unsafe { asm!("mov {0:r}, cr0", out(reg) cr0) }
cr0
}
pub fn read_cr2() -> usize {
let cr2: usize;
unsafe { asm!("mov {0:r}, cr2", out(reg) cr2) }
cr2
}
pub fn read_cr3() -> u64 {
let cr3: u64;
unsafe { asm!("mov {0:r}, cr3", out(reg) cr3) }
cr3
}
pub fn write_cr3(val: u64) {
unsafe { asm!("mov cr3, {0:r}", in(reg) val) }
}
pub fn read_cr4() -> u64 {
let cr4: u64;
unsafe { asm!("mov {0:r}, cr4", out(reg) cr4) }
cr4
}
pub fn interrupt_disable() {
unsafe {
asm!("cli");
}
}
pub fn interrupt_enable() {
unsafe {
asm!("sti");
}
}
pub fn halt() {
unsafe {
asm!("hlt");
}
}
pub fn nop() { pub fn nop() {
unsafe { ::x86_64::instructions::nop();
asm!("nop");
}
}
pub fn port_read_u8(port: u16) -> u8 {
let result: u8;
unsafe {
asm! {
"in al dx",
in("dx") port,
out("al") result
}
}
result
}
pub fn port_read_u16(port: u16) -> u16 {
let result: u16;
unsafe {
asm! {
"in ax dx",
in("dx") port,
out("ax") result
}
}
result
}
pub fn port_read_u32(port: u16) -> u32 {
let result: u32;
unsafe {
asm! {
"in eax dx",
in("dx") port,
out("eax") result
}
}
result
}
pub fn port_write_u8(port: u16, data: u8) {
unsafe {
asm! {
"out dx, al",
in("dx") port,
in("al") data,
}
}
}
pub fn port_write_u16(port: u16, data: u16) {
unsafe {
asm! {
"out dx, ax",
in("dx") port,
in("ax") data,
}
}
}
pub fn port_write_u32(port: u16, data: u32) {
unsafe {
asm! {
"out dx eax",
in("dx") port,
in("eax") data,
}
}
} }

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use crate::LogLevel; use crate::LogLevel;
use crate::{LOGGER, arch::asm::read_cr2, format, log_trace}; use crate::{LOGGER, format, log_trace};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use x86_64::structures::idt::*; use x86_64::structures::idt::*;
@ -26,10 +26,13 @@ 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 = read_cr2(); let addr = x86_64::registers::control::Cr2::read();
log_trace!( log_trace!(
"Fault: Page fault with address 0x{:x}, error code 0b{:b}", "Fault: Page fault with {}, error code 0b{:b}",
addr, match addr {
Ok(addr_inner) => format!("address 0x{:x}", addr_inner),
Err(_) => "invalid virtual address".into(),
},
errcode errcode
); );
if errcode.contains(PageFaultErrorCode::USER_MODE) { if errcode.contains(PageFaultErrorCode::USER_MODE) {
@ -43,7 +46,7 @@ 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(addr, info_formatted) crate::interrupt::page_fault(addr.unwrap().as_u64() as usize, info_formatted)
} else { } else {
todo!() todo!()
} }

View File

@ -1,22 +1,22 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::arch; use crate::{LOGGER, LogLevel, format, log_info};
use crate::memory::HHDM_RESPONSE; use x86_64::registers::control::*;
use crate::{LOGGER, LogLevel, format, log_info, log_trace};
use intbits::Bits;
use x86_64::structures::paging::PageTableFlags;
use x86_64::structures::paging::page_table::PageTable;
pub fn get_mappings() { pub fn get_mappings() {
log_info!("HHDM offset: 0x{:X}", HHDM_RESPONSE.offset()); log_info!("Paging: {}", Cr0::read().contains(Cr0Flags::PAGING));
log_info!(
log_info!("Paging: {}", arch::asm::read_cr0().bit(31)); "Protection: {}",
log_info!("Protection: {}", arch::asm::read_cr0().bit(0)); Cr0::read().contains(Cr0Flags::PROTECTED_MODE_ENABLE)
);
log_info!( log_info!(
"Physical Address Extensions: {}", "Physical Address Extensions: {}",
arch::asm::read_cr4().bit(5) x86_64::registers::control::Cr4::read().contains(Cr4Flags::PHYSICAL_ADDRESS_EXTENSION)
);
log_info!(
"Page Size Extensions: {}",
Cr4::read().contains(Cr4Flags::PAGE_SIZE_EXTENSION)
); );
log_info!("Page Size Extensions: {}", arch::asm::read_cr4().bit(4));
log_info!( log_info!(
"Paging mode: {}", "Paging mode: {}",
match crate::memory::PAGING_REQUEST.get_response().unwrap().mode() { match crate::memory::PAGING_REQUEST.get_response().unwrap().mode() {
@ -25,14 +25,14 @@ pub fn get_mappings() {
_ => unreachable!(), _ => unreachable!(),
} }
); );
log_info!("CR3 Value: 0b{:064b}", arch::asm::read_cr3()); let pml4_addr = Cr3::read_raw().0.start_address();
// Physical address of Page Map Level 4 Table log_info!("Page Map Level 4 Address: 0x{:X}", pml4_addr.as_u64());
let pml4_ptr: *const PageTable = log_info!(
((arch::asm::read_cr3().bits(12..=63) << 12) + HHDM_RESPONSE.offset()) as *const PageTable; "Page-Level Write-Through: {}",
let pagemap_lvl4 = unsafe { &*pml4_ptr }; Cr3::read().1.contains(Cr3Flags::PAGE_LEVEL_WRITETHROUGH)
for entry in pagemap_lvl4.iter() { );
if entry.flags().contains(PageTableFlags::PRESENT) { log_info!(
log_trace!("Page Table Level 4 Entry: 0x{:X}", entry.addr()); "Page-Level Cache Disable: {}",
} Cr3::read().1.contains(Cr3Flags::PAGE_LEVEL_CACHE_DISABLE)
} );
} }

View File

@ -1,24 +1,13 @@
// Copyright (c) 2025 shibedrill // Copyright (c) 2025 shibedrill
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
use crate::arch::asm::*;
use crate::log::LogSubscriber; use crate::log::LogSubscriber;
use x86_64::instructions::port::Port;
#[derive(Clone, Copy)] impl LogSubscriber for Port<u8> {
pub struct Serialport { fn log_write(&mut self, msg: &str) {
port: u16,
}
impl LogSubscriber for Serialport {
fn write(&self, msg: &str) {
for c in msg.chars() { for c in msg.chars() {
port_write_u8(self.port, c as u8); unsafe { self.write(c as u8) };
} }
} }
} }
impl Serialport {
pub fn new(port: u16) -> Self {
Serialport { port }
}
}

View File

@ -80,7 +80,7 @@ pub struct LoggerInner {
} }
pub trait LogSubscriber: Send + Sync { pub trait LogSubscriber: Send + Sync {
fn write(&self, msg: &str); fn log_write(&mut self, msg: &str);
} }
impl Default for LoggerInner { impl Default for LoggerInner {
@ -112,7 +112,7 @@ impl LoggerInner {
"[{level_string}] {file}:{line},{column} - {msg}" "[{level_string}] {file}:{line},{column} - {msg}"
) )
.unwrap(); .unwrap();
sub.lock().write(&message); sub.lock().log_write(&message);
} }
} }
} }

View File

@ -20,9 +20,6 @@ mod process;
#[macro_use] #[macro_use]
mod util; mod util;
#[cfg(target_arch = "x86_64")]
use arch::x86_64::serial::Serialport;
use boot::{BASE_REVISION, params, *}; use boot::{BASE_REVISION, params, *};
use constants::*; use constants::*;
use limine::firmware_type::FirmwareType; use limine::firmware_type::FirmwareType;
@ -44,6 +41,9 @@ unsafe extern "C" fn main() -> ! {
// Ensure IDT exists // Ensure IDT exists
IDT.load(); IDT.load();
#[cfg(target_arch = "x86_64")]
let serial: x86_64::instructions::port::Port<u8> = x86_64::instructions::port::Port::new(0x3f8);
// Set up logging level from params // Set up logging level from params
// Nothing we can do here if this fails since no log subscribers are initialized yet // Nothing we can do here if this fails since no log subscribers are initialized yet
if let Some(level) = PARAMS.get("-loglevel") if let Some(level) = PARAMS.get("-loglevel")
@ -60,7 +60,7 @@ unsafe extern "C" fn main() -> ! {
if log_device_list.contains(&"serial") { if log_device_list.contains(&"serial") {
// TODO: Set up device discovery // TODO: Set up device discovery
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
LOGGER.add_subscriber(Serialport::new(0x3f8)); LOGGER.add_subscriber(serial);
} }
log_trace!("Configured kernel logging devices"); log_trace!("Configured kernel logging devices");
} }
@ -120,6 +120,7 @@ unsafe extern "C" fn main() -> ! {
boot::modules::log_modules(); boot::modules::log_modules();
memory::log_memory(); memory::log_memory();
memory::log_address();
arch::x86_64::paging::get_mappings(); arch::x86_64::paging::get_mappings();

View File

@ -86,6 +86,22 @@ pub fn log_memory() {
} }
} }
pub fn log_address() {
if let Some(resp) = ADDRESS_REQUEST.get_response() {
log_info!(
"Kernel physical start address: 0x{:X}",
resp.physical_base()
);
log_info!("Kernel virtual start address: 0x{:X}", resp.virtual_base());
} else {
log_warning!("No kernel address response provided.");
}
log_info!(
"Higher Half direct map offset: 0x{:X}",
HHDM_RESPONSE.offset()
);
}
#[used] #[used]
#[unsafe(link_section = ".requests")] #[unsafe(link_section = ".requests")]
pub static PAGING_REQUEST: PagingModeRequest = limine::request::PagingModeRequest::new(); pub static PAGING_REQUEST: PagingModeRequest = limine::request::PagingModeRequest::new();