From 840fe5384578f4324610c70f593dcb5baa3b4a70 Mon Sep 17 00:00:00 2001 From: Yuke Peng Date: Wed, 15 Mar 2023 01:48:40 -0700 Subject: [PATCH] Remove x86_64_util --- .../jinux-frame/src/device/io_port.rs | 73 ++--- src/framework/jinux-frame/src/device/pci.rs | 10 +- .../jinux-frame/src/device/serial.rs | 95 ++++--- src/framework/jinux-frame/src/driver/pic.rs | 54 ++-- src/framework/jinux-frame/src/driver/rtc.rs | 23 +- .../jinux-frame/src/driver/timer/apic.rs | 7 +- .../jinux-frame/src/driver/timer/pit.rs | 19 +- src/framework/jinux-frame/src/driver/xapic.rs | 19 +- src/framework/jinux-frame/src/lib.rs | 25 +- .../jinux-frame/src/mm/page_table.rs | 50 +--- src/framework/jinux-frame/src/user.rs | 16 +- src/framework/jinux-frame/src/vm/space.rs | 12 +- src/framework/jinux-frame/src/x86_64_util.rs | 253 ------------------ src/services/comps/pci/src/util.rs | 8 +- 14 files changed, 222 insertions(+), 442 deletions(-) delete mode 100644 src/framework/jinux-frame/src/x86_64_util.rs diff --git a/src/framework/jinux-frame/src/device/io_port.rs b/src/framework/jinux-frame/src/device/io_port.rs index f2f063cc..2af657f2 100644 --- a/src/framework/jinux-frame/src/device/io_port.rs +++ b/src/framework/jinux-frame/src/device/io_port.rs @@ -1,55 +1,60 @@ -use crate::{prelude::*, x86_64_util}; +use spin::Mutex; +use x86_64::{ + instructions::port::Port, + structures::port::{PortRead, PortWrite}, +}; /// An I/O port, representing a specific address in the I/O address of x86. -pub struct IoPort { +/// +/// The following code shows and example to read and write u32 value to an I/O port: +/// +/// ```rust +/// static PORT: IoPort = IoPort::new(0x12); +/// +/// fn port_value_increase(){ +/// PORT.write(PORT.read() + 1) +/// } +/// ``` +/// +pub struct IoPort { addr: u16, + port: Mutex>, } -impl IoPort { +impl IoPort { /// Create an I/O port. /// /// # Safety /// /// This function is marked unsafe as creating an I/O port is considered /// a privileged operation. - pub unsafe fn new(addr: u16) -> Result { - Ok(Self { addr: addr }) + pub const unsafe fn new(addr: u16) -> Self { + Self { + addr, + port: Mutex::new(Port::new(addr)), + } } } -impl IoPort { +impl IoPort { /// Get the address of this I/O port. pub fn addr(&self) -> u16 { self.addr } +} - /// Read a value of `u32`. - pub fn read_u32(&self) -> u32 { - x86_64_util::in32(self.addr) - } - - /// Write a value of `u32`. - pub fn write_u32(&self, val: u32) { - x86_64_util::out32(self.addr, val) - } - - /// Read a value of `u16`. - pub fn read_u16(&self) -> u16 { - x86_64_util::in16(self.addr) - } - - /// Write a value of `u16`. - pub fn write_u16(&self, val: u16) { - x86_64_util::out16(self.addr, val) - } - - /// Read a value of `u8`. - pub fn read_u8(&self) -> u8 { - x86_64_util::in8(self.addr) - } - - /// Write a value of `u8`. - pub fn write_u8(&self, val: u8) { - x86_64_util::out8(self.addr, val) +impl IoPort { + /// Reads from the port. + pub fn read(&self) -> T { + unsafe { (*self.port.lock()).read() } + } +} + +impl IoPort { + /// Writes to the port. + pub fn write(&self, val: T) { + unsafe { + self.port.lock().write(val); + } } } diff --git a/src/framework/jinux-frame/src/device/pci.rs b/src/framework/jinux-frame/src/device/pci.rs index 05bad0c2..8bd646be 100644 --- a/src/framework/jinux-frame/src/device/pci.rs +++ b/src/framework/jinux-frame/src/device/pci.rs @@ -1,12 +1,6 @@ //! PCI bus io port use super::io_port::IoPort; -use lazy_static::lazy_static; -const CONFIG_ADDRESS: u16 = 0x0CF8; -const CONFIG_DATA: u16 = 0x0CFC; - -lazy_static! { - pub static ref PCI_ADDRESS_PORT: IoPort = unsafe { IoPort::new(CONFIG_ADDRESS).unwrap() }; - pub static ref PCI_DATA_PORT: IoPort = unsafe { IoPort::new(CONFIG_DATA).unwrap() }; -} +pub static PCI_ADDRESS_PORT: IoPort = unsafe { IoPort::new(0x0CF8) }; +pub static PCI_DATA_PORT: IoPort = unsafe { IoPort::new(0x0CFC) }; diff --git a/src/framework/jinux-frame/src/device/serial.rs b/src/framework/jinux-frame/src/device/serial.rs index d2487984..544b4f96 100644 --- a/src/framework/jinux-frame/src/device/serial.rs +++ b/src/framework/jinux-frame/src/device/serial.rs @@ -1,9 +1,11 @@ +//! A port-mapped UART. Copied from uart_16550. use alloc::{sync::Arc, vec::Vec}; use log::debug; use spin::{Mutex, Once}; use trapframe::TrapFrame; +use x86_64::instructions::port::{Port, PortWriteOnly}; -use crate::{driver::pic_allocate_irq, trap::IrqAllocateHandle, x86_64_util::*}; +use crate::{driver::pic_allocate_irq, trap::IrqAllocateHandle}; use core::fmt::{self, Write}; bitflags::bitflags! { @@ -13,13 +15,18 @@ bitflags::bitflags! { } } -/// A port-mapped UART. Copied from uart_16550. -const SERIAL_DATA: u16 = 0x3F8; -const SERIAL_INT_EN: u16 = SERIAL_DATA + 1; -const SERIAL_FIFO_CTRL: u16 = SERIAL_DATA + 2; -const SERIAL_LINE_CTRL: u16 = SERIAL_DATA + 3; -const SERIAL_MODEM_CTRL: u16 = SERIAL_DATA + 4; -const SERIAL_LINE_STS: u16 = SERIAL_DATA + 5; +const SERIAL_DATA_PORT: u16 = 0x3F8; + +static SERIAL_DATA: Mutex> = Mutex::new(Port::new(SERIAL_DATA_PORT)); +static SERIAL_INT_EN: Mutex> = + Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 1)); +static SERIAL_FIFO_CTRL: Mutex> = + Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 2)); +static SERIAL_LINE_CTRL: Mutex> = + Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 3)); +static SERIAL_MODEM_CTRL: Mutex> = + Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 4)); +static SERIAL_LINE_STS: Mutex> = Mutex::new(Port::new(SERIAL_DATA_PORT + 5)); static CONSOLE_IRQ_CALLBACK: Once> = Once::new(); static SERIAL_INPUT_CALLBACKS: Mutex>> = @@ -27,23 +34,30 @@ static SERIAL_INPUT_CALLBACKS: Mutex /// Initializes the serial port. pub(crate) fn init() { - // Disable interrupts - out8(SERIAL_INT_EN, 0x00); - // Enable DLAB - out8(SERIAL_LINE_CTRL, 0x80); - // Set maximum speed to 38400 bps by configuring DLL and DLM - out8(SERIAL_DATA, 0x03); - out8(SERIAL_INT_EN, 0x00); - // Disable DLAB and set data word length to 8 bits - out8(SERIAL_LINE_CTRL, 0x03); - // Enable FIFO, clear TX/RX queues and - // set interrupt watermark at 14 bytes - out8(SERIAL_FIFO_CTRL, 0xC7); - // Mark data terminal ready, signal request to send - // and enable auxilliary output #2 (used as interrupt line for CPU) - out8(SERIAL_MODEM_CTRL, 0x0B); - // Enable interrupts - out8(SERIAL_INT_EN, 0x01); + let mut serial_line_ctrl_lock = SERIAL_LINE_CTRL.lock(); + let mut serial_int_en_lock = SERIAL_INT_EN.lock(); + let mut serial_data_lock = SERIAL_DATA.lock(); + let mut serial_fifo_ctrl_lock = SERIAL_FIFO_CTRL.lock(); + let mut serial_modem_ctrl_lock = SERIAL_MODEM_CTRL.lock(); + unsafe { + // Disable interrupts + serial_int_en_lock.write(0x00); + // Enable DLAB + serial_line_ctrl_lock.write(0x80); + // Set maximum speed to 38400 bps by configuring DLL and DLM + serial_data_lock.write(0x03); + serial_int_en_lock.write(0x00); + // Disable DLAB and set data word length to 8 bits + serial_line_ctrl_lock.write(0x03); + // Enable FIFO, clear TX/RX queues and + // set interrupt watermark at 14 bytes + serial_fifo_ctrl_lock.write(0xC7); + // Mark data terminal ready, signal request to send + // and enable auxilliary output #2 (used as interrupt line for CPU) + serial_modem_ctrl_lock.write(0x0B); + // Enable interrupts + serial_int_en_lock.write(0x01); + } } pub fn register_serial_input_callback(f: impl Fn(u8) + Send + Sync + 'static) { @@ -81,23 +95,26 @@ fn handle_serial_input(trap_frame: &TrapFrame) { } fn line_sts() -> LineSts { - LineSts::from_bits_truncate(in8(SERIAL_LINE_STS)) + LineSts::from_bits_truncate(unsafe { SERIAL_LINE_STS.lock().read() }) } /// Sends a byte on the serial port. pub fn send(data: u8) { - match data { - 8 | 0x7F => { - while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} - out8(SERIAL_DATA, 8); - while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} - out8(SERIAL_DATA, b' '); - while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} - out8(SERIAL_DATA, 8) - } - _ => { - while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} - out8(SERIAL_DATA, data); + let mut lock = SERIAL_DATA.lock(); + unsafe { + match data { + 8 | 0x7F => { + while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} + lock.write(8); + while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} + lock.write(b' '); + while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} + lock.write(8); + } + _ => { + while !line_sts().contains(LineSts::OUTPUT_EMPTY) {} + lock.write(data); + } } } } @@ -105,7 +122,7 @@ pub fn send(data: u8) { /// Receives a byte on the serial port. non-blocking pub fn receive_char() -> Option { if line_sts().contains(LineSts::INPUT_FULL) { - Some(in8(SERIAL_DATA)) + unsafe { Some(SERIAL_DATA.lock().read()) } } else { None } diff --git a/src/framework/jinux-frame/src/driver/pic.rs b/src/framework/jinux-frame/src/driver/pic.rs index 7275d82c..813d3bbc 100644 --- a/src/framework/jinux-frame/src/driver/pic.rs +++ b/src/framework/jinux-frame/src/driver/pic.rs @@ -1,12 +1,13 @@ +use crate::trap::allocate_target_irq; use crate::trap::IrqAllocateHandle; -use crate::{trap::allocate_target_irq, x86_64_util::out8}; use core::sync::atomic::Ordering::Relaxed; use core::sync::atomic::{AtomicBool, AtomicU8}; -const MASTER_CMD: u16 = 0x20; -const MASTER_DATA: u16 = MASTER_CMD + 1; -const SLAVE_CMD: u16 = 0xA0; -const SLAVE_DATA: u16 = SLAVE_CMD + 1; +static MASTER_CMD: Mutex> = Mutex::new(PortWriteOnly::new(0x20)); +static MASTER_DATA: Mutex> = Mutex::new(PortWriteOnly::new(0x21)); +static SLAVE_CMD: Mutex> = Mutex::new(PortWriteOnly::new(0xA0)); +static SLAVE_DATA: Mutex> = Mutex::new(PortWriteOnly::new(0xA1)); + const IRQ_OFFSET: u8 = 0x20; const TIMER_IRQ_NUM: u8 = 32; @@ -15,6 +16,7 @@ use alloc::vec::Vec; use lazy_static::lazy_static; use log::info; use spin::Mutex; +use x86_64::instructions::port::PortWriteOnly; lazy_static! { /// store the irq, although we have APIC for manage interrupts @@ -96,30 +98,36 @@ pub(crate) fn disable_temp() { #[inline(always)] pub(crate) unsafe fn set_mask(master_mask: u8, slave_mask: u8) { - // Start initialization - out8(MASTER_CMD, 0x11); - out8(SLAVE_CMD, 0x11); + let mut master_data_lock = MASTER_DATA.lock(); + let mut slave_data_lock = SLAVE_DATA.lock(); + unsafe { + // Start initialization + MASTER_CMD.lock().write(0x11); + SLAVE_CMD.lock().write(0x11); - // Set offsets - // map master PIC vector 0x00~0x07 to 0x20~0x27 IRQ number - out8(MASTER_DATA, IRQ_OFFSET); - // map slave PIC vector 0x00~0x07 to 0x28~0x2f IRQ number - out8(SLAVE_DATA, IRQ_OFFSET + 0x08); + // Set offsets + // map master PIC vector 0x00~0x07 to 0x20~0x27 IRQ number + master_data_lock.write(IRQ_OFFSET); + // map slave PIC vector 0x00~0x07 to 0x28~0x2f IRQ number + slave_data_lock.write(IRQ_OFFSET + 0x08); - // Set up cascade, there is slave at IRQ2 - out8(MASTER_DATA, 4); - out8(SLAVE_DATA, 2); + // Set up cascade, there is slave at IRQ2 + master_data_lock.write(4); + slave_data_lock.write(2); - // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) - out8(MASTER_DATA, 1); - out8(SLAVE_DATA, 1); + // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) + master_data_lock.write(1); + slave_data_lock.write(1); - // mask interrupts - out8(MASTER_DATA, master_mask); - out8(SLAVE_DATA, slave_mask); + // mask interrupts + master_data_lock.write(master_mask); + slave_data_lock.write(slave_mask); + } } #[inline(always)] pub(crate) fn ack() { - out8(MASTER_CMD, 0x20); + unsafe { + MASTER_CMD.lock().write(0x20); + } } diff --git a/src/framework/jinux-frame/src/driver/rtc.rs b/src/framework/jinux-frame/src/driver/rtc.rs index 427941f1..fd41f00e 100644 --- a/src/framework/jinux-frame/src/driver/rtc.rs +++ b/src/framework/jinux-frame/src/driver/rtc.rs @@ -4,16 +4,15 @@ use core::sync::atomic::Ordering::Relaxed; use acpi::{fadt::Fadt, sdt::Signature}; use lazy_static::lazy_static; use spin::Mutex; +use x86_64::instructions::port::{PortReadOnly, PortWriteOnly}; -use crate::{ - time::Time, - x86_64_util::{in8, out8}, -}; +use crate::time::Time; use super::acpi::ACPI_TABLES; -const CMOS_ADDRESS: u16 = 0x70; -const CMOS_DATA: u16 = 0x71; +static CMOS_ADDRESS: Mutex> = Mutex::new(PortWriteOnly::new(0x70)); +static CMOS_DATA: Mutex> = Mutex::new(PortReadOnly::new(0x71)); + pub(crate) static CENTURY_REGISTER: AtomicU8 = AtomicU8::new(0); lazy_static! { @@ -33,13 +32,17 @@ pub fn init() { } pub fn get_cmos(reg: u8) -> u8 { - out8(CMOS_ADDRESS, reg as u8); - in8(CMOS_DATA) + unsafe { + CMOS_ADDRESS.lock().write(reg); + CMOS_DATA.lock().read() + } } pub fn is_updating() -> bool { - out8(CMOS_ADDRESS, 0x0A); - in8(CMOS_DATA) & 0x80 != 0 + unsafe { + CMOS_ADDRESS.lock().write(0x0A); + CMOS_DATA.lock().read() & 0x80 != 0 + } } pub fn read() -> Time { diff --git a/src/framework/jinux-frame/src/driver/timer/apic.rs b/src/framework/jinux-frame/src/driver/timer/apic.rs index 54ec6cae..6595b55a 100644 --- a/src/framework/jinux-frame/src/driver/timer/apic.rs +++ b/src/framework/jinux-frame/src/driver/timer/apic.rs @@ -4,7 +4,6 @@ use trapframe::TrapFrame; use crate::{ config, driver::{pic, timer, xapic::XAPIC_INSTANCE}, - x86_64_util, }; use x86::apic::xapic; @@ -24,13 +23,13 @@ pub fn init() { static mut IS_FINISH: bool = false; // wait until it is finish - x86_64_util::enable_interrupts(); + x86_64::instructions::interrupts::enable(); unsafe { while !IS_FINISH { - x86_64_util::hlt(); + x86_64::instructions::hlt(); } } - x86_64_util::disable_interrupts(); + x86_64::instructions::interrupts::disable(); drop(a); drop(handle); diff --git a/src/framework/jinux-frame/src/driver/timer/pit.rs b/src/framework/jinux-frame/src/driver/timer/pit.rs index 3065cf34..6fcf52fb 100644 --- a/src/framework/jinux-frame/src/driver/timer/pit.rs +++ b/src/framework/jinux-frame/src/driver/timer/pit.rs @@ -1,17 +1,22 @@ //! used for PIT Timer -use crate::{config::TIMER_FREQ, x86_64_util::out8}; +use spin::Mutex; +use x86_64::instructions::port::PortWriteOnly; + +use crate::config::TIMER_FREQ; const TIMER_RATE: u32 = 1193182; -const TIMER_PERIOD_IO_PORT: u16 = 0x40; -const TIMER_MODE_IO_PORT: u16 = 0x43; -const TIMER_SQUARE_WAVE: u8 = 0x36; +static TIMER_PERIOD: Mutex> = Mutex::new(PortWriteOnly::new(0x40)); +static TIMER_MOD: Mutex> = Mutex::new(PortWriteOnly::new(0x43)); +static TIMER_SQUARE_WAVE: u8 = 0x36; pub(crate) fn init() { // Initialize timer. let cycle = TIMER_RATE / TIMER_FREQ as u32; - out8(TIMER_MODE_IO_PORT, TIMER_SQUARE_WAVE); - out8(TIMER_PERIOD_IO_PORT, (cycle & 0xFF) as _); - out8(TIMER_PERIOD_IO_PORT, (cycle >> 8) as _); + unsafe { + TIMER_MOD.lock().write(TIMER_SQUARE_WAVE); + TIMER_PERIOD.lock().write((cycle & 0xFF) as _); + TIMER_PERIOD.lock().write((cycle >> 8) as _); + } } diff --git a/src/framework/jinux-frame/src/driver/xapic.rs b/src/framework/jinux-frame/src/driver/xapic.rs index 40778376..934237ca 100644 --- a/src/framework/jinux-frame/src/driver/xapic.rs +++ b/src/framework/jinux-frame/src/driver/xapic.rs @@ -1,11 +1,11 @@ -use crate::{mm, x86_64_util}; +use crate::mm; use log::debug; use spin::{Mutex, Once}; use x86::apic::xapic; pub(crate) const IA32_APIC_BASE_MSR: u32 = 0x1B; pub(crate) const IA32_APIC_BASE_MSR_BSP: u32 = 0x100; // Processor is a BSP -pub(crate) const IA32_APIC_BASE_MSR_ENABLE: u32 = 0x800; +pub(crate) const IA32_APIC_BASE_MSR_ENABLE: u64 = 0x800; const APIC_LVT_MASK_BITS: u32 = 1 << 16; @@ -40,7 +40,7 @@ impl XAPIC { } pub(crate) fn has_apic() -> bool { - let value = unsafe { x86_64_util::cpuid(1) }; + let value = unsafe { core::arch::x86_64::__cpuid(1) }; value.edx & 0x100 != 0 } @@ -79,13 +79,16 @@ pub fn ack() { /// set APIC base address and enable it fn set_apic_base_address(address: usize) { - x86_64_util::set_msr( - IA32_APIC_BASE_MSR, - address | IA32_APIC_BASE_MSR_ENABLE as usize, - ) + unsafe { + x86_64::registers::model_specific::Msr::new(IA32_APIC_BASE_MSR) + .write(address as u64 | IA32_APIC_BASE_MSR_ENABLE); + } } /// get APIC base address fn get_apic_base_address() -> usize { - x86_64_util::get_msr(IA32_APIC_BASE_MSR) & 0xf_ffff_f000 + unsafe { + (x86_64::registers::model_specific::Msr::new(IA32_APIC_BASE_MSR).read() & 0xf_ffff_f000) + as usize + } } diff --git a/src/framework/jinux-frame/src/lib.rs b/src/framework/jinux-frame/src/lib.rs index f90417a7..112e8b6f 100644 --- a/src/framework/jinux-frame/src/lib.rs +++ b/src/framework/jinux-frame/src/lib.rs @@ -32,7 +32,6 @@ pub mod trap; pub mod user; mod util; pub mod vm; -pub(crate) mod x86_64_util; pub use self::error::Error; pub use self::prelude::Result; @@ -42,7 +41,6 @@ pub use limine::LimineModuleRequest; use trap::{IrqCallbackHandle, IrqLine}; use trapframe::TrapFrame; pub use util::AlignExt; -use x86_64_util::enable_common_cpu_features; static mut IRQ_CALLBACK_LIST: Vec = Vec::new(); @@ -74,7 +72,6 @@ fn register_irq_common_callback() { for i in 0..256 { IRQ_CALLBACK_LIST.push(IrqLine::acquire(i as u8).on_active(general_handler)) } - let value = x86_64_util::cpuid(1); } } @@ -93,6 +90,27 @@ fn invoke_c_init_funcs() { } } +fn enable_common_cpu_features() { + use x86_64::registers::{control::Cr4Flags, model_specific::EferFlags, xcontrol::XCr0Flags}; + let mut cr4 = x86_64::registers::control::Cr4::read(); + cr4 |= Cr4Flags::FSGSBASE | Cr4Flags::OSXSAVE | Cr4Flags::OSFXSR | Cr4Flags::OSXMMEXCPT_ENABLE; + unsafe { + x86_64::registers::control::Cr4::write(cr4); + } + + let mut xcr0 = x86_64::registers::xcontrol::XCr0::read(); + xcr0 |= XCr0Flags::AVX | XCr0Flags::SSE; + unsafe { + x86_64::registers::xcontrol::XCr0::write(xcr0); + } + + unsafe { + // enable non-executable page protection + x86_64::registers::model_specific::Efer::update(|efer| { + *efer |= EferFlags::NO_EXECUTE_ENABLE; + }); + } +} fn general_handler(trap_frame: &TrapFrame) { // info!("general handler"); // println!("{:#x?}", trap_frame); @@ -138,7 +156,6 @@ pub fn test_panic_handler(info: &PanicInfo) -> ! { } pub fn panic_handler() { - // println!("[panic]: cr3:{:x}", x86_64_util::get_cr3()); // let mut fp: usize; // let stop = unsafe{ // Task::current().kstack.get_top() diff --git a/src/framework/jinux-frame/src/mm/page_table.rs b/src/framework/jinux-frame/src/mm/page_table.rs index cdae5422..859f70f7 100644 --- a/src/framework/jinux-frame/src/mm/page_table.rs +++ b/src/framework/jinux-frame/src/mm/page_table.rs @@ -7,9 +7,7 @@ use crate::{ config::{ENTRY_COUNT, PAGE_SIZE, PHYS_OFFSET}, println, vm::VmFrame, - x86_64_util, }; -use ::log::info; use alloc::{collections::BTreeMap, vec, vec::Vec}; use core::{fmt, panic}; use lazy_static::lazy_static; @@ -213,56 +211,30 @@ fn next_table_or_create<'a>( /// translate a virtual address to physical address which cannot use offset to get physical address /// Note: this may not useful for accessing usermode data, use offset first -pub fn translate_not_offset_virtual_address(va: usize) -> usize { - let cr3 = x86_64_util::get_cr3(); +pub fn translate_not_offset_virtual_address(address: usize) -> usize { + let (cr3, _) = x86_64::registers::control::Cr3::read(); + let cr3 = cr3.start_address().as_u64() as usize; let p4 = table_of(PhysAddr(cr3)); - let a = VirtAddr(va); + let virtual_address = VirtAddr(address); - let pte = p4[p4_index(a)]; + let pte = p4[p4_index(virtual_address)]; let p3 = table_of(pte.pa()); - let pte = p3[p3_index(a)]; + let pte = p3[p3_index(virtual_address)]; let p2 = table_of(pte.pa()); - let pte = p2[p2_index(a)]; + let pte = p2[p2_index(virtual_address)]; let p1 = table_of(pte.pa()); - let pte = p1[p1_index(a)]; - (pte.pa().0 & ((1 << 48) - 1)) + (va & ((1 << 12) - 1)) -} - -pub fn print_virtual_address_translate_information(va: usize) { - let cr3 = x86_64_util::get_cr3(); - - let p4 = table_of(PhysAddr(cr3)); - - let a = VirtAddr(va); - info!("p4 index:{:x}", p4_index(a)); - let pte = p4[p4_index(a)]; - info!("p4 pte:{:x}", pte.0); - - let p3 = table_of(pte.pa()); - info!("p3 index:{:x}", p3_index(a)); - let pte = p3[p3_index(a)]; - info!("p3 pte:{:x}", pte.0); - - let p2 = table_of(pte.pa()); - - info!("p2 index:{:x}", p2_index(a)); - let pte = p2[p2_index(a)]; - info!("p2 pte:{:x}", pte.0); - - let p1 = table_of(pte.pa()); - - info!("p1 index:{:x}", p1_index(a)); - let pte = p1[p1_index(a)]; - info!("p1 pte:{:x}", pte.0); + let pte = p1[p1_index(virtual_address)]; + (pte.pa().0 & ((1 << 48) - 1)) + (address & ((1 << 12) - 1)) } pub(crate) fn init() { - let cr3 = x86_64_util::get_cr3(); + let (cr3, _) = x86_64::registers::control::Cr3::read(); + let cr3 = cr3.start_address().as_u64() as usize; let p4 = table_of(PhysAddr(cr3)); // Cancel mapping in lowest addresses. diff --git a/src/framework/jinux-frame/src/user.rs b/src/framework/jinux-frame/src/user.rs index 9e179d7b..81a163d0 100644 --- a/src/framework/jinux-frame/src/user.rs +++ b/src/framework/jinux-frame/src/user.rs @@ -1,10 +1,11 @@ //! User space. use crate::trap::call_irq_callback_functions; -use crate::x86_64_util::{self, rdfsbase, wrfsbase}; use log::debug; use trapframe::{TrapFrame, UserContext}; use x86_64::registers::rflags::RFlags; +use x86_64::registers::segmentation::Segment64; +use x86_64::registers::segmentation::FS; use crate::cpu::CpuContext; use crate::prelude::*; @@ -115,7 +116,9 @@ impl<'a> UserMode<'a> { self.context.gp_regs.rflag = (RFlags::INTERRUPT_FLAG | RFlags::ID).bits() | 0x2; } // write fsbase - wrfsbase(self.user_space.cpu_ctx.fs_base); + unsafe { + FS::write_base(x86_64::VirtAddr::new(self.user_space.cpu_ctx.fs_base)); + } let fp_regs = self.user_space.cpu_ctx.fp_regs; if fp_regs.is_valid() { fp_regs.restore(); @@ -123,9 +126,11 @@ impl<'a> UserMode<'a> { self.executed = true; } else { // write fsbase - if rdfsbase() != self.context.fs_base { + if FS::read_base().as_u64() != self.context.fs_base { debug!("write fsbase: 0x{:x}", self.context.fs_base); - wrfsbase(self.context.fs_base); + unsafe { + FS::write_base(x86_64::VirtAddr::new(self.context.fs_base)); + } } // write fp_regs @@ -167,12 +172,11 @@ impl<'a> UserMode<'a> { } x86_64::instructions::interrupts::enable(); self.context = CpuContext::from(self.user_context); + self.context.fs_base = FS::read_base().as_u64(); if self.user_context.trap_num != 0x100 { - self.context.fs_base = rdfsbase(); // self.context.fp_regs.save(); UserEvent::Exception } else { - self.context.fs_base = rdfsbase(); // self.context.fp_regs.save(); // debug!("[kernel] syscall id:{}", self.context.gp_regs.rax); // debug!("[kernel] rsp: 0x{:x}", self.context.gp_regs.rsp); diff --git a/src/framework/jinux-frame/src/vm/space.rs b/src/framework/jinux-frame/src/vm/space.rs index 214405c5..dbfb4c74 100644 --- a/src/framework/jinux-frame/src/vm/space.rs +++ b/src/framework/jinux-frame/src/vm/space.rs @@ -1,8 +1,8 @@ use crate::config::PAGE_SIZE; -use crate::x86_64_util; use bitflags::bitflags; use core::ops::Range; use spin::Mutex; +use x86_64::structures::paging::PhysFrame; use crate::mm::address::{is_aligned, VirtAddr}; use crate::mm::{MapArea, MemorySet, PTFlags}; @@ -37,7 +37,13 @@ impl VmSpace { } /// Activate the page table, load root physical address to cr3 pub unsafe fn activate(&self) { - x86_64_util::set_cr3(self.memory_set.lock().pt.root_pa.0); + x86_64::registers::control::Cr3::write( + PhysFrame::from_start_address(x86_64::PhysAddr::new( + self.memory_set.lock().pt.root_pa.0 as u64, + )) + .unwrap(), + x86_64::registers::control::Cr3Flags::PAGE_LEVEL_CACHE_DISABLE, + ); } /// Maps some physical memory pages into the VM space according to the given @@ -87,7 +93,7 @@ impl VmSpace { /// clear all mappings pub fn clear(&self) { self.memory_set.lock().clear(); - crate::x86_64_util::flush_tlb(); + x86_64::instructions::tlb::flush_all(); } /// Update the VM protection permissions within the VM address range. diff --git a/src/framework/jinux-frame/src/x86_64_util.rs b/src/framework/jinux-frame/src/x86_64_util.rs deleted file mode 100644 index 47b7527d..00000000 --- a/src/framework/jinux-frame/src/x86_64_util.rs +++ /dev/null @@ -1,253 +0,0 @@ -//! util for x86_64, it will rename to x86_64 when depend x86_64 isn't necessary -use core::arch::{asm, x86_64::CpuidResult}; - -use x86_64::registers::{ - control::Cr4Flags, model_specific::EferFlags, segmentation::Segment64, xcontrol::XCr0Flags, -}; - -#[inline(always)] -pub fn read_rsp() -> usize { - let val: usize; - unsafe { - asm!("mov {}, rsp", out(reg) val); - } - val -} - -#[inline(always)] -pub fn in8(port: u16) -> u8 { - // ::x86_64::instructions::port::Port::read() - let val: u8; - unsafe { - asm!("in al, dx", out("al") val, in("dx") port, options(nomem, nostack, preserves_flags)); - } - val -} - -#[inline(always)] -pub fn in16(port: u16) -> u16 { - let val: u16; - unsafe { - asm!("in ax, dx", out("ax") val, in("dx") port, options(nomem, nostack, preserves_flags)); - } - val -} - -#[inline(always)] -pub fn in32(port: u16) -> u32 { - let val: u32; - unsafe { - asm!("in eax, dx", out("eax") val, in("dx") port, options(nomem, nostack, preserves_flags)); - } - val -} - -#[inline(always)] -pub fn out8(port: u16, val: u8) { - unsafe { - asm!("out dx, al", in("dx") port, in("al") val, options(nomem, nostack, preserves_flags)); - } -} - -#[inline(always)] -pub fn out16(port: u16, val: u16) { - unsafe { - asm!("out dx, ax", in("dx") port, in("ax") val, options(nomem, nostack, preserves_flags)); - } -} - -#[inline(always)] -pub fn out32(port: u16, val: u32) { - unsafe { - asm!("out dx, eax", in("dx") port, in("eax") val, options(nomem, nostack, preserves_flags)); - } -} - -#[inline(always)] -pub unsafe fn cpuid(leaf: u32) -> CpuidResult { - core::arch::x86_64::__cpuid(leaf) -} - -#[inline(always)] -pub fn hlt() { - unsafe { - asm!("hlt", options(nomem, nostack)); - } -} - -#[inline(always)] -pub fn disable_interrupts() { - unsafe { - asm!("cli", options(nomem, nostack)); - } -} - -#[inline(always)] -pub fn enable_interrupts_and_hlt() { - unsafe { - asm!("sti; hlt", options(nomem, nostack)); - } -} - -#[inline] -pub fn enable_interrupts() { - unsafe { - asm!("sti", options(nomem, nostack)); - } -} - -pub const RING0: u16 = 0; -pub const RING3: u16 = 3; - -pub const RFLAGS_IF: usize = 1 << 9; - -#[inline(always)] -pub fn get_msr(id: u32) -> usize { - let (high, low): (u32, u32); - unsafe { - asm!("rdmsr", in("ecx") id, out("eax") low, out("edx") high, options(nomem, nostack, preserves_flags)); - } - ((high as usize) << 32) | (low as usize) -} - -#[inline(always)] -pub fn set_msr(id: u32, val: usize) { - let low = val as u32; - let high = (val >> 32) as u32; - unsafe { - asm!("wrmsr", in("ecx") id, in("eax") low, in("edx") high, options(nostack, preserves_flags)); - } -} - -pub const EFER_MSR: u32 = 0xC000_0080; -pub const STAR_MSR: u32 = 0xC000_0081; -pub const LSTAR_MSR: u32 = 0xC000_0082; -pub const SFMASK_MSR: u32 = 0xC000_0084; - -#[derive(Debug, Clone, Copy)] -#[repr(C, packed)] -pub struct DescriptorTablePointer { - /// Size of the DT. - pub limit: u16, - /// Pointer to the memory region containing the DT. - pub base: usize, -} - -/// Load a GDT. -#[inline(always)] -pub fn lgdt(gdt: &DescriptorTablePointer) { - unsafe { - asm!("lgdt [{}]", in(reg) gdt, options(readonly, nostack, preserves_flags)); - } -} - -/// Load an IDT. -#[inline(always)] -pub fn lidt(idt: &DescriptorTablePointer) { - unsafe { - asm!("lidt [{}]", in(reg) idt, options(readonly, nostack, preserves_flags)); - } -} - -/// Load the task state register using the `ltr` instruction. -#[inline(always)] -pub fn load_tss(sel: u16) { - unsafe { - asm!("ltr {0:x}", in(reg) sel, options(nomem, nostack, preserves_flags)); - } -} - -#[inline(always)] -pub fn set_cs(sel: u16) { - unsafe { - asm!( - "push {sel}", - "lea {tmp}, [1f + rip]", - "push {tmp}", - "retfq", - "1:", - sel = in(reg) sel as usize, - tmp = lateout(reg) _, - options(preserves_flags), - ); - } -} - -#[inline(always)] -pub fn set_ss(sel: u16) { - unsafe { - asm!("mov ss, {0:x}", in(reg) sel, options(nostack, preserves_flags)); - } -} - -#[inline(always)] -pub fn get_cr3() -> usize { - let val: usize; - unsafe { - asm!("mov {}, cr3", out(reg) val, options(nomem, nostack, preserves_flags)); - } - // Mask top bits and flags. - val & 0x_000f_ffff_ffff_f000 -} - -#[inline(always)] -pub fn get_cr3_raw() -> usize { - let val: usize; - unsafe { - asm!("mov {}, cr3", out(reg) val, options(nomem, nostack, preserves_flags)); - } - // Mask top bits and flags. - val -} - -#[inline(always)] -pub fn get_return_address() -> usize { - let val: usize; - unsafe { - asm!("mov {}, [rsp]", out(reg) val); - } - val -} - -#[inline(always)] -pub fn set_cr3(pa: usize) { - unsafe { - asm!("mov cr3, {}", in(reg) pa, options(nostack, preserves_flags)); - } -} - -#[inline(always)] -pub fn wrfsbase(base: u64) { - unsafe { asm!("wrfsbase {0}", in(reg) base, options(att_syntax)) } -} - -#[inline(always)] -pub fn rdfsbase() -> u64 { - let fs_base = x86_64::registers::segmentation::FS::read_base(); - fs_base.as_u64() -} - -pub fn enable_common_cpu_features() { - let mut cr4 = x86_64::registers::control::Cr4::read(); - cr4 |= Cr4Flags::FSGSBASE | Cr4Flags::OSXSAVE | Cr4Flags::OSFXSR | Cr4Flags::OSXMMEXCPT_ENABLE; - unsafe { - x86_64::registers::control::Cr4::write(cr4); - } - - let mut xcr0 = x86_64::registers::xcontrol::XCr0::read(); - xcr0 |= XCr0Flags::AVX | XCr0Flags::SSE; - unsafe { - x86_64::registers::xcontrol::XCr0::write(xcr0); - } - - unsafe { - // enable non-executable page protection - x86_64::registers::model_specific::Efer::update(|efer| { - *efer |= EferFlags::NO_EXECUTE_ENABLE; - }); - } -} - -pub fn flush_tlb() { - x86_64::instructions::tlb::flush_all(); -} diff --git a/src/services/comps/pci/src/util.rs b/src/services/comps/pci/src/util.rs index 117e5028..104de554 100644 --- a/src/services/comps/pci/src/util.rs +++ b/src/services/comps/pci/src/util.rs @@ -66,8 +66,8 @@ impl CSpaceAccessMethod { match self { CSpaceAccessMethod::IO => { jinux_frame::device::pci::PCI_ADDRESS_PORT - .write_u32(loc.encode() | ((offset as u32) & 0b11111100)); - jinux_frame::device::pci::PCI_DATA_PORT.read_u32().to_le() + .write(loc.encode() | ((offset as u32) & 0b11111100)); + jinux_frame::device::pci::PCI_DATA_PORT.read().to_le() } //MemoryMapped(ptr) => { // // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here. // ::core::intrinsics::volatile_load(::core::intrinsics::arith_offset(ptr, offset as usize)) @@ -108,8 +108,8 @@ impl CSpaceAccessMethod { match self { CSpaceAccessMethod::IO => { jinux_frame::device::pci::PCI_ADDRESS_PORT - .write_u32(loc.encode() | (offset as u32 & 0b11111100)); - jinux_frame::device::pci::PCI_DATA_PORT.write_u32(val.to_le()) + .write(loc.encode() | (offset as u32 & 0b11111100)); + jinux_frame::device::pci::PCI_DATA_PORT.write(val.to_le()) } //MemoryMapped(ptr) => { // // FIXME: Clarify whether the rules for GEP/GEPi forbid using regular .offset() here. // ::core::intrinsics::volatile_load(::core::intrinsics::arith_offset(ptr, offset as usize))