1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 08:58:11 +00:00

Kernel: Implement software context switching and Processor structure

Moving certain globals into a new Processor structure for
each CPU allows us to eventually run an instance of the
scheduler on each CPU.
This commit is contained in:
Tom 2020-06-27 13:42:28 -06:00 committed by Andreas Kling
parent 10407061d2
commit fb41d89384
22 changed files with 1002 additions and 513 deletions

View file

@ -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;