summaryrefslogtreecommitdiff
path: root/Kernel/Memory
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2022-01-25 17:35:34 -0700
committerIdan Horowitz <idan.horowitz@gmail.com>2022-01-26 09:21:04 +0200
commit6e46e21c425405e0dd2c6a603007f2c4a9bbbe27 (patch)
tree94aeccd585b8323295e5ef9e90dc2adbc7d9d642 /Kernel/Memory
parent1abbe9b02ce235a588aa56a4b80bca444eb1a1ec (diff)
downloadserenity-6e46e21c425405e0dd2c6a603007f2c4a9bbbe27.zip
Kernel: Implement Page Attribute Table (PAT) support and Write-Combine
This allows us to enable Write-Combine on e.g. framebuffers, significantly improving performance on bare metal. To keep things simple we right now only use one of up to three bits (bit 7 in the PTE), which maps to the PA4 entry in the PAT MSR, which we set to the Write-Combine mode on each CPU at boot time.
Diffstat (limited to 'Kernel/Memory')
-rw-r--r--Kernel/Memory/Region.cpp14
-rw-r--r--Kernel/Memory/Region.h4
2 files changed, 18 insertions, 0 deletions
diff --git a/Kernel/Memory/Region.cpp b/Kernel/Memory/Region.cpp
index b7c741ec19..d3323fbc99 100644
--- a/Kernel/Memory/Region.cpp
+++ b/Kernel/Memory/Region.cpp
@@ -212,6 +212,8 @@ bool Region::map_individual_page_impl(size_t page_index)
pte->set_writable(is_writable());
if (Processor::current().has_feature(CPUFeature::NX))
pte->set_execute_disabled(!is_executable());
+ if (Processor::current().has_feature(CPUFeature::PAT))
+ pte->set_pat(is_write_combine());
pte->set_user_allowed(user_allowed);
}
return true;
@@ -311,6 +313,18 @@ void Region::remap()
TODO();
}
+ErrorOr<void> Region::set_write_combine(bool enable)
+{
+ if (enable && !Processor::current().has_feature(CPUFeature::PAT)) {
+ dbgln("PAT is not supported, implement MTRR fallback if available");
+ return Error::from_errno(ENOTSUP);
+ }
+
+ m_write_combine = enable;
+ remap();
+ return {};
+}
+
void Region::clear_to_zero()
{
VERIFY(vmobject().is_anonymous());
diff --git a/Kernel/Memory/Region.h b/Kernel/Memory/Region.h
index 3c447296e7..7dc83a78cb 100644
--- a/Kernel/Memory/Region.h
+++ b/Kernel/Memory/Region.h
@@ -87,6 +87,9 @@ public:
[[nodiscard]] bool is_mmap() const { return m_mmap; }
void set_mmap(bool mmap) { m_mmap = mmap; }
+ [[nodiscard]] bool is_write_combine() const { return m_write_combine; }
+ ErrorOr<void> set_write_combine(bool);
+
[[nodiscard]] bool is_user() const { return !is_kernel(); }
[[nodiscard]] bool is_kernel() const { return vaddr().get() < USER_RANGE_BASE || vaddr().get() >= kernel_mapping_base; }
@@ -220,6 +223,7 @@ private:
bool m_stack : 1 { false };
bool m_mmap : 1 { false };
bool m_syscall_region : 1 { false };
+ bool m_write_combine : 1 { false };
IntrusiveRedBlackTreeNode<FlatPtr, Region, RawPtr<Region>> m_tree_node;
IntrusiveListNode<Region> m_vmobject_list_node;