proc: implement proper TLS for i686
This commit is contained in:
parent
e0e39d2f23
commit
961ff9ff6f
@ -74,6 +74,8 @@ pub struct InterruptFrame {
|
||||
struct Inner {
|
||||
// 0x00
|
||||
sp: usize,
|
||||
|
||||
gs_base: usize,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -88,11 +90,29 @@ pub struct TaskContextImpl<
|
||||
|
||||
cr3: u32,
|
||||
tss_esp0: u32,
|
||||
gs_base: usize,
|
||||
|
||||
_pd: PhantomData<(K, PA)>,
|
||||
}
|
||||
|
||||
impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddress>>
|
||||
TaskContextImpl<K, PA>
|
||||
{
|
||||
unsafe fn store_state(&self) {
|
||||
if let Some(fpu) = self.fpu_context.as_ref() {
|
||||
FpuContext::store(fpu.get());
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn load_state(&self) {
|
||||
if let Some(fpu) = self.fpu_context.as_ref() {
|
||||
FpuContext::restore(fpu.get());
|
||||
}
|
||||
gdt::set_gs_base((*self.inner.get()).gs_base);
|
||||
TSS.esp0 = self.tss_esp0;
|
||||
CR3.set(self.cr3 as _);
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddress>>
|
||||
TaskContext<K, PA> for TaskContextImpl<K, PA>
|
||||
{
|
||||
@ -123,14 +143,16 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
let fpu_context = FpuContext::new(true);
|
||||
|
||||
Ok(Self {
|
||||
inner: UnsafeCell::new(Inner { sp }),
|
||||
inner: UnsafeCell::new(Inner {
|
||||
sp,
|
||||
gs_base: context.thread_pointer,
|
||||
}),
|
||||
fpu_context: Some(UnsafeCell::new(fpu_context)),
|
||||
stack_base_phys,
|
||||
stack_size: USER_TASK_PAGES * 0x1000,
|
||||
|
||||
tss_esp0: esp0 as _,
|
||||
cr3: context.address_space.try_into().unwrap(),
|
||||
gs_base: context.thread_pointer,
|
||||
|
||||
_pd: PhantomData,
|
||||
})
|
||||
@ -166,61 +188,42 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
||||
// TODO stack is leaked
|
||||
|
||||
Ok(Self {
|
||||
inner: UnsafeCell::new(Inner { sp }),
|
||||
inner: UnsafeCell::new(Inner { sp, gs_base: 0 }),
|
||||
fpu_context: None,
|
||||
stack_base_phys,
|
||||
stack_size: KERNEL_TASK_PAGES * 0x1000,
|
||||
|
||||
tss_esp0: 0,
|
||||
cr3,
|
||||
gs_base: 0,
|
||||
|
||||
_pd: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn switch(&self, from: &Self) {
|
||||
let dst = self.inner.get();
|
||||
let src = from.inner.get();
|
||||
|
||||
if dst != src {
|
||||
// Save the old context
|
||||
if let Some(src_fpu) = from.fpu_context.as_ref() {
|
||||
FpuContext::store(src_fpu.get());
|
||||
}
|
||||
// Load next context
|
||||
if let Some(dst_fpu) = self.fpu_context.as_ref() {
|
||||
FpuContext::restore(dst_fpu.get());
|
||||
}
|
||||
|
||||
gdt::set_gs_base(self.gs_base);
|
||||
TSS.esp0 = self.tss_esp0;
|
||||
CR3.set(self.cr3 as _);
|
||||
|
||||
__i686_switch_task(dst, src);
|
||||
if core::ptr::addr_eq(self, from) {
|
||||
return;
|
||||
}
|
||||
|
||||
from.store_state();
|
||||
self.load_state();
|
||||
|
||||
__i686_switch_task(self.inner.get(), from.inner.get());
|
||||
}
|
||||
|
||||
unsafe fn enter(&self) -> ! {
|
||||
if let Some(dst_fpu) = self.fpu_context.as_ref() {
|
||||
FpuContext::restore(dst_fpu.get());
|
||||
}
|
||||
gdt::set_gs_base(self.gs_base);
|
||||
TSS.esp0 = self.tss_esp0;
|
||||
CR3.set(self.cr3 as _);
|
||||
|
||||
self.load_state();
|
||||
__i686_enter_task(self.inner.get())
|
||||
}
|
||||
|
||||
unsafe fn switch_and_drop(&self, thread: *const ()) {
|
||||
if let Some(dst_fpu) = self.fpu_context.as_ref() {
|
||||
FpuContext::restore(dst_fpu.get());
|
||||
}
|
||||
gdt::set_gs_base(self.gs_base);
|
||||
TSS.esp0 = self.tss_esp0;
|
||||
CR3.set(self.cr3 as _);
|
||||
self.load_state();
|
||||
__i686_switch_and_drop(self.inner.get(), thread);
|
||||
}
|
||||
|
||||
__i686_switch_and_drop(self.inner.get(), thread)
|
||||
fn set_thread_pointer(&self, tp: usize) {
|
||||
unsafe { (*self.inner.get()).gs_base = tp };
|
||||
gdt::set_gs_base(tp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use abi::error::Error;
|
||||
use abi::{error::Error, process::ThreadOption};
|
||||
|
||||
pub fn get_thread_pointer() -> usize {
|
||||
let tp: usize;
|
||||
@ -11,5 +11,5 @@ pub fn get_thread_pointer() -> usize {
|
||||
}
|
||||
|
||||
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
|
||||
todo!()
|
||||
crate::sys::set_thread_option(&ThreadOption::ThreadPointer(value))
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ pub fn clone_tls(image: &TlsImage, tcb_size: usize) -> Result<(usize, usize), Er
|
||||
// Zero the TCB after the self-pointer
|
||||
tcb[size_of::<usize>()..].fill(0);
|
||||
|
||||
crate::debug_trace!("TLS: base={:#x}, tp={:#x}", base, tp);
|
||||
|
||||
Ok((base, tp))
|
||||
}
|
||||
|
||||
|
33
userspace/dyn-loader/src/relocation/i686.rs
Normal file
33
userspace/dyn-loader/src/relocation/i686.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use elf::relocation::{Rel, Rela};
|
||||
|
||||
use crate::{error::Error, object::ResolvedSymbol, state::State};
|
||||
|
||||
use super::{RelValue, RelaValue, Relocation};
|
||||
|
||||
impl Relocation for Rela {
|
||||
type Value = RelaValue;
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
_state: &State,
|
||||
_name: &str,
|
||||
_symbol: &ResolvedSymbol,
|
||||
_load_base: usize,
|
||||
) -> Result<Option<Self::Value>, Error> {
|
||||
unimplemented!("rela-type relocations are not implemented for i686")
|
||||
}
|
||||
}
|
||||
|
||||
impl Relocation for Rel {
|
||||
type Value = RelValue;
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
state: &State,
|
||||
name: &str,
|
||||
symbol: &ResolvedSymbol,
|
||||
load_base: usize,
|
||||
) -> Result<Option<Self::Value>, Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -2,11 +2,17 @@ use crate::{error::Error, mapping::Mapping, object::ResolvedSymbol, state::State
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
mod x86_64;
|
||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||
mod i686;
|
||||
|
||||
pub enum RelaValue {
|
||||
QWord(i64),
|
||||
}
|
||||
|
||||
pub enum RelValue {
|
||||
|
||||
}
|
||||
|
||||
pub trait RelocationValue {
|
||||
fn write(&self, mapping: &mut Mapping, offset: u64);
|
||||
}
|
||||
@ -30,3 +36,9 @@ impl RelocationValue for RelaValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelocationValue for RelValue {
|
||||
fn write(&self, mapping: &mut Mapping, offset: u64) {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use walkdir::WalkDir;
|
||||
use crate::{
|
||||
build::{c, cargo::CargoBuilder},
|
||||
check::AllOk,
|
||||
env::BuildEnv,
|
||||
env::{Arch, BuildEnv},
|
||||
error::Error,
|
||||
util,
|
||||
};
|
||||
@ -62,8 +62,6 @@ const PROGRAMS: &[(&str, &str)] = &[
|
||||
("crypt", "bin/crypt"),
|
||||
("dyn-loader", "libexec/dyn-loader"),
|
||||
// TODO: proper process for C program builds
|
||||
("c-test", "c-test"),
|
||||
("c-test-static", "c-test-static"),
|
||||
];
|
||||
|
||||
fn build_userspace(
|
||||
@ -73,8 +71,11 @@ fn build_userspace(
|
||||
) -> Result<(), Error> {
|
||||
log::info!("Building userspace");
|
||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace"))?;
|
||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
|
||||
c::build_c(env, extra)?;
|
||||
// TODO other architectures
|
||||
if env.arch == Arch::x86_64 {
|
||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
|
||||
c::build_c(env, extra)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -116,20 +117,22 @@ fn build_rootfs<S: AsRef<Path>, D: AsRef<Path>>(
|
||||
|
||||
// TODO this is a temporary hack
|
||||
fs::create_dir_all(rootfs_dir.join("lib"))?;
|
||||
util::copy_file(
|
||||
env.workspace_root.join(format!(
|
||||
"userspace/dynload-program/target/{}-unknown-yggdrasil/{}/dynload-program",
|
||||
env.arch.name(),
|
||||
env.profile.name()
|
||||
)),
|
||||
rootfs_dir.join("dynload-program"),
|
||||
)?;
|
||||
util::copy_file(format!(
|
||||
"/home/alnyan/build/ygg/toolchain/build/host/stage1-std/{}-unknown-yggdrasil/release/libstd.so",
|
||||
env.arch.name()
|
||||
), rootfs_dir.join("lib/libstd.so"))?;
|
||||
// TODO other architectures
|
||||
if env.arch == Arch::x86_64 {
|
||||
util::copy_file(
|
||||
env.workspace_root.join(format!(
|
||||
"userspace/dynload-program/target/{}-unknown-yggdrasil/{}/dynload-program",
|
||||
env.arch.name(),
|
||||
env.profile.name()
|
||||
)),
|
||||
rootfs_dir.join("dynload-program"),
|
||||
)?;
|
||||
|
||||
log::info!("Installing ygglibc");
|
||||
util::copy_file(format!(
|
||||
"/home/alnyan/build/ygg/toolchain/build/host/stage1-std/{}-unknown-yggdrasil/release/libstd.so",
|
||||
env.arch.name()
|
||||
), rootfs_dir.join("lib/libstd.so"))?;
|
||||
}
|
||||
|
||||
log::info!("Installing extras");
|
||||
for (src, dst) in install_extra {
|
||||
|
Loading…
x
Reference in New Issue
Block a user