#pragma once /// \file vm_area.h /// Definition of VMA objects and related functions #include #include #include "j6/signals.h" #include "kutil/enum_bitfields.h" #include "kutil/vector.h" #include "kernel_memory.h" #include "objects/kobject.h" class page_tree; class vm_space; enum class vm_flags : uint32_t { none = 0x00000000, write = 0x00000001, exec = 0x00000002, zero = 0x00000010, contiguous = 0x00000020, large_pages = 0x00000100, huge_pages = 0x00000200, mmio = 0x00010000, write_combine = 0x00020000, user_mask = 0x0000ffff ///< flags allowed via syscall }; /// Virtual memory areas allow control over memory allocation class vm_area : public kobject { public: static constexpr kobject::type type = kobject::type::vma; /// Constructor. /// \arg size Initial virtual size of the memory area /// \arg flags Flags for this memory area vm_area(size_t size, vm_flags flags = vm_flags::none); virtual ~vm_area(); /// Get the current virtual size of the memory area inline size_t size() const { return m_size; } /// Get the flags set for this area inline vm_flags flags() const { return m_flags; } /// Track that this area was added to a vm_space /// \arg space The space to add this area to /// \returns False if this area cannot be added virtual bool add_to(vm_space *space); /// Track that this area was removed frm a vm_space /// \arg space The space that is removing this area /// \returns True if the removing space should free the pages /// mapped for this area virtual bool remove_from(vm_space *space); /// Change the virtual size of the memory area. This may cause /// deallocation if the new size is smaller than the current size. /// Note that if resizing is unsuccessful, the previous size will /// be returned. /// \arg size The desired new virtual size /// \returns The new virtual size virtual size_t resize(size_t size); /// Get the physical page for the given offset /// \arg offset The offset into the VMA /// \arg phys [out] Receives the physical page address, if any /// \returns True if there should be a page at the given offset virtual bool get_page(uintptr_t offset, uintptr_t &phys) = 0; protected: virtual void on_no_handles() override; bool can_resize(size_t size); size_t m_size; vm_flags m_flags; kutil::vector m_spaces; // Initial static space for m_spaces - most areas will never grow // beyond this size, so avoid allocations static constexpr size_t static_size = 2; vm_space *m_vector_static[static_size]; }; /// A shareable but non-allocatable memory area of contiguous physical /// addresses (like mmio) class vm_area_fixed : public vm_area { public: /// Constructor. /// \arg start Starting physical address of this area /// \arg size Size of the physical memory area /// \arg flags Flags for this memory area vm_area_fixed(uintptr_t start, size_t size, vm_flags flags = vm_flags::none); virtual ~vm_area_fixed(); virtual size_t resize(size_t size) override; virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: uintptr_t m_start; }; /// Area that allows open allocation class vm_area_open : public vm_area { public: /// Constructor. /// \arg size Initial virtual size of the memory area /// \arg flags Flags for this memory area vm_area_open(size_t size, vm_flags flags); virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: page_tree *m_mapped; }; /// Area that does not track its allocations and thus cannot be shared class vm_area_untracked : public vm_area { public: /// Constructor. /// \arg size Initial virtual size of the memory area /// \arg flags Flags for this memory area vm_area_untracked(size_t size, vm_flags flags); virtual ~vm_area_untracked(); virtual bool add_to(vm_space *space) override; virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; }; /// Area split into standard-sized segments, separated by guard pages. /// Based on vm_area_untracked, can not be shared. class vm_area_guarded : public vm_area_untracked { public: /// Constructor. /// \arg start Initial address where this area is mapped /// \arg sec_pages Pages in an individual section /// \arg size Initial virtual size of the memory area /// \arg flags Flags for this memory area vm_area_guarded( uintptr_t start, size_t sec_pages, size_t size, vm_flags flags); /// Get an available section in this area uintptr_t get_section(); /// Return a section address to the available pool void return_section(uintptr_t addr); virtual bool get_page(uintptr_t offset, uintptr_t &phys) override; private: kutil::vector m_cache; uintptr_t m_start; size_t m_pages; uintptr_t m_next; }; IS_BITFIELD(vm_flags);