Commit graph

92 commits

Author SHA1 Message Date
Andreas Kling
6eb48f7df6 Kernel: Consolidate kmalloc_aligned() and use kfree_sized() within
This patch does two things:

- Combines kmalloc_aligned() and kmalloc_aligned_cxx(). Templatizing
  the alignment parameter doesn't seem like a valuable enough
  optimization to justify having two almost-identical implementations.

- Stores the real allocation size of an aligned allocation along with
  the other alignment metadata, and uses it to call kfree_sized()
  instead of kfree().
2021-12-26 21:22:59 +01:00
Idan Horowitz
7757d874ad Kernel: Assert that a KmallocSubheap fits inside a page
Since we allocate the subheap in the first page of the given storage
let's assert that the subheap can actually fit in a single page, to
prevent the possible future headache of trying to debug the cause of
random kernel memory corruption :^)
2021-12-26 11:26:39 +01:00
Andreas Kling
1c99f99e99 Kernel: Make kmalloc expansions scale to incoming allocation request
This allows kmalloc() to satisfy arbitrary allocation requests instead
of being limited to a static subheap expansion size.
2021-12-26 10:43:07 +01:00
Andreas Kling
f49649645c Kernel: Allocate page tables for the entire kmalloc VM range up front
This avoids getting caught with our pants down when heap expansion fails
due to missing page tables. It also avoids a circular dependency on
kmalloc() by way of HashMap::set() in MemoryManager::ensure_pte().
2021-12-26 02:42:49 +01:00
Andreas Kling
d58880b5b0 Kernel: Write to debug log when creating new kmalloc subheaps 2021-12-26 01:25:02 +01:00
Andreas Kling
4d585cdb82 Kernel: Set NX bit on expanded kmalloc memory mappings if supported
We never want to execute kmalloc memory.
2021-12-25 22:07:59 +01:00
Andreas Kling
f7a4c34929 Kernel: Make kmalloc heap expansion kmalloc-free
Previously, the heap expansion logic could end up calling kmalloc
recursively, which was quite messy and hard to reason about.

This patch redesigns heap expansion so that it's kmalloc-free:

- We make a single large virtual range allocation at startup
- When expanding, we bump allocate VM from that region
- When expanding, we populate page tables directly ourselves,
  instead of going via MemoryManager.

This makes heap expansion a great deal simpler. However, do note that it
introduces two new flaws that we'll need to deal with eventually:

- The single virtual range allocation is limited to 64 MiB and once
  exhausted, kmalloc() will fail. (Actually, it will PANIC for now..)

- The kmalloc heap can no longer shrink once expanded. Subheaps stay
  in place once constructed.
2021-12-25 22:07:59 +01:00
Andreas Kling
b443e9e1a9 Kernel: Use a larger kmalloc chunk size on 64-bit platforms
This reduces test-js runtime by over 40% on my machine.

(And once again we find another way to defer writing a better kernel
heap allocator..)
2021-10-26 10:38:35 +02:00
Brian Gianforcaro
92844a6af6 Kernel: Access Processor static methods statically
SonarCloud flagged this "Code Smell", where we are accessing these
static methods as if they are instance methods. While it is technically
possible, it is very confusing to read when you realize they are static
functions.
2021-10-02 18:16:15 +02:00
Andreas Kling
75564b4a5f Kernel: Make kernel region allocators return KResultOr<NOP<Region>>
This expands the reach of error propagation greatly throughout the
kernel. Sadly, it also exposes the fact that we're allocating (and
doing other fallible things) in constructors all over the place.

This patch doesn't attempt to address that of course. That's work for
our future selves.
2021-09-06 01:55:27 +02:00
Brian Gianforcaro
9d1b27263f Kernel: Declare type aliases with "using" instead of "typedef"
This is the idiomatic way to declare type aliases in modern C++.
Flagged by Sonar Cloud as a "Code Smell", but I happen to agree
with this particular one. :^)
2021-09-05 09:48:43 +01:00
Andreas Kling
c922a7da09 Kernel: Rename ScopedSpinlock => SpinlockLocker
This matches MutexLocker, and doesn't sound like it's a lock itself.
2021-08-22 03:34:10 +02:00
Andreas Kling
55adace359 Kernel: Rename SpinLock => Spinlock 2021-08-22 03:34:10 +02:00
Daniel Bertalan
5c7524b1d8 Kernel: Allow aligned operator new to return nullptr
In e7fb70b05, regular kmalloc was changed to return nullptr on
allocation failure instead of crashing. The `kmalloc_aligned_cxx`
wrapper used by the aligned operator new should do the same.
2021-08-13 22:02:23 +02:00
Brian Gianforcaro
e7fb70b05c Kernel: Allow kmalloc(..) / kmalloc_aligned(..) to return nullptr
Now that we have a significant amount of code paths handling OOM, lets
enable kmalloc and friends to actually return nullptr. This way we can
start stressing these paths and validating all of they work as expected.
2021-08-13 11:09:25 +02:00
Andreas Kling
9babb92a4b Kernel/SMP: Make entering/leaving critical sections multi-processor safe
By making these functions static we close a window where we could get
preempted after calling Processor::current() and move to another
processor.

Co-authored-by: Tom <tomut@yahoo.com>
2021-08-10 02:49:37 +02:00
Daniel Bertalan
5d617be462 Kernel: Bump eternal kmalloc range to 4 MiB
Kernels built with Clang seem to be quite allocation-heavy compared to
their GCC counterparts. We would sometimes end up crashing during boot
because the eternal ranges had no free capacity.
2021-08-08 10:55:36 +02:00
Jean-Baptiste Boric
2c3b0baf76 Kernel: Move SpinLock.h into Locking/ 2021-08-07 11:48:00 +02:00
Andreas Kling
2cd8b21974 Kernel: Add convenience values to the Memory::Region::Access enum
Instead of `Memory::Region::Access::Read | Memory::Region::AccessWrite`
you can now say `Memory::Region::Access::ReadWrite`.
2021-08-06 22:25:00 +02:00
Andreas Kling
93d98d4976 Kernel: Move Kernel/Memory/ code into Kernel::Memory namespace 2021-08-06 14:05:58 +02:00
Andreas Kling
a1d7ebf85a Kernel: Rename Kernel/VM/ to Kernel/Memory/
This directory isn't just about virtual memory, it's about all kinds
of memory management.
2021-08-06 14:05:58 +02:00
Daniel Bertalan
dd4ed4d22d Kernel: Implement aligned operator new and use it
The compiler will use these to allocate objects that have alignment
requirements greater than that of our normal `operator new` (4/8 byte
aligned).

This means we can now use smart pointers for over-aligned types.

Fixes a FIXME.
2021-07-16 20:51:13 +02:00
Brian Gianforcaro
661809408e Kernel: Remove unused header includes in Heap subtree 2021-07-11 21:37:38 +02:00
Andreas Kling
25e850ebb1 Kernel: Remove krealloc()
This was only used by a single class (AK::ByteBuffer) in the kernel
and not in an OOM-safe way.

Now that ByteBuffer no longer uses it, there's no need for the kernel
heap to burden itself with supporting this.
2021-07-11 14:14:51 +02:00
Andreas Kling
f684742f15 Kernel: VERIFY_NOT_REACHED in un-sized operator delete
All deletes in kernel code should now be of known size. :^)
2021-07-11 14:14:51 +02:00
Andreas Kling
d38b4e4665 Kernel: Add kfree_sized(), kfree() with a known allocation size
C++14 gave us sized operator delete, but we haven't been taking
advantage of it. Let's get to a point where it can help us by
adding kfree_sized(void*, size_t).
2021-07-11 14:14:51 +02:00
Daniel Bertalan
b9f30c6f2a Everywhere: Fix some alignment issues
When creating uninitialized storage for variables, we need to make sure
that the alignment is correct. Fixes a KUBSAN failure when running
kernels compiled with Clang.

In `Syscalls/socket.cpp`, we can simply use local variables, as
`sockaddr_un` is a POD type.

Along with moving the `alignas` specifier to the correct member,
`AK::Optional`'s internal buffer has been made non-zeroed by default.
GCC emitted bogus uninitialized memory access warnings, so we now use
`__builtin_launder` to tell the compiler that we know what we are doing.
This might disable some optimizations, but judging by how GCC failed to
notice that the memory's initialization is dependent on `m_has_value`,
I'm not sure that's a bad thing.
2021-07-03 01:56:31 +04:30
Gunnar Beutner
d67fd37847 Kernel: Increase kmalloc eternal heap to 3MiB
The kernel wouldn't boot reliably on x86_64 with just 2MiB.
2021-06-28 15:55:00 +02:00
Daniel Bertalan
5491e0cdcc AK+Kernel: Make fallible allocations compiler-agnostic
In standard C++, operators `new` and `new[]` are guaranteed to return a
valid (non-null) pointer and throw an exception if the allocation
couldn't be performed. Based on this, compilers did not check the
returned pointer before attempting to use them for object construction.

To avoid this, the allocator operators were changed to be `noexcept` in
PR #7026, which made GCC emit the desired null checks. Unfortunately,
this is a non-standard feature which meant that Clang would not accept
these function definitions, as it did not match its expected
declaration.

To make compiling using Clang possible, the special "nothrow" versions
of `new` are implemented in this commit. These take a tag type of
`std::nothrow_t` (used for disambiguating from placement new/etc.), and
are allowed by the standard to return null. There is a global variable,
`std::nothrow`, declared with this type, which is also exported into the
global namespace.

To perform fallible allocations, the following syntax should be used:

```cpp
auto ptr = new (nothrow) T;
```

As we don't support exceptions in the kernel, the only way of uphold the
"throwing" new's guarantee is to abort if the allocation couldn't be
performed. Once we have proper OOM handling in the kernel, this should
only be used for critical allocations, where we wouldn't be able to
recover from allocation failures anyway.
2021-06-24 17:35:49 +04:30
Hendiadyoin1
62f9377656 Kernel: Move special sections into Sections.h
This also removes a lot of CPU.h includes infavor for Sections.h
2021-06-24 00:38:23 +02:00
Gunnar Beutner
01c75e3a34 Kernel: Don't log profile data before/after the process/thread lifetime
There were a few cases where we could end up logging profiling events
before or after the associated process or thread exists in the profile:

After enabling profiling we might end up with CPU samples before we
had a chance to synthesize process/thread creation events.

After a thread exits we would still log associated kmalloc/kfree
events. Instead we now just ignore those events.
2021-05-30 19:03:03 +02:00
Gunnar Beutner
277f333b2b Kernel: Add support for profiling kmalloc()/kfree() 2021-05-19 22:51:42 +02:00
Gunnar Beutner
f89e8fb71a AK+LibC: Implement malloc_good_size() and use it for Vector/HashTable
This implements the macOS API malloc_good_size() which returns the
true allocation size for a given requested allocation size. This
allows us to make use of all the available memory in a malloc chunk.

For example, for a malloc request of 35 bytes our malloc would
internally use a chunk of size 64, however the remaining 29 bytes
would be unused.

Knowing the true allocation size allows us to request more usable
memory that would otherwise be wasted and make that available for
Vector, HashTable and potentially other callers in the future.
2021-05-15 16:30:14 +02:00
Brian Gianforcaro
9c38475608 Kernel: Add the ability to verify we don't kmalloc under spinlock.
Ideally we would never allocate under a spinlock, as it has many
performance and potentially functionality (deadlock) pitfalls.

We violate that rule in many places today, but we need a tool to track
them all down and fix them. This change introduces a new macro option
named `KMALLOC_VERIFY_NO_SPINLOCK_HELD` which can catch these
situations at runtime via an assert.
2021-05-14 13:28:21 +02:00
Brian Gianforcaro
97adaaf933 Kernel: Declare operator new/delete as noexcept for the Kernel
For Kernel OOM hardening to work correctly, we need to be able to
call a "nothrow" version of operator new. Unfortunately the default
"throwing" version of operator new assumes that the allocation will
never return on failure and will always throw an exception. This isn't
true in the Kernel, as we don't have exceptions. So if we call the
normal/throwing new and kmalloc returns NULL, the generated code will
happily go and dereference that NULL pointer by invoking the constructor
before we have a chance to handle the failure.

To fix this we declare operator new as noexcept in the Kernel headers,
which will allow the caller to actually handle allocation failure.

The delete implementations need to match the prototype of the new which
allocated them, so we need define delete as noexcept as well. GCC then
errors out declaring that you should implement sized delete as well, so
this change provides those stubs in order to compile cleanly.

Finally the new operator definitions have been standardized as being
declared with [[nodiscard]] to avoid potential memory leaks. So lets
declares the kernel versions that way as well.
2021-05-13 08:29:01 +02:00
Brian Gianforcaro
1682f0b760 Everything: Move to SPDX license identifiers in all files.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.

See: https://spdx.dev/resources/use/#identifiers

This was done with the `ambr` search and replace tool.

 ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-22 11:22:27 +02:00
Hendiadyoin1
0d934fc991 Kernel::CPU: Move headers into common directory
Alot of code is shared between i386/i686/x86 and x86_64
and a lot probably will be used for compatability modes.
So we start by moving the headers into one Directory.
We will probalby be able to move some cpp files aswell.
2021-03-21 09:35:23 +01:00
Andreas Kling
b1e0e2ad4a Kernel: Suppress logging during kmalloc heap expansion
The system is extremely sensitive to heap allocations during heap
expansion. This was causing frequent OOM panics under various loads.

Work around the issue for now by putting the logging behind
KMALLOC_DEBUG. Ideally dmesgln() & friends would not reqiure any
heap allocations, but we're not there right now.

Fixes #5724.
2021-03-11 15:28:42 +01:00
Andreas Kling
52ef08081c Kernel: Remove some unused things in kmalloc.cpp 2021-03-09 22:10:41 +01:00
Andreas Kling
cb4fcaa4b5 Kernel: Convert klog() => dmesgln() in kmalloc 2021-03-09 22:10:41 +01:00
Andreas Kling
38c8dc22cf Kernel: Remove unused KMALLOC_DEBUG_LARGE_ALLOCATIONS mode
This was a thing back when the system was so little that any kernel
allocation above 1 MiB was basically guaranteed to be a bug. :^)
2021-03-04 11:25:45 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
AnotherTest
531d72fdfd Kernel: Fix a dmesgln() format error 2021-02-23 13:59:33 +01:00
Andreas Kling
fdf03852c9 Kernel: Slap UNMAP_AFTER_INIT on a whole bunch of functions
There's no real system here, I just added it to various functions
that I don't believe we ever want to call after initialization
has finished.

With these changes, we're able to unmap 60 KiB of kernel text
after init. :^)
2021-02-19 20:23:05 +01:00
Andreas Kling
99f596fd51 Kernel: Mark a handful of things in kmalloc.cpp as READONLY_AFTER_INIT 2021-02-14 18:12:00 +01:00
Andreas Kling
09b1b09c19 Kernel: Assert if rounding-up-to-page-size would wrap around to 0
If we try to align a number above 0xfffff000 to the next multiple of
the page size (4 KiB), it would wrap around to 0. This is most likely
never what we want, so let's assert if that happens.
2021-02-14 10:01:50 +01:00
Andreas Kling
b712345c92 Kernel: Use PANIC() in a bunch of places :^) 2021-02-14 09:36:58 +01:00
Andreas Kling
8415866c03 Kernel: Remove user/kernel flags from Region
Now that we no longer need to support the signal trampolines being
user-accessible inside the kernel memory range, we can get rid of the
"kernel" and "user-accessible" flags on Region and simply use the
address of the region to determine whether it's kernel or user.

This also tightens the page table mapping code, since it can now set
user-accessibility based solely on the virtual address of a page.
2021-02-14 01:34:23 +01:00
Jean-Baptiste Boric
3cbe805486 Kernel: Move kmalloc heaps and super pages inside .bss segment
The kernel ignored the first 8 MiB of RAM while parsing the memory map
because the kmalloc heaps and the super physical pages lived here. Move
all that stuff inside the .bss segment so that those memory regions are
accounted for, otherwise we risk overwriting boot modules placed next
to the kernel.
2021-01-22 22:17:39 +01:00
asynts
dca6f1f49b Everywhere: Replace a bundle of dbg with dbgln.
These changes are arbitrarily divided into multiple commits to make it
easier to find potentially introduced bugs with git bisect.Everything:
2021-01-11 11:55:47 +01:00