Skip to content

Commit 6e961a3

Browse files
authored
Add rdfsbase, rdgsbase, wrfsbase, wrgsbase (#172)
1 parent f5c4224 commit 6e961a3

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

src/asm/asm.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,27 @@ _x86_64_asm_wrmsr:
233233
_x86_64_asm_hlt:
234234
hlt
235235
retq
236+
237+
.global _x86_64_asm_rdfsbase
238+
.p2align 4
239+
_x86_64_asm_rdfsbase:
240+
rdfsbase %rax
241+
retq
242+
243+
.global _x86_64_asm_wrfsbase
244+
.p2align 4
245+
_x86_64_asm_wrfsbase:
246+
wrfsbase %rdi
247+
retq
248+
249+
.global _x86_64_asm_rdgsbase
250+
.p2align 4
251+
_x86_64_asm_rdgsbase:
252+
rdgsbase %rax
253+
retq
254+
255+
.global _x86_64_asm_wrgsbase
256+
.p2align 4
257+
_x86_64_asm_wrgsbase:
258+
wrgsbase %rdi
259+
retq

src/asm/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,28 @@ extern "C" {
203203
link_name = "_x86_64_asm_write_rflags"
204204
)]
205205
pub(crate) fn x86_64_asm_write_rflags(val: u64);
206+
207+
#[cfg_attr(
208+
any(target_env = "gnu", target_env = "musl"),
209+
link_name = "_x86_64_asm_rdfsbase"
210+
)]
211+
pub(crate) fn x86_64_asm_rdfsbase() -> u64;
212+
213+
#[cfg_attr(
214+
any(target_env = "gnu", target_env = "musl"),
215+
link_name = "_x86_64_asm_wrfsbase"
216+
)]
217+
pub(crate) fn x86_64_asm_wrfsbase(val: u64);
218+
219+
#[cfg_attr(
220+
any(target_env = "gnu", target_env = "musl"),
221+
link_name = "_x86_64_asm_rdgsbase"
222+
)]
223+
pub(crate) fn x86_64_asm_rdgsbase() -> u64;
224+
225+
#[cfg_attr(
226+
any(target_env = "gnu", target_env = "musl"),
227+
link_name = "_x86_64_asm_wrgsbase"
228+
)]
229+
pub(crate) fn x86_64_asm_wrgsbase(val: u64);
206230
}

src/registers/mod.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,102 @@ pub fn read_rip() -> u64 {
1818
}
1919
rip
2020
}
21+
22+
/// Writes the FS segment base address
23+
///
24+
/// ## Safety
25+
///
26+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
27+
///
28+
/// The caller must ensure that this write operation has no unsafe side
29+
/// effects, as the FS segment base address is often used for thread
30+
/// local storage.
31+
#[inline]
32+
pub unsafe fn wrfsbase(val: u64) {
33+
#[cfg(feature = "inline_asm")]
34+
#[inline(always)]
35+
unsafe fn inner(val: u64) {
36+
llvm_asm!("wrfsbase $0" :: "r"(val) :: "volatile")
37+
}
38+
39+
#[cfg(not(feature = "inline_asm"))]
40+
#[inline(always)]
41+
unsafe fn inner(val: u64) {
42+
crate::asm::x86_64_asm_wrfsbase(val)
43+
}
44+
45+
inner(val)
46+
}
47+
48+
/// Reads the FS segment base address
49+
///
50+
/// ## Safety
51+
///
52+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
53+
#[inline]
54+
pub unsafe fn rdfsbase() -> u64 {
55+
#[cfg(feature = "inline_asm")]
56+
#[inline(always)]
57+
unsafe fn inner() -> u64 {
58+
let val: u64;
59+
llvm_asm!("rdfsbase $0" : "=r" (val) ::: "volatile");
60+
val
61+
}
62+
63+
#[cfg(not(feature = "inline_asm"))]
64+
#[inline(always)]
65+
unsafe fn inner() -> u64 {
66+
crate::asm::x86_64_asm_rdfsbase()
67+
}
68+
69+
inner()
70+
}
71+
72+
/// Writes the GS segment base address
73+
///
74+
/// ## Safety
75+
///
76+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
77+
///
78+
/// The caller must ensure that this write operation has no unsafe side
79+
/// effects, as the GS segment base address might be in use.
80+
#[inline]
81+
pub unsafe fn wrgsbase(val: u64) {
82+
#[cfg(feature = "inline_asm")]
83+
#[inline(always)]
84+
unsafe fn inner(val: u64) {
85+
llvm_asm!("wrgsbase $0" :: "r"(val) :: "volatile")
86+
}
87+
88+
#[cfg(not(feature = "inline_asm"))]
89+
#[inline(always)]
90+
unsafe fn inner(val: u64) {
91+
crate::asm::x86_64_asm_wrgsbase(val)
92+
}
93+
94+
inner(val)
95+
}
96+
97+
/// Reads the GS segment base address
98+
///
99+
/// ## Safety
100+
///
101+
/// If `CR4.FSGSBASE` is not set, this instruction will throw an `#UD`.
102+
#[inline]
103+
pub unsafe fn rdgsbase() -> u64 {
104+
#[cfg(feature = "inline_asm")]
105+
#[inline(always)]
106+
unsafe fn inner() -> u64 {
107+
let val: u64;
108+
llvm_asm!("rdgsbase $0" : "=r" (val) ::: "volatile");
109+
val
110+
}
111+
112+
#[cfg(not(feature = "inline_asm"))]
113+
#[inline(always)]
114+
unsafe fn inner() -> u64 {
115+
crate::asm::x86_64_asm_rdgsbase()
116+
}
117+
118+
inner()
119+
}

0 commit comments

Comments
 (0)