|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  |  #pragma once
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#include <list>
 | 
	
		
			
				|  |  | +#include <set>
 | 
	
		
			
				|  |  |  #include <vector>
 | 
	
		
			
				|  |  |  #include <bit>
 | 
	
		
			
				|  |  |  #include <cstddef>
 | 
	
	
		
			
				|  | @@ -33,7 +33,7 @@ struct page {
 | 
	
		
			
				|  |  |      // 0 :11 : pte_index
 | 
	
		
			
				|  |  |      // 12:31 : pt_page
 | 
	
		
			
				|  |  |      uint32_t pg_pteidx;
 | 
	
		
			
				|  |  | -    uint32_t attr;
 | 
	
		
			
				|  |  | +    mutable uint32_t attr;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // private memory mapping
 | 
	
	
		
			
				|  | @@ -50,14 +50,6 @@ int mmap(
 | 
	
		
			
				|  |  |      int write,
 | 
	
		
			
				|  |  |      int priv);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -using page_arr = std::vector<page,
 | 
	
		
			
				|  |  | -    types::allocator_adapter<page, types::kernel_ident_allocator>>;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// forward declaration
 | 
	
		
			
				|  |  | -namespace kernel {
 | 
	
		
			
				|  |  | -class mm_list;
 | 
	
		
			
				|  |  | -} // namespace kernel
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  template <uint32_t base, uint32_t expo>
 | 
	
		
			
				|  |  |  constexpr uint32_t pow()
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -116,44 +108,6 @@ void free_page(page* pg);
 | 
	
		
			
				|  |  |  page_t __alloc_raw_page(void);
 | 
	
		
			
				|  |  |  void __free_raw_page(page_t pg);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct mm {
 | 
	
		
			
				|  |  | -public:
 | 
	
		
			
				|  |  | -    void* start;
 | 
	
		
			
				|  |  | -    union {
 | 
	
		
			
				|  |  | -        uint32_t v;
 | 
	
		
			
				|  |  | -        struct {
 | 
	
		
			
				|  |  | -            uint32_t read : 1;
 | 
	
		
			
				|  |  | -            uint32_t write : 1;
 | 
	
		
			
				|  |  | -            uint32_t system : 1;
 | 
	
		
			
				|  |  | -        } in;
 | 
	
		
			
				|  |  | -    } attr;
 | 
	
		
			
				|  |  | -    kernel::mm_list* owner;
 | 
	
		
			
				|  |  | -    page_arr* pgs = nullptr;
 | 
	
		
			
				|  |  | -    fs::inode* mapped_file = nullptr;
 | 
	
		
			
				|  |  | -    size_t file_offset = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -public:
 | 
	
		
			
				|  |  | -    constexpr void* end(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return (char*)this->start + this->pgs->size() * PAGE_SIZE;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    constexpr bool is_kernel_space(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return this->start >= std::bit_cast<void*>(0xc0000000);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    constexpr bool is_avail(void* start, void* end) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        void* m_start = this->start;
 | 
	
		
			
				|  |  | -        void* m_end = this->end();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        return (start >= m_end || end <= m_start);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    int append_page(page& pg, uint32_t attr, bool priv);
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  namespace kernel {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void* pmap(page_t pg);
 | 
	
	
		
			
				|  | @@ -184,120 +138,113 @@ public:
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace memory {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct mm {
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +    using pages_vector = std::vector<page,
 | 
	
		
			
				|  |  | +        types::allocator_adapter<page, types::kernel_ident_allocator>>;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +    void* start {};
 | 
	
		
			
				|  |  | +    struct mm_attr {
 | 
	
		
			
				|  |  | +        uint32_t write : 1;
 | 
	
		
			
				|  |  | +        uint32_t system : 1;
 | 
	
		
			
				|  |  | +        uint32_t mapped : 1;
 | 
	
		
			
				|  |  | +    } attr {};
 | 
	
		
			
				|  |  | +    pages_vector* pgs {};
 | 
	
		
			
				|  |  | +    fs::inode* mapped_file {};
 | 
	
		
			
				|  |  | +    size_t file_offset {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +    constexpr void* end() const noexcept
 | 
	
		
			
				|  |  | +    { return vptradd(start, pgs->size() * PAGE_SIZE); }
 | 
	
		
			
				|  |  | +    constexpr bool is_kernel_space() const noexcept
 | 
	
		
			
				|  |  | +    { return start >= std::bit_cast<void*>(0xc0000000); }
 | 
	
		
			
				|  |  | +    constexpr bool is_avail(void* ostart, void* oend) const noexcept
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        void* m_start = start;
 | 
	
		
			
				|  |  | +        void* m_end = end();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return (ostart >= m_end || oend <= m_start);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    void append_page(pd_t pd, const page& pg, uint32_t attr, bool priv);
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class mm_list {
 | 
	
		
			
				|  |  | +private:
 | 
	
		
			
				|  |  | +    struct comparator {
 | 
	
		
			
				|  |  | +        constexpr bool operator()(const mm& lhs, const mm& rhs) const noexcept
 | 
	
		
			
				|  |  | +        { return lhs.start < rhs.start; }
 | 
	
		
			
				|  |  | +        constexpr bool operator()(const mm& lhs, void* rhs) const noexcept
 | 
	
		
			
				|  |  | +        { return lhs.end() <= rhs; }
 | 
	
		
			
				|  |  | +        constexpr bool operator()(void* lhs, const mm& rhs) const noexcept
 | 
	
		
			
				|  |  | +        { return lhs < rhs.start; }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  public:
 | 
	
		
			
				|  |  | -    using list_type = std::list<mm,
 | 
	
		
			
				|  |  | +    using list_type = std::set<mm, comparator,
 | 
	
		
			
				|  |  |          types::allocator_adapter<mm, types::kernel_ident_allocator>>;
 | 
	
		
			
				|  |  | -    using iterator_type = list_type::iterator;
 | 
	
		
			
				|  |  | -    using const_iterator_type = list_type::const_iterator;
 | 
	
		
			
				|  |  | +    using iterator = list_type::iterator;
 | 
	
		
			
				|  |  | +    using const_iterator = list_type::const_iterator;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +    static inline mm_list* s_kernel_mms;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  private:
 | 
	
		
			
				|  |  |      list_type m_areas;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -public:
 | 
	
		
			
				|  |  |      page_t m_pd;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  public:
 | 
	
		
			
				|  |  | +    // for system initialization only
 | 
	
		
			
				|  |  |      explicit constexpr mm_list(page_t pd)
 | 
	
		
			
				|  |  | -        : m_pd(pd)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    mm_list(const mm_list& v);
 | 
	
		
			
				|  |  | +        : m_pd(pd) { }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // default constructor copies kernel_mms
 | 
	
		
			
				|  |  | +    explicit mm_list();
 | 
	
		
			
				|  |  | +    // copies kernel_mms and mirrors user space
 | 
	
		
			
				|  |  | +    explicit mm_list(const mm_list& other);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      constexpr mm_list(mm_list&& v)
 | 
	
		
			
				|  |  |          : m_areas(std::move(v.m_areas))
 | 
	
		
			
				|  |  | -        , m_pd(v.m_pd)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        v.m_pd = 0;
 | 
	
		
			
				|  |  | -        for (auto& area : m_areas)
 | 
	
		
			
				|  |  | -            area.owner = this;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ~mm_list()
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        if (!m_pd)
 | 
	
		
			
				|  |  | -            return;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        this->clear_user();
 | 
	
		
			
				|  |  | -        dealloc_pd(m_pd);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +        , m_pd(std::exchange(v.m_pd, 0)) { }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    constexpr iterator_type begin(void)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.begin();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    constexpr iterator_type end(void)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.end();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    constexpr const_iterator_type begin(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.begin();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    constexpr const_iterator_type end(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.end();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    constexpr const_iterator_type cbegin(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.cbegin();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    constexpr const_iterator_type cend(void) const
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        return m_areas.cend();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    ~mm_list();
 | 
	
		
			
				|  |  | +    void switch_pd() const;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      constexpr mm& addarea(void* start, bool w, bool system)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        return m_areas.emplace_back(mm {
 | 
	
		
			
				|  |  | +        auto [ iter, inserted ] = m_areas.emplace(mm {
 | 
	
		
			
				|  |  |              .start = start,
 | 
	
		
			
				|  |  |              .attr {
 | 
	
		
			
				|  |  | -                .in {
 | 
	
		
			
				|  |  | -                    .read = 1,
 | 
	
		
			
				|  |  | -                    .write = w,
 | 
	
		
			
				|  |  | -                    .system = system,
 | 
	
		
			
				|  |  | -                },
 | 
	
		
			
				|  |  | +                .write = w,
 | 
	
		
			
				|  |  | +                .system = system,
 | 
	
		
			
				|  |  | +                .mapped = 0,
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  | -            .owner = this,
 | 
	
		
			
				|  |  | -            .pgs = types::_new<types::kernel_ident_allocator, page_arr>(),
 | 
	
		
			
				|  |  | +            .pgs = types::_new<types::kernel_ident_allocator, mm::pages_vector>(),
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  | +        assert(inserted);
 | 
	
		
			
				|  |  | +        return *iter;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    mm& add_empty_area(void* start, std::size_t page_count,
 | 
	
		
			
				|  |  | +        uint32_t page_attr, bool w, bool system);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      constexpr void clear_user()
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        for (auto iter = this->begin(); iter != this->end();) {
 | 
	
		
			
				|  |  | +        for (auto iter = m_areas.begin(); iter != m_areas.end(); ) {
 | 
	
		
			
				|  |  |              if (iter->is_kernel_space()) {
 | 
	
		
			
				|  |  |                  ++iter;
 | 
	
		
			
				|  |  |                  continue;
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              this->unmap(iter);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              iter = m_areas.erase(iter);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    constexpr int mirror_area(mm& src)
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -        auto& area = this->addarea(
 | 
	
		
			
				|  |  | -            src.start, src.attr.in.write, src.attr.in.system);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        if (src.mapped_file) {
 | 
	
		
			
				|  |  | -            area.mapped_file = src.mapped_file;
 | 
	
		
			
				|  |  | -            area.file_offset = src.file_offset;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        for (auto& pg : *src.pgs) {
 | 
	
		
			
				|  |  | -            if (area.append_page(pg,
 | 
	
		
			
				|  |  | -                    PAGE_COW | (pg.attr & PAGE_MMAP),
 | 
	
		
			
				|  |  | -                    src.attr.in.system)
 | 
	
		
			
				|  |  | -                != GB_OK) {
 | 
	
		
			
				|  |  | -                return GB_FAILED;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        return GB_OK;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    inline void unmap(iterator_type area)
 | 
	
		
			
				|  |  | +    inline void unmap(iterator area)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          int i = 0;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -318,36 +265,40 @@ public:
 | 
	
		
			
				|  |  |              invalidate_tlb((uint32_t)area->start + (i++) * PAGE_SIZE);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          types::pdelete<types::kernel_ident_allocator>(area->pgs);
 | 
	
		
			
				|  |  | -        area->attr.v = 0;
 | 
	
		
			
				|  |  | -        area->start = 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    constexpr iterator_type find(void* lp)
 | 
	
		
			
				|  |  | +    constexpr mm* find(void* lp)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        for (auto iter = this->begin(); iter != this->end(); ++iter)
 | 
	
		
			
				|  |  | -            if (lp >= iter->start && lp < iter->end())
 | 
	
		
			
				|  |  | -                return iter;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        return this->end();
 | 
	
		
			
				|  |  | +        auto iter = m_areas.find(lp);
 | 
	
		
			
				|  |  | +        if (iter == m_areas.end())
 | 
	
		
			
				|  |  | +            return nullptr;
 | 
	
		
			
				|  |  | +        return &*iter;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    constexpr const mm* find(void* lp) const
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        auto iter = m_areas.find(lp);
 | 
	
		
			
				|  |  | +        if (iter == m_areas.end())
 | 
	
		
			
				|  |  | +            return nullptr;
 | 
	
		
			
				|  |  | +        return &*iter;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    constexpr bool is_avail(void* start, size_t len)
 | 
	
		
			
				|  |  | +    constexpr bool is_avail(void* start, size_t len) const noexcept
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          start = align_down<12>(start);
 | 
	
		
			
				|  |  |          len = vptrdiff(align_up<12>(vptradd(start, len)), start);
 | 
	
		
			
				|  |  | -        for (const auto& area : *this) {
 | 
	
		
			
				|  |  | -            if (!area.is_avail(start, (char*)start + len))
 | 
	
		
			
				|  |  | +        for (const auto& area : m_areas) {
 | 
	
		
			
				|  |  | +            if (!area.is_avail(start, vptradd(start, len)))
 | 
	
		
			
				|  |  |                  return false;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          return true;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +} // namespace memory
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  } // namespace kernel
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // global variables
 | 
	
		
			
				|  |  | -inline kernel::mm_list* kernel_mms;
 | 
	
		
			
				|  |  |  inline page empty_page;
 | 
	
		
			
				|  |  |  // --------------------------------
 | 
	
		
			
				|  |  |  
 |