From 03eed5115da9f83afba2580886a263313c047fbe Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sun, 28 Apr 2024 10:30:18 +0200 Subject: [PATCH] Only enable instructions on `x86_64` A build on non-x86_64 platforms with the `instructions` feature enabled should not results in lots of inline assembly errors. --- src/instructions/mod.rs | 2 +- src/registers/control.rs | 2 +- src/registers/debug.rs | 12 ++++++------ src/registers/mod.rs | 2 +- src/registers/model_specific.rs | 11 +++++++---- src/registers/mxcsr.rs | 4 ++-- src/registers/rflags.rs | 4 ++-- src/registers/xcontrol.rs | 2 +- src/structures/gdt.rs | 21 ++++++++++++--------- src/structures/idt.rs | 12 ++++++------ src/structures/paging/mapper/mod.rs | 21 ++++++++++++--------- src/structures/paging/mod.rs | 2 +- 12 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 984c13284..4b676c557 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "instructions")] +#![cfg(all(feature = "instructions", target_arch = "x86_64"))] //! Special x86_64 instructions. diff --git a/src/registers/control.rs b/src/registers/control.rs index 6bdbaf9d7..f1975751d 100644 --- a/src/registers/control.rs +++ b/src/registers/control.rs @@ -159,7 +159,7 @@ bitflags! { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; use crate::{ diff --git a/src/registers/debug.rs b/src/registers/debug.rs index 068b2ee52..0a9f276b8 100644 --- a/src/registers/debug.rs +++ b/src/registers/debug.rs @@ -1,6 +1,6 @@ //! Functions to read and write debug registers. -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] use core::arch::asm; use core::ops::Range; @@ -15,11 +15,11 @@ pub trait DebugAddressRegister { const NUM: DebugAddressRegisterNumber; /// Reads the current breakpoint address. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] fn read() -> u64; /// Writes the provided breakpoint address. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] fn write(addr: u64); } @@ -34,7 +34,7 @@ macro_rules! debug_address_register { impl DebugAddressRegister for $Dr { const NUM: DebugAddressRegisterNumber = DebugAddressRegisterNumber::$Dr; - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] fn read() -> u64 { let addr; @@ -44,7 +44,7 @@ macro_rules! debug_address_register { addr } - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] fn write(addr: u64) { unsafe { @@ -437,7 +437,7 @@ impl Dr7Value { #[derive(Debug)] pub struct Dr7; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; diff --git a/src/registers/mod.rs b/src/registers/mod.rs index 60c6ca545..43da56c4e 100644 --- a/src/registers/mod.rs +++ b/src/registers/mod.rs @@ -8,5 +8,5 @@ pub mod rflags; pub mod segmentation; pub mod xcontrol; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub use crate::instructions::read_rip; diff --git a/src/registers/model_specific.rs b/src/registers/model_specific.rs index 8d50072ab..075048780 100644 --- a/src/registers/model_specific.rs +++ b/src/registers/model_specific.rs @@ -6,7 +6,10 @@ use bitflags::bitflags; use crate::registers::segmentation::{FS, GS}; /// A model specific register. -#[cfg_attr(not(feature = "instructions"), allow(dead_code))] // FIXME +#[cfg_attr( + not(all(feature = "instructions", target_arch = "x86_64")), + allow(dead_code) +)] // FIXME #[derive(Debug)] pub struct Msr(u32); @@ -29,7 +32,7 @@ pub struct FsBase; /// [GS].Base Model Specific Register. /// #[cfg_attr( - feature = "instructions", + all(feature = "instructions", target_arch = "x86_64"), doc = "[`GS::swap`] swaps this register with [`KernelGsBase`]." )] #[derive(Debug)] @@ -38,7 +41,7 @@ pub struct GsBase; /// KernelGsBase Model Specific Register. /// #[cfg_attr( - feature = "instructions", + all(feature = "instructions", target_arch = "x86_64"), doc = "[`GS::swap`] swaps this register with [`GsBase`]." )] #[derive(Debug)] @@ -158,7 +161,7 @@ bitflags! { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; use crate::addr::VirtAddr; diff --git a/src/registers/mxcsr.rs b/src/registers/mxcsr.rs index 19db2741d..46e107782 100644 --- a/src/registers/mxcsr.rs +++ b/src/registers/mxcsr.rs @@ -1,6 +1,6 @@ //! Functions to read and write MXCSR register. -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub use self::x86_64::*; use bitflags::bitflags; @@ -60,7 +60,7 @@ impl Default for MxCsr { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; use core::arch::asm; diff --git a/src/registers/rflags.rs b/src/registers/rflags.rs index 921bb8f2c..15c580b85 100644 --- a/src/registers/rflags.rs +++ b/src/registers/rflags.rs @@ -1,6 +1,6 @@ //! Processor state stored in the RFLAGS register. -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub use self::x86_64::*; use bitflags::bitflags; @@ -64,7 +64,7 @@ bitflags! { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; use core::arch::asm; diff --git a/src/registers/xcontrol.rs b/src/registers/xcontrol.rs index 09087a430..dc61ec789 100644 --- a/src/registers/xcontrol.rs +++ b/src/registers/xcontrol.rs @@ -50,7 +50,7 @@ bitflags! { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod x86_64 { use super::*; use core::arch::asm; diff --git a/src/structures/gdt.rs b/src/structures/gdt.rs index 74c3919ad..c04b4e426 100644 --- a/src/structures/gdt.rs +++ b/src/structures/gdt.rs @@ -10,9 +10,9 @@ use core::fmt; #[cfg(doc)] use crate::registers::segmentation::{Segment, CS, SS}; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] use core::sync::atomic::{AtomicU64 as EntryValue, Ordering}; -#[cfg(not(feature = "instructions"))] +#[cfg(not(all(feature = "instructions", target_arch = "x86_64")))] use u64 as EntryValue; /// 8-byte entry in a descriptor table. @@ -28,7 +28,7 @@ pub struct Entry(EntryValue); impl Entry { // Create a new Entry from a raw value. const fn new(raw: u64) -> Self { - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] let raw = EntryValue::new(raw); Self(raw) } @@ -37,9 +37,9 @@ impl Entry { /// bits may correspond to those in [`DescriptorFlags`]. pub fn raw(&self) -> u64 { // TODO: Make this const fn when AtomicU64::load is const. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] let raw = self.0.load(Ordering::SeqCst); - #[cfg(not(feature = "instructions"))] + #[cfg(not(all(feature = "instructions", target_arch = "x86_64")))] let raw = self.0; raw } @@ -153,7 +153,10 @@ impl GlobalDescriptorTable { /// * the provided slice has more than `MAX` entries /// * the provided slice is empty /// * the first entry is not zero - #[cfg_attr(not(feature = "instructions"), allow(rustdoc::broken_intra_doc_links))] + #[cfg_attr( + not(all(feature = "instructions", target_arch = "x86_64")), + allow(rustdoc::broken_intra_doc_links) + )] #[inline] pub const fn from_raw_entries(slice: &[u64]) -> Self { let len = slice.len(); @@ -215,7 +218,7 @@ impl GlobalDescriptorTable { /// segment registers; you **must** (re)load them yourself using [the appropriate /// functions](crate::instructions::segmentation): /// [`SS::set_reg()`] and [`CS::set_reg()`]. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub fn load(&'static self) { // SAFETY: static lifetime ensures no modification after loading. @@ -233,7 +236,7 @@ impl GlobalDescriptorTable { /// this means its up to the user to ensure that there will be no modifications /// after loading and that the GDT will live for as long as it's loaded. /// - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub unsafe fn load_unsafe(&self) { use crate::instructions::tables::lgdt; @@ -261,7 +264,7 @@ impl GlobalDescriptorTable { /// Creates the descriptor pointer for this table. This pointer can only be /// safely used if the table is never modified or destroyed while in use. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] fn pointer(&self) -> super::DescriptorTablePointer { super::DescriptorTablePointer { base: crate::VirtAddr::new(self.table.as_ptr() as u64), diff --git a/src/structures/idt.rs b/src/structures/idt.rs index 302145abe..9652585d6 100644 --- a/src/structures/idt.rs +++ b/src/structures/idt.rs @@ -489,7 +489,7 @@ impl InterruptDescriptorTable { } /// Loads the IDT in the CPU using the `lidt` command. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub fn load(&'static self) { unsafe { self.load_unsafe() } @@ -505,7 +505,7 @@ impl InterruptDescriptorTable { /// - `self` always stays at the same memory location. It is recommended to wrap it in /// a `Box`. /// - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub unsafe fn load_unsafe(&self) { use crate::instructions::tables::lidt; @@ -516,7 +516,7 @@ impl InterruptDescriptorTable { /// Creates the descriptor pointer for this table. This pointer can only be /// safely used if the table is never modified or destroyed while in use. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] fn pointer(&self) -> crate::structures::DescriptorTablePointer { use core::mem::size_of; crate::structures::DescriptorTablePointer { @@ -792,7 +792,7 @@ impl Entry { /// /// The caller must ensure that `addr` is the address of a valid interrupt handler function, /// and the signature of such a function is correct for the entry type. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub unsafe fn set_handler_addr(&mut self, addr: VirtAddr) -> &mut EntryOptions { use crate::instructions::segmentation::{Segment, CS}; @@ -821,7 +821,7 @@ impl Entry { } } -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] impl Entry { /// Sets the handler function for the IDT entry and sets the following defaults: /// - The code selector is the code segment currently active in the CPU @@ -1093,7 +1093,7 @@ impl InterruptStackFrameValue { /// CS and SS register can all cause undefined behaviour when done incorrectly. /// #[inline(always)] - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub unsafe fn iretq(&self) -> ! { unsafe { core::arch::asm!( diff --git a/src/structures/paging/mapper/mod.rs b/src/structures/paging/mapper/mod.rs index 99d693bed..5db479b81 100644 --- a/src/structures/paging/mapper/mod.rs +++ b/src/structures/paging/mapper/mod.rs @@ -3,7 +3,7 @@ pub use self::mapped_page_table::{MappedPageTable, PageTableFrameMapping}; #[cfg(target_pointer_width = "64")] pub use self::offset_page_table::OffsetPageTable; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] pub use self::recursive_page_table::{InvalidPageTable, RecursivePageTable}; use crate::structures::paging::{ @@ -16,7 +16,7 @@ use crate::{PhysAddr, VirtAddr}; mod mapped_page_table; mod offset_page_table; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] mod recursive_page_table; /// An empty convencience trait that requires the `Mapper` trait for all page sizes. @@ -154,12 +154,12 @@ pub trait Mapper { /// Create a USER_ACCESSIBLE mapping: /// /// ``` - /// # #[cfg(feature = "instructions")] + /// # #[cfg(all(feature = "instructions", target_arch = "x86_64"))] /// # use x86_64::structures::paging::{ /// # Mapper, Page, PhysFrame, FrameAllocator, /// # Size4KiB, OffsetPageTable, page_table::PageTableFlags /// # }; - /// # #[cfg(feature = "instructions")] + /// # #[cfg(all(feature = "instructions", target_arch = "x86_64"))] /// # unsafe fn test(mapper: &mut OffsetPageTable, frame_allocator: &mut impl FrameAllocator, /// # page: Page, frame: PhysFrame) { /// mapper @@ -243,12 +243,12 @@ pub trait Mapper { /// the top hierarchy only with USER_ACCESSIBLE: /// /// ``` - /// # #[cfg(feature = "instructions")] + /// # #[cfg(all(feature = "instructions", target_arch = "x86_64"))] /// # use x86_64::structures::paging::{ /// # Mapper, PhysFrame, Page, FrameAllocator, /// # Size4KiB, OffsetPageTable, page_table::PageTableFlags /// # }; - /// # #[cfg(feature = "instructions")] + /// # #[cfg(all(feature = "instructions", target_arch = "x86_64"))] /// # unsafe fn test(mapper: &mut OffsetPageTable, frame_allocator: &mut impl FrameAllocator, /// # page: Page, frame: PhysFrame) { /// mapper @@ -383,7 +383,10 @@ pub trait Mapper { /// changed the mapping of a page to ensure that the TLB flush is not forgotten. #[derive(Debug)] #[must_use = "Page Table changes must be flushed or ignored."] -#[cfg_attr(not(feature = "instructions"), allow(dead_code))] // FIXME +#[cfg_attr( + not(all(feature = "instructions", target_arch = "x86_64")), + allow(dead_code) +)] // FIXME pub struct MapperFlush(Page); impl MapperFlush { @@ -397,7 +400,7 @@ impl MapperFlush { } /// Flush the page from the TLB to ensure that the newest mapping is used. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub fn flush(self) { crate::instructions::tlb::flush(self.0.start_address()); @@ -428,7 +431,7 @@ impl MapperFlushAll { } /// Flush all pages from the TLB to ensure that the newest mapping is used. - #[cfg(feature = "instructions")] + #[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[inline] pub fn flush_all(self) { crate::instructions::tlb::flush_all() diff --git a/src/structures/paging/mod.rs b/src/structures/paging/mod.rs index 6a3a9ae32..741f683c3 100644 --- a/src/structures/paging/mod.rs +++ b/src/structures/paging/mod.rs @@ -9,7 +9,7 @@ pub use self::mapper::MappedPageTable; #[cfg(target_pointer_width = "64")] #[doc(no_inline)] pub use self::mapper::OffsetPageTable; -#[cfg(feature = "instructions")] +#[cfg(all(feature = "instructions", target_arch = "x86_64"))] #[doc(no_inline)] pub use self::mapper::RecursivePageTable; pub use self::mapper::{Mapper, Translate};