About half of the Processor code is common across architectures, so
let's share it with a templated base class. Also, other code that can be
shared in some ways, like FPUState and TrapFrame functions, is adjusted
here. Functions which cannot be shared trivially (without internal
refactoring) are left alone for now.
Setting the page table base register (ttbr0_el1) is not enough, and will
not flush the TLB caches, in contrary with x86_64 where setting the CR3
register will actually flush the caches. This commit adds the necessary
code to properly flush the TLB caches when context switching. This
commit also changes Processor::flush_tlb_local to use the vmalle1
variant, as previously we would be flushing the tlb's of all the cores
in the inner-shareable domain.
The details of the specific interrupt bits that must be turned on are
irrelevant to the sys$execve implementation. Abstract it away to the
Processor implementations using the InterruptsState enum.
This commit adds Processor::set_thread_specific_data, and this function
is used to factor out architecture specific implementation of setting
the thread specific data. This function is implemented for
aarch64 and x86_64, and the callsites are changed to use this function
instead.
These instances were detected by searching for files that include
Array.h, but don't match the regex:
\\b(Array(?!\.h>)|iota_array|integer_sequence_generate_array)\\b
These are the three symbols defined by Array.h.
In theory, one might use LibCPP to detect things like this
automatically, but let's do this one step after another.
For pause we use isb sy which will put the processor to sleep while the
pipeline is being flushed. This instruction is also used by Rust in spin
loops and found to be more efficient, as well as being a rough
equivalent to the x86 pause instruction which we also use here.
For wait_check we use yield, which is a hinted nop that is faster to
execute, and I leave a FIXME for processing SMP messages once we support
SMP.
These two changes probably make spin loops work on aarch64 :^)
I can't think of a reason why copying the Processor class makes sense,
so lets make sure it's not possible to do it by accident by declaring
the copy constructor as deleted.
This removes the x86 specific hlt instruction from the scheduler, and
allows us to run the scheduler code for aarch64 by implementing
Processor::wait_for_interrupt for aarch64.
Having this function return `nullptr` explicitly triggers the compiler's
inbuilt checker, as it knows the destination is null. Having this as a
static (scoped) variable for now circumvents this problem.
This makes it easier to differentiate between cases where certain
functionality is not implemented vs. cases where a code location
should really be unreachable.
In a few places we check `!Processor::in_critical()` to validate
that the current processor doesn't hold any kernel spinlocks.
Instead lets provide it a first class name for readability.
I'll also be adding more of these, so I would rather add more
usages of a nice API instead of this implicit/assumed logic.
Instead of storing the current Processor into a core local register, we
currently just store it into a global, since we don't support SMP for
aarch64 anyway. This simplifies the initial implementation.
These functions are called by kmalloc, and since there is no support for
threading in the aarch64 build yet, we can simply remove the
VERIFY_NOT_REACHED().
When calling dbgln(), the formatting code in AK/Format.h calls
Processor::is_initialized() to determine whether to add some text about
the current processor to the debug output. Instead of crashing, we just
return false, such that we can use dbgln() etc in the aarch64 Kernel.