Commit graph

63 commits

Author SHA1 Message Date
Andreas Kling
a12e19c015 Kernel: Move kernel region checks from x86 page fault handler to MM
Ideally the x86 fault handler would only do x86 specific things and
delegate the rest of the work to MemoryManager. This patch moves some of
the address checks to a more generic place.
2022-01-28 23:41:18 +01:00
Andreas Kling
5092813a45 Kernel: Quickly reject userspace addresses in kernel_region_from_vaddr()
This avoids taking and releasing the MM lock just to reject an address
that we can tell from just looking at it that it won't ever be in the
kernel regions tree.
2022-01-28 23:41:18 +01:00
Idan Horowitz
5146315a15 Kernel: Convert MemoryManager::allocate_user_physical_page to ErrorOr
This allows is to use the TRY macro at the call sites, instead of using
clunky null checks.
2022-01-28 19:05:52 +02:00
Idan Horowitz
bd5b56cab0 Kernel: Make allocate_supervisor_physical_page OOM-fallible 2022-01-28 19:05:52 +02:00
Idan Horowitz
4d2f1a05ec Kernel: Make allocate_contiguous_supervisor_physical_pages OOM-fallible 2022-01-28 19:05:52 +02:00
Idan Horowitz
956824afe2 Kernel: Use memset instead of fast_u32_fill in MemoryManager zero fills
When the values we're setting are not actually u32s and the size of the
area we're setting is PAGE_SIZE-aligned and a multiple of PAGE_SIZE in
size, there's no point in using fast_u32_fill, as that forces us to use
STOSDs instead of STOSQs.
2022-01-28 19:05:52 +02:00
Andreas Kling
df34f7b90b Kernel: Use an IntrusiveRedBlackTree for kernel regions
We were already using a non-intrusive RedBlackTree, and since the kernel
regions tree is non-owning, this is a trivial conversion that makes a
bunch of the tree operations infallible (by being allocation-free.) :^)
2022-01-16 23:31:01 +01:00
Andreas Kling
8e0387e674 Kernel: Only register kernel regions with MemoryManager
We were already only tracking kernel regions, this patch just makes it
more clear by having it reflected in the name of the registration
helpers.

We also stop calling them for userspace regions, avoiding some spinlock
action in such cases.
2022-01-15 19:51:15 +01:00
Andreas Kling
24ecf1d021 Kernel: Remove redundant hash map of page tables in PageDirectory
The purpose of the PageDirectory::m_page_tables map was really just
to act as ref-counting storage for PhysicalPage objects that were
being used for the directory's page tables.

However, this was basically redundant, since we can find the physical
address of each page table from the page directory, and we can find the
PhysicalPage object from MemoryManager::get_physical_page_entry().
So if we just manually ref() and unref() the pages when they go in and
out of the directory, we no longer need PageDirectory::m_page_tables!

Not only does this remove a bunch of kmalloc() traffic, it also solves
a race condition that would occur when lazily adding a new page table
to a directory:

Previously, when MemoryManager::ensure_pte() would call HashMap::set()
to insert the new page table into m_page_tables, if the HashMap had to
grow its internal storage, it would call kmalloc(). If that kmalloc()
would need to perform heap expansion, it would end up calling
ensure_pte() again, which would clobber the page directory mapping used
by the outer invocation of ensure_pte().

The net result of the above bug would be that any invocation of
MemoryManager::ensure_pte() could erroneously return a pointer into
a kernel page table instead of the correct one!

This whole problem goes away when we remove the HashMap, as ensure_pte()
no longer does anything that allocates from the heap.
2022-01-10 16:22:37 +01:00
Hendiadyoin1
1cdace7898 Kernel: Add implied auto qualifiers in Memory 2022-01-09 23:29:57 -08:00
Pankaj Raghav
59da9bd0bd Kernel: Overload DMA helper without Physical Page output parameter
Not all drivers need the PhysicalPage output parameter while creating
a DMA buffer. This overload will avoid creating a temporary variable
for the caller
2022-01-09 00:45:38 +01:00
Pankaj Raghav
e79f94f998 Kernel: Set Cacheable parameter to NO explicitly in DMA helpers
The cacheable parameter to allocate_kernel_region should be explicitly
set to No as this region is used to do physical memory transfers. Even
though most architectures ignore this even if it is set, it is better
to make this explicit.
2022-01-09 00:45:38 +01:00
Liav A
ca254699ec Kernel: Implement read functionality for MemoryDevice
So far we only had mmap(2) functionality on the /dev/mem device, but now
we can also do read(2) on it.

The test unit was updated to check we are doing it safely.
2022-01-08 13:21:16 +02:00
Liav A
876559d283 Kernel: Change method name to clarify physical memory mmap validation 2022-01-08 13:21:16 +02:00
Liav A
3e066d380d Kernel/Memory: Remove needless VERIFY in /dev/mem mmap validation method
As it was pointed by Idan Horowitz, the rest of the method doesn't
assume we have any reserved ranges to allow mmap(2) to work on them, so
the VERIFY is not needed at all.
2022-01-07 19:13:27 +02:00
Tom
10efbfb09e Kernel: Scan ACPI memory ranges for the RSDP table
On some systems the ACPI RSDP table may be located in ACPI reserved
memory ranges rather than in the EBDA or BIOS areas.
2022-01-04 17:46:36 +00:00
Pankaj Raghav
602b35aa62 Kernel: Add DMA allocate functions that are TRY-able
Add DMA allocate buffer helper functions in MemoryManager.
2022-01-01 14:55:58 +01:00
Guilherme Goncalves
33b78915d3 Kernel: Propagate overflow errors from Memory::page_round_up
Fixes #11402.
2021-12-28 23:08:50 +01:00
Brian Gianforcaro
1c950773fb Kernel: Make MemoryManager::protect_ksyms_after_init UNMAP_AFTER_INIT
The function to protect ksyms after initialization, is only used during
boot of the system, so it can be UNMAP_AFTER_INIT as well.

This requires we switch the order of the init sequence, so we now call
`MM.protect_ksyms_after_init()` before `MM.unmap_text_after_init()`.
2021-12-24 14:28:59 -08:00
Daniel Bertalan
4fc28bfe02 Kernel: Unmap Prekernel pages after they are no longer needed
The Prekernel's memory is only accessed until MemoryManager has been
initialized. Keeping them around afterwards is both unnecessary and bad,
as it prevents the userland from using the 0x100000-0x155000 virtual
address range.

Co-authored-by: Idan Horowitz <idan.horowitz@gmail.com>
2021-12-22 00:02:36 -08:00
Andreas Kling
1f2d0d0ad4 Kernel: Use ksyms in-place instead of duplicating them into eternal heap
We can leave the .ksyms section mapped-but-read-only and then have the
symbols index simply point into it.

Note that we manually insert null-terminators into the symbols section
while parsing it.

This gets rid of ~950 KiB of kmalloc_eternal() at startup. :^)
2021-12-18 11:30:10 +01:00
Andreas Kling
813593a485 Kernel: Fix overly loose MemoryManager::kernel_region_from_vaddr()
It's not enough to just find the largest-address-not-above the argument,
we must also check that the found region actually contains the argument.

Regressed in a23edd42b8, thanks to Idan
for pointing this out.
2021-12-11 21:18:42 +01:00
Andreas Kling
a23edd42b8 Kernel: Store kernel memory regions in a RedBlackTree
We were already doing this for userspace memory regions (in the
Memory::AddressSpace class), so let's do it for kernel regions as well.

This gives a nice speed-up on test-js and probably basically everything
else as well. :^)
2021-12-11 20:13:20 +01:00
Idan Horowitz
40f64d7379 Kernel: Dispatch handle-able signals instead of crashing if possible
This matches the behaviour of the other *nixs and allows processes to
try and recover from such signals in userland.
2021-12-01 21:44:11 +02:00
Idan Horowitz
a9e436c4a3 Kernel: Replace usages of SIGSTKFLT with SIGSEGV
SIGSTKFLT is a signal that signifies a stack fault in a x87 coprocessor,
this signal is not POSIX and also unused by Linux and the BSDs, so let's
use SIGSEGV so programs that setup signal handlers for the common
signals could still handle them in serenity.
2021-12-01 21:44:11 +02:00
James Mintram
eb33df0c30 Kernel: Add an x86 include check+error in x86/PageFault.h 2021-12-01 11:22:04 -08:00
Andreas Kling
f2d5548d7a Kernel: Add MemoryManager::copy_physical_page()
This is a handy helper that copies out the full contents of a physical
page into a caller-provided buffer. It uses quickmapping internally
(and takes the MM lock for the duration.)
2021-11-17 19:32:07 +01:00
Andreas Kling
79fa9765ca Kernel: Replace KResult and KResultOr<T> with Error and ErrorOr<T>
We now use AK::Error and AK::ErrorOr<T> in both kernel and userspace!
This was a slightly tedious refactoring that took a long time, so it's
not unlikely that some bugs crept in.

Nevertheless, it does pass basic functionality testing, and it's just
real nice to finally see the same pattern in all contexts. :^)
2021-11-08 01:10:53 +01:00
Liav A
026687816d Kernel: Fix restrictions in is_allowed_to_mmap_to_userspace function
This small change simplifies the function a bit but also fixes a problem
with it.
Let's take an example to see this:
Let's say we have a reserved range between 0xe0000 to 0xfffff (EBDA),
then we want to map from the memory device (/dev/mem) the entire
EBDA to a program. If a program tries to map more than 131072 bytes,
the current logic will work - the start address is 0xe0000, and ofcourse
it's below the limit, hence it passes the first two restrictions.
Then, the third if statement will fail if we try to mmap more than
the said allowed bytes.
However, let's take another scenario, where we try to mmap from
0xf0000 - but we try to mmap less than 131072 - but more than 65536.
In such case, we again pass the first two if statements, but the third
one is passed two, because it doesn't take into account the offseted
address from the start of the reserved range (0xe0000). In such case,
a user can easily mmap 65535 bytes above 0x100000. This might
seem negligible. However, it's still a severe bug that can theoretically
be exploited into a info leak or tampering with important kernel
structures.
2021-10-22 13:13:00 +02:00
Nico Weber
5a951d6258 Kernel: Fix a few typos 2021-10-01 00:51:49 +01:00
Liav A
86fa5d71c0 Kernel/Memory: Add more super pages to satisfy contiguous allocations
When testing the RTL8168 driver, it seems we can't allocate super pages
anymore. Either we expand the super pages range, or find a solution to
dynamically expand the range (or let drivers utilize other ranges).
2021-09-18 17:49:24 +03:00
Brian Gianforcaro
abc523a5ab Kernel: Specify a lock rank for s_mm_lock 2021-09-07 13:16:01 +02:00
Andreas Kling
56a2594de7 Kernel: Make KString factories return KResultOr + use TRY() everywhere
There are a number of places that don't have an error propagation path
right now, so I've added FIXME's about that.
2021-09-06 19:25:36 +02:00
Andreas Kling
cd8d52e6ae Kernel: Improve API names for switching address spaces
- enter_space => enter_address_space
- enter_process_paging_scope => enter_process_address_space
2021-09-06 18:56:51 +02:00
Andreas Kling
e3a716ceff Kernel: Make Memory::Region::map() return KResult
..and use TRY() at the call sites to propagate errors. :^)
2021-09-06 13:06:05 +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
Andreas Kling
f4a9a0d561 Kernel: Make VirtualRangeAllocator return KResultOr<VirtualRange>
This achieves two things:
- The allocator can report more specific errors
- Callers can (and now do) use TRY() :^)
2021-09-06 01:55:27 +02:00
Andreas Kling
2f790cf78f Kernel: Make MM.commit_user_physical_pages() return KResultOr
..and use TRY() at call sites. :^)
2021-09-06 01:55:27 +02:00
Luke Wilde
01af7d1ae1 Kernel: Don't use {:p} when printing out invalid userspace stack pointer
`userspace_esp` is a virtual address and thus using `{:p}` on it is
invalid and will cause an assertion failure.

I ran into this while testing #9772.
2021-09-03 11:46:40 +02:00
Andreas Kling
68bf6db673 Kernel: Rename Spinlock::is_owned_by_current_thread()
...to is_owned_by_current_processor(). As Tom pointed out, this is
much more accurate. :^)
2021-08-29 22:19:42 +02:00
Andreas Kling
0b4671add7 Kernel: {Mutex,Spinlock}::own_lock() => is_locked_by_current_thread()
Rename these API's to make it more clear what they are checking.
2021-08-29 12:53:11 +02:00
Brian Gianforcaro
485f51690d Kernel: Always observe the return value of Region::map and remap
We have seen cases where the map fails, but we return the region
to the caller, causing them to page fault later on when they touch
the region.

The fix is to always observe the return code of map/remap.
2021-08-25 00:18:42 +02:00
Andreas Kling
a930877f31 Kernel: Mape quickmap functions VERIFY that MM lock is held
The quickmap_page() and unquickmap_page() functions are used to map a
single physical page at a kernel virtual address for temporary access.

These use the per-CPU quickmap buffer in the page tables, and access to
this is guarded by the MM lock. To prevent bugs, quickmap_page() should
not *take* the MM lock, but rather verify that it is already held!

This exposed two situations where we were using quickmap without holding
the MM lock during page fault handling. This patch is forced to fix
these issues (which is great!) :^)
2021-08-23 00:02:09 +02:00
Andreas Kling
dea93a8bb9 Kernel: Rename Processor::id() => current_id()
And let id() be the non-static version that gives you the ID of a
Processor object.
2021-08-23 00:02:09 +02:00
Andreas Kling
d60635cb9d Kernel: Convert Processor::in_irq() to static current_in_irq()
This closes the race window between Processor::current() and a context
switch happening before in_irq().
2021-08-23 00:02:09 +02: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
Andreas Kling
7979b5a8bb Kernel: Port VMObject to ListedRefCounted
The VMObject class now manages its own instance list (it was previously
a member of MemoryManager.) Removal from the list is done safely on the
last unref(), closing a race window in the previous implementation.

Note that VMObject::all_instances() now has its own lock instead of
using the global MM lock.
2021-08-17 01:21:47 +02:00
Andreas Kling
a154faebb7 Kernel: Use NonnullRefPtr<PhysicalPage> in PageDirectory::m_page_tables
We don't care to store null page pointers in the page table map.
2021-08-15 16:53:03 +02:00
sin-ack
0a18425cbb Kernel: Make Memory::Region allocation functions return KResultOr
This makes for some nicer handling of errors compared to checking an
OwnPtr for null state.
2021-08-15 15:41:02 +02:00