Skip to content

Commit 5765c15

Browse files
committed
Merge remote-tracking branch 'upstream/master' into map-ranges
2 parents 7a00802 + cd4d3c2 commit 5765c15

31 files changed

+1145
-309
lines changed

.github/workflows/build.yml

+15-7
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ jobs:
6565
with:
6666
command: build
6767

68+
- name: "Run cargo doc"
69+
uses: actions-rs/cargo@v1
70+
with:
71+
command: doc
72+
73+
- name: "Run cargo doc for stable"
74+
uses: actions-rs/cargo@v1
75+
with:
76+
command: doc
77+
args: --no-default-features --features external_asm,instructions
78+
if: runner.os != 'Windows'
79+
6880
- name: "Run cargo build for stable without instructions"
6981
uses: actions-rs/cargo@v1
7082
with:
@@ -133,14 +145,10 @@ jobs:
133145
HOMEBREW_NO_AUTO_UPDATE: 1
134146
HOMEBREW_NO_BOTTLE_SOURCE_FALLBACK: 1
135147
HOMEBREW_NO_INSTALL_CLEANUP: 1
136-
- name: Install Scoop (Windows)
137-
run: |
138-
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
139-
echo "$HOME\scoop\shims" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
140-
if: runner.os == 'Windows'
141-
shell: pwsh
142148
- name: Install QEMU (Windows)
143-
run: scoop install qemu
149+
run: |
150+
choco install qemu --version 2021.5.5
151+
echo "$Env:Programfiles\qemu" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
144152
if: runner.os == 'Windows'
145153
shell: pwsh
146154

.github/workflows/release.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- 'master'
7+
8+
jobs:
9+
release:
10+
name: "Release"
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 15
13+
environment: crates_io_release
14+
15+
steps:
16+
- name: "Checkout Repository"
17+
uses: actions/checkout@v1
18+
19+
- name: "Install Python Libraries"
20+
run: python -m pip install --user -r requirements.txt
21+
working-directory: "scripts"
22+
23+
- name: "Run release script"
24+
run: "python3 scripts/ci-release.py"
25+
env:
26+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
27+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Cargo.toml

+3-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ license = "MIT/Apache-2.0"
2222
name = "x86_64"
2323
readme = "README.md"
2424
repository = "https://github.com/rust-osdev/x86_64"
25-
version = "0.14.3"
25+
version = "0.14.4"
2626
edition = "2018"
2727

2828
[dependencies]
@@ -37,13 +37,11 @@ cc = { version = "1.0.37", optional = true }
3737
default = [ "nightly", "instructions" ]
3838
instructions = []
3939
external_asm = [ "cc" ]
40-
nightly = [ "inline_asm", "const_fn", "abi_x86_interrupt" ]
40+
nightly = [ "inline_asm", "const_fn", "abi_x86_interrupt", "doc_cfg" ]
4141
inline_asm = []
4242
abi_x86_interrupt = []
4343
const_fn = []
44-
45-
[package.metadata.docs.rs]
46-
rustdoc-args = ["--cfg", "docsrs"]
44+
doc_cfg = []
4745

4846
[package.metadata.release]
4947
no-dev-version = true

Changelog.md

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,43 @@
11
# Unreleased
22

3+
# 0.14.4 – 2021-07-19
4+
5+
- Add `instructions::tables::sgdt` ([#279](https://github.com/rust-osdev/x86_64/pull/279))
6+
- Improve control register bits ([#273](https://github.com/rust-osdev/x86_64/pull/273))
7+
- Add `Cr0` bits: `EXTENSION_TYPE` (ET)
8+
- Add `Cr4` bits:
9+
- `KEY_LOCKER` (KL)
10+
- `CONTROL_FLOW_ENFORCEMENT` (CET)
11+
- `PROTECTION_KEY_SUPERVISOR` (PKS)
12+
- Add `XCr0` bits: `BNDREG`, `BNDCSR`, `OPMASK`, `ZMM_HI256`, `HI16_ZMM`
13+
- Add consistency checks for `XCr0` bits
14+
- Add `SelectorErrorCode` for parsing interrupt error codes from `#TS`, `#NP`, `#SS`, and `#GP` ([#274](https://github.com/rust-osdev/x86_64/pull/274))
15+
- Make `addr::{align_up, align_down}` const ([#270](https://github.com/rust-osdev/x86_64/pull/270))
16+
- Make `structures::idt` available on stable Rust ([#271](https://github.com/rust-osdev/x86_64/pull/271))
17+
- Use dummy types for the `HandlerFunc`s if the `"abi_x86_interrupt"` feature is disabled
18+
- Add unsafe `set_handler_addr` that just takes a `VirtAddr`
19+
- Add common abstractions for x86 Segments ([#258](https://github.com/rust-osdev/x86_64/pull/258))
20+
- Add `SS`, `CS`, `DS`, `ES`, `FS`, `GS` marker types
21+
- Add `Segment` trait for reading/writing the segment register
22+
- Add `Segment64` trait for reading/writing the segment base
23+
- Add `GS::swap()`
24+
- Deprecate the corresponding free functions:
25+
- `cs`, `set_cs`
26+
- `swap_gs`
27+
- `load_{ss,ds,es,fs,gs}`
28+
- `{wr,rd}{fs,gs}base`
29+
- Bug fixes:
30+
- Corrected documentation typo ([#278](https://github.com/rust-osdev/x86_64/pull/278))
31+
- 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))
32+
- Specify `sysv64` as the calling convention for the `"external_asm"` functions ([#267](https://github.com/rust-osdev/x86_64/pull/267))
33+
334
# 0.14.3 – 2021-05-14
435

536
- Make the following types aliases of the new `PortGeneric` type ([#248](https://github.com/rust-osdev/x86_64/pull/248)):
637
- `Port<T> = PortGeneric<T, ReadWriteAccess>`
738
- `PortReadOnly<T> = PortGeneric<T, ReadOnlyAccess>`
839
- `PortWriteOnly<T> = PortGeneric<T, WriteOnlyAccess>`
9-
- The following methods no longer require the `nightly` feature to be `const fn`s` ([#255](https://github.com/rust-osdev/x86_64/pull/255)):
40+
- The following methods no longer require the `nightly` feature to be `const fn`s ([#255](https://github.com/rust-osdev/x86_64/pull/255)):
1041
- `PageTable::new`
1142
- `GlobalDescriptorTable::from_raw_slice`
1243
- `MappedFrame::{start_address, size}`

scripts/ci-release.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import toml
2+
import requests
3+
import subprocess
4+
5+
cargo_toml = toml.load("Cargo.toml")
6+
crate_version = cargo_toml["package"]["version"]
7+
print("Detected crate version " + crate_version)
8+
9+
api_url = "https://crates.io/api/v1/crates/x86_64/" + crate_version
10+
released_version = requests.get(api_url).json()
11+
12+
if "version" in released_version:
13+
version = released_version["version"]
14+
assert (version["crate"] == "x86_64")
15+
assert (version["num"] == crate_version)
16+
print("Version " + crate_version + " already exists on crates.io")
17+
18+
else:
19+
print("Could not find version " + crate_version +
20+
" on crates.io; creating a new release")
21+
22+
print(" Running `cargo publish`")
23+
subprocess.run(["cargo", "publish"], check=True)
24+
25+
tag_name = "v" + crate_version
26+
print(" Tagging commit as " + tag_name)
27+
sha = subprocess.run(["git", "rev-parse", "HEAD"], check=True,
28+
stdout=subprocess.PIPE).stdout.decode("utf-8").strip()
29+
subprocess.run([
30+
"gh", "api", "/repos/rust-osdev/x86_64/git/refs",
31+
"-X", "POST", "-H", "Accept: application/vnd.github.v3+json",
32+
"-F", "ref=refs/tags/" + tag_name,
33+
"-F", "sha="+sha
34+
])
35+
36+
print(" Done")

scripts/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
toml

src/addr.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use core::fmt;
44
use core::ops::{Add, AddAssign, Sub, SubAssign};
55

6+
use crate::structures::paging::page_table::PageTableLevel;
67
use crate::structures::paging::{PageOffset, PageTableIndex};
78
use bit_field::BitField;
89

@@ -198,6 +199,12 @@ impl VirtAddr {
198199
pub const fn p4_index(self) -> PageTableIndex {
199200
PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9 >> 9) as u16)
200201
}
202+
203+
/// Returns the 9-bit level page table index.
204+
#[inline]
205+
pub const fn page_table_index(self, level: PageTableLevel) -> PageTableIndex {
206+
PageTableIndex::new_truncate((self.0 >> 12 >> ((level as u8 - 1) * 9)) as u16)
207+
}
201208
}
202209

203210
impl fmt::Debug for VirtAddr {
@@ -531,21 +538,25 @@ impl Sub<PhysAddr> for PhysAddr {
531538

532539
/// Align address downwards.
533540
///
534-
/// Returns the greatest x with alignment `align` so that x <= addr. The alignment must be
535-
/// a power of 2.
541+
/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
542+
///
543+
/// Panics if the alignment is not a power of two. Without the `const_fn`
544+
/// feature, the panic message will be "index out of bounds".
536545
#[inline]
537-
pub fn align_down(addr: u64, align: u64) -> u64 {
538-
assert!(align.is_power_of_two(), "`align` must be a power of two");
546+
pub const fn align_down(addr: u64, align: u64) -> u64 {
547+
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
539548
addr & !(align - 1)
540549
}
541550

542551
/// Align address upwards.
543552
///
544-
/// Returns the smallest x with alignment `align` so that x >= addr. The alignment must be
545-
/// a power of 2.
553+
/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
554+
///
555+
/// Panics if the alignment is not a power of two. Without the `const_fn`
556+
/// feature, the panic message will be "index out of bounds".
546557
#[inline]
547-
pub fn align_up(addr: u64, align: u64) -> u64 {
548-
assert!(align.is_power_of_two(), "`align` must be a power of two");
558+
pub const fn align_up(addr: u64, align: u64) -> u64 {
559+
const_assert!(align.is_power_of_two(), "`align` must be a power of two");
549560
let align_mask = align - 1;
550561
if addr & align_mask == 0 {
551562
addr // already aligned

src/asm/asm.s

+36
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ _x86_64_asm_lidt:
123123
lidt (%rdi)
124124
retq
125125

126+
.global _x86_64_asm_sgdt
127+
.p2align 4
128+
_x86_64_asm_sgdt:
129+
sgdt (%rdi)
130+
retq
131+
126132
.global _x86_64_asm_sidt
127133
.p2align 4
128134
_x86_64_asm_sidt:
@@ -173,6 +179,36 @@ _x86_64_asm_load_gs:
173179
mov %di, %gs
174180
retq
175181

182+
.global _x86_64_asm_get_ss
183+
.p2align 4
184+
_x86_64_asm_get_ss:
185+
mov %ss, %ax
186+
retq
187+
188+
.global _x86_64_asm_get_ds
189+
.p2align 4
190+
_x86_64_asm_get_ds:
191+
mov %ds, %ax
192+
retq
193+
194+
.global _x86_64_asm_get_es
195+
.p2align 4
196+
_x86_64_asm_get_es:
197+
mov %es, %ax
198+
retq
199+
200+
.global _x86_64_asm_get_fs
201+
.p2align 4
202+
_x86_64_asm_get_fs:
203+
mov %fs, %ax
204+
retq
205+
206+
.global _x86_64_asm_get_gs
207+
.p2align 4
208+
_x86_64_asm_get_gs:
209+
mov %gs, %ax
210+
retq
211+
176212
.global _x86_64_asm_swapgs
177213
.p2align 4
178214
_x86_64_asm_swapgs:

src/asm/mod.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[link(name = "x86_64_asm", kind = "static")]
2-
extern "C" {
2+
extern "sysv64" {
33
#[cfg_attr(
44
any(target_env = "gnu", target_env = "musl"),
55
link_name = "_x86_64_asm_interrupt_enable"
@@ -114,6 +114,36 @@ extern "C" {
114114
)]
115115
pub(crate) fn x86_64_asm_load_gs(sel: u16);
116116

117+
#[cfg_attr(
118+
any(target_env = "gnu", target_env = "musl"),
119+
link_name = "_x86_64_asm_get_ss"
120+
)]
121+
pub(crate) fn x86_64_asm_get_ss() -> u16;
122+
123+
#[cfg_attr(
124+
any(target_env = "gnu", target_env = "musl"),
125+
link_name = "_x86_64_asm_get_ds"
126+
)]
127+
pub(crate) fn x86_64_asm_get_ds() -> u16;
128+
129+
#[cfg_attr(
130+
any(target_env = "gnu", target_env = "musl"),
131+
link_name = "_x86_64_asm_get_es"
132+
)]
133+
pub(crate) fn x86_64_asm_get_es() -> u16;
134+
135+
#[cfg_attr(
136+
any(target_env = "gnu", target_env = "musl"),
137+
link_name = "_x86_64_asm_get_fs"
138+
)]
139+
pub(crate) fn x86_64_asm_get_fs() -> u16;
140+
141+
#[cfg_attr(
142+
any(target_env = "gnu", target_env = "musl"),
143+
link_name = "_x86_64_asm_get_gs"
144+
)]
145+
pub(crate) fn x86_64_asm_get_gs() -> u16;
146+
117147
#[cfg_attr(
118148
any(target_env = "gnu", target_env = "musl"),
119149
link_name = "_x86_64_asm_swapgs"
@@ -138,6 +168,12 @@ extern "C" {
138168
)]
139169
pub(crate) fn x86_64_asm_lidt(idt: *const crate::instructions::tables::DescriptorTablePointer);
140170

171+
#[cfg_attr(
172+
any(target_env = "gnu", target_env = "musl"),
173+
link_name = "_x86_64_asm_sgdt"
174+
)]
175+
pub(crate) fn x86_64_asm_sgdt(gdt: *mut crate::instructions::tables::DescriptorTablePointer);
176+
141177
#[cfg_attr(
142178
any(target_env = "gnu", target_env = "musl"),
143179
link_name = "_x86_64_asm_sidt"

src/instructions/interrupts.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,17 @@ pub fn int3() {
149149

150150
/// Generate a software interrupt by invoking the `int` instruction.
151151
///
152-
/// ## Safety
153-
///
154-
/// Invoking an arbitrary interrupt is unsafe. It can cause your system to
155-
/// crash if you invoke a double-fault (#8) or machine-check (#18) exception.
156-
/// It can also cause memory/register corruption depending on the interrupt
157-
/// implementation (if it expects values/pointers to be passed in registers).
152+
/// This currently needs to be a macro because the `int` argument needs to be an
153+
/// immediate. This macro will be replaced by a generic function when support for
154+
/// const generics is implemented in Rust.
158155
#[cfg(feature = "inline_asm")]
159-
#[cfg_attr(docsrs, doc(cfg(any(feature = "nightly", feature = "inline_asm"))))]
160-
pub unsafe fn software_interrupt<const NUM: u8>() {
161-
asm!("int {num}", num = const NUM, options(nomem, nostack));
156+
#[cfg_attr(
157+
feature = "doc_cfg",
158+
doc(cfg(any(feature = "nightly", feature = "inline_asm")))
159+
)]
160+
#[macro_export]
161+
macro_rules! software_interrupt {
162+
($x:expr) => {{
163+
asm!("int {id}", id = const $x, options(nomem, nostack));
164+
}};
162165
}

src/instructions/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ pub fn bochs_breakpoint() {
5454
/// Gets the current instruction pointer. Note that this is only approximate as it requires a few
5555
/// instructions to execute.
5656
#[cfg(feature = "inline_asm")]
57-
#[cfg_attr(docsrs, doc(cfg(any(feature = "nightly", feature = "inline_asm"))))]
57+
#[cfg_attr(
58+
feature = "doc_cfg",
59+
doc(cfg(any(feature = "nightly", feature = "inline_asm")))
60+
)]
5861
#[inline(always)]
5962
pub fn read_rip() -> crate::VirtAddr {
6063
let rip: u64;

0 commit comments

Comments
 (0)