summaryrefslogtreecommitdiff
path: root/Kernel/Arch
AgeCommit message (Collapse)Author
2021-02-08Kernel: Reorganize ptrace implementation a bitAndreas Kling
The generic parts of ptrace now live in Kernel/Syscalls/ptrace.cpp and the i386 specific parts are moved to Arch/i386/CPU.cpp
2021-02-08Everywhere: Replace dbgln<flag>(...) with dbgln_if(flag, ...)AnotherTest
Replacement made by `find Kernel Userland -name '*.h' -o -name '*.cpp' | sed -i -Ee 's/dbgln\b<(\w+)>\(/dbgln_if(\1, /g'`
2021-02-08Kernel: Make Arch/i386/CPU.cpp safe to run through clang-formatAnotherTest
This file was far too messy, and touching it was a major pain. Also enable clang-format linting on it.
2021-02-02Kernel: Limit the size of stack tracesAndreas Kling
Let's not allow infinitely long stack traces. Cap it at 4096 frames.
2021-01-27Kernel: Track processor idle state and wake processors when waking threadsTom
Attempt to wake idle processors to get threads to be scheduled more quickly. We don't want to wait until the next timer tick if we have processors that aren't doing anything.
2021-01-27Kernel: Make Processor::id a static functionTom
This eliminates the window between calling Processor::current and the member function where a thread could be moved to another processor. This is generally not as big of a concern as with Processor::current_thread, but also slightly more light weight.
2021-01-27Kernel: Make Thread::current smp-safeTom
Change Thread::current to be a static function and read using the fs register, which eliminates a window between Processor::current() returning and calling a function on it, which can trigger preemption and a move to a different processor, which then causes operating on the wrong object.
2021-01-27Kernel: Make entering and leaving critical sections atomicTom
We also need to store m_in_critical in the Thread upon switching, and we need to restore it. This solves a problem where threads moving between different processors could end up with an unexpected value.
2021-01-27Kernel: Track previous mode when entering/exiting trapsTom
This allows us to determine what the previous mode (user or kernel) was, e.g. in the timer interrupt. This is used e.g. to determine whether a signal handler should be set up. Fixes #5096
2021-01-26Meta: Split debug defines into multiple headers.asynts
The following script was used to make these changes: #!/bin/bash set -e tmp=$(mktemp -d) echo "tmp=$tmp" find Kernel \( -name '*.cpp' -o -name '*.h' \) | sort > $tmp/Kernel.files find . \( -path ./Toolchain -prune -o -path ./Build -prune -o -path ./Kernel -prune \) -o \( -name '*.cpp' -o -name '*.h' \) -print | sort > $tmp/EverythingExceptKernel.files cat $tmp/Kernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/Kernel.macros cat $tmp/EverythingExceptKernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/EverythingExceptKernel.macros comm -23 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/Kernel.unique comm -1 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/EverythingExceptKernel.unique cat $tmp/Kernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/Kernel.header cat $tmp/EverythingExceptKernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/EverythingExceptKernel.header for macro in $(cat $tmp/Kernel.unique) do cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.new-includes ||: done cat $tmp/Kernel.new-includes | sort > $tmp/Kernel.new-includes.sorted for macro in $(cat $tmp/EverythingExceptKernel.unique) do cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.old-includes ||: done cat $tmp/Kernel.old-includes | sort > $tmp/Kernel.old-includes.sorted comm -23 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.new comm -13 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.old comm -12 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.mixed for file in $(cat $tmp/Kernel.includes.new) do sed -i -E 's/#include <AK\/Debug\.h>/#include <Kernel\/Debug\.h>/' $file done for file in $(cat $tmp/Kernel.includes.mixed) do echo "mixed include in $file, requires manual editing." done
2021-01-25Kernel: Fix possible context switch within first context switch of a threadTom
We were enabling interrupts too early, before the first context switch to a thread was complete. This could then trigger another context switch within the context switch, which lead to a crash.
2021-01-25Everywhere: Debug macros instead of constexpr.asynts
This was done with the following script: find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec sed -i -E 's/dbgln<debug_([a-z_]+)>/dbgln<\U\1_DEBUG>/' {} \; find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec sed -i -E 's/if constexpr \(debug_([a-z0-9_]+)/if constexpr \(\U\1_DEBUG/' {} \;
2021-01-25Everywhere: Use CMake to generate AK/Debug.h.asynts
This was done with the help of several scripts, I dump them here to easily find them later: awk '/#ifdef/ { print "#cmakedefine01 "$2 }' AK/Debug.h.in for debug_macro in $(awk '/#ifdef/ { print $2 }' AK/Debug.h.in) do find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec sed -i -E 's/#ifdef '$debug_macro'/#if '$debug_macro'/' {} \; done # Remember to remove WRAPPER_GERNERATOR_DEBUG from the list. awk '/#cmake/ { print "set("$2" ON)" }' AK/Debug.h.in
2021-01-24Kernel: Make use of interrupts as an entropy sourceJean-Baptiste Boric
Booting old computers without RDRAND/RDSEED and without a disk makes the system severely starved for entropy. Uses interrupts as a source to side-step that issue. Also warn whenever the system is starved of entropy, because that's a non-obvious failure mode.
2021-01-22Everywhere: Replace a bundle of dbg with dbgln.asynts
These changes are arbitrarily divided into multiple commits to make it easier to find potentially introduced bugs with git bisect.
2021-01-21Kernel: Don't let signals unblock threads while handling a page faultAndreas Kling
It was possible to signal a process while it was paging in an inode backed VM object. This would cause the inode read to EINTR, and the page fault handler would assert. Solve this by simply not unblocking threads due to signals if they are currently busy handling a page fault. This is probably not the best way to solve this issue, so I've added a FIXME to that effect.
2021-01-19Boot: Fix undefined Multiboot behaviorsJean-Baptiste Boric
Both ESP and GDTR are left undefined by the Multiboot specification and OS images must not rely on these values to be valid. Fix the undefined behaviors so that booting with PXELINUX does not triple-fault the CPU.
2021-01-17Kernel: Add safe atomic functionsTom
This allows us to perform atomic operations on potentially unsafe user space pointers.
2021-01-11Everywhere: Replace a bundle of dbg with dbgln.asynts
These changes are arbitrarily divided into multiple commits to make it easier to find potentially introduced bugs with git bisect.Everything:
2021-01-11Everywhere: Replace a bundle of dbg with dbgln.asynts
These changes are arbitrarily divided into multiple commits to make it easier to find potentially introduced bugs with git bisect.Everything:
2021-01-09Everywhere: Replace a bundle of dbg with dbgln.asynts
These changes are arbitrarily divided into multiple commits to make it easier to find potentially introduced bugs with git bisect.Everything: The modifications in this commit were automatically made using the following command: find . -name '*.cpp' -exec sed -i -E 's/dbg\(\) << ("[^"{]*");/dbgln\(\1\);/' {} \;
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.