summaryrefslogtreecommitdiff
path: root/Kernel/Process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Process.cpp')
-rw-r--r--Kernel/Process.cpp51
1 files changed, 26 insertions, 25 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index dc773828d4..ad85ed1c7b 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -859,9 +859,17 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
// No other thread from this process will be scheduled to run
m_exec_tid = Thread::current->tid();
- auto old_page_directory = move(m_page_directory);
- auto old_regions = move(m_regions);
- m_page_directory = PageDirectory::create_for_userspace(*this);
+ RefPtr<PageDirectory> old_page_directory;
+ NonnullOwnPtrVector<Region> old_regions;
+
+ {
+ // Need to make sure we don't swap contexts in the middle
+ InterruptDisabler disabler;
+ old_page_directory = move(m_page_directory);
+ old_regions = move(m_regions);
+ m_page_directory = PageDirectory::create_for_userspace(*this);
+ }
+
#ifdef MM_DEBUG
dbg() << "Process " << pid() << " exec: PD=" << m_page_directory.ptr() << " created";
#endif
@@ -898,6 +906,8 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
{
ArmedScopeGuard rollback_regions_guard([&]() {
ASSERT(Process::current == this);
+ // Need to make sure we don't swap contexts in the middle
+ InterruptDisabler disabler;
m_page_directory = move(old_page_directory);
m_regions = move(old_regions);
MM.enter_process_paging_scope(*this);
@@ -1028,7 +1038,7 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
// and we don't want to deal with faults after this point.
u32 new_userspace_esp = new_main_thread->make_userspace_stack_for_main_thread(move(arguments), move(environment));
- // We cli() manually here because we don't want to get interrupted between do_exec() and Schedule::yield().
+ // We cli() manually here because we don't want to get interrupted between do_exec() and Processor::assume_context().
// The reason is that the task redirection we've set up above will be clobbered by the timer IRQ.
// If we used an InterruptDisabler that sti()'d on exit, we might timer tick'd too soon in exec().
if (Process::current == this)
@@ -1036,15 +1046,9 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
// NOTE: Be careful to not trigger any page faults below!
- Scheduler::prepare_to_modify_tss(*new_main_thread);
-
m_name = parts.take_last();
new_main_thread->set_name(m_name);
- auto& tss = new_main_thread->m_tss;
-
- u32 old_esp0 = tss.esp0;
-
m_master_tls_size = master_tls_size;
m_master_tls_alignment = master_tls_alignment;
@@ -1052,25 +1056,21 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve
new_main_thread->make_thread_specific_region({});
new_main_thread->reset_fpu_state();
- memset(&tss, 0, sizeof(TSS32));
- tss.iomapbase = sizeof(TSS32);
-
- tss.eflags = 0x0202;
+ // NOTE: if a context switch were to happen, tss.eip and tss.esp would get overwritten!!!
+ auto& tss = new_main_thread->m_tss;
+ tss.cs = GDT_SELECTOR_CODE3 | 3;
+ tss.ds = GDT_SELECTOR_DATA3 | 3;
+ tss.es = GDT_SELECTOR_DATA3 | 3;
+ tss.ss = GDT_SELECTOR_DATA3 | 3;
+ tss.fs = GDT_SELECTOR_DATA3 | 3;
+ tss.gs = GDT_SELECTOR_TLS | 3;
tss.eip = entry_eip;
- tss.cs = 0x1b;
- tss.ds = 0x23;
- tss.es = 0x23;
- tss.fs = 0x23;
- tss.gs = thread_specific_selector() | 3;
- tss.ss = 0x23;
- tss.cr3 = page_directory().cr3();
tss.esp = new_userspace_esp;
- tss.ss0 = 0x10;
- tss.esp0 = old_esp0;
+ tss.cr3 = m_page_directory->cr3();
tss.ss2 = m_pid;
#ifdef TASK_DEBUG
- klog() << "Process exec'd " << path.characters() << " @ " << String::format("%p", tss.eip);
+ klog() << "Process exec'd " << path.characters() << " @ " << String::format("%p", entry_eip);
#endif
if (was_profiling)
@@ -1261,7 +1261,8 @@ int Process::exec(String path, Vector<String> arguments, Vector<String> environm
}
if (Process::current == this) {
- Scheduler::yield();
+ Thread::current->set_state(Thread::State::Running);
+ Processor::assume_context(*Thread::current);
ASSERT_NOT_REACHED();
}
return 0;