Skip to content

Commit 58d783e

Browse files
committed
Add more ## Safety comments to docs
1 parent 2456019 commit 58d783e

File tree

8 files changed

+143
-21
lines changed

8 files changed

+143
-21
lines changed

src/instructions/port.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ impl<T: PortRead> PortReadOnly<T> {
134134

135135
/// Reads from the port.
136136
///
137+
/// ## Safety
138+
///
137139
/// This function is unsafe because the I/O port could have side effects that violate memory
138140
/// safety.
139141
#[inline]
@@ -163,6 +165,8 @@ impl<T: PortWrite> PortWriteOnly<T> {
163165

164166
/// Writes to the port.
165167
///
168+
/// ## Safety
169+
///
166170
/// This function is unsafe because the I/O port could have side effects that violate memory
167171
/// safety.
168172
#[inline]
@@ -192,6 +196,8 @@ impl<T: PortReadWrite> Port<T> {
192196

193197
/// Reads from the port.
194198
///
199+
/// ## Safety
200+
///
195201
/// This function is unsafe because the I/O port could have side effects that violate memory
196202
/// safety.
197203
#[inline]
@@ -201,6 +207,8 @@ impl<T: PortReadWrite> Port<T> {
201207

202208
/// Writes to the port.
203209
///
210+
/// ## Safety
211+
///
204212
/// This function is unsafe because the I/O port could have side effects that violate memory
205213
/// safety.
206214
#[inline]

src/instructions/segmentation.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ use crate::structures::gdt::SegmentSelector;
88
/// to %cs. Instead we push the new segment selector
99
/// and return value on the stack and use lretq
1010
/// to reload cs and continue at 1:.
11+
///
12+
/// ## Safety
13+
///
14+
/// This function is unsafe because the caller must ensure that `sel`
15+
/// is a valid code segment descriptor.
1116
pub unsafe fn set_cs(sel: SegmentSelector) {
1217
#[cfg(feature = "inline_asm")]
1318
#[inline(always)]
@@ -29,6 +34,11 @@ pub unsafe fn set_cs(sel: SegmentSelector) {
2934
}
3035

3136
/// Reload stack segment register.
37+
///
38+
/// ## Safety
39+
///
40+
/// This function is unsafe because the caller must ensure that `sel`
41+
/// is a valid stack segment descriptor.
3242
#[inline]
3343
pub unsafe fn load_ss(sel: SegmentSelector) {
3444
#[cfg(feature = "inline_asm")]
@@ -39,6 +49,11 @@ pub unsafe fn load_ss(sel: SegmentSelector) {
3949
}
4050

4151
/// Reload data segment register.
52+
///
53+
/// ## Safety
54+
///
55+
/// This function is unsafe because the caller must ensure that `sel`
56+
/// is a valid data segment descriptor.
4257
#[inline]
4358
pub unsafe fn load_ds(sel: SegmentSelector) {
4459
#[cfg(feature = "inline_asm")]
@@ -49,6 +64,11 @@ pub unsafe fn load_ds(sel: SegmentSelector) {
4964
}
5065

5166
/// Reload es segment register.
67+
///
68+
/// ## Safety
69+
///
70+
/// This function is unsafe because the caller must ensure that `sel`
71+
/// is a valid extra segment descriptor.
5272
#[inline]
5373
pub unsafe fn load_es(sel: SegmentSelector) {
5474
#[cfg(feature = "inline_asm")]
@@ -59,6 +79,11 @@ pub unsafe fn load_es(sel: SegmentSelector) {
5979
}
6080

6181
/// Reload fs segment register.
82+
///
83+
/// ## Safety
84+
///
85+
/// This function is unsafe because the caller must ensure that `sel`
86+
/// is a valid fs segment descriptor.
6287
#[inline]
6388
pub unsafe fn load_fs(sel: SegmentSelector) {
6489
#[cfg(feature = "inline_asm")]
@@ -69,6 +94,11 @@ pub unsafe fn load_fs(sel: SegmentSelector) {
6994
}
7095

7196
/// Reload gs segment register.
97+
///
98+
/// ## Safety
99+
///
100+
/// This function is unsafe because the caller must ensure that `sel`
101+
/// is a valid gs segment descriptor.
72102
#[inline]
73103
pub unsafe fn load_gs(sel: SegmentSelector) {
74104
#[cfg(feature = "inline_asm")]
@@ -79,6 +109,11 @@ pub unsafe fn load_gs(sel: SegmentSelector) {
79109
}
80110

81111
/// Swap `KernelGsBase` MSR and `GsBase` MSR.
112+
///
113+
/// ## Safety
114+
///
115+
/// This function is unsafe because the caller must ensure that the
116+
/// swap operation cannot lead to undefined behavior.
82117
#[inline]
83118
pub unsafe fn swap_gs() {
84119
#[cfg(feature = "inline_asm")]

src/instructions/tables.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@ use crate::structures::gdt::SegmentSelector;
44

55
pub use crate::structures::DescriptorTablePointer;
66

7-
/// Load a GDT. Use the
7+
/// Load a GDT.
8+
///
9+
/// Use the
810
/// [`GlobalDescriptorTable`](crate::structures::gdt::GlobalDescriptorTable) struct for a high-level
911
/// interface to loading a GDT.
12+
///
13+
/// ## Safety
14+
///
15+
/// This function is unsafe because the caller must ensure that the given
16+
/// `DescriptorTablePointer` points to a valid GDT and that loading this
17+
/// GDT is safe.
1018
#[inline]
1119
pub unsafe fn lgdt(gdt: &DescriptorTablePointer) {
1220
#[cfg(feature = "inline_asm")]
@@ -16,9 +24,17 @@ pub unsafe fn lgdt(gdt: &DescriptorTablePointer) {
1624
crate::asm::x86_64_asm_lgdt(gdt as *const _);
1725
}
1826

19-
/// Load an IDT. Use the
27+
/// Load an IDT.
28+
///
29+
/// Use the
2030
/// [`InterruptDescriptorTable`](crate::structures::idt::InterruptDescriptorTable) struct for a high-level
2131
/// interface to loading an IDT.
32+
///
33+
/// ## Safety
34+
///
35+
/// This function is unsafe because the caller must ensure that the given
36+
/// `DescriptorTablePointer` points to a valid IDT and that loading this
37+
/// IDT is safe.
2238
#[inline]
2339
pub unsafe fn lidt(idt: &DescriptorTablePointer) {
2440
#[cfg(feature = "inline_asm")]
@@ -29,6 +45,12 @@ pub unsafe fn lidt(idt: &DescriptorTablePointer) {
2945
}
3046

3147
/// Load the task state register using the `ltr` instruction.
48+
///
49+
/// ## Safety
50+
///
51+
/// This function is unsafe because the caller must ensure that the given
52+
/// `SegmentSelector` points to a valid TSS entry in the GDT and that loading
53+
/// this TSS is safe.
3254
#[inline]
3355
pub unsafe fn load_tss(sel: SegmentSelector) {
3456
#[cfg(feature = "inline_asm")]

src/registers/control.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,12 @@ mod x86_64 {
158158

159159
/// Write CR0 flags.
160160
///
161-
/// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
162-
/// safety by e.g. disabling paging.
161+
/// Preserves the value of reserved fields.
162+
///
163+
/// ## Safety
164+
///
165+
/// This function is unsafe because it's possible to violate memory
166+
/// safety through it, e.g. by disabling paging.
163167
#[inline]
164168
pub unsafe fn write(flags: Cr0Flags) {
165169
let old_value = Self::read_raw();
@@ -171,8 +175,12 @@ mod x86_64 {
171175

172176
/// Write raw CR0 flags.
173177
///
174-
/// Does _not_ preserve any values, including reserved fields. Unsafe because it's possible to violate memory
175-
/// safety by e.g. disabling paging.
178+
/// Does _not_ preserve any values, including reserved fields.
179+
///
180+
/// ## Safety
181+
///
182+
/// This function is unsafe because it's possible to violate memory
183+
/// safety through it, e.g. by disabling paging.
176184
#[inline]
177185
pub unsafe fn write_raw(value: u64) {
178186
#[cfg(feature = "inline_asm")]
@@ -184,8 +192,12 @@ mod x86_64 {
184192

185193
/// Updates CR0 flags.
186194
///
187-
/// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
188-
/// safety by e.g. disabling paging.
195+
/// Preserves the value of reserved fields.
196+
///
197+
/// ## Safety
198+
///
199+
/// This function is unsafe because it's possible to violate memory
200+
/// safety through it, e.g. by disabling paging.
189201
#[inline]
190202
pub unsafe fn update<F>(f: F)
191203
where
@@ -283,8 +295,13 @@ mod x86_64 {
283295

284296
/// Write CR4 flags.
285297
///
286-
/// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
287-
/// safety by e.g. physical address extension.
298+
/// Preserves the value of reserved fields.
299+
///
300+
/// ## Safety
301+
///
302+
/// This function is unsafe because it's possible to violate memory
303+
/// safety through it, e.g. by overwriting the physical address extension
304+
/// flag.
288305
#[inline]
289306
pub unsafe fn write(flags: Cr4Flags) {
290307
let old_value = Self::read_raw();
@@ -296,8 +313,13 @@ mod x86_64 {
296313

297314
/// Write raw CR4 flags.
298315
///
299-
/// Does _not_ preserve any values, including reserved fields. Unsafe because it's possible to violate memory
300-
/// safety by e.g. physical address extension.
316+
/// Does _not_ preserve any values, including reserved fields.
317+
///
318+
/// ## Safety
319+
///
320+
/// This function is unsafe because it's possible to violate memory
321+
/// safety through it, e.g. by overwriting the physical address extension
322+
/// flag.
301323
#[inline]
302324
pub unsafe fn write_raw(value: u64) {
303325
#[cfg(feature = "inline_asm")]
@@ -309,8 +331,12 @@ mod x86_64 {
309331

310332
/// Updates CR4 flags.
311333
///
312-
/// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
313-
/// safety by e.g. physical address extension.
334+
/// Preserves the value of reserved fields.
335+
/// ## Safety
336+
///
337+
/// This function is unsafe because it's possible to violate memory
338+
/// safety through it, e.g. by overwriting the physical address extension
339+
/// flag.
314340
#[inline]
315341
pub unsafe fn update<F>(f: F)
316342
where

src/registers/model_specific.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ mod x86_64 {
110110

111111
impl Msr {
112112
/// Read 64 bits msr register.
113+
///
114+
/// ## Safety
115+
///
116+
/// The caller must ensure that this read operation has no unsafe side
117+
/// effects.
113118
#[inline]
114119
pub unsafe fn read(&self) -> u64 {
115120
#[cfg(feature = "inline_asm")]
@@ -124,6 +129,11 @@ mod x86_64 {
124129
}
125130

126131
/// Write 64 bits to msr register.
132+
///
133+
/// ## Safety
134+
///
135+
/// The caller must ensure that this write operation has no unsafe side
136+
/// effects.
127137
#[inline]
128138
pub unsafe fn write(&mut self, value: u64) {
129139
#[cfg(feature = "inline_asm")]
@@ -153,8 +163,12 @@ mod x86_64 {
153163

154164
/// Write the EFER flags, preserving reserved values.
155165
///
156-
/// Preserves the value of reserved fields. Unsafe because it's possible to break memory
157-
/// safety, e.g. by disabling long mode.
166+
/// Preserves the value of reserved fields.
167+
///
168+
/// ## Safety
169+
///
170+
/// Unsafe because it's possible to break memory
171+
/// safety with wrong flags, e.g. by disabling long mode.
158172
#[inline]
159173
pub unsafe fn write(flags: EferFlags) {
160174
let old_value = Self::read_raw();
@@ -166,17 +180,25 @@ mod x86_64 {
166180

167181
/// Write the EFER flags.
168182
///
169-
/// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
170-
/// break memory safety, e.g. by disabling long mode.
183+
/// Does not preserve any bits, including reserved fields.
184+
///
185+
/// ## Safety
186+
///
187+
/// Unsafe because it's possible to
188+
/// break memory safety with wrong flags, e.g. by disabling long mode.
171189
#[inline]
172190
pub unsafe fn write_raw(flags: u64) {
173191
Self::MSR.write(flags);
174192
}
175193

176194
/// Update EFER flags.
177195
///
178-
/// Preserves the value of reserved fields. Unsafe because it's possible to break memory
179-
/// safety, e.g. by disabling long mode.
196+
/// Preserves the value of reserved fields.
197+
///
198+
/// ## Safety
199+
///
200+
/// Unsafe because it's possible to break memory
201+
/// safety with wrong flags, e.g. by disabling long mode.
180202
#[inline]
181203
pub unsafe fn update<F>(f: F)
182204
where
@@ -284,7 +306,8 @@ mod x86_64 {
284306
/// this field + 8. Because SYSCALL always switches to CPL 0, the RPL bits
285307
/// 33:32 should be initialized to 00b.
286308
///
287-
/// # Unsafety
309+
/// # Safety
310+
///
288311
/// Unsafe because this can cause system instability if passed in the
289312
/// wrong values for the fields.
290313
#[inline]

src/structures/idt.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ pub struct InterruptStackFrame {
755755
impl InterruptStackFrame {
756756
/// Gives mutable access to the contents of the interrupt stack frame.
757757
///
758+
/// ## Safety
759+
///
758760
/// This function is unsafe since modifying the content of the interrupt stack frame
759761
/// can easily lead to undefined behavior. For example, by writing an invalid value to
760762
/// the instruction pointer field, the CPU can jump to arbitrary code at the end of the

src/structures/paging/mapper/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ pub trait Mapper<S: PageSize> {
113113
fn translate_page(&self, page: Page<S>) -> Result<PhysFrame<S>, TranslateError>;
114114

115115
/// Maps the given frame to the virtual page with the same address.
116+
///
117+
/// ## Safety
118+
///
119+
/// TODO: Should this function be safe?
116120
#[inline]
117121
unsafe fn identity_map<A>(
118122
&mut self,

src/structures/paging/mapper/offset_page_table.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ impl<'a> OffsetPageTable<'a> {
1919
/// the mapper needs to access page tables, which are not mapped into the virtual address
2020
/// space by default.
2121
///
22+
/// ## Safety
23+
///
2224
/// This function is unsafe because the caller must guarantee that the passed `phys_offset`
2325
/// is correct. Also, the passed `level_4_table` must point to the level 4 page table
2426
/// of a valid page table hierarchy. Otherwise this function might break memory safety, e.g.

0 commit comments

Comments
 (0)