diff options
author | Andreas Kling <kling@serenityos.org> | 2022-04-03 15:27:47 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-03 21:51:58 +0200 |
commit | e852a69a069de6176cd6ff3534d5a606d383f396 (patch) | |
tree | 43fb2916aa4c0d25efbefb15315663549c854c30 /Kernel/Interrupts/APIC.cpp | |
parent | cbf52d474c9bc0a88e132cfd9f5ba12361b70453 (diff) | |
download | serenity-e852a69a069de6176cd6ff3534d5a606d383f396.zip |
LibWeb: Make VM allocation atomic for kernel regions
Instead of first allocating the VM range, and then inserting a region
with that range into the MM region tree, we now do both things in a
single atomic operation:
- RegionTree::place_anywhere(Region&, size, alignment)
- RegionTree::place_specifically(Region&, address, size)
To reduce the number of things we do while locking the region tree,
we also require callers to provide a constructed Region object.
Diffstat (limited to 'Kernel/Interrupts/APIC.cpp')
-rw-r--r-- | Kernel/Interrupts/APIC.cpp | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp index e54437c1fd..75bf6cecfd 100644 --- a/Kernel/Interrupts/APIC.cpp +++ b/Kernel/Interrupts/APIC.cpp @@ -319,19 +319,14 @@ UNMAP_AFTER_INIT bool APIC::init_bsp() return true; } -UNMAP_AFTER_INIT static NonnullOwnPtr<Memory::Region> create_identity_mapped_region(PhysicalAddress paddr, size_t size) +UNMAP_AFTER_INIT static ErrorOr<NonnullOwnPtr<Memory::Region>> create_identity_mapped_region(PhysicalAddress paddr, size_t size) { - auto maybe_vmobject = Memory::AnonymousVMObject::try_create_for_physical_range(paddr, size); - // FIXME: Would be nice to be able to return a ErrorOr from here. - VERIFY(!maybe_vmobject.is_error()); - - auto region_or_error = MM.allocate_kernel_region_with_vmobject( - Memory::VirtualRange { VirtualAddress { static_cast<FlatPtr>(paddr.get()) }, size }, - maybe_vmobject.release_value(), - {}, - Memory::Region::Access::ReadWriteExecute); - VERIFY(!region_or_error.is_error()); - return region_or_error.release_value(); + auto vmobject = TRY(Memory::AnonymousVMObject::try_create_for_physical_range(paddr, size)); + auto region = TRY(Memory::Region::create_unplaced(move(vmobject), 0, {}, Memory::Region::Access::ReadWriteExecute)); + Memory::VirtualRange range { VirtualAddress { paddr.get() }, size }; + TRY(MM.region_tree().place_specifically(*region, range)); + TRY(region->map(MM.kernel_page_directory())); + return region; } UNMAP_AFTER_INIT void APIC::setup_ap_boot_environment() @@ -347,7 +342,7 @@ UNMAP_AFTER_INIT void APIC::setup_ap_boot_environment() constexpr u64 apic_startup_region_base = 0x8000; auto apic_startup_region_size = Memory::page_round_up(apic_ap_start_size + (2 * aps_to_enable * sizeof(FlatPtr))).release_value_but_fixme_should_propagate_errors(); VERIFY(apic_startup_region_size < USER_RANGE_BASE); - auto apic_startup_region = create_identity_mapped_region(PhysicalAddress(apic_startup_region_base), apic_startup_region_size); + auto apic_startup_region = MUST(create_identity_mapped_region(PhysicalAddress(apic_startup_region_base), apic_startup_region_size)); u8* apic_startup_region_ptr = apic_startup_region->vaddr().as_ptr(); memcpy(apic_startup_region_ptr, reinterpret_cast<void const*>(apic_ap_start), apic_ap_start_size); |