Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use rustversion and remove const_fn! #353

Merged
merged 4 commits into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: doc
args: --no-default-features --features external_asm,instructions
args: --no-default-features --features instructions
if: runner.os != 'Windows'

- name: "Run cargo doc without default features"
Expand All @@ -83,14 +83,14 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: build
args: --no-default-features --features external_asm,instructions
args: --no-default-features --features instructions
if: runner.os != 'Windows'

- name: "Run cargo build for stable on musl"
uses: actions-rs/cargo@v1
with:
command: build
args: --target x86_64-unknown-linux-musl --no-default-features --features external_asm,instructions
args: --target x86_64-unknown-linux-musl --no-default-features --features instructions
if: runner.os == 'Linux'

- name: "Run cargo test"
Expand All @@ -102,14 +102,14 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --no-default-features --features external_asm,instructions
args: --no-default-features --features instructions
if: runner.os != 'Windows'

- name: "Run cargo test for stable on musl"
uses: actions-rs/cargo@v1
with:
command: test
args: --target x86_64-unknown-linux-musl --no-default-features --features external_asm,instructions
args: --target x86_64-unknown-linux-musl --no-default-features --features instructions
if: runner.os == 'Linux'

- name: "Install Rustup Targets"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ edition = "2018"
bit_field = "0.10.1"
bitflags = "1.0.4"
volatile = "0.4.4"
rustversion = "1.0.5"

[features]
default = [ "nightly", "instructions" ]
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Support for x86_64 specific instructions (e.g. TLB flush), registers (e.g. contr

* `nightly`: Enables features only available on nightly Rust; enabled by default.
* `instructions`: Enabled by default, turns on x86\_64 specific instructions, and dependent features. Only available for x86\_64 targets.
* `external_asm`: Use this to build with non-nightly rust. Needs `default-features = false, features = ["instructions"]`. Is unsupported on Windows.

## Building with stable rust

Expand Down
6 changes: 2 additions & 4 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,7 @@ impl Sub<PhysAddr> for PhysAddr {
///
/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
///
/// Panics if the alignment is not a power of two. Without the `const_fn`
/// feature, the panic message will be "index out of bounds".
/// Panics if the alignment is not a power of two.
#[inline]
pub const fn align_down(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
Expand All @@ -637,8 +636,7 @@ pub const fn align_down(addr: u64, align: u64) -> u64 {
///
/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
///
/// Panics if the alignment is not a power of two. Without the `const_fn`
/// feature, the panic message will be "index out of bounds".
/// Panics if the alignment is not a power of two.
#[inline]
pub const fn align_up(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
Expand Down
31 changes: 0 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,6 @@

pub use crate::addr::{align_down, align_up, PhysAddr, VirtAddr};

/// Makes a function const only when `feature = "const_fn"` is enabled.
///
/// This is needed for const functions with bounds on their generic parameters,
/// such as those in `Page` and `PhysFrame` and many more.
macro_rules! const_fn {
(
$(#[$attr:meta])*
$sv:vis fn $($fn:tt)*
) => {
$(#[$attr])*
#[cfg(feature = "const_fn")]
$sv const fn $($fn)*

$(#[$attr])*
#[cfg(not(feature = "const_fn"))]
$sv fn $($fn)*
};
(
$(#[$attr:meta])*
$sv:vis unsafe fn $($fn:tt)*
) => {
$(#[$attr])*
#[cfg(feature = "const_fn")]
$sv const unsafe fn $($fn)*

$(#[$attr])*
#[cfg(not(feature = "const_fn"))]
$sv unsafe fn $($fn)*
};
}

pub mod addr;
pub mod instructions;
pub mod registers;
Expand Down
73 changes: 35 additions & 38 deletions src/structures/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,36 +93,34 @@ impl GlobalDescriptorTable {
&self.table[..self.next_free]
}

const_fn! {
/// Adds the given segment descriptor to the GDT, returning the segment selector.
///
/// Panics if the GDT has no free entries left. Without the `const_fn`
/// feature, the panic message will be "index out of bounds".
#[inline]
pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector {
let index = match entry {
Descriptor::UserSegment(value) => self.push(value),
Descriptor::SystemSegment(value_low, value_high) => {
let index = self.push(value_low);
self.push(value_high);
index
}
};
/// Adds the given segment descriptor to the GDT, returning the segment selector.
///
/// Panics if the GDT has no free entries left.
#[inline]
#[cfg_attr(feature = "const_fn", rustversion::attr(all(), const))]
pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector {
let index = match entry {
Descriptor::UserSegment(value) => self.push(value),
Descriptor::SystemSegment(value_low, value_high) => {
let index = self.push(value_low);
self.push(value_high);
index
}
};

let rpl = match entry {
Descriptor::UserSegment(value) => {
if DescriptorFlags::from_bits_truncate(value).contains(DescriptorFlags::DPL_RING_3)
{
PrivilegeLevel::Ring3
} else {
PrivilegeLevel::Ring0
}
let rpl = match entry {
Descriptor::UserSegment(value) => {
if DescriptorFlags::from_bits_truncate(value).contains(DescriptorFlags::DPL_RING_3)
{
PrivilegeLevel::Ring3
} else {
PrivilegeLevel::Ring0
}
Descriptor::SystemSegment(_, _) => PrivilegeLevel::Ring0,
};
}
Descriptor::SystemSegment(_, _) => PrivilegeLevel::Ring0,
};

SegmentSelector::new(index as u16, rpl)
}
SegmentSelector::new(index as u16, rpl)
}

/// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
Expand Down Expand Up @@ -156,17 +154,16 @@ impl GlobalDescriptorTable {
}
}

const_fn! {
#[inline]
fn push(&mut self, value: u64) -> usize {
if self.next_free < self.table.len() {
let index = self.next_free;
self.table[index] = value;
self.next_free += 1;
index
} else {
panic!("GDT full");
}
#[inline]
#[cfg_attr(feature = "const_fn", rustversion::attr(all(), const))]
fn push(&mut self, value: u64) -> usize {
if self.next_free < self.table.len() {
let index = self.next_free;
self.table[index] = value;
self.next_free += 1;
index
} else {
panic!("GDT full");
}
}

Expand Down
64 changes: 31 additions & 33 deletions src/structures/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,39 +410,37 @@ pub struct InterruptDescriptorTable {
}

impl InterruptDescriptorTable {
// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Creates a new IDT filled with non-present entries.
#[inline]
pub fn new() -> InterruptDescriptorTable {
InterruptDescriptorTable {
divide_error: Entry::missing(),
debug: Entry::missing(),
non_maskable_interrupt: Entry::missing(),
breakpoint: Entry::missing(),
overflow: Entry::missing(),
bound_range_exceeded: Entry::missing(),
invalid_opcode: Entry::missing(),
device_not_available: Entry::missing(),
double_fault: Entry::missing(),
coprocessor_segment_overrun: Entry::missing(),
invalid_tss: Entry::missing(),
segment_not_present: Entry::missing(),
stack_segment_fault: Entry::missing(),
general_protection_fault: Entry::missing(),
page_fault: Entry::missing(),
reserved_1: Entry::missing(),
x87_floating_point: Entry::missing(),
alignment_check: Entry::missing(),
machine_check: Entry::missing(),
simd_floating_point: Entry::missing(),
virtualization: Entry::missing(),
reserved_2: [Entry::missing(); 8],
vmm_communication_exception: Entry::missing(),
security_exception: Entry::missing(),
reserved_3: Entry::missing(),
interrupts: [Entry::missing(); 256 - 32],
}
/// Creates a new IDT filled with non-present entries.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn new() -> InterruptDescriptorTable {
InterruptDescriptorTable {
divide_error: Entry::missing(),
debug: Entry::missing(),
non_maskable_interrupt: Entry::missing(),
breakpoint: Entry::missing(),
overflow: Entry::missing(),
bound_range_exceeded: Entry::missing(),
invalid_opcode: Entry::missing(),
device_not_available: Entry::missing(),
double_fault: Entry::missing(),
coprocessor_segment_overrun: Entry::missing(),
invalid_tss: Entry::missing(),
segment_not_present: Entry::missing(),
stack_segment_fault: Entry::missing(),
general_protection_fault: Entry::missing(),
page_fault: Entry::missing(),
reserved_1: Entry::missing(),
x87_floating_point: Entry::missing(),
alignment_check: Entry::missing(),
machine_check: Entry::missing(),
simd_floating_point: Entry::missing(),
virtualization: Entry::missing(),
reserved_2: [Entry::missing(); 8],
vmm_communication_exception: Entry::missing(),
security_exception: Entry::missing(),
reserved_3: Entry::missing(),
interrupts: [Entry::missing(); 256 - 32],
}
}

Expand Down
72 changes: 31 additions & 41 deletions src/structures/paging/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,17 @@ impl<S: PageSize> PhysFrame<S> {
Ok(unsafe { PhysFrame::from_start_address_unchecked(address) })
}

// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Returns the frame that starts at the given virtual address.
///
/// ## Safety
///
/// The address must be correctly aligned.
#[inline]
pub unsafe fn from_start_address_unchecked(start_address: PhysAddr) -> Self {
PhysFrame {
start_address,
size: PhantomData,
}
/// Returns the frame that starts at the given virtual address.
///
/// ## Safety
///
/// The address must be correctly aligned.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub unsafe fn from_start_address_unchecked(start_address: PhysAddr) -> Self {
PhysFrame {
start_address,
size: PhantomData,
}
}

Expand All @@ -55,40 +53,32 @@ impl<S: PageSize> PhysFrame<S> {
}
}

// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Returns the start address of the frame.
#[inline]
pub fn start_address(self) -> PhysAddr {
self.start_address
}
/// Returns the start address of the frame.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn start_address(self) -> PhysAddr {
self.start_address
}

// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Returns the size the frame (4KB, 2MB or 1GB).
#[inline]
pub fn size(self) -> u64 {
S::SIZE
}
/// Returns the size the frame (4KB, 2MB or 1GB).
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn size(self) -> u64 {
S::SIZE
}

// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Returns a range of frames, exclusive `end`.
#[inline]
pub fn range(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRange<S> {
PhysFrameRange { start, end }
}
/// Returns a range of frames, exclusive `end`.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn range(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRange<S> {
PhysFrameRange { start, end }
}

// TODO: Remove const_fn! when our minimum supported stable Rust version is 1.61
const_fn! {
/// Returns a range of frames, inclusive `end`.
#[inline]
pub fn range_inclusive(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRangeInclusive<S> {
PhysFrameRangeInclusive { start, end }
}
/// Returns a range of frames, inclusive `end`.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn range_inclusive(start: PhysFrame<S>, end: PhysFrame<S>) -> PhysFrameRangeInclusive<S> {
PhysFrameRangeInclusive { start, end }
}
}

Expand Down
Loading