summaryrefslogtreecommitdiff
path: root/Kernel/VM
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/VM')
-rw-r--r--Kernel/VM/ContiguousVMObject.cpp8
-rw-r--r--Kernel/VM/ContiguousVMObject.h4
-rw-r--r--Kernel/VM/MemoryManager.cpp10
-rw-r--r--Kernel/VM/MemoryManager.h4
-rw-r--r--Kernel/VM/PhysicalRegion.cpp20
-rw-r--r--Kernel/VM/PhysicalRegion.h6
6 files changed, 29 insertions, 23 deletions
diff --git a/Kernel/VM/ContiguousVMObject.cpp b/Kernel/VM/ContiguousVMObject.cpp
index e084f7d69d..d4f09d3c3c 100644
--- a/Kernel/VM/ContiguousVMObject.cpp
+++ b/Kernel/VM/ContiguousVMObject.cpp
@@ -31,15 +31,15 @@
namespace Kernel {
-NonnullRefPtr<ContiguousVMObject> ContiguousVMObject::create_with_size(size_t size)
+NonnullRefPtr<ContiguousVMObject> ContiguousVMObject::create_with_size(size_t size, size_t physical_alignment)
{
- return adopt(*new ContiguousVMObject(size));
+ return adopt(*new ContiguousVMObject(size, physical_alignment));
}
-ContiguousVMObject::ContiguousVMObject(size_t size)
+ContiguousVMObject::ContiguousVMObject(size_t size, size_t physical_alignment)
: VMObject(size)
{
- auto contiguous_physical_pages = MM.allocate_contiguous_supervisor_physical_pages(size);
+ auto contiguous_physical_pages = MM.allocate_contiguous_supervisor_physical_pages(size, physical_alignment);
for (size_t i = 0; i < page_count(); i++) {
physical_pages()[i] = contiguous_physical_pages[i];
dbgln<CONTIGUOUS_VMOBJECT_DEBUG>("Contiguous page[{}]: {}", i, physical_pages()[i]->paddr());
diff --git a/Kernel/VM/ContiguousVMObject.h b/Kernel/VM/ContiguousVMObject.h
index 3c273b6e7b..0cac59d269 100644
--- a/Kernel/VM/ContiguousVMObject.h
+++ b/Kernel/VM/ContiguousVMObject.h
@@ -35,10 +35,10 @@ class ContiguousVMObject final : public VMObject {
public:
virtual ~ContiguousVMObject() override;
- static NonnullRefPtr<ContiguousVMObject> create_with_size(size_t);
+ static NonnullRefPtr<ContiguousVMObject> create_with_size(size_t, size_t physical_alignment = PAGE_SIZE);
private:
- explicit ContiguousVMObject(size_t);
+ explicit ContiguousVMObject(size_t, size_t physical_alignment);
explicit ContiguousVMObject(const ContiguousVMObject&);
virtual const char* class_name() const override { return "ContiguousVMObject"; }
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index d0d427c5fb..5a7c1687d6 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -394,14 +394,14 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault)
return region->handle_fault(fault, lock);
}
-OwnPtr<Region> MemoryManager::allocate_contiguous_kernel_region(size_t size, const StringView& name, u8 access, bool user_accessible, bool cacheable)
+OwnPtr<Region> MemoryManager::allocate_contiguous_kernel_region(size_t size, const StringView& name, u8 access, size_t physical_alignment, bool user_accessible, bool cacheable)
{
ASSERT(!(size % PAGE_SIZE));
ScopedSpinLock lock(s_mm_lock);
auto range = kernel_page_directory().range_allocator().allocate_anywhere(size);
if (!range.has_value())
return {};
- auto vmobject = ContiguousVMObject::create_with_size(size);
+ auto vmobject = ContiguousVMObject::create_with_size(size, physical_alignment);
return allocate_kernel_region_with_vmobject(range.value(), vmobject, name, access, user_accessible, cacheable);
}
@@ -610,7 +610,7 @@ void MemoryManager::deallocate_supervisor_physical_page(const PhysicalPage& page
ASSERT_NOT_REACHED();
}
-NonnullRefPtrVector<PhysicalPage> MemoryManager::allocate_contiguous_supervisor_physical_pages(size_t size)
+NonnullRefPtrVector<PhysicalPage> MemoryManager::allocate_contiguous_supervisor_physical_pages(size_t size, size_t physical_alignment)
{
ASSERT(!(size % PAGE_SIZE));
ScopedSpinLock lock(s_mm_lock);
@@ -618,9 +618,9 @@ NonnullRefPtrVector<PhysicalPage> MemoryManager::allocate_contiguous_supervisor_
NonnullRefPtrVector<PhysicalPage> physical_pages;
for (auto& region : m_super_physical_regions) {
- physical_pages = region.take_contiguous_free_pages((count), true);
+ physical_pages = region.take_contiguous_free_pages(count, true, physical_alignment);
if (!physical_pages.is_empty())
- break;
+ continue;
}
if (physical_pages.is_empty()) {
diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h
index 1afd405a37..efe338cee5 100644
--- a/Kernel/VM/MemoryManager.h
+++ b/Kernel/VM/MemoryManager.h
@@ -137,11 +137,11 @@ public:
NonnullRefPtr<PhysicalPage> allocate_committed_user_physical_page(ShouldZeroFill = ShouldZeroFill::Yes);
RefPtr<PhysicalPage> allocate_user_physical_page(ShouldZeroFill = ShouldZeroFill::Yes, bool* did_purge = nullptr);
RefPtr<PhysicalPage> allocate_supervisor_physical_page();
- NonnullRefPtrVector<PhysicalPage> allocate_contiguous_supervisor_physical_pages(size_t size);
+ NonnullRefPtrVector<PhysicalPage> allocate_contiguous_supervisor_physical_pages(size_t size, size_t physical_alignment = PAGE_SIZE);
void deallocate_user_physical_page(const PhysicalPage&);
void deallocate_supervisor_physical_page(const PhysicalPage&);
- OwnPtr<Region> allocate_contiguous_kernel_region(size_t, const StringView& name, u8 access, bool user_accessible = false, bool cacheable = true);
+ OwnPtr<Region> allocate_contiguous_kernel_region(size_t, const StringView& name, u8 access, size_t physical_alignment = PAGE_SIZE, bool user_accessible = false, bool cacheable = true);
OwnPtr<Region> allocate_kernel_region(size_t, const StringView& name, u8 access, bool user_accessible = false, AllocationStrategy strategy = AllocationStrategy::Reserve, bool cacheable = true);
OwnPtr<Region> allocate_kernel_region(PhysicalAddress, size_t, const StringView& name, u8 access, bool user_accessible = false, bool cacheable = true);
OwnPtr<Region> allocate_kernel_region_identity(PhysicalAddress, size_t, const StringView& name, u8 access, bool user_accessible = false, bool cacheable = true);
diff --git a/Kernel/VM/PhysicalRegion.cpp b/Kernel/VM/PhysicalRegion.cpp
index c5aeef81b2..0df7cd4049 100644
--- a/Kernel/VM/PhysicalRegion.cpp
+++ b/Kernel/VM/PhysicalRegion.cpp
@@ -65,7 +65,7 @@ unsigned PhysicalRegion::finalize_capacity()
return size();
}
-NonnullRefPtrVector<PhysicalPage> PhysicalRegion::take_contiguous_free_pages(size_t count, bool supervisor)
+NonnullRefPtrVector<PhysicalPage> PhysicalRegion::take_contiguous_free_pages(size_t count, bool supervisor, size_t physical_alignment)
{
ASSERT(m_pages);
ASSERT(m_used != m_pages);
@@ -73,18 +73,19 @@ NonnullRefPtrVector<PhysicalPage> PhysicalRegion::take_contiguous_free_pages(siz
NonnullRefPtrVector<PhysicalPage> physical_pages;
physical_pages.ensure_capacity(count);
- auto first_contiguous_page = find_contiguous_free_pages(count);
+ auto first_contiguous_page = find_contiguous_free_pages(count, physical_alignment);
for (size_t index = 0; index < count; index++)
physical_pages.append(PhysicalPage::create(m_lower.offset(PAGE_SIZE * (index + first_contiguous_page)), supervisor));
return physical_pages;
}
-unsigned PhysicalRegion::find_contiguous_free_pages(size_t count)
+unsigned PhysicalRegion::find_contiguous_free_pages(size_t count, size_t physical_alignment)
{
ASSERT(count != 0);
+ ASSERT(physical_alignment % PAGE_SIZE == 0);
// search from the last page we allocated
- auto range = find_and_allocate_contiguous_range(count);
+ auto range = find_and_allocate_contiguous_range(count, physical_alignment / PAGE_SIZE);
ASSERT(range.has_value());
return range.value();
}
@@ -118,16 +119,21 @@ Optional<unsigned> PhysicalRegion::find_one_free_page()
return page_index;
}
-Optional<unsigned> PhysicalRegion::find_and_allocate_contiguous_range(size_t count)
+Optional<unsigned> PhysicalRegion::find_and_allocate_contiguous_range(size_t count, unsigned alignment)
{
ASSERT(count != 0);
size_t found_pages_count = 0;
- auto first_index = m_bitmap.find_longest_range_of_unset_bits(count, found_pages_count);
+ // TODO: Improve how we deal with alignment != 1
+ auto first_index = m_bitmap.find_longest_range_of_unset_bits(count + alignment - 1, found_pages_count);
if (!first_index.has_value())
return {};
auto page = first_index.value();
- if (count == found_pages_count) {
+ if (alignment != 1) {
+ auto lower_page = m_lower.get() / PAGE_SIZE;
+ page = ((lower_page + page + alignment - 1) & ~(alignment - 1)) - lower_page;
+ }
+ if (found_pages_count >= count) {
m_bitmap.set_range<true>(page, count);
m_used += count;
m_free_hint = first_index.value() + count + 1; // Just a guess
diff --git a/Kernel/VM/PhysicalRegion.h b/Kernel/VM/PhysicalRegion.h
index 4997b30499..436ee6cce3 100644
--- a/Kernel/VM/PhysicalRegion.h
+++ b/Kernel/VM/PhysicalRegion.h
@@ -52,12 +52,12 @@ public:
bool contains(const PhysicalPage& page) const { return page.paddr() >= m_lower && page.paddr() <= m_upper; }
RefPtr<PhysicalPage> take_free_page(bool supervisor);
- NonnullRefPtrVector<PhysicalPage> take_contiguous_free_pages(size_t count, bool supervisor);
+ NonnullRefPtrVector<PhysicalPage> take_contiguous_free_pages(size_t count, bool supervisor, size_t physical_alignment = PAGE_SIZE);
void return_page(const PhysicalPage& page);
private:
- unsigned find_contiguous_free_pages(size_t count);
- Optional<unsigned> find_and_allocate_contiguous_range(size_t count);
+ unsigned find_contiguous_free_pages(size_t count, size_t physical_alignment = PAGE_SIZE);
+ Optional<unsigned> find_and_allocate_contiguous_range(size_t count, unsigned alignment = 1);
Optional<unsigned> find_one_free_page();
void free_page_at(PhysicalAddress addr);