summaryrefslogtreecommitdiff
path: root/Kernel/Arch
AgeCommit message (Collapse)Author
2021-01-02Kernel: Ignore TLB flush requests for user addresses of other processesTom
If a TLB flush request is broadcast to other processors and the addresses to flush are user mode addresses, we can ignore such a request on the target processor if the page directory currently in use doesn't match the addresses to be flushed. We still need to broadcast to all processors in that case because the other processors may switch to that same page directory at any time.
2020-12-31Everywhere: Re-format with clang-format-11Linus Groh
Compared to version 10 this fixes a bunch of formatting issues, mostly around structs/classes with attributes like [[gnu::packed]], and incorrect insertion of spaces in parameter types ("T &"/"T &&"). I also removed a bunch of // clang-format off/on and FIXME comments that are no longer relevant - on the other hand it tried to destroy a couple of neatly formatted comments, so I had to add some as well.
2020-12-30Kernel: Prevent sign bit extension when creating a PDPTELuke
When doing the cast to u64 on the page directory physical address, the sign bit was being extended. This only beomes an issue when crossing the 2 GiB boundary. At >= 2 GiB, the physical address has the sign bit set. For example, 0x80000000. This set all the reserved bits in the PDPTE, causing a GPF when loading the PDPT pointer into CR3. The reserved bits are presumably there to stop you writing out a physical address that the CPU physically cannot handle, as the size of the reserved bits is determined by the physical address width of the CPU. This fixes this by casting to FlatPtr instead. I believe the sign extension only happens when casting to a bigger type. I'm also using FlatPtr because it's a pointer we're writing into the PDPTE. sizeof(FlatPtr) will always be the same size as sizeof(void*). This also now asserts that the physical address in the PDPTE is within the max physical address the CPU supports. This is better than getting a GPF, because CPU::handle_crash tries to do the same operation that caused the GPF in the first place. That would cause an infinite loop of GPFs until the stack was exhausted, causing a triple fault. As far as I know and tested, I believe we can now use the full 32-bit physical range without crashing. Fixes #4584. See that issue for the full debugging story.
2020-12-26Everywhere: void arguments to C functionsLenny Maiorani
Problem: - C functions with no arguments require a single `void` in the argument list. Solution: - Put the `void` in the argument list of functions in C header files.
2020-12-23Kernel: Panic if we're about to switch to a user thread with IOPL!=0Andreas Kling
This is a crude protection against IOPL elevation attacks. If for any reason we find ourselves about to switch to a user mode thread with IOPL != 0, we'll now simply panic the kernel. If this happens, it basically means that something tricked the kernel into incorrectly modifying the IOPL of a thread, so it's no longer safe to trust the kernel anyway.
2020-12-22Kernel: Don't allow modifying IOPL via sys$ptrace() or sys$sigreturn()Andreas Kling
It was possible to overwrite the entire EFLAGS register since we didn't do any masking in the ptrace and sigreturn syscalls. This made it trivial to gain IO privileges by raising IOPL to 3 and then you could talk to hardware to do all kinds of nasty things. Thanks to @allesctf for finding these issues! :^) Their exploit/write-up: https://github.com/allesctf/writeups/blob/master/2020/hxpctf/wisdom2/writeup.md
2020-12-21Kernel: Allow to install a real IRQ handler on a spurious oneLiav A
IRQ 7 and 15 on the PIC architecture are used for spurious interrupts. IRQ 7 could also be used for LPT connection, and IRQ 15 can be used for the secondary IDE channel. Therefore, we need to allow to install a real IRQ handler and check if a real IRQ was asserted. If so, we handle them in the usual way. A note on this fix - unregistering or registering a new IRQ handler after we already registered one in the spurious interrupt handler is not supported yet.
2020-12-21Everywhere: Switch from (void) to [[maybe_unused]] (#4473)Lenny Maiorani
Problem: - `(void)` simply casts the expression to void. This is understood to indicate that it is ignored, but this is really a compiler trick to get the compiler to not generate a warning. Solution: - Use the `[[maybe_unused]]` attribute to indicate the value is unused. Note: - Functions taking a `(void)` argument list have also been changed to `()` because this is not needed and shows up in the same grep command.
2020-12-12Kernel: Change wait blocking to Process-only blockingTom
This prevents zombies created by multi-threaded applications and brings our model back to closer to what other OSs do. This also means that SIGSTOP needs to halt all threads, and SIGCONT needs to resume those threads.
2020-12-12Kernel: Fix some issues related to fixes and block conditionsTom
Fix some problems with join blocks where the joining thread block condition was added twice, which lead to a crash when trying to unblock that condition a second time. Deferred block condition evaluation by File objects were also not properly keeping the File object alive, which lead to some random crashes and corruption problems. Other problems were caused by the fact that the Queued state didn't handle signals/interruptions consistently. To solve these issues we remove this state entirely, along with Thread::wait_on and change the WaitQueue into a BlockCondition instead. Also, deliver signals even if there isn't going to be a context switch to another thread. Fixes #4336 and #4330
2020-12-02Kernel: Flush TLBs concurrentlyTom
Instead of flushing the TLB on the current processor first and then notifying the other processors to do the same, notify the others first, and while waiting on the others flush our own.
2020-12-02Kernel: Fix counting interruptsTom
Move counting interrupts out of the handle_interrupt method so that it is done in all cases without the interrupt handler having to implement it explicitly. Also make the counter an atomic value as e.g. the LocalAPIC interrupts may be triggered on multiple processors simultaneously. Fixes #4297
2020-12-01Kernel: Fix some problems with Thread::wait_on and LockTom
This changes the Thread::wait_on function to not enable interrupts upon leaving, which caused some problems with page fault handlers and in other situations. It may now be called from critical sections, with interrupts enabled or disabled, and returns to the same state. This also requires some fixes to Lock. To aid debugging, a new define LOCK_DEBUG is added that enables checking for Lock leaks upon finalization of a Thread.
2020-11-30Kernel: Allow passing a thread argument for new kernel threadsTom
This adds the ability to pass a pointer to kernel thread/process. Also add the ability to use a closure as thread function, which allows passing information to a kernel thread more easily.
2020-11-11Kernel: Fix deadlock when unicasting/broadcasting SMP messageTom
When two processors send each others a SMP message at the same time they need to process messages while waiting for delivery of the message they just sent, or they will deadlock.
2020-11-11Kernel: Implement capturing stack trace on a different CPUTom
When trying to get a stack trace of a thread on another CPU we send a SMP message to that processor to capture the stack trace for us.
2020-11-11Kernel: Make m_halt_requested an atomic variableTom
We need to make sure the change to this variable is visible to all processors instantly.
2020-11-04Kernel: Add mechanism to queue deferred function callsTom
Function calls that are deferred will be executed before a thread enters a pre-emptable state (meaning it is not in a critical section and it is not in an irq handler). If it is not already in such a state, it will be called immediately. This is meant to be used from e.g. IRQ handlers where we might want to block a thread until an interrupt happens.
2020-10-26Kernel: Halt all processors on assertion failureTom
2020-10-26Kernel: Fix race condition waiting for IPI while other CPU requested haltTom
It's possible that we broadcast an IPI message right at the same time another processor requests a halt. Rather than spinning forever waiting for that message to be handled, check if we should halt while waiting.
2020-10-20Everywhere: Redundant inline specifier on constexpr functions (#3807)Lenny Maiorani
Problem: - `constexpr` functions are decorated with the `inline` specifier keyword. This is redundant because `constexpr` functions are implicitly `inline`. - [dcl.constexpr], ยง7.1.5/2 in the C++11 standard): "constexpr functions and constexpr constructors are implicitly inline (7.1.2)". Solution: - Remove the redundant `inline` keyword.
2020-10-08Kernel: Add some CPU feature flags related to TSCNico Weber
In case we want to rely more on TSC in time keeping in the future, idk This adds: - RDTSCP, for when the RDTSCP instruction is available - CONSTANT_TSC, for when the TSC has a constant frequency, invariant under things like the CPU boosting its frequency. - NONSTOP_TSC, for when the TSC doesn't pause when the CPU enters sleep states. AMD cpus and newer intel cpus set the INVSTC bit (bit 8 in edx of extended cpuid 0x8000000008), which implies both CONSTANT_TSC and NONSTOP_TSC. Some older intel processors have CONSTANT_TSC but not NONSTOP_TSC; this is set based on cpu model checks. There isn't a ton of documentation on this, so this follows Linux terminology and http://blog.tinola.com/?e=54 CONSTANT_TSC: https://github.com/torvalds/linux/commit/39b3a7910556005a7a0d042ecb7ff98bfa84ea57 NONSTOP_TSC: https://github.com/torvalds/linux/commit/40fb17152c50a69dc304dd632131c2f41281ce44 qemu disables invtsc (bit 8 in edx of extended cpuid 0x8000000008) by default even if the host cpu supports it. It can be enabled by running with `SERENITY_QEMU_CPU=host,migratable=off` set.
2020-10-03Everywhere: Fix more typosLinus Groh
2020-09-25Meta+Kernel: Make clang-format-10 cleanBen Wiederhake
2020-09-14Kernel: Handle safe_memcpy/safe_memset/safe_strnlen faults in irq handlersTom
Fix gracefully failing these calls if used within IRQ handlers. If we're handling IRQs, we need to handle these failures first, because we can't really resolve page faults in a meaningful way. But if we know that it was one of these functions that failed, then we can gracefully handle the situation. This solves a crash where the Scheduler attempts to produce backtraces in the timer irq, some of which cause faults. Fixes #3492
2020-09-13Kernel: Make copy_to/from_user safe and remove unnecessary checksTom
Since the CPU already does almost all necessary validation steps for us, we don't really need to attempt to do this. Doing it ourselves doesn't really work very reliably, because we'd have to account for other processors modifying virtual memory, and we'd have to account for e.g. pages not being able to be allocated due to insufficient resources. So change the copy_to/from_user (and associated helper functions) to use the new safe_memcpy, which will return whether it succeeded or not. The only manual validation step needed (which the CPU can't perform for us) is making sure the pointers provided by user mode aren't pointing to kernel mappings. To make it easier to read/write from/to either kernel or user mode data add the UserOrKernelBuffer helper class, which will internally either use copy_from/to_user or directly memcpy, or pass the data through directly using a temporary buffer on the stack. Last but not least we need to keep syscall params trivial as we need to copy them from/to user mode using copy_from/to_user.
2020-09-13Kernel: Add safe_memcpy, safe_memset and safe_strnlenTom
These special functions can be used to safely copy/set memory or determine the length of a string, e.g. provided by user mode. In the event of a page fault, safe_memcpy/safe_memset will return false and safe_strnlen will return -1.
2020-09-10Kernel: Rename Process::is_ring0/3 to Process::is_kernel/user_processTom
Since "rings" typically refer to code execution and user processes can also execute in ring 0, rename these functions to more accurately describe what they mean: kernel processes and user processes.
2020-09-10Kernel: Fix detecting in what ring a crash happenedTom
The ring is determined based on the CS register. This fixes crashes being handled as ring 3 crashes even though EIP/CS clearly showed that the crash happened in the kernel.
2020-08-31Kernel: Fix Processor::features_string() stopping too early and detect more โ†ตLuke
features The exit condition for the loop was sizeof(m_features) * 8, which was 32. Presumably this was supposed to mean 32 bits, but it actually made it stop as soon as it reached the 6th bit. Also add detection for more SIMD CPU features.
2020-08-28Kernel: Release page tables when no longer neededTom
When unmapping regions, check if page tables can be freed. This is a follow-up change for #3254.
2020-08-19Kernel: Remove unneeded #include in ProcessorInfo.cpp (#3211)Muhammad Zahalqa
2020-08-18Kernel: ProcessorInfo.cpp remove unused headersMuhammad Zahalqa
2020-08-16AK: Rename KB, MB, GB to KiB, MiB, GiBNico Weber
The SI prefixes "k", "M", "G" mean "10^3", "10^6", "10^9". The IEC prefixes "Ki", "Mi", "Gi" mean "2^10", "2^20", "2^30". Let's use the correct name, at least in code. Only changes the name of the constants, no other behavior change.
2020-08-15Kernel: Fix behaviour of PT_TRACEME in ptraceItamar
The behaviour of the PT_TRACEME feature has been broken for some time, this change fixes it. When this ptrace flag is used, the traced process should be paused before exiting execve. We previously were sending the SIGSTOP signal at a stage where interrupts are disabled, and the traced process continued executing normally, without pausing and waiting for the tracer. This change fixes it.
2020-08-12Kernel: Tell compiler about invisible callsBen Wiederhake
This makes the Kernel build cleanly with -Wmissing-declarations.
2020-08-02Kernel: Prevent recursive calls into the schedulerTom
Upon leaving a critical section (such as a SpinLock) we need to check if we're already asynchronously invoking the Scheduler. Otherwise we might end up triggering another context switch as soon as leaving the scheduler lock. Fixes #2883
2020-08-01Kernel: Tell the bootloader to put us into graphics modeetaIneLp
2020-07-15LibC+Kernel: Start implementing sysconfNico Weber
For now, only the non-standard _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are implemented. Use them to make ninja pick a better default -j value. While here, make the ninja package script not fail if no other port has been built yet.
2020-07-09Kernel: Fix some flaws that caused crashes or hangs during bootTom
We need to halt the BSP briefly until all APs are ready for the first context switch, but we can't hold the same spinlock by all of them while doing so. So, while the APs are waiting on each other they need to release the scheduler lock, and then once signaled re-acquire it. Should solve some timing dependent hangs or crashes, most easily observed using qemu with kvm disabled.
2020-07-08Kernel: Detect syscall/sysenter supportTom
2020-07-06Kernel: Aggregate TLB flush requests for Regions for SMPTom
Rather than sending one TLB flush request for each page, aggregate them so that we're not spamming the other processors with FlushTLB IPIs.
2020-07-06Kernel: Add SMP IPI supportTom
We can now properly initialize all processors without crashing by sending SMP IPI messages to synchronize memory between processors. We now initialize the APs once we have the scheduler running. This is so that we can process IPI messages from the other cores. Also rework interrupt handling a bit so that it's more of a 1:1 mapping. We need to allocate non-sharable interrupts for IPIs. This also fixes the occasional hang/crash because all CPUs now synchronize memory with each other.
2020-07-06Kernel: Thread::wait_on() must always leave interrupts enabled on exitAndreas Kling
The short-circuit path added for waiting on a queue that already had a pending wake was able to return with interrupts disabled, which breaks the API contract of wait_on() always returning with IF=1. Fix this by adding a way to override the restored IF in ScopedCritical.
2020-07-06Kernel: Tidy up the ScopedCritical class a little bitAndreas Kling
2020-07-06Kernel: Various context switch fixesTom
These changes solve a number of problems with the software context swithcing: * The scheduler lock really should be held throughout context switches * Transitioning from the initial (idle) thread to another needs to hold the scheduler lock * Transitioning from a dying thread to another also needs to hold the scheduler lock * Dying threads cannot necessarily be finalized if they haven't switched out of it yet, so flag them as active while a processor is running it (the Running state may be switched to Dying while it still is actually running)
2020-07-03Kernel: Fix retreiving frame pointer from a threadTom
If we're trying to walk the stack for another thread, we can no longer retreive the EBP register from Thread::m_tss. Instead, we need to look at the top of the kernel stack, because all threads not currently running were last in kernel mode. Context switches now always trigger a brief switch to kernel mode, and Thread::m_tss only is used to save ESP and EIP. Fixes #2678
2020-07-03Kernel: Consolidate features into CPUFeature enumTom
This allows us to consolidate printing out all the CPU features into one log statement. Also expose them in /proc/cpuinfo
2020-07-03Kernel: Fix signal deliveryTom
When delivering urgent signals to the current thread we need to check if we should be unblocked, and if not we need to yield to another process. We also need to make sure that we suppress context switches during Process::exec() so that we don't clobber the registers that it sets up (eip mainly) by a context switch. To be able to do that we add the concept of a critical section, which are similar to Process::m_in_irq but different in that they can be requested at any time. Calls to Scheduler::yield and Scheduler::donate_to will return instantly without triggering a context switch, but the processor will then asynchronously trigger a context switch once the critical section is left.
2020-07-03Kernel: Split initialization of Processor structureTom
We need to very early on initialize the Processor structure so that we can use RecursiveSpinLock early on.