proc: implement proper TLS for i686
This commit is contained in:
parent
e0e39d2f23
commit
961ff9ff6f
@ -74,6 +74,8 @@ pub struct InterruptFrame {
|
|||||||
struct Inner {
|
struct Inner {
|
||||||
// 0x00
|
// 0x00
|
||||||
sp: usize,
|
sp: usize,
|
||||||
|
|
||||||
|
gs_base: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -88,11 +90,29 @@ pub struct TaskContextImpl<
|
|||||||
|
|
||||||
cr3: u32,
|
cr3: u32,
|
||||||
tss_esp0: u32,
|
tss_esp0: u32,
|
||||||
gs_base: usize,
|
|
||||||
|
|
||||||
_pd: PhantomData<(K, PA)>,
|
_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>>
|
impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddress>>
|
||||||
TaskContext<K, PA> for TaskContextImpl<K, PA>
|
TaskContext<K, PA> for TaskContextImpl<K, PA>
|
||||||
{
|
{
|
||||||
@ -123,14 +143,16 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
|||||||
let fpu_context = FpuContext::new(true);
|
let fpu_context = FpuContext::new(true);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: UnsafeCell::new(Inner { sp }),
|
inner: UnsafeCell::new(Inner {
|
||||||
|
sp,
|
||||||
|
gs_base: context.thread_pointer,
|
||||||
|
}),
|
||||||
fpu_context: Some(UnsafeCell::new(fpu_context)),
|
fpu_context: Some(UnsafeCell::new(fpu_context)),
|
||||||
stack_base_phys,
|
stack_base_phys,
|
||||||
stack_size: USER_TASK_PAGES * 0x1000,
|
stack_size: USER_TASK_PAGES * 0x1000,
|
||||||
|
|
||||||
tss_esp0: esp0 as _,
|
tss_esp0: esp0 as _,
|
||||||
cr3: context.address_space.try_into().unwrap(),
|
cr3: context.address_space.try_into().unwrap(),
|
||||||
gs_base: context.thread_pointer,
|
|
||||||
|
|
||||||
_pd: PhantomData,
|
_pd: PhantomData,
|
||||||
})
|
})
|
||||||
@ -166,61 +188,42 @@ impl<K: KernelTableManager, PA: PhysicalMemoryAllocator<Address = PhysicalAddres
|
|||||||
// TODO stack is leaked
|
// TODO stack is leaked
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: UnsafeCell::new(Inner { sp }),
|
inner: UnsafeCell::new(Inner { sp, gs_base: 0 }),
|
||||||
fpu_context: None,
|
fpu_context: None,
|
||||||
stack_base_phys,
|
stack_base_phys,
|
||||||
stack_size: KERNEL_TASK_PAGES * 0x1000,
|
stack_size: KERNEL_TASK_PAGES * 0x1000,
|
||||||
|
|
||||||
tss_esp0: 0,
|
tss_esp0: 0,
|
||||||
cr3,
|
cr3,
|
||||||
gs_base: 0,
|
|
||||||
|
|
||||||
_pd: PhantomData,
|
_pd: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn switch(&self, from: &Self) {
|
unsafe fn switch(&self, from: &Self) {
|
||||||
let dst = self.inner.get();
|
if core::ptr::addr_eq(self, from) {
|
||||||
let src = from.inner.get();
|
return;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
from.store_state();
|
||||||
|
self.load_state();
|
||||||
|
|
||||||
|
__i686_switch_task(self.inner.get(), from.inner.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn enter(&self) -> ! {
|
unsafe fn enter(&self) -> ! {
|
||||||
if let Some(dst_fpu) = self.fpu_context.as_ref() {
|
self.load_state();
|
||||||
FpuContext::restore(dst_fpu.get());
|
|
||||||
}
|
|
||||||
gdt::set_gs_base(self.gs_base);
|
|
||||||
TSS.esp0 = self.tss_esp0;
|
|
||||||
CR3.set(self.cr3 as _);
|
|
||||||
|
|
||||||
__i686_enter_task(self.inner.get())
|
__i686_enter_task(self.inner.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn switch_and_drop(&self, thread: *const ()) {
|
unsafe fn switch_and_drop(&self, thread: *const ()) {
|
||||||
if let Some(dst_fpu) = self.fpu_context.as_ref() {
|
self.load_state();
|
||||||
FpuContext::restore(dst_fpu.get());
|
__i686_switch_and_drop(self.inner.get(), thread);
|
||||||
}
|
}
|
||||||
gdt::set_gs_base(self.gs_base);
|
|
||||||
TSS.esp0 = self.tss_esp0;
|
|
||||||
CR3.set(self.cr3 as _);
|
|
||||||
|
|
||||||
__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)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use abi::error::Error;
|
use abi::{error::Error, process::ThreadOption};
|
||||||
|
|
||||||
pub fn get_thread_pointer() -> usize {
|
pub fn get_thread_pointer() -> usize {
|
||||||
let tp: usize;
|
let tp: usize;
|
||||||
@ -11,5 +11,5 @@ pub fn get_thread_pointer() -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn set_thread_pointer(value: usize) -> Result<(), Error> {
|
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
|
// Zero the TCB after the self-pointer
|
||||||
tcb[size_of::<usize>()..].fill(0);
|
tcb[size_of::<usize>()..].fill(0);
|
||||||
|
|
||||||
|
crate::debug_trace!("TLS: base={:#x}, tp={:#x}", base, tp);
|
||||||
|
|
||||||
Ok((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))]
|
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||||
mod x86_64;
|
mod x86_64;
|
||||||
|
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||||
|
mod i686;
|
||||||
|
|
||||||
pub enum RelaValue {
|
pub enum RelaValue {
|
||||||
QWord(i64),
|
QWord(i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum RelValue {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
pub trait RelocationValue {
|
pub trait RelocationValue {
|
||||||
fn write(&self, mapping: &mut Mapping, offset: u64);
|
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::{
|
use crate::{
|
||||||
build::{c, cargo::CargoBuilder},
|
build::{c, cargo::CargoBuilder},
|
||||||
check::AllOk,
|
check::AllOk,
|
||||||
env::BuildEnv,
|
env::{Arch, BuildEnv},
|
||||||
error::Error,
|
error::Error,
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
@ -62,8 +62,6 @@ const PROGRAMS: &[(&str, &str)] = &[
|
|||||||
("crypt", "bin/crypt"),
|
("crypt", "bin/crypt"),
|
||||||
("dyn-loader", "libexec/dyn-loader"),
|
("dyn-loader", "libexec/dyn-loader"),
|
||||||
// TODO: proper process for C program builds
|
// TODO: proper process for C program builds
|
||||||
("c-test", "c-test"),
|
|
||||||
("c-test-static", "c-test-static"),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
fn build_userspace(
|
fn build_userspace(
|
||||||
@ -73,8 +71,11 @@ fn build_userspace(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
log::info!("Building userspace");
|
log::info!("Building userspace");
|
||||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace"))?;
|
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace"))?;
|
||||||
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
|
// TODO other architectures
|
||||||
c::build_c(env, extra)?;
|
if env.arch == Arch::x86_64 {
|
||||||
|
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
|
||||||
|
c::build_c(env, extra)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -116,20 +117,22 @@ fn build_rootfs<S: AsRef<Path>, D: AsRef<Path>>(
|
|||||||
|
|
||||||
// TODO this is a temporary hack
|
// TODO this is a temporary hack
|
||||||
fs::create_dir_all(rootfs_dir.join("lib"))?;
|
fs::create_dir_all(rootfs_dir.join("lib"))?;
|
||||||
util::copy_file(
|
// TODO other architectures
|
||||||
env.workspace_root.join(format!(
|
if env.arch == Arch::x86_64 {
|
||||||
"userspace/dynload-program/target/{}-unknown-yggdrasil/{}/dynload-program",
|
util::copy_file(
|
||||||
env.arch.name(),
|
env.workspace_root.join(format!(
|
||||||
env.profile.name()
|
"userspace/dynload-program/target/{}-unknown-yggdrasil/{}/dynload-program",
|
||||||
)),
|
env.arch.name(),
|
||||||
rootfs_dir.join("dynload-program"),
|
env.profile.name()
|
||||||
)?;
|
)),
|
||||||
util::copy_file(format!(
|
rootfs_dir.join("dynload-program"),
|
||||||
"/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 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");
|
log::info!("Installing extras");
|
||||||
for (src, dst) in install_extra {
|
for (src, dst) in install_extra {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user