From 30d5f2c1fcd0a59efca3dc69d13a35ed9eef36b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Holz?= Date: Sun, 30 Aug 2026 14:57:36 +0200 Subject: [PATCH] Kernel/Memory: Allow subclassing VirtualRange This will be used for GPU virtual address ranges. Use an explicit Self template parameter instead of just using `VirtualRangeBase` as argument/return type to make different subclasses intentionally incompatible with each other. This will e.g. not allow comparing CPU virtual address ranges with GPU virtual address ranges. Don't put expand_to_page_boundaries() in the new base class since this function assumes a CPU page size of 4K. Additionally, since this is a static member function, deducing this would not work and we would have to use CRTP for this function (but we could still use deducing this for the other ones). --- Kernel/Memory/VirtualRange.h | 59 +++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/Kernel/Memory/VirtualRange.h b/Kernel/Memory/VirtualRange.h index b49f48c3670..feffa04e85f 100644 --- a/Kernel/Memory/VirtualRange.h +++ b/Kernel/Memory/VirtualRange.h @@ -13,10 +13,11 @@ namespace Kernel::Memory { -class VirtualRange { +template +class VirtualRangeBase { public: - VirtualRange() = delete; - VirtualRange(VirtualAddress base, size_t size) + VirtualRangeBase() = delete; + VirtualRangeBase(VirtualAddress base, size_t size) : m_base(base) , m_size(size) { @@ -30,9 +31,10 @@ public: VirtualAddress end() const { return m_base.offset(m_size); } - bool operator==(VirtualRange const& other) const + template + bool operator==(this Self const& self, Self const& other) { - return m_base == other.m_base && m_size == other.m_size; + return self.m_base == other.m_base && self.m_size == other.m_size; } bool contains(VirtualAddress base, size_t size) const @@ -42,39 +44,43 @@ public: return base >= m_base && base.offset(size) <= end(); } - bool contains(VirtualRange const& other) const + template + bool contains(this Self const& self, Self const& other) { - return contains(other.base(), other.size()); + return self.contains(other.base(), other.size()); } - Vector carve(VirtualRange const& taken) const + template + Vector carve(this Self const& self, Self const& taken) { VERIFY((taken.size() % PAGE_SIZE) == 0); - Vector parts; - if (taken == *this) + Vector parts; + if (taken == self) return {}; - if (taken.base() > base()) - parts.unchecked_append({ base(), taken.base().get() - base().get() }); - if (taken.end() < end()) - parts.unchecked_append({ taken.end(), end().get() - taken.end().get() }); + if (taken.base() > self.base()) + parts.unchecked_append({ self.base(), taken.base().get() - self.base().get() }); + if (taken.end() < self.end()) + parts.unchecked_append({ taken.end(), self.end().get() - taken.end().get() }); return parts; } - VirtualRange intersect(VirtualRange const& other) const + template + Self intersect(this Self const& self, Self const& other) { - if (*this == other) { - return *this; + if (self == other) { + return self; } - auto new_base = max(base(), other.base()); - auto new_end = min(end(), other.end()); + auto new_base = max(self.base(), other.base()); + auto new_end = min(self.end(), other.end()); VERIFY(new_base < new_end); - return VirtualRange(new_base, (new_end - new_base).get()); + return Self(new_base, (new_end - new_base).get()); } - bool intersects(VirtualRange const& other) const + template + bool intersects(this Self const& self, Self const& other) { - auto a = *this; + auto a = self; auto b = other; if (a.base() > b.base()) @@ -83,13 +89,18 @@ public: return a.base() < b.end() && b.base() < a.end(); } - static ErrorOr expand_to_page_boundaries(FlatPtr address, size_t size); - private: VirtualAddress m_base; size_t m_size { 0 }; }; +class VirtualRange : public VirtualRangeBase { + using VirtualRangeBase::VirtualRangeBase; + +public: + static ErrorOr expand_to_page_boundaries(FlatPtr address, size_t size); +}; + } template<>