Skip to content

Commit 467ceb9

Browse files
spinup: add a restore point for the GS base
Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent 984eebe commit 467ceb9

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

src/aero_kernel/src/arch/x86_64/task.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub struct ArchTask {
118118
context_switch_rsp: VirtAddr,
119119

120120
fs_base: VirtAddr,
121+
gs_base: VirtAddr,
121122
}
122123

123124
impl ArchTask {
@@ -129,7 +130,9 @@ impl ArchTask {
129130
// Since the IDLE task is a special kernel task, we use the kernel's
130131
// address space here and we also use the kernel privilage level here.
131132
address_space: AddressSpace::this(),
133+
132134
fs_base: VirtAddr::zero(),
135+
gs_base: VirtAddr::zero(),
133136
}
134137
}
135138

@@ -166,7 +169,9 @@ impl ArchTask {
166169
context: unsafe { Unique::new_unchecked(context) },
167170
address_space,
168171
context_switch_rsp: VirtAddr::new(task_stack as u64),
172+
169173
fs_base: VirtAddr::zero(),
174+
gs_base: VirtAddr::zero(),
170175
}
171176
}
172177

@@ -225,8 +230,10 @@ impl ArchTask {
225230
context: unsafe { Unique::new_unchecked(context) },
226231
context_switch_rsp: VirtAddr::new(switch_stack as u64),
227232
address_space: new_address_space,
228-
// The FS base is inherited from the parent process.
233+
234+
// The FS and GS bases are inherited from the parent process.
229235
fs_base: self.fs_base.clone(),
236+
gs_base: self.gs_base.clone(),
230237
})
231238
}
232239

@@ -327,7 +334,23 @@ impl ArchTask {
327334
Ok(())
328335
}
329336

330-
/// Returns the FS base for this instance.
337+
/// Returns the saved GS base for this task.
338+
pub fn get_gs_base(&self) -> VirtAddr {
339+
self.gs_base
340+
}
341+
342+
/// Sets the GS base to the provided `base`.
343+
///
344+
/// ## Safety
345+
/// This function **must** be called by the process that this [`ArchTask`] instance
346+
/// belongs to. This is required since we also update the GS base register with the
347+
/// `base` immediately (not waiting for a switch).
348+
pub unsafe fn set_gs_base(&mut self, base: VirtAddr) {
349+
io::wrmsr(io::IA32_KERNEL_GSBASE, base.as_u64());
350+
self.gs_base = base;
351+
}
352+
353+
/// Returns the saved FS base for this task.
331354
pub fn get_fs_base(&self) -> VirtAddr {
332355
self.fs_base
333356
}
@@ -358,5 +381,10 @@ pub fn arch_task_spinup(from: &mut ArchTask, to: &ArchTask) {
358381
from.fs_base = VirtAddr::new(io::rdmsr(io::IA32_FS_BASE));
359382
// switch to the new FS base.
360383
io::wrmsr(io::IA32_FS_BASE, to.fs_base.as_u64());
384+
385+
// make a restore point for the current GS base.
386+
from.gs_base = VirtAddr::new(io::rdmsr(io::IA32_KERNEL_GSBASE));
387+
// update the swap GS target to point to the new GS base.
388+
io::wrmsr(io::IA32_KERNEL_GSBASE, to.gs_base.as_u64());
361389
}
362390
}

src/aero_kernel/src/syscall/process.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,24 @@ pub fn arch_prctl(command: usize, address: usize) -> Result<usize, AeroSyscallEr
7070

7171
ARCH_GET_FS => Ok(scheduler::get_scheduler()
7272
.current_task()
73-
.arch_task_mut()
73+
.arch_task()
7474
.get_fs_base()
7575
.as_u64() as usize),
7676

77-
ARCH_SET_GS => unimplemented!(),
78-
ARCH_GET_GS => unimplemented!(),
77+
ARCH_SET_GS => unsafe {
78+
scheduler::get_scheduler()
79+
.current_task()
80+
.arch_task_mut()
81+
.set_gs_base(VirtAddr::new(address as u64));
82+
83+
Ok(0x00)
84+
},
85+
86+
ARCH_GET_GS => Ok(scheduler::get_scheduler()
87+
.current_task()
88+
.arch_task()
89+
.get_gs_base()
90+
.as_u64() as usize),
7991

8092
_ => Err(AeroSyscallError::EINVAL),
8193
}

src/aero_kernel/src/utils/io.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,15 @@
2121
2222
pub const IA32_EFER: u32 = 0xc0000080;
2323

24+
/// Map of BASE Address of FS (R/W) See Table 35-2.
2425
pub const IA32_FS_BASE: u32 = 0xC0000100;
26+
27+
/// Map of BASE Address of GS (R/W) See Table 35-2.
2528
pub const IA32_GS_BASE: u32 = 0xc0000101;
2629

30+
/// Swap Target of BASE Address of GS (R/W) See Table 35-2.
31+
pub const IA32_KERNEL_GSBASE: u32 = 0xc0000102;
32+
2733
/// System Call Target Address (R/W).
2834
pub const IA32_STAR: u32 = 0xc0000081;
2935

0 commit comments

Comments
 (0)