Commit graph

351 commits

Author SHA1 Message Date
Tom
82c4812730 Kernel: Remove flawed SharedInodeVMObject assertion
This assertion cannot be safely/reliably made in the
~SharedInodeVMObject destructor. The problem is that
Inode::is_shared_vmobject holds a weak reference to the instance
that is being destroyed (ref count 0). Checking the pointer using
WeakPtr::unsafe_ptr will produce nullptr depending on timing in
this case, and WeakPtr::safe_ref will reliably produce a nullptr
as soon as the reference count drops to 0. The only case where
this assertion could succeed is when WeakPtr::unsafe_ptr returned
the pointer because it won the race against revoking it. And
because WeakPtr::safe_ref will always return a nullptr, we cannot
reliably assert this from the ~SharedInodeVMObject destructor.

Fixes #4621
2020-12-31 10:52:45 +01:00
Luke
865f5ed4f6 Kernel: Prevent sign bit extension when creating a PDPTE
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-30 20:33:15 +01:00
asynts
50d24e4f98 AK: Make binary_search signature more generic. 2020-12-30 02:13:30 +01:00
Andreas Kling
30dbe9c78a Kernel+LibC: Add a very limited sys$mremap() implementation
This syscall can currently only remap a shared file-backed mapping into
a private file-backed mapping.
2020-12-29 02:20:43 +01:00
Luke
b980782343 Kernel/VM: Make local_offset in PhysicalRegion::find_one_free_page unsigned
An extension to #4613, as I didn't notice that it also happens here.
2020-12-29 02:20:26 +01:00
Luke
eb38fe4a82 Kernel/VM: Make local_offset in PhysicalRegion::free_page_at unsigned
Anything above or equal to the 2 GB mark has the left most bit set
(0x8000...), which was falsely interpreted as negative due to
local_offset being signed.

This makes it unsigned by using FlatPtr. To check for underflow as
was intended, lets use Checked instead.

Fixes #4585
2020-12-29 01:41:16 +01:00
Andreas Kling
ed5c26d698 AK: Remove custom %w format string specifier
This was a non-standard specifier alias for %04x. This patch replaces
all uses of it with new-style formatting functions instead.
2020-12-25 17:05:05 +01:00
Liav A
afba614d68 Kernel: Don't skip if found free page to allocate from a super region
This was a bad pattern that wasn't detected because we only had one
super physical region that was initialized by MemoryManager.
2020-12-21 00:15:58 +01:00
Lenny Maiorani
765936ebae
Everywhere: Switch from (void) to [[maybe_unused]] (#4473)
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-21 00:09:48 +01:00
Andreas Kling
8e79bde2b7 Kernel: Move KBufferBuilder to the fallible KBuffer API
KBufferBuilder::build() now returns an OwnPtr<KBuffer> and can fail.
Clients of the API have been updated to handle that situation.
2020-12-18 19:22:26 +01:00
Tom
da5cc34ebb Kernel: Fix some issues related to fixes and block conditions
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-12 21:28:12 +01:00
Tom
78f1b5e359 Kernel: Fix some problems with Thread::wait_on and Lock
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-12-01 09:48:34 +01:00
Tom
5b38132e3c Kernel: Protect the PageDirectory from concurrent access 2020-11-11 12:27:25 +01:00
Tom
2b25a89ab5 Kernel: Add locks around RangeAllocator
We need to keep multiple processors from changing it at the same time.
2020-11-11 12:27:25 +01:00
Tom
75f61fe3d9 AK: Make RefPtr, NonnullRefPtr, WeakPtr thread safe
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.

Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.

In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
2020-11-10 19:11:52 +01:00
Tom
13aa3d2d62 Kernel: Flush TLB when quick-mapping PD/PT that was mapped on other CPU
If a PD/PT was quick-mapped by another CPU we still need to flush the
TLB on the current CPU.

Fixes #3885
2020-11-01 18:48:36 +01:00
Tom
6fbced6f4f Kernel: Ensure PhysicalRegion free page hint is within valid range
Fixes #3770
2020-10-16 17:39:42 +02:00
asynts
71fd54f76b MemoryManager: Off-by-one error when collecting memory pages.
Notice that we ensured that the size is a multiple of the page size and
that there is at least one page there, otherwise, this change would be
invalid.

We create an empty region and then expand it:

    // First iteration.
    m_user_physical_regions.append(PhysicalRegion::create(addr, addr));

    // Following iterations.
    region->expand(region->lower(), addr);

So if the memory region only has one page, we would end up with an empty
region. Thus we need to do one more iteration.
2020-10-12 19:39:00 +02:00
Ben Wiederhake
64cc3f51d0 Meta+Kernel: Make clang-format-10 clean 2020-09-25 21:18:17 +02:00
Luke
68b361bd21 Kernel: Return ENOMEM in more places
There are plenty of places in the kernel that aren't
checking if they actually got their allocation.

This fixes some of them, but definitely not all.

Fixes #3390
Fixes #3391

Also, let's make find_one_free_page() return nullptr
if it doesn't get a free index. This stops the kernel
crashing when out of memory and allows memory purging
to take place again.

Fixes #3487
2020-09-16 20:38:19 +02:00
Tom
c8d9f1b9c9 Kernel: Make copy_to/from_user safe and remove unnecessary checks
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-13 21:19:15 +02:00
Ben Wiederhake
0d79e57c4d Kernel: Fix various forward declarations
I decided to modify MappedROM.h because all other entried in Forward.h
are also classes, and this is visually more pleasing.

Other than that, it just doesn't make any difference which way we resolve
the conflicts.
2020-09-12 13:46:15 +02:00
Tom
efe2b75017 Kernel: Optimize single physical page allocation and randomize returns
Rather than trying to find a contiguous set of bits of size 1, just
find one single available bit using a hint.

Also, try to randomize returned physical pages a bit by placing them
into a 256 entry queue rather than making them available immediately.
Then, once the queue is filled, pick a random one, make it available
again and use that slot for the latest page to be returned.
2020-09-09 13:02:14 +02:00
asynts
ec1080b18a Refactor: Replace usages of FixedArray with Vector. 2020-09-08 14:01:21 +02:00
Tom
bf268a0185 Kernel: Handle committing pages in regions more gracefully
Sometimes a physical underlying page may be there, but we may be
unable to allocate a page table that may be needed to map it. Bubble
up such mapping errors so that they can be handled more appropriately.
2020-09-02 00:35:56 +02:00
Tom
83ddf3d850 Kernel: Fix memory purge clobbering mapped page directory in ensure_pte
If allocating a page table triggers purging memory, we need to call
quickmap_pd again to make sure the underlying physical page is
remapped to the correct one. This is needed because purging itself
may trigger calls to ensure_pte as well.

Fixes #3370
2020-09-01 22:08:43 +02:00
Tom
30d36a3ad1 Kernel: Remove assertion from Region::commit
We should be able to gracefully fail a commit in low-memory situations.
2020-09-01 22:08:43 +02:00
Tom
eb1cc5d665 Kernel: Only remap regions if memory was purged from them 2020-09-01 22:08:43 +02:00
Andreas Kling
171868e4f7 Kernel: Preserve internal state in cloned PurgeableVMObjects
When cloning a purgeable memory region (which happens on fork),
we need to preserve the "was purged" and "volatile" state of the
original region, or they will always appear as non-volatile and
unpurged regions in the child process.

Fixes #3374.
2020-09-01 17:45:28 +02:00
Andreas Kling
cc5403f77b Kernel: Remove unused variable PhysicalRegion::m_last 2020-08-30 13:13:55 +02:00
Tom
4b66692a55 Kernel: Make Heap implementation reusable, and make kmalloc expandable
Add an ExpandableHeap and switch kmalloc to use it, which allows
for the kmalloc heap to grow as needed.

In order to make heap expansion to work, we keep around a 1 MiB backup
memory region, because creating a region would require space in the
same heap. This means, the heap will grow as soon as the reported
utilization is less than 1 MiB. It will also return memory if an entire
subheap is no longer needed, although that is rarely possible.
2020-08-30 11:39:38 +02:00
Ben Wiederhake
081bb29626 Kernel: Unbreak building with extra debug macros, part 2 2020-08-30 09:43:49 +02:00
Tom
67dbb56444 Kernel: Release page tables when no longer needed
When unmapping regions, check if page tables can be freed.

This is a follow-up change for #3254.
2020-08-28 09:21:24 +02:00
Tom
dd83f6a266 Kernel: Fix losing PTEs
We can't use a HashMap with a small key that doesn't guarantee
collisions. Change it to a HashTable instead.

Fixes #3254
2020-08-26 01:25:06 +02:00
Tom
bcbe2fe525 Kernel: Protect looping over VMObject regions
We need to hold the memory manager lock so nobody else can modify
these lists while we're iterating them.
2020-08-26 01:25:06 +02:00
Tom
d89582880e Kernel: Switch singletons to use new Singleton class
MemoryManager cannot use the Singleton class because
MemoryManager::initialize is called before the global constructors
are run. That caused the Singleton to be re-initialized, causing
it to create another MemoryManager instance.

Fixes #3226
2020-08-25 09:48:48 +02:00
Tom
ba6e4fb77f Kernel: Fix kmalloc memory corruption
Rather than hardcoding where the kmalloc pool should be, place
it at the end of the kernel image instead. This avoids corrupting
global variables or other parts of the kernel as it grows.

Fixes #3257
2020-08-25 09:48:48 +02:00
Tom
08a569fbe0 Kernel: Make PhysicalPage not movable and use atomic ref counting
We should not be moving ref-counted objects.
2020-08-25 09:48:48 +02:00
Andreas Kling
2fd9e72264 Revert "Kernel: Switch singletons to use new Singleton class"
This reverts commit f48feae0b2.
2020-08-22 18:01:59 +02:00
Andreas Kling
8925ad3fa0 Revert "Kernel: Move Singleton class to AK"
This reverts commit f0906250a1.
2020-08-22 16:34:49 +02:00
Andreas Kling
b0a24a83be Revert "Kernel: Fix regression where MemoryManager is initialized twice"
This reverts commit 8a75e0b892.
2020-08-22 16:34:15 +02:00
Andreas Kling
68580d5a8d Revert "AK: Get rid of make_singleton function"
This reverts commit 5a98e329d1.
2020-08-22 16:34:14 +02:00
Andreas Kling
0db7e04c2e Revert "Kernel: Make PhysicalPage not movable and use atomic ref counting"
This reverts commit a89ccd842b.
2020-08-22 16:34:11 +02:00
Tom
a89ccd842b Kernel: Make PhysicalPage not movable and use atomic ref counting
We should not be moving ref-counted objects.
2020-08-22 10:46:24 +02:00
Tom
5a98e329d1 AK: Get rid of make_singleton function
Just default the InitFunction template argument.
2020-08-22 10:46:24 +02:00
Tom
8a75e0b892 Kernel: Fix regression where MemoryManager is initialized twice
MemoryManager cannot use the Singleton class because
MemoryManager::initialize is called before the global constructors
are run. That caused the Singleton to be re-initialized, causing
it to create another MemoryManager instance.
2020-08-22 10:46:24 +02:00
Tom
f0906250a1 Kernel: Move Singleton class to AK 2020-08-22 10:46:24 +02:00
Tom
cf8ce839da Kernel: Fix assertion when releasing contiguous memory region
There is no guarantee that the memory manager lock is held when
physical pages are released, so just acquire the memory manager
lock.
2020-08-21 12:03:20 +02:00
Tom
f48feae0b2 Kernel: Switch singletons to use new Singleton class
Fixes #3226
2020-08-21 11:47:35 +02:00
Nico Weber
b31aa2e918 Kernel: Switch a comment to GiB 2020-08-16 16:33:28 +02:00