Skip to content

Commit dbeb826

Browse files
committed
Merge branch 'master' into next
2 parents 00b5634 + bd471fa commit dbeb826

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

Changelog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
- **Breaking:** Remove `PortReadWrite` trait, which is no longer needed ([#217](https://github.com/rust-osdev/x86_64/pull/217))
1818
- Relaxe `Sized` requirement for `FrameAllocator` in `Mapper::map_to` ([204](https://github.com/rust-osdev/x86_64/pull/204))
1919

20+
# 0.12.4 – 2020-12-28
21+
22+
- Fix bad conversion from llvm_asm! to asm! ([#218](https://github.com/rust-osdev/x86_64/pull/218))
23+
- GDT: Add `load_unchecked`, `from_raw_slice`, and `as_raw_slice` ([#210](https://github.com/rust-osdev/x86_64/pull/210))
24+
2025
# 0.12.3 – 2020-10-31
2126

2227
- Use `asm!` instead of perma-unstable `llvm_asm!` macro ([#165](https://github.com/rust-osdev/x86_64/pull/165))

src/instructions/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn nop() {
5050
#[inline]
5151
pub fn bochs_breakpoint() {
5252
unsafe {
53-
asm!("xchgw bx, bx", options(nomem, nostack));
53+
asm!("xchg bx, bx", options(nomem, nostack));
5454
}
5555
}
5656

src/structures/gdt.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,40 @@ impl GlobalDescriptorTable {
108108
}
109109
}
110110

111+
/// Forms a GDT from a slice of `u64`.
112+
///
113+
/// # Safety
114+
///
115+
/// * The user must make sure that the entries are well formed
116+
/// * The provided slice **must not be larger than 8 items** (only up to the first 8 will be observed.)
117+
#[inline]
118+
#[cfg(feature = "const_fn")]
119+
pub const unsafe fn from_raw_slice(slice: &[u64]) -> GlobalDescriptorTable {
120+
assert!(
121+
slice.len() <= 8,
122+
"initializing a GDT from a slice requires it to be **at most** 8 elements."
123+
);
124+
let next_free = slice.len();
125+
126+
let mut table = [0; 8];
127+
let mut idx = 0;
128+
129+
while idx != next_free {
130+
table[idx] = slice[idx];
131+
idx += 1;
132+
}
133+
134+
GlobalDescriptorTable { table, next_free }
135+
}
136+
137+
/// Get a reference to the internal table.
138+
///
139+
/// The resulting slice may contain system descriptors, which span two `u64`s.
140+
#[inline]
141+
pub fn as_raw_slice(&self) -> &[u64] {
142+
&self.table[..self.next_free]
143+
}
144+
111145
const_fn! {
112146
/// Adds the given segment descriptor to the GDT, returning the segment selector.
113147
///
@@ -147,9 +181,27 @@ impl GlobalDescriptorTable {
147181
#[cfg(feature = "instructions")]
148182
#[inline]
149183
pub fn load(&'static self) {
150-
use crate::instructions::tables::lgdt;
151184
// SAFETY: static lifetime ensures no modification after loading.
152-
unsafe { lgdt(&self.pointer()) };
185+
unsafe { self.load_unsafe() };
186+
}
187+
188+
/// Loads the GDT in the CPU using the `lgdt` instruction. This does **not** alter any of the
189+
/// segment registers; you **must** (re)load them yourself using [the appropriate
190+
/// functions](crate::instructions::segmentation):
191+
/// [load_ss](crate::instructions::segmentation::load_ss),
192+
/// [set_cs](crate::instructions::segmentation::set_cs).
193+
///
194+
/// # Safety
195+
///
196+
/// Unlike `load` this function will not impose a static lifetime constraint
197+
/// this means its up to the user to ensure that there will be no modifications
198+
/// after loading and that the GDT will live for as long as it's loaded.
199+
///
200+
#[cfg(feature = "instructions")]
201+
#[inline]
202+
pub unsafe fn load_unsafe(&self) {
203+
use crate::instructions::tables::lgdt;
204+
lgdt(&self.pointer());
153205
}
154206

155207
const_fn! {

0 commit comments

Comments
 (0)