mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 01:37:39 +03:00
Kernel: Consolidate a bunch of i386/x86_64 code paths
Add some arch-specific getters and setters that allow us to merge blocks that were previously specific to either ARCH(I386) or ARCH(X86_64).
This commit is contained in:
parent
3f5a42b3dd
commit
961f727448
Notes:
sideshowbarker
2024-07-18 05:28:43 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/961f7274480
@ -68,41 +68,35 @@ struct [[gnu::packed]] RegisterState {
|
|||||||
FlatPtr userspace_ss;
|
FlatPtr userspace_ss;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ARCH(I386)
|
||||||
FlatPtr userspace_sp() const
|
FlatPtr userspace_sp() const
|
||||||
{
|
{
|
||||||
#if ARCH(I386)
|
|
||||||
return userspace_esp;
|
return userspace_esp;
|
||||||
#else
|
}
|
||||||
|
void set_userspace_sp(FlatPtr value) { userspace_esp = value; }
|
||||||
|
FlatPtr ip() const { return eip; }
|
||||||
|
void set_ip(FlatPtr value) { eip = value; }
|
||||||
|
void set_dx(FlatPtr value) { edx = value; }
|
||||||
|
FlatPtr bp() const { return ebp; }
|
||||||
|
void set_bp(FlatPtr value) { ebp = value; }
|
||||||
|
FlatPtr flags() const { return eflags; }
|
||||||
|
void set_flags(FlatPtr value) { eflags = value; }
|
||||||
|
void set_return_reg(FlatPtr value) { eax = value; }
|
||||||
|
#elif ARCH(X86_64)
|
||||||
|
FlatPtr userspace_sp() const
|
||||||
|
{
|
||||||
return userspace_rsp;
|
return userspace_rsp;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
void set_userspace_sp(FlatPtr value) { userspace_rsp = value; }
|
||||||
FlatPtr ip() const
|
FlatPtr ip() const { return rip; }
|
||||||
{
|
void set_ip(FlatPtr value) { rip = value; }
|
||||||
#if ARCH(I386)
|
void set_dx(FlatPtr value) { rdx = value; }
|
||||||
return eip;
|
FlatPtr bp() const { return rbp; }
|
||||||
#else
|
void set_bp(FlatPtr value) { rbp = value; }
|
||||||
return rip;
|
FlatPtr flags() const { return rflags; }
|
||||||
|
void set_flags(FlatPtr value) { rflags = value; }
|
||||||
|
void set_return_reg(FlatPtr value) { rax = value; }
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
FlatPtr bp() const
|
|
||||||
{
|
|
||||||
#if ARCH(I386)
|
|
||||||
return ebp;
|
|
||||||
#else
|
|
||||||
return rbp;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatPtr flags() const
|
|
||||||
{
|
|
||||||
#if ARCH(I386)
|
|
||||||
return eflags;
|
|
||||||
#else
|
|
||||||
return rflags;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void capture_syscall_params(FlatPtr& function, FlatPtr& arg1, FlatPtr& arg2, FlatPtr& arg3, FlatPtr& arg4) const
|
void capture_syscall_params(FlatPtr& function, FlatPtr& arg1, FlatPtr& arg2, FlatPtr& arg3, FlatPtr& arg4) const
|
||||||
{
|
{
|
||||||
@ -118,24 +112,6 @@ struct [[gnu::packed]] RegisterState {
|
|||||||
arg2 = rcx;
|
arg2 = rcx;
|
||||||
arg3 = rbx;
|
arg3 = rbx;
|
||||||
arg4 = rsi;
|
arg4 = rsi;
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_ip_reg(FlatPtr value)
|
|
||||||
{
|
|
||||||
#if ARCH(I386)
|
|
||||||
eip = value;
|
|
||||||
#else
|
|
||||||
rip = value;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_return_reg(FlatPtr value)
|
|
||||||
{
|
|
||||||
#if ARCH(I386)
|
|
||||||
eax = value;
|
|
||||||
#else
|
|
||||||
rax = value;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -299,13 +299,8 @@ bool handle_safe_access_fault(RegisterState& regs, FlatPtr fault_address)
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if ARCH(I386)
|
regs.set_ip(ip);
|
||||||
regs.eip = ip;
|
regs.set_dx(fault_address);
|
||||||
regs.edx = fault_address;
|
|
||||||
#else
|
|
||||||
regs.rip = ip;
|
|
||||||
regs.rdx = fault_address;
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ip >= (FlatPtr)&start_of_safemem_atomic_text && ip < (FlatPtr)&end_of_safemem_atomic_text) {
|
if (ip >= (FlatPtr)&start_of_safemem_atomic_text && ip < (FlatPtr)&end_of_safemem_atomic_text) {
|
||||||
@ -325,13 +320,8 @@ bool handle_safe_access_fault(RegisterState& regs, FlatPtr fault_address)
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if ARCH(I386)
|
regs.set_ip(ip);
|
||||||
regs.eip = ip;
|
regs.set_dx(1);
|
||||||
regs.edx = 1;
|
|
||||||
#else
|
|
||||||
regs.rip = ip;
|
|
||||||
regs.rdx = 1;
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -195,11 +195,10 @@ RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, Str
|
|||||||
auto process = Process::create(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true);
|
auto process = Process::create(first_thread, move(name), (uid_t)0, (gid_t)0, ProcessID(0), true);
|
||||||
if (!first_thread || !process)
|
if (!first_thread || !process)
|
||||||
return {};
|
return {};
|
||||||
|
first_thread->regs().set_ip((FlatPtr)entry);
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
first_thread->regs().eip = (FlatPtr)entry;
|
|
||||||
first_thread->regs().esp = FlatPtr(entry_data); // entry function argument is expected to be in regs.esp
|
first_thread->regs().esp = FlatPtr(entry_data); // entry function argument is expected to be in regs.esp
|
||||||
#else
|
#else
|
||||||
first_thread->regs().rip = (FlatPtr)entry;
|
|
||||||
first_thread->regs().rdi = FlatPtr(entry_data); // entry function argument is expected to be in regs.rdi
|
first_thread->regs().rdi = FlatPtr(entry_data); // entry function argument is expected to be in regs.rdi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -769,13 +768,8 @@ RefPtr<Thread> Process::create_kernel_thread(void (*entry)(void*), void* entry_d
|
|||||||
thread->detach();
|
thread->detach();
|
||||||
|
|
||||||
auto& regs = thread->regs();
|
auto& regs = thread->regs();
|
||||||
#if ARCH(I386)
|
regs.set_ip((FlatPtr)entry);
|
||||||
regs.eip = (FlatPtr)entry;
|
regs.set_sp((FlatPtr)entry_data); // entry function argument is expected to be in the SP register
|
||||||
regs.esp = FlatPtr(entry_data); // entry function argument is expected to be in regs.rsp
|
|
||||||
#else
|
|
||||||
regs.rip = (FlatPtr)entry;
|
|
||||||
regs.rsp = FlatPtr(entry_data); // entry function argument is expected to be in regs.rsp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ScopedSpinLock lock(g_scheduler_lock);
|
ScopedSpinLock lock(g_scheduler_lock);
|
||||||
thread->set_state(Thread::State::Runnable);
|
thread->set_state(Thread::State::Runnable);
|
||||||
|
@ -60,14 +60,10 @@ KResultOr<FlatPtr> Process::sys$create_thread(void* (*entry)(void*), Userspace<c
|
|||||||
thread->detach();
|
thread->detach();
|
||||||
|
|
||||||
auto& regs = thread->regs();
|
auto& regs = thread->regs();
|
||||||
#if ARCH(I386)
|
regs.set_ip((FlatPtr)entry);
|
||||||
regs.eip = (FlatPtr)entry;
|
regs.set_flags(0x0202);
|
||||||
regs.eflags = 0x0202;
|
regs.set_sp(user_sp.value());
|
||||||
regs.esp = user_sp.value();
|
#if ARCH(X86_64)
|
||||||
#else
|
|
||||||
regs.rip = (FlatPtr)entry;
|
|
||||||
regs.rflags = 0x0202;
|
|
||||||
regs.rsp = user_sp.value();
|
|
||||||
regs.rdi = params.rdi;
|
regs.rdi = params.rdi;
|
||||||
regs.rsi = params.rsi;
|
regs.rsi = params.rsi;
|
||||||
regs.rdx = params.rdx;
|
regs.rdx = params.rdx;
|
||||||
|
@ -86,10 +86,10 @@ Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Memory::Region> ker
|
|||||||
|
|
||||||
reset_fpu_state();
|
reset_fpu_state();
|
||||||
|
|
||||||
#if ARCH(I386)
|
|
||||||
// Only IF is set when a process boots.
|
// Only IF is set when a process boots.
|
||||||
m_regs.eflags = 0x0202;
|
m_regs.set_flags(0x0202);
|
||||||
|
|
||||||
|
#if ARCH(I386)
|
||||||
if (m_process->is_kernel_process()) {
|
if (m_process->is_kernel_process()) {
|
||||||
m_regs.cs = GDT_SELECTOR_CODE0;
|
m_regs.cs = GDT_SELECTOR_CODE0;
|
||||||
m_regs.ds = GDT_SELECTOR_DATA0;
|
m_regs.ds = GDT_SELECTOR_DATA0;
|
||||||
@ -106,9 +106,6 @@ Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Memory::Region> ker
|
|||||||
m_regs.gs = GDT_SELECTOR_TLS | 3;
|
m_regs.gs = GDT_SELECTOR_TLS | 3;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Only IF is set when a process boots.
|
|
||||||
m_regs.rflags = 0x0202;
|
|
||||||
|
|
||||||
if (m_process->is_kernel_process())
|
if (m_process->is_kernel_process())
|
||||||
m_regs.cs = GDT_SELECTOR_CODE0;
|
m_regs.cs = GDT_SELECTOR_CODE0;
|
||||||
else
|
else
|
||||||
@ -121,20 +118,15 @@ Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Memory::Region> ker
|
|||||||
m_kernel_stack_top = m_kernel_stack_region->vaddr().offset(default_kernel_stack_size).get() & ~(FlatPtr)0x7u;
|
m_kernel_stack_top = m_kernel_stack_region->vaddr().offset(default_kernel_stack_size).get() & ~(FlatPtr)0x7u;
|
||||||
|
|
||||||
if (m_process->is_kernel_process()) {
|
if (m_process->is_kernel_process()) {
|
||||||
#if ARCH(I386)
|
m_regs.set_sp(m_kernel_stack_top);
|
||||||
m_regs.esp = m_regs.esp0 = m_kernel_stack_top;
|
m_regs.set_sp0(m_kernel_stack_top);
|
||||||
#else
|
|
||||||
m_regs.rsp = m_regs.rsp0 = m_kernel_stack_top;
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
// Ring 3 processes get a separate stack for ring 0.
|
// Ring 3 processes get a separate stack for ring 0.
|
||||||
// The ring 3 stack will be assigned by exec().
|
// The ring 3 stack will be assigned by exec().
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
m_regs.ss0 = GDT_SELECTOR_DATA0;
|
m_regs.ss0 = GDT_SELECTOR_DATA0;
|
||||||
m_regs.esp0 = m_kernel_stack_top;
|
|
||||||
#else
|
|
||||||
m_regs.rsp0 = m_kernel_stack_top;
|
|
||||||
#endif
|
#endif
|
||||||
|
m_regs.set_sp0(m_kernel_stack_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to add another reference if we could successfully create
|
// We need to add another reference if we could successfully create
|
||||||
@ -938,21 +930,12 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
m_have_any_unmasked_pending_signals.store(m_pending_signals & ~m_signal_mask, AK::memory_order_release);
|
m_have_any_unmasked_pending_signals.store(m_pending_signals & ~m_signal_mask, AK::memory_order_release);
|
||||||
|
|
||||||
auto setup_stack = [&](RegisterState& state) {
|
auto setup_stack = [&](RegisterState& state) {
|
||||||
#if ARCH(I386)
|
FlatPtr stack = state.userspace_sp();
|
||||||
FlatPtr stack = state.userspace_esp;
|
FlatPtr old_sp = stack;
|
||||||
FlatPtr old_esp = stack;
|
FlatPtr ret_ip = state.ip();
|
||||||
FlatPtr ret_eip = state.eip;
|
FlatPtr ret_flags = state.flags();
|
||||||
FlatPtr ret_eflags = state.eflags;
|
|
||||||
|
|
||||||
dbgln_if(SIGNAL_DEBUG, "Setting up user stack to return to EIP {:p}, ESP {:p}", ret_eip, old_esp);
|
dbgln_if(SIGNAL_DEBUG, "Setting up user stack to return to IP {:p}, SP {:p}", ret_ip, old_sp);
|
||||||
#elif ARCH(X86_64)
|
|
||||||
FlatPtr stack = state.userspace_rsp;
|
|
||||||
FlatPtr old_rsp = stack;
|
|
||||||
FlatPtr ret_rip = state.rip;
|
|
||||||
FlatPtr ret_rflags = state.rflags;
|
|
||||||
|
|
||||||
dbgln_if(SIGNAL_DEBUG, "Setting up user stack to return to RIP {:p}, RSP {:p}", ret_rip, old_rsp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
// Align the stack to 16 bytes.
|
// Align the stack to 16 bytes.
|
||||||
@ -963,14 +946,14 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
FlatPtr stack_alignment = (stack - 8) % 16;
|
FlatPtr stack_alignment = (stack - 8) % 16;
|
||||||
stack -= stack_alignment;
|
stack -= stack_alignment;
|
||||||
|
|
||||||
push_value_on_user_stack(stack, ret_eflags);
|
push_value_on_user_stack(stack, ret_flags);
|
||||||
|
|
||||||
push_value_on_user_stack(stack, ret_eip);
|
push_value_on_user_stack(stack, ret_ip);
|
||||||
push_value_on_user_stack(stack, state.eax);
|
push_value_on_user_stack(stack, state.eax);
|
||||||
push_value_on_user_stack(stack, state.ecx);
|
push_value_on_user_stack(stack, state.ecx);
|
||||||
push_value_on_user_stack(stack, state.edx);
|
push_value_on_user_stack(stack, state.edx);
|
||||||
push_value_on_user_stack(stack, state.ebx);
|
push_value_on_user_stack(stack, state.ebx);
|
||||||
push_value_on_user_stack(stack, old_esp);
|
push_value_on_user_stack(stack, old_sp);
|
||||||
push_value_on_user_stack(stack, state.ebp);
|
push_value_on_user_stack(stack, state.ebp);
|
||||||
push_value_on_user_stack(stack, state.esi);
|
push_value_on_user_stack(stack, state.esi);
|
||||||
push_value_on_user_stack(stack, state.edi);
|
push_value_on_user_stack(stack, state.edi);
|
||||||
@ -984,9 +967,9 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
FlatPtr stack_alignment = stack % 16;
|
FlatPtr stack_alignment = stack % 16;
|
||||||
stack -= 128 + stack_alignment;
|
stack -= 128 + stack_alignment;
|
||||||
|
|
||||||
push_value_on_user_stack(stack, ret_rflags);
|
push_value_on_user_stack(stack, ret_flags);
|
||||||
|
|
||||||
push_value_on_user_stack(stack, ret_rip);
|
push_value_on_user_stack(stack, ret_ip);
|
||||||
push_value_on_user_stack(stack, state.r15);
|
push_value_on_user_stack(stack, state.r15);
|
||||||
push_value_on_user_stack(stack, state.r14);
|
push_value_on_user_stack(stack, state.r14);
|
||||||
push_value_on_user_stack(stack, state.r13);
|
push_value_on_user_stack(stack, state.r13);
|
||||||
@ -999,7 +982,7 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
push_value_on_user_stack(stack, state.rcx);
|
push_value_on_user_stack(stack, state.rcx);
|
||||||
push_value_on_user_stack(stack, state.rdx);
|
push_value_on_user_stack(stack, state.rdx);
|
||||||
push_value_on_user_stack(stack, state.rbx);
|
push_value_on_user_stack(stack, state.rbx);
|
||||||
push_value_on_user_stack(stack, old_rsp);
|
push_value_on_user_stack(stack, old_sp);
|
||||||
push_value_on_user_stack(stack, state.rbp);
|
push_value_on_user_stack(stack, state.rbp);
|
||||||
push_value_on_user_stack(stack, state.rsi);
|
push_value_on_user_stack(stack, state.rsi);
|
||||||
push_value_on_user_stack(stack, state.rdi);
|
push_value_on_user_stack(stack, state.rdi);
|
||||||
@ -1014,11 +997,7 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
|
|
||||||
// We write back the adjusted stack value into the register state.
|
// We write back the adjusted stack value into the register state.
|
||||||
// We have to do this because we can't just pass around a reference to a packed field, as it's UB.
|
// We have to do this because we can't just pass around a reference to a packed field, as it's UB.
|
||||||
#if ARCH(I386)
|
state.set_userspace_sp(stack);
|
||||||
state.userspace_esp = stack;
|
|
||||||
#else
|
|
||||||
state.userspace_rsp = stack;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VERIFY((stack % 16) == 0);
|
VERIFY((stack % 16) == 0);
|
||||||
};
|
};
|
||||||
@ -1030,7 +1009,7 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
|
|||||||
auto& regs = get_register_dump_from_stack();
|
auto& regs = get_register_dump_from_stack();
|
||||||
setup_stack(regs);
|
setup_stack(regs);
|
||||||
auto signal_trampoline_addr = process.signal_trampoline().get();
|
auto signal_trampoline_addr = process.signal_trampoline().get();
|
||||||
regs.set_ip_reg(signal_trampoline_addr);
|
regs.set_ip(signal_trampoline_addr);
|
||||||
|
|
||||||
dbgln_if(SIGNAL_DEBUG, "Thread in state '{}' has been primed with signal handler {:#04x}:{:p} to deliver {}", state_string(), m_regs.cs, m_regs.ip(), signal);
|
dbgln_if(SIGNAL_DEBUG, "Thread in state '{}' has been primed with signal handler {:#04x}:{:p} to deliver {}", state_string(), m_regs.cs, m_regs.ip(), signal);
|
||||||
|
|
||||||
|
@ -105,11 +105,23 @@ struct ThreadRegisters {
|
|||||||
FlatPtr rsp0;
|
FlatPtr rsp0;
|
||||||
#endif
|
#endif
|
||||||
FlatPtr cs;
|
FlatPtr cs;
|
||||||
|
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
FlatPtr eflags;
|
FlatPtr eflags;
|
||||||
|
FlatPtr flags() const { return eflags; }
|
||||||
|
void set_flags(FlatPtr value) { eflags = value; }
|
||||||
|
void set_sp(FlatPtr value) { esp = value; }
|
||||||
|
void set_sp0(FlatPtr value) { esp0 = value; }
|
||||||
|
void set_ip(FlatPtr value) { eip = value; }
|
||||||
#else
|
#else
|
||||||
FlatPtr rflags;
|
FlatPtr rflags;
|
||||||
|
FlatPtr flags() const { return rflags; }
|
||||||
|
void set_flags(FlatPtr value) { rflags = value; }
|
||||||
|
void set_sp(FlatPtr value) { rsp = value; }
|
||||||
|
void set_sp0(FlatPtr value) { rsp0 = value; }
|
||||||
|
void set_ip(FlatPtr value) { rip = value; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FlatPtr cr3;
|
FlatPtr cr3;
|
||||||
|
|
||||||
FlatPtr ip() const
|
FlatPtr ip() const
|
||||||
|
Loading…
Reference in New Issue
Block a user