Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into map-ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
Freax13 committed Sep 5, 2021
2 parents 7a00802 + cd4d3c2 commit 5765c15
Show file tree
Hide file tree
Showing 31 changed files with 1,145 additions and 309 deletions.
22 changes: 15 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ jobs:
with:
command: build

- name: "Run cargo doc"
uses: actions-rs/cargo@v1
with:
command: doc

- name: "Run cargo doc for stable"
uses: actions-rs/cargo@v1
with:
command: doc
args: --no-default-features --features external_asm,instructions
if: runner.os != 'Windows'

- name: "Run cargo build for stable without instructions"
uses: actions-rs/cargo@v1
with:
Expand Down Expand Up @@ -133,14 +145,10 @@ jobs:
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_BOTTLE_SOURCE_FALLBACK: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1
- name: Install Scoop (Windows)
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
echo "$HOME\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
if: runner.os == 'Windows'
shell: pwsh
- name: Install QEMU (Windows)
run: scoop install qemu
run: |
choco install qemu --version 2021.5.5
echo "$Env:Programfiles\qemu" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
if: runner.os == 'Windows'
shell: pwsh

Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release

on:
push:
branches:
- 'master'

jobs:
release:
name: "Release"
runs-on: ubuntu-latest
timeout-minutes: 15
environment: crates_io_release

steps:
- name: "Checkout Repository"
uses: actions/checkout@v1

- name: "Install Python Libraries"
run: python -m pip install --user -r requirements.txt
working-directory: "scripts"

- name: "Run release script"
run: "python3 scripts/ci-release.py"
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8 changes: 3 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ license = "MIT/Apache-2.0"
name = "x86_64"
readme = "README.md"
repository = "https://github.com/rust-osdev/x86_64"
version = "0.14.3"
version = "0.14.4"
edition = "2018"

[dependencies]
Expand All @@ -37,13 +37,11 @@ cc = { version = "1.0.37", optional = true }
default = [ "nightly", "instructions" ]
instructions = []
external_asm = [ "cc" ]
nightly = [ "inline_asm", "const_fn", "abi_x86_interrupt" ]
nightly = [ "inline_asm", "const_fn", "abi_x86_interrupt", "doc_cfg" ]
inline_asm = []
abi_x86_interrupt = []
const_fn = []

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
doc_cfg = []

[package.metadata.release]
no-dev-version = true
Expand Down
33 changes: 32 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,43 @@
# Unreleased

# 0.14.4 – 2021-07-19

- Add `instructions::tables::sgdt` ([#279](https://github.com/rust-osdev/x86_64/pull/279))
- Improve control register bits ([#273](https://github.com/rust-osdev/x86_64/pull/273))
- Add `Cr0` bits: `EXTENSION_TYPE` (ET)
- Add `Cr4` bits:
- `KEY_LOCKER` (KL)
- `CONTROL_FLOW_ENFORCEMENT` (CET)
- `PROTECTION_KEY_SUPERVISOR` (PKS)
- Add `XCr0` bits: `BNDREG`, `BNDCSR`, `OPMASK`, `ZMM_HI256`, `HI16_ZMM`
- Add consistency checks for `XCr0` bits
- Add `SelectorErrorCode` for parsing interrupt error codes from `#TS`, `#NP`, `#SS`, and `#GP` ([#274](https://github.com/rust-osdev/x86_64/pull/274))
- Make `addr::{align_up, align_down}` const ([#270](https://github.com/rust-osdev/x86_64/pull/270))
- Make `structures::idt` available on stable Rust ([#271](https://github.com/rust-osdev/x86_64/pull/271))
- Use dummy types for the `HandlerFunc`s if the `"abi_x86_interrupt"` feature is disabled
- Add unsafe `set_handler_addr` that just takes a `VirtAddr`
- Add common abstractions for x86 Segments ([#258](https://github.com/rust-osdev/x86_64/pull/258))
- Add `SS`, `CS`, `DS`, `ES`, `FS`, `GS` marker types
- Add `Segment` trait for reading/writing the segment register
- Add `Segment64` trait for reading/writing the segment base
- Add `GS::swap()`
- Deprecate the corresponding free functions:
- `cs`, `set_cs`
- `swap_gs`
- `load_{ss,ds,es,fs,gs}`
- `{wr,rd}{fs,gs}base`
- Bug fixes:
- Corrected documentation typo ([#278](https://github.com/rust-osdev/x86_64/pull/278))
- Avoided off-by-one error in `GlobalDescriptorTable::from_raw_slice` when `"const_fn"` is not enabled ([#269](https://github.com/rust-osdev/x86_64/pull/269))
- Specify `sysv64` as the calling convention for the `"external_asm"` functions ([#267](https://github.com/rust-osdev/x86_64/pull/267))

# 0.14.3 – 2021-05-14

- Make the following types aliases of the new `PortGeneric` type ([#248](https://github.com/rust-osdev/x86_64/pull/248)):
- `Port<T> = PortGeneric<T, ReadWriteAccess>`
- `PortReadOnly<T> = PortGeneric<T, ReadOnlyAccess>`
- `PortWriteOnly<T> = PortGeneric<T, WriteOnlyAccess>`
- The following methods no longer require the `nightly` feature to be `const fn`s` ([#255](https://github.com/rust-osdev/x86_64/pull/255)):
- The following methods no longer require the `nightly` feature to be `const fn`s ([#255](https://github.com/rust-osdev/x86_64/pull/255)):
- `PageTable::new`
- `GlobalDescriptorTable::from_raw_slice`
- `MappedFrame::{start_address, size}`
Expand Down
36 changes: 36 additions & 0 deletions scripts/ci-release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import toml
import requests
import subprocess

cargo_toml = toml.load("Cargo.toml")
crate_version = cargo_toml["package"]["version"]
print("Detected crate version " + crate_version)

api_url = "https://crates.io/api/v1/crates/x86_64/" + crate_version
released_version = requests.get(api_url).json()

if "version" in released_version:
version = released_version["version"]
assert (version["crate"] == "x86_64")
assert (version["num"] == crate_version)
print("Version " + crate_version + " already exists on crates.io")

else:
print("Could not find version " + crate_version +
" on crates.io; creating a new release")

print(" Running `cargo publish`")
subprocess.run(["cargo", "publish"], check=True)

tag_name = "v" + crate_version
print(" Tagging commit as " + tag_name)
sha = subprocess.run(["git", "rev-parse", "HEAD"], check=True,
stdout=subprocess.PIPE).stdout.decode("utf-8").strip()
subprocess.run([
"gh", "api", "/repos/rust-osdev/x86_64/git/refs",
"-X", "POST", "-H", "Accept: application/vnd.github.v3+json",
"-F", "ref=refs/tags/" + tag_name,
"-F", "sha="+sha
])

print(" Done")
1 change: 1 addition & 0 deletions scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
toml
27 changes: 19 additions & 8 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use core::fmt;
use core::ops::{Add, AddAssign, Sub, SubAssign};

use crate::structures::paging::page_table::PageTableLevel;
use crate::structures::paging::{PageOffset, PageTableIndex};
use bit_field::BitField;

Expand Down Expand Up @@ -198,6 +199,12 @@ impl VirtAddr {
pub const fn p4_index(self) -> PageTableIndex {
PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9 >> 9) as u16)
}

/// Returns the 9-bit level page table index.
#[inline]
pub const fn page_table_index(self, level: PageTableLevel) -> PageTableIndex {
PageTableIndex::new_truncate((self.0 >> 12 >> ((level as u8 - 1) * 9)) as u16)
}
}

impl fmt::Debug for VirtAddr {
Expand Down Expand Up @@ -531,21 +538,25 @@ impl Sub<PhysAddr> for PhysAddr {

/// Align address downwards.
///
/// Returns the greatest x with alignment `align` so that x <= addr. The alignment must be
/// a power of 2.
/// 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".
#[inline]
pub fn align_down(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
pub const fn align_down(addr: u64, align: u64) -> u64 {
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
addr & !(align - 1)
}

/// Align address upwards.
///
/// Returns the smallest x with alignment `align` so that x >= addr. The alignment must be
/// a power of 2.
/// 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".
#[inline]
pub fn align_up(addr: u64, align: u64) -> u64 {
assert!(align.is_power_of_two(), "`align` must be a power of two");
pub const fn align_up(addr: u64, align: u64) -> u64 {
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
let align_mask = align - 1;
if addr & align_mask == 0 {
addr // already aligned
Expand Down
36 changes: 36 additions & 0 deletions src/asm/asm.s
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ _x86_64_asm_lidt:
lidt (%rdi)
retq

.global _x86_64_asm_sgdt
.p2align 4
_x86_64_asm_sgdt:
sgdt (%rdi)
retq

.global _x86_64_asm_sidt
.p2align 4
_x86_64_asm_sidt:
Expand Down Expand Up @@ -173,6 +179,36 @@ _x86_64_asm_load_gs:
mov %di, %gs
retq

.global _x86_64_asm_get_ss
.p2align 4
_x86_64_asm_get_ss:
mov %ss, %ax
retq

.global _x86_64_asm_get_ds
.p2align 4
_x86_64_asm_get_ds:
mov %ds, %ax
retq

.global _x86_64_asm_get_es
.p2align 4
_x86_64_asm_get_es:
mov %es, %ax
retq

.global _x86_64_asm_get_fs
.p2align 4
_x86_64_asm_get_fs:
mov %fs, %ax
retq

.global _x86_64_asm_get_gs
.p2align 4
_x86_64_asm_get_gs:
mov %gs, %ax
retq

.global _x86_64_asm_swapgs
.p2align 4
_x86_64_asm_swapgs:
Expand Down
38 changes: 37 additions & 1 deletion src/asm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[link(name = "x86_64_asm", kind = "static")]
extern "C" {
extern "sysv64" {
#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_interrupt_enable"
Expand Down Expand Up @@ -114,6 +114,36 @@ extern "C" {
)]
pub(crate) fn x86_64_asm_load_gs(sel: u16);

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_get_ss"
)]
pub(crate) fn x86_64_asm_get_ss() -> u16;

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_get_ds"
)]
pub(crate) fn x86_64_asm_get_ds() -> u16;

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_get_es"
)]
pub(crate) fn x86_64_asm_get_es() -> u16;

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_get_fs"
)]
pub(crate) fn x86_64_asm_get_fs() -> u16;

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_get_gs"
)]
pub(crate) fn x86_64_asm_get_gs() -> u16;

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_swapgs"
Expand All @@ -138,6 +168,12 @@ extern "C" {
)]
pub(crate) fn x86_64_asm_lidt(idt: *const crate::instructions::tables::DescriptorTablePointer);

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_sgdt"
)]
pub(crate) fn x86_64_asm_sgdt(gdt: *mut crate::instructions::tables::DescriptorTablePointer);

#[cfg_attr(
any(target_env = "gnu", target_env = "musl"),
link_name = "_x86_64_asm_sidt"
Expand Down
21 changes: 12 additions & 9 deletions src/instructions/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,17 @@ pub fn int3() {

/// Generate a software interrupt by invoking the `int` instruction.
///
/// ## Safety
///
/// Invoking an arbitrary interrupt is unsafe. It can cause your system to
/// crash if you invoke a double-fault (#8) or machine-check (#18) exception.
/// It can also cause memory/register corruption depending on the interrupt
/// implementation (if it expects values/pointers to be passed in registers).
/// This currently needs to be a macro because the `int` argument needs to be an
/// immediate. This macro will be replaced by a generic function when support for
/// const generics is implemented in Rust.
#[cfg(feature = "inline_asm")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "nightly", feature = "inline_asm"))))]
pub unsafe fn software_interrupt<const NUM: u8>() {
asm!("int {num}", num = const NUM, options(nomem, nostack));
#[cfg_attr(
feature = "doc_cfg",
doc(cfg(any(feature = "nightly", feature = "inline_asm")))
)]
#[macro_export]
macro_rules! software_interrupt {
($x:expr) => {{
asm!("int {id}", id = const $x, options(nomem, nostack));
}};
}
5 changes: 4 additions & 1 deletion src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ pub fn bochs_breakpoint() {
/// Gets the current instruction pointer. Note that this is only approximate as it requires a few
/// instructions to execute.
#[cfg(feature = "inline_asm")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "nightly", feature = "inline_asm"))))]
#[cfg_attr(
feature = "doc_cfg",
doc(cfg(any(feature = "nightly", feature = "inline_asm")))
)]
#[inline(always)]
pub fn read_rip() -> crate::VirtAddr {
let rip: u64;
Expand Down
Loading

0 comments on commit 5765c15

Please sign in to comment.