Sync x86 and x86_64

This commit is contained in:
Jeremy Soller
2022-07-29 18:49:55 -06:00
parent 166e1e304b
commit 07015d17ba
19 changed files with 107 additions and 83 deletions

View File

@@ -14,7 +14,7 @@ use crate::syscall::io::Mmio;
use crate::devices::uart_16550::SerialPort;
#[cfg(feature = "graphical_debug")]
use super::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
use crate::devices::graphical_debug::{DEBUG_DISPLAY, DebugDisplay};
#[cfg(feature = "lpss_debug")]
use super::device::serial::LPSS;
#[cfg(feature = "serial_debug")]

View File

@@ -12,7 +12,7 @@ pub fn cpu_info<W: Write>(w: &mut W) -> Result {
};
if let Some(info) = cpuid.get_vendor_info() {
writeln!(w, "Vendor: {}", info.as_string())?;
writeln!(w, "Vendor: {}", info.as_str())?;
}
if let Some(brand) = cpuid.get_processor_brand_string() {

View File

@@ -69,7 +69,7 @@ pub unsafe fn init(hpet: &mut Hpet) -> bool {
}
pub unsafe fn debug(hpet: &mut Hpet) {
println!("HPET @ {:#x}", hpet.base_address.address);
println!("HPET @ {:#x}", { hpet.base_address.address });
let capability = hpet.base_address.read_u64(CAPABILITY_OFFSET);
{

View File

@@ -296,7 +296,7 @@ pub struct IdtEntry {
attribute: u8,
offsetm: u16,
offseth: u32,
zero2: u32
_zero2: u32
}
impl IdtEntry {
@@ -308,7 +308,7 @@ impl IdtEntry {
attribute: 0,
offsetm: 0,
offseth: 0,
zero2: 0
_zero2: 0
}
}

View File

@@ -3,7 +3,7 @@ use core::{mem, str};
use goblin::elf::sym;
use rustc_demangle::demangle;
use crate::{context, paging::{KernelMapper, VirtualAddress}};
use crate::{paging::{KernelMapper, VirtualAddress}};
/// Get a stack trace
//TODO: Check for stack being mapped before dereferencing

View File

@@ -16,10 +16,6 @@ pub mod device;
/// Global descriptor table
pub mod gdt;
/// Graphical debug
#[cfg(feature = "graphical_debug")]
mod graphical_debug;
/// Interrupt instructions
#[macro_use]
pub mod interrupt;

View File

@@ -14,8 +14,8 @@ pub use rmm::{
PhysicalAddress,
TableKind,
VirtualAddress,
X86Arch as RmmA,
};
pub use super::CurrentRmmArch as RmmA;
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
pub use crate::rmm::KernelMapper;

View File

@@ -18,10 +18,10 @@ use rmm::{
PageMapper,
PhysicalAddress,
VirtualAddress,
X86Arch as RmmA,
};
use spin::Mutex;
use spin::{Mutex, MutexGuard};
use super::CurrentRmmArch as RmmA;
extern "C" {
/// The starting byte of the text (code) data segment.
@@ -76,7 +76,6 @@ unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> PageFlags<A> {
}
}
//TODO: problems if RAM > 1GiB
unsafe fn inner<A: Arch>(
areas: &'static [MemoryArea],
kernel_base: usize, kernel_size_aligned: usize,
@@ -141,8 +140,8 @@ unsafe fn inner<A: Arch>(
}
let mut identity_map = |base, size_aligned| {
// Map stack with identity mapping
for i in 0..size / A::PAGE_SIZE {
// Map with identity mapping
for i in 0..size_aligned / A::PAGE_SIZE {
let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE);
let virt = A::phys_to_virt(phys);
let flags = page_flags::<A>(virt);
@@ -155,7 +154,6 @@ unsafe fn inner<A: Arch>(
}
};
identity_map(stack_base, stack_size_aligned);
identity_map(env_base, env_size_aligned);
identity_map(acpi_base, acpi_size_aligned);
@@ -164,7 +162,7 @@ unsafe fn inner<A: Arch>(
// Ensure graphical debug region remains paged
#[cfg(feature = "graphical_debug")]
{
use super::graphical_debug::DEBUG_DISPLAY;
use crate::devices::graphical_debug::DEBUG_DISPLAY;
use super::paging::entry::EntryFlags;
let (base, size) = if let Some(debug_display) = &*DEBUG_DISPLAY.lock() {
@@ -366,7 +364,7 @@ pub unsafe fn init(
// Copy memory map from bootloader location, and page align it
let mut area_i = 0;
for bootloader_area in bootloader_areas.iter() {
if bootloader_area.kind != BootloaderMemoryKind::Free {
if { bootloader_area.kind } != BootloaderMemoryKind::Free {
// Not a free area
continue;
}

View File

@@ -9,18 +9,17 @@ use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use crate::allocator;
#[cfg(feature = "acpi")]
use crate::acpi;
use crate::arch::pti;
use crate::arch::flags::*;
use crate::device;
#[cfg(feature = "graphical_debug")]
use crate::devices::graphical_debug;
use crate::gdt;
use crate::idt;
use crate::interrupt;
use crate::log::{self, info};
use crate::paging::{self, KernelMapper};
#[cfg(feature = "graphical_debug")]
use super::graphical_debug;
use super::pti;
use super::flags::*;
/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
@@ -107,13 +106,13 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
});
info!("Redox OS starting...");
info!("Kernel: {:X}:{:X}", args.kernel_base, args.kernel_base + args.kernel_size);
info!("Stack: {:X}:{:X}", args.stack_base, args.stack_base + args.stack_size);
info!("Env: {:X}:{:X}", args.env_base, args.env_base + args.env_size);
info!("RSDPs: {:X}:{:X}", args.acpi_rsdps_base, args.acpi_rsdps_base + args.acpi_rsdps_size);
info!("Areas: {:X}:{:X}", args.areas_base, args.areas_base + args.areas_size);
info!("Bootstrap: {:X}:{:X}", args.bootstrap_base, args.bootstrap_base + args.bootstrap_size);
info!("Bootstrap entry point: {:X}", args.bootstrap_entry);
info!("Kernel: {:X}:{:X}", { args.kernel_base }, { args.kernel_base } + { args.kernel_size });
info!("Stack: {:X}:{:X}", { args.stack_base }, { args.stack_base } + { args.stack_size });
info!("Env: {:X}:{:X}", { args.env_base }, { args.env_base } + { args.env_size });
info!("RSDPs: {:X}:{:X}", { args.acpi_rsdps_base }, { args.acpi_rsdps_base } + { args.acpi_rsdps_size });
info!("Areas: {:X}:{:X}", { args.areas_base }, { args.areas_base } + { args.areas_size });
info!("Bootstrap: {:X}:{:X}", { args.bootstrap_base }, { args.bootstrap_base } + { args.bootstrap_size });
info!("Bootstrap entry point: {:X}", { args.bootstrap_entry });
// Set up GDT before paging
gdt::init();
@@ -255,7 +254,7 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
assert_eq!(TBSS_TEST_ZERO, 1);
assert_eq!(TDATA_TEST_NONZERO, usize::max_value());
TDATA_TEST_NONZERO -= 1;
assert_eq!(TDATA_TEST_NONZERO, usize::max_value());
assert_eq!(TDATA_TEST_NONZERO, usize::max_value() - 1);
}
// Initialize devices (for AP)

14
src/arch/x86_64/cpuid.rs Normal file
View File

@@ -0,0 +1,14 @@
use raw_cpuid::{CpuId, CpuIdResult};
pub fn cpuid() -> Option<CpuId> {
//TODO: ensure that CPUID exists! https://wiki.osdev.org/CPUID#Checking_CPUID_availability
Some(CpuId::with_cpuid_fn(|a, c| {
let result = unsafe { core::arch::x86::__cpuid_count(a, c) };
CpuIdResult {
eax: result.eax,
ebx: result.ebx,
ecx: result.ecx,
edx: result.edx,
}
}))
}

View File

@@ -1,11 +1,15 @@
extern crate raw_cpuid;
use core::fmt::{Result, Write};
use self::raw_cpuid::CpuId;
use super::super::cpuid::cpuid;
pub fn cpu_info<W: Write>(w: &mut W) -> Result {
let cpuid = CpuId::new();
let cpuid = match cpuid() {
Some(some) => some,
None => {
writeln!(w, "CPUID instruction not supported")?;
return Ok(());
}
};
if let Some(info) = cpuid.get_vendor_info() {
writeln!(w, "Vendor: {}", info.as_str())?;

View File

@@ -11,6 +11,7 @@ use crate::memory::Frame;
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch};
use crate::paging::entry::EntryFlags;
use super::super::cpuid::cpuid;
use super::pic;
pub struct IoApicRegs {
@@ -285,7 +286,7 @@ pub unsafe fn handle_src_override(src_override: &'static MadtIntSrcOverride) {
}
pub unsafe fn init(active_table: &mut KernelMapper) {
let bsp_apic_id = x86::cpuid::CpuId::new().get_feature_info().unwrap().initial_local_apic_id(); // TODO
let bsp_apic_id = cpuid().unwrap().get_feature_info().unwrap().initial_local_apic_id(); // TODO: remove unwraps
// search the madt for all IOAPICs.
#[cfg(feature = "acpi")]

View File

@@ -1,10 +1,11 @@
use core::sync::atomic::{self, AtomicU64};
use core::intrinsics::{volatile_load, volatile_store};
use x86::cpuid::CpuId;
use x86::msr::*;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags, RmmA, RmmArch};
use super::super::cpuid::cpuid;
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
@@ -47,7 +48,11 @@ impl LocalApic {
let virtaddr = RmmA::phys_to_virt(physaddr);
self.address = virtaddr.data();
self.x2 = CpuId::new().get_feature_info().unwrap().has_x2apic();
self.x2 = cpuid().map_or(false, |cpuid| {
cpuid.get_feature_info().map_or(false, |feature_info| {
feature_info.has_x2apic()
})
});
if ! self.x2 {
log::info!("Detected xAPIC at {:#x}", physaddr.data());

View File

@@ -10,6 +10,8 @@ use x86::dtables::{self, DescriptorTablePointer};
use x86::segmentation::{self, Descriptor as SegmentDescriptor, SegmentSelector};
use x86::task;
use super::cpuid::cpuid;
pub const GDT_NULL: usize = 0;
pub const GDT_KERNEL_CODE: usize = 1;
pub const GDT_KERNEL_DATA: usize = 2;
@@ -210,9 +212,11 @@ pub unsafe fn init_paging(cpu_id: u32, tcb_offset: usize, stack_offset: usize) {
// Load the task register
task::load_tr(SegmentSelector::new(GDT_TSS as u16, Ring::Ring0));
let has_fsgsbase = raw_cpuid::CpuId::new()
.get_extended_feature_info()
.map_or(false, |extended_features| extended_features.has_fsgsbase());
let has_fsgsbase = cpuid().map_or(false, |cpuid| {
cpuid.get_extended_feature_info().map_or(false, |extended_features| {
extended_features.has_fsgsbase()
})
});
if cfg!(feature = "x86_fsgsbase") {
assert!(has_fsgsbase, "running kernel with features not supported by the current CPU");

View File

@@ -323,7 +323,7 @@ impl IdtEntry {
self.selector = selector;
self.offsetl = base as u16;
self.offsetm = (base >> 16) as u16;
self.offseth = (base >> 32) as u32;
self.offseth = ((base as u64) >> 32) as u32;
}
// A function to set the offset more easily

View File

@@ -4,6 +4,9 @@ pub mod macros;
/// Constants like memory locations
pub mod consts;
/// CPUID wrapper
pub mod cpuid;
/// Debugging support
pub mod debug;

View File

@@ -14,8 +14,8 @@ pub use rmm::{
PhysicalAddress,
TableKind,
VirtualAddress,
X8664Arch as RmmA,
};
pub use super::CurrentRmmArch as RmmA;
pub type PageMapper = rmm::PageMapper<RmmA, crate::arch::rmm::LockedAllocator>;
pub use crate::rmm::KernelMapper;

View File

@@ -18,11 +18,11 @@ use rmm::{
PageMapper,
PhysicalAddress,
VirtualAddress,
X8664Arch as RmmA,
};
use spin::Mutex;
use super::CurrentRmmArch as RmmA;
extern "C" {
/// The starting byte of the text (code) data segment.
static mut __text_start: u8;
@@ -191,7 +191,7 @@ unsafe fn inner<A: Arch>(
}
log::debug!("Table: {:X}", mapper.table().phys().data());
for i in 0..512 {
for i in 0..A::PAGE_ENTRIES {
if let Some(entry) = mapper.table().entry(i) {
if entry.present() {
log::debug!("{}: {:X}", i, entry.data());

View File

@@ -23,13 +23,13 @@ use crate::paging::{self, KernelMapper};
/// Test of zero values in BSS.
static BSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in data.
static DATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
static DATA_TEST_NONZERO: usize = usize::max_value();
/// Test of zero values in thread BSS
#[thread_local]
static mut TBSS_TEST_ZERO: usize = 0;
/// Test of non-zero values in thread data.
#[thread_local]
static mut TDATA_TEST_NONZERO: usize = 0xFFFF_FFFF_FFFF_FFFF;
static mut TDATA_TEST_NONZERO: usize = usize::max_value();
pub static KERNEL_BASE: AtomicUsize = AtomicUsize::new(0);
pub static KERNEL_SIZE: AtomicUsize = AtomicUsize::new(0);
@@ -39,12 +39,12 @@ static BSP_READY: AtomicBool = AtomicBool::new(false);
#[repr(packed)]
pub struct KernelArgs {
kernel_base: usize,
kernel_size: usize,
stack_base: usize,
stack_size: usize,
env_base: usize,
env_size: usize,
kernel_base: u64,
kernel_size: u64,
stack_base: u64,
stack_size: u64,
env_base: u64,
env_size: u64,
/// The base 64-bit pointer to an array of saved RSDPs. It's up to the kernel (and possibly
/// userspace), to decide which RSDP to use. The buffer will be a linked list containing a
@@ -53,19 +53,19 @@ pub struct KernelArgs {
/// This field can be NULL, and if so, the system has not booted with UEFI or in some other way
/// retrieved the RSDPs. The kernel or a userspace driver will thus try searching the BIOS
/// memory instead. On UEFI systems, BIOS-like searching is not guaranteed to actually work though.
acpi_rsdps_base: usize,
acpi_rsdps_base: u64,
/// The size of the RSDPs region.
acpi_rsdps_size: usize,
acpi_rsdps_size: u64,
areas_base: usize,
areas_size: usize,
areas_base: u64,
areas_size: u64,
/// The physical base 64-bit pointer to the contiguous bootstrap/initfs.
bootstrap_base: usize,
bootstrap_base: u64,
/// Size of contiguous bootstrap/initfs physical region, not necessarily page aligned.
bootstrap_size: usize,
bootstrap_size: u64,
/// Entry point the kernel will jump to.
bootstrap_entry: usize,
bootstrap_entry: u64,
}
/// The entry to Rust, all things must be initialized
@@ -77,14 +77,14 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// BSS should already be zero
{
assert_eq!(BSS_TEST_ZERO, 0);
assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
assert_eq!(DATA_TEST_NONZERO, usize::max_value());
}
KERNEL_BASE.store(args.kernel_base, Ordering::SeqCst);
KERNEL_SIZE.store(args.kernel_size, Ordering::SeqCst);
KERNEL_BASE.store(args.kernel_base as usize, Ordering::SeqCst);
KERNEL_SIZE.store(args.kernel_size as usize, Ordering::SeqCst);
// Convert env to slice
let env = slice::from_raw_parts((args.env_base + crate::PHYS_OFFSET) as *const u8, args.env_size);
let env = slice::from_raw_parts((args.env_base as usize + crate::PHYS_OFFSET) as *const u8, args.env_size as usize);
// Set up graphical debug
#[cfg(feature = "graphical_debug")]
@@ -97,7 +97,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
log::init_logger(|r| {
use core::fmt::Write;
let _ = write!(
crate::arch::x86_64::debug::Writer::new(),
super::debug::Writer::new(),
"{}:{} -- {}\n",
r.target(),
r.level(),
@@ -122,19 +122,19 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Initialize RMM
crate::arch::rmm::init(
args.kernel_base, args.kernel_size,
args.stack_base, args.stack_size,
args.env_base, args.env_size,
args.acpi_rsdps_base, args.acpi_rsdps_size,
args.areas_base, args.areas_size,
args.bootstrap_base, args.bootstrap_size,
args.kernel_base as usize, args.kernel_size as usize,
args.stack_base as usize, args.stack_size as usize,
args.env_base as usize, args.env_size as usize,
args.acpi_rsdps_base as usize, args.acpi_rsdps_size as usize,
args.areas_base as usize, args.areas_size as usize,
args.bootstrap_base as usize, args.bootstrap_size as usize,
);
// Initialize paging
let tcb_offset = paging::init(0);
// Set up GDT after paging with TLS
gdt::init_paging(0, tcb_offset, args.stack_base + args.stack_size);
gdt::init_paging(0, tcb_offset, args.stack_base as usize + args.stack_size as usize);
// Set up IDT
idt::init_paging_bsp();
@@ -147,9 +147,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
assert_eq!(TBSS_TEST_ZERO, 0);
TBSS_TEST_ZERO += 1;
assert_eq!(TBSS_TEST_ZERO, 1);
assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
assert_eq!(TDATA_TEST_NONZERO, usize::max_value());
TDATA_TEST_NONZERO -= 1;
assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
assert_eq!(TDATA_TEST_NONZERO, usize::max_value() - 1);
}
// Reset AP variables
@@ -176,7 +176,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
#[cfg(feature = "acpi")]
{
acpi::init(if args.acpi_rsdps_base != 0 && args.acpi_rsdps_size > 0 {
Some(((args.acpi_rsdps_base + crate::PHYS_OFFSET) as u64, args.acpi_rsdps_size as u64))
Some(((args.acpi_rsdps_base as usize + crate::PHYS_OFFSET) as u64, args.acpi_rsdps_size as u64))
} else {
None
});
@@ -193,9 +193,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
BSP_READY.store(true, Ordering::SeqCst);
crate::Bootstrap {
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(args.bootstrap_base)),
page_count: args.bootstrap_size / crate::memory::PAGE_SIZE,
entry: args.bootstrap_entry,
base: crate::memory::Frame::containing_address(crate::paging::PhysicalAddress::new(args.bootstrap_base as usize)),
page_count: (args.bootstrap_size as usize) / crate::memory::PAGE_SIZE,
entry: args.bootstrap_entry as usize,
env,
}
};
@@ -221,7 +221,7 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
let stack_end = args.stack_end as usize;
assert_eq!(BSS_TEST_ZERO, 0);
assert_eq!(DATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
assert_eq!(DATA_TEST_NONZERO, usize::max_value());
// Set up GDT before paging
gdt::init();
@@ -252,9 +252,9 @@ pub unsafe extern fn kstart_ap(args_ptr: *const KernelArgsAp) -> ! {
assert_eq!(TBSS_TEST_ZERO, 0);
TBSS_TEST_ZERO += 1;
assert_eq!(TBSS_TEST_ZERO, 1);
assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFF);
assert_eq!(TDATA_TEST_NONZERO, usize::max_value());
TDATA_TEST_NONZERO -= 1;
assert_eq!(TDATA_TEST_NONZERO, 0xFFFF_FFFF_FFFF_FFFE);
assert_eq!(TDATA_TEST_NONZERO, usize::max_value() - 1);
}
// Initialize devices (for AP)