:github_url: https://github.com/nyx-org/gaia


.. _program_listing_file_vm_vm.hpp:

Program Listing for File vm.hpp
===============================

|exhale_lsh| :ref:`Return to documentation for file <file_vm_vm.hpp>` (``vm/vm.hpp``)

.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS

.. code-block:: cpp

   /* SPDX-License-Identifier: BSD-2-Clause */
   #pragma once
   #include "frg/spinlock.hpp"
   #include "lib/list.hpp"
   #include <hal/hal.hpp>
   #include <hal/mmu.hpp>
   #include <lib/base.hpp>
   #include <vm/vmem.h>
   
   #define VM_ENABLE_COW 1
   
   namespace Gaia::Vm {
   void init();
   
   extern Hal::Vm::Pagemap kernel_pagemap;
   
   struct Object;
   
   class Space {
   public:
     Result<uintptr_t, Error> map(Object *obj, frg::optional<uintptr_t> address,
                                  size_t size, Hal::Vm::Prot prot);
   
     Result<Void, Error> unmap(uintptr_t address, size_t size);
   
     // Matches i386 mmu
     enum FaultFlags {
       PRESENT = (1 << 0),
       WRITE = (1 << 1),
       USER = (1 << 2),
       EXEC = (1 << 4),
     };
   
     // Fault on address, returns true if fault was resolved
     bool fault(uintptr_t address, FaultFlags flags);
   
     Result<uintptr_t, Error> new_anon(frg::optional<uintptr_t> address,
                                       size_t size, Hal::Vm::Prot prot);
   
     Result<Void, Error> copy(Space *dest);
   
     void activate() { pagemap->activate(); }
   
     Space(Hal::Vm::Pagemap *pagemap, Vmem vmem) : pagemap(pagemap), vmem(vmem) {}
   
     Space(const char *name, bool user) {
       pagemap = new Hal::Vm::Pagemap();
       pagemap->init(!user);
   
       vmem_init(&vmem, name, (void *)0x80000000000, 0x100000000, 0x1000, 0, 0, 0,
                 0, 0);
     }
   
     void release();
   
     Hal::Vm::Pagemap *pagemap;
   
   private:
     struct Entry {
       ListNode<Entry> link;
       uintptr_t start;
       size_t size;
       Object *obj;
       Hal::Vm::Prot prot;
   
       Entry(uintptr_t start, size_t size, Object *obj, Hal::Vm::Prot prot)
           : start(start), size(size), obj(obj), prot(prot) {}
     };
   
     List<Entry, &Entry::link> entries;
   
     Vmem vmem;
   };
   
   class AnonMap;
   
   struct Anon;
   
   struct Object {
     int refcnt;
     size_t size;
   
     union {
       struct {
         AnonMap *amap;
         Object *parent; // if copied-on-write, original parent
       } anon;
     };
   
     // Create a (CoW-optimized) copy of the object
     Object *copy();
   
     // Retain a reference to an object
     void retain();
   
     // Release the object
     // NOTE: if the refcnt reaches 0, object WILL commit suicide (`delete this`)
     void release();
   
     Object(size_t size);
     Object(size_t size, AnonMap *amap);
   
     // Try and resolve a fault on the object
     bool fault(Space *map, uintptr_t vaddr, size_t offset,
                Space::FaultFlags flags, Hal::Vm::Prot obj_prot);
   };
   
   struct Anon {
     int refcnt;
     void *physpage;
     size_t offset; // offset within the amap
     frg::simple_spinlock lock;
   
     void release();
     Anon *copy();
     Anon(void *physpage, size_t offset)
         : refcnt(1), physpage(physpage), offset(offset){};
   };
   
   class AnonMap {
   public:
     struct Entry {
       Anon *anon;
       ListNode<Entry> link;
     };
   
     frg::optional<Entry *> anon_at(uintptr_t page);
   
     void insert_anon(Anon *anon);
   
     AnonMap *copy();
   
     void release();
   
   private:
     List<Entry, &Entry::link> entries;
   };
   } // namespace Gaia::Vm