Remove x86_64_util

This commit is contained in:
Yuke Peng 2023-03-15 01:48:40 -07:00 committed by Tate, Hongliang Tian
parent 02731914dc
commit 840fe53845
14 changed files with 222 additions and 442 deletions

View File

@ -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<u32> = IoPort::new(0x12);
///
/// fn port_value_increase(){
/// PORT.write(PORT.read() + 1)
/// }
/// ```
///
pub struct IoPort<T> {
addr: u16,
port: Mutex<Port<T>>,
}
impl IoPort {
impl<T> IoPort<T> {
/// 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<Self> {
Ok(Self { addr: addr })
pub const unsafe fn new(addr: u16) -> Self {
Self {
addr,
port: Mutex::new(Port::new(addr)),
}
}
}
impl IoPort {
impl<T> IoPort<T> {
/// 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<T: PortRead> IoPort<T> {
/// Reads from the port.
pub fn read(&self) -> T {
unsafe { (*self.port.lock()).read() }
}
}
impl<T: PortWrite> IoPort<T> {
/// Writes to the port.
pub fn write(&self, val: T) {
unsafe {
self.port.lock().write(val);
}
}
}

View File

@ -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<u32> = unsafe { IoPort::new(0x0CF8) };
pub static PCI_DATA_PORT: IoPort<u32> = unsafe { IoPort::new(0x0CFC) };

View File

@ -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<Port<u8>> = Mutex::new(Port::new(SERIAL_DATA_PORT));
static SERIAL_INT_EN: Mutex<PortWriteOnly<u8>> =
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 1));
static SERIAL_FIFO_CTRL: Mutex<PortWriteOnly<u8>> =
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 2));
static SERIAL_LINE_CTRL: Mutex<PortWriteOnly<u8>> =
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 3));
static SERIAL_MODEM_CTRL: Mutex<PortWriteOnly<u8>> =
Mutex::new(PortWriteOnly::new(SERIAL_DATA_PORT + 4));
static SERIAL_LINE_STS: Mutex<Port<u8>> = Mutex::new(Port::new(SERIAL_DATA_PORT + 5));
static CONSOLE_IRQ_CALLBACK: Once<Mutex<IrqAllocateHandle>> = Once::new();
static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>>> =
@ -27,23 +34,30 @@ static SERIAL_INPUT_CALLBACKS: Mutex<Vec<Arc<dyn Fn(u8) + Send + Sync + 'static>
/// 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<u8> {
if line_sts().contains(LineSts::INPUT_FULL) {
Some(in8(SERIAL_DATA))
unsafe { Some(SERIAL_DATA.lock().read()) }
} else {
None
}

View File

@ -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<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x20));
static MASTER_DATA: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x21));
static SLAVE_CMD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0xA0));
static SLAVE_DATA: Mutex<PortWriteOnly<u8>> = 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);
}
}

View File

@ -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<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x70));
static CMOS_DATA: Mutex<PortReadOnly<u8>> = 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 {

View File

@ -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);

View File

@ -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<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x40));
static TIMER_MOD: Mutex<PortWriteOnly<u8>> = 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 _);
}
}

View File

@ -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
}
}

View File

@ -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<IrqCallbackHandle> = 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()

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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();
}

View File

@ -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))