diff options
Diffstat (limited to 'src/include/kernel/block.H')
-rw-r--r-- | src/include/kernel/block.H | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/include/kernel/block.H b/src/include/kernel/block.H new file mode 100644 index 000000000..1de1c1280 --- /dev/null +++ b/src/include/kernel/block.H @@ -0,0 +1,161 @@ +/** @file block.H + * @brief Defines the implementation for the generic VMM block class. + */ +#ifndef __KERNEL_BLOCK_H +#define __KERNEL_BLOCK_H + +#include <stdint.h> +#include <kernel/task.H> +#include <kernel/vmmmgr.H> + +class ShadowPTE; +class Segment; + +/** @class Block + * @brief Provides management of the memory pages associated with a block of + * virtual memory. + * + * This class is organized to be either an independent block (typically + * managed by the Segment container in some way) or as a chain of blocks. + * + * When the instance is assigned down-stream blocks, the instance will + * forward requests that do not belong to it down the chain for handling + * by a block responsible for the request. Also, when used in this manner, + * this block is responsible for the ownership of all down-stream blocks, + * including calling their destructor when necessary. + * + * There is currently no mechanism for dynamically removing blocks from the + * chain. The expectation is that all known use cases would suggest either + * a fixed (increasing-only) chain or a known-sized array of blocks. + */ +class Block +{ + public: + /** + * @brief Constructor. + * + * @param[in] i_baseAddr - Base virtual Address of the block. + * @param[in] i_size - Size of the block (in bytes). + * + * Will allocate enough shadow PTEs to track pages in the block. + */ + Block(uint64_t i_baseAddr, uint64_t i_size) : + iv_baseAddr(i_baseAddr), iv_size(i_size), + iv_parent(NULL), iv_nextBlock(NULL), iv_ptes(NULL) + { init(); }; + + /** + * @brief Destructor. + * + * Releases associated memory and down-stream blocks. + */ + ~Block(); + + /** + * @brief Get the base address of this block. + * @return Base address (as uint64_t). + */ + uint64_t getBaseAddress() const { return iv_baseAddr; }; + + /** + * @brief Determines if a virtual address is in the range of the block. + * + * @param[in] i_addr - The virtual address in question. + * @return true - Address is contained within the block. + * @return false - Address is not contained within the block. + */ + bool isContained(uint64_t i_addr) const + { return (i_addr >= iv_baseAddr) && + (i_addr < iv_baseAddr + iv_size); }; + + /** + * @brief Responsible for handling page faults within the block [chain]. + * + * @param[in] i_task - Task causing the page fault. + * @param[in] i_addr - Effective address accessed to cause fault. + * + * @return true - Page fault was successfully handled. + * + * If the page fault is not successfully handled the expectation is + * that the VMM will perform appropriate action, such as killing the + * task. + * + * If the address is not within this block, the block will attempt to + * make calls down the block-chain if it exists. + */ + bool handlePageFault(task_t* i_task, uint64_t i_addr); + + friend class Segment; + friend class BaseSegment; + friend class StackSegment; + + protected: + /** + * @brief Assign a segment to a parent relationship to this block. + * + * @param[in] i_parent - The segment to assign as a parent. + */ + void setParent(Segment* i_parent) { iv_parent = i_parent; }; + + /** + * @brief Add a block to the end of this block-chain. + * + * @param[in] i_block - The block tp append. + */ + void appendBlock(Block* i_block) + { + if (NULL == iv_nextBlock) iv_nextBlock = i_block; + else iv_nextBlock->appendBlock(i_block); + } + + /** + * @brief Set up a virtual-physical mapping for a static page. + * + * @param[in] i_vAddr - The virtual address of the page. + * @param[in] i_pAddr - The physical address of the page. + * @param[in] i_access - The permissions of the page. + */ + void setPhysicalPage(uint64_t i_vAddr, uint64_t i_pAddr, + VmmManager::ACCESS_TYPES i_access); + + private: + /** Base address of the block */ + const uint64_t iv_baseAddr; + /** Size of the block */ + const uint64_t iv_size; + + /** Pointer to the parent (containing) segment. */ + Segment* iv_parent; + /** Pointer to the next block in the chain. */ + Block* iv_nextBlock; + + /** Pointer to the Shadow PTE entries. */ + ShadowPTE* iv_ptes; + + /** + * @brief Finish initialization of block. + * + * Construct ShadowPTE entries. + * + * This is defined as a separate function to reduce the code + * footprint of the class constructors. GCC emits an "in-charge" and + * "not-in-charge" version of each constructor, so put as much + * common code into an init function. + */ + void init(); + + /** + * @brief Find the Shadow PTE for a virtual address. + * + * @param[in] i_addr - The virtual address to find a page for. + * @note This function does no bounds checking. + */ + ShadowPTE* getPTE(uint64_t i_addr) const; + + + Block(const Block&); // prohibit copy. + Block& operator=(const Block&); // prohibit assignment. + +}; + +#endif |