<commit_before>#/** \ingroup kernel
* \{
*
* \file kernel/memory_map.hpp
* \brief This file defines the memory map used by the
*        kernel as well as some auxilliary types.
*/

#ifndef H_kernel_memory
#define H_kernel_memory

#include <common/types.hpp>

#include "dynarray.hpp"
#include "debug.hpp"
#include "constants.hpp"

#include <memory_resource>
#include <algorithm>
#include <limits>

namespace UtopiaOS
{
    namespace kernel
    {
        /** \enum memory_type
         * \brief Analogous to the UEFI memory type
         *        but contains only types the kernel
         *        actually knows about.
         */
        enum class memory_type : common::uint32
        {
            general_purpose,
            unusable
        };
        
        /** \struct memory_request
         * \brief Encapsulates a memory requirement
         * \tparam ALIGN Specifies the alignment
         */
        template<std::size_t ALIGN>
        struct memory_request
        {
            std::size_t size;
            static constexpr std::size_t alignment = ALIGN;
        };
        
        /** \brief Aligns a pointer to a given alignment.
         * \param[in] ptr The pointer to align
         * \param[in] alignment The alignment to meet
         * \returns An aligned pointer or 0 if the pointer
         *          could not be aligned.
         *
         * The aligned pointer is guaranteed to point to
         * an address not smaller than the original pointer.
         * It is guaranteed that there is no other aligned
         * address in the range [\a ptr, \a return-value].
         * If the pointer cannot be aligned, i.e it points
         * to an address so large that the next aligned
         * address would not fit into the data type,
         * 0 is returned.
         *
         * \warning If \a alignment is not a power of two,
         *          the behaviour is undefined!
         */
        static inline common::uintptr align( common::uintptr ptr, std::size_t alignment )
        {
            static_assert( std::numeric_limits<common::uintptr>::max() >=
                          std::numeric_limits<std::size_t>::max(),
                          "This implementation cannot guarantee to work." );
            debug_assert( (alignment % 2) == 0, "alignment has to be a power of two" );
            
            common::un mask = alignment - 1; // ...0000011111...
            common::un diff = (ptr & mask);
            
            if( diff == 0 )
                return ptr;
            
            return (ptr + alignment - diff);
        }
        
        /** \struct memory_descriptor
         * \brief Analogous to a UEFI memory descriptor,
         *        but usable by the kernel. It also has
         *        a well-defined size.
         *
         * It is guaranteed that
         * (\a start + \a number_of_pages * \a pagesize)
         * does not overflow, where \a start is either
         * \a physical_start or \a virtual_start
         */
        struct memory_descriptor
        {
            memory_type type;
            common::uint64 physical_start;
            common::uint64 virtual_start;
            common::uint64 number_of_pages;
            
            /** \brief Construct a kernel-usable memory
             *         descriptor from a UEFI one.
             */
            memory_descriptor( const UEFI::memory_descriptor_v1 &uefi_desc );
            
            /** \brief Checks whether the memory described by
             *         the memory descriptor can be used to
             *         fulfil a memory request.
             * \tparam ALIGN Specifies the alignment
             * \returns \a true if the request can be fulfilled
             *          and \a false otherwise.
             */
            template<std::size_t ALIGN>
            bool can_meet_request( const memory_request<ALIGN> &request ) const
            {
                static_assert( std::numeric_limits<common::uintptr>::max() >=
                              std::numeric_limits<std::size_t>::max(),
                              "This implementation cannot guarantee to work." );
                if( type != memory_type::general_purpose )
                    return false;
                
                auto aligned_address = align( virtual_start, request.alignment );
                common::uintptr request_end = aligned_address + request.size;
                
                if( (request_end - virtual_start) / pagesize <= number_of_pages )
                    return true;
                
                return false;
            }
        };
        
        /** \class memory_map
         * \brief The memory map used by the kernel<commit_msg>Implemented UEFI memory_descriptor to kernel memory descriptor conversion.<commit_after>#/** \ingroup kernel
* \{
*
* \file kernel/memory_map.hpp
* \brief This file defines the memory map used by the
*        kernel as well as some auxilliary types.
*/

#ifndef H_kernel_memory
#define H_kernel_memory

#include <common/types.hpp>

#include "dynarray.hpp"
#include "debug.hpp"
#include "constants.hpp"

#include <memory_resource>
#include <algorithm>
#include <limits>

namespace UtopiaOS
{
    namespace kernel
    {
        /** \enum memory_type
         * \brief Analogous to the UEFI memory type
         *        but contains only types the kernel
         *        actually knows about.
         */
        enum class memory_type : common::uint32
        {
            general_purpose,
            unusable,
            invalid
        };
        
        /** \struct memory_request
         * \brief Encapsulates a memory requirement
         * \tparam ALIGN Specifies the alignment
         */
        template<std::size_t ALIGN>
        struct memory_request
        {
            std::size_t size;
            static constexpr std::size_t alignment = ALIGN;
        };
        
        /** \brief Aligns a pointer to a given alignment.
         * \param[in] ptr The pointer to align
         * \param[in] alignment The alignment to meet
         * \returns An aligned pointer or 0 if the pointer
         *          could not be aligned.
         *
         * The aligned pointer is guaranteed to point to
         * an address not smaller than the original pointer.
         * It is guaranteed that there is no other aligned
         * address in the range [\a ptr, \a return-value].
         * If the pointer cannot be aligned, i.e it points
         * to an address so large that the next aligned
         * address would not fit into the data type,
         * 0 is returned.
         *
         * \warning If \a alignment is not a power of two,
         *          the behaviour is undefined!
         */
        static inline common::uintptr align( common::uintptr ptr, std::size_t alignment )
        {
            static_assert( std::numeric_limits<common::uintptr>::max() >=
                          std::numeric_limits<std::size_t>::max(),
                          "This implementation cannot guarantee to work." );
            debug_assert( (alignment % 2) == 0, "alignment has to be a power of two" );
            
            common::un mask = alignment - 1; // ...0000011111...
            common::un diff = (ptr & mask);
            
            if( diff == 0 )
                return ptr;
            
            return (ptr + alignment - diff);
        }
        
        /** \struct memory_descriptor
         * \brief Analogous to a UEFI memory descriptor,
         *        but usable by the kernel. It also has
         *        a well-defined size.
         *
         * It is guaranteed that
         * (\a start + \a number_of_pages * \a pagesize)
         * does not overflow, where \a start is either
         * \a physical_start or \a virtual_start.
         * For memory_descriptor with its type set to
         * \a memory_type::invalid the contents of the
         * other fields are undefined.
         */
        struct memory_descriptor
        {
            memory_type type;
            common::uint64 physical_start;
            common::uint64 virtual_start;
            common::uint64 number_of_pages;
            
            /** \brief Construct a kernel-usable memory
             *         descriptor from a UEFI one.
             *
             * \warning If there is an overflow in
             *          (\a start + \a number_of_pages * \a UEFI::pagesize)
             *          where \a start is either
             *          \a physical_start or \a virtual_start
             *          the memory_type will be set to unusable.
             * \warning If the total memory block is smaller than
             *          the kernel pagesize the type will be set
             *          to invalid and the other fields are undefined.
             * \warning If the kernel pagesize cannot be used to fully
             *          cover the memory region, the memory region
             *          will be truncated accordingly.
             */
            memory_descriptor( const UEFI::memory_descriptor_v1 &uefi_desc )
            : type( uefi_desc.type == UEFI::memory_type::EfiConventionalMemory ?
                   memory_type::general_purpose : memory_type::unusable ),
            physical_start( uefi_desc.physical_start ),
            virtual_start( uefi_desc.virtual_start ),
            number_of_pages( (uefi_desc.number_of_pages * UEFI::pagesize) / pagesize )
            {
                if( number_of_pages == 0 )
                    type = memory_type::invalid;
            }
            
            /** \brief Checks whether the memory described by
             *         the memory descriptor can be used to
             *         fulfil a memory request.
             * \tparam ALIGN Specifies the alignment
             * \returns \a true if the request can be fulfilled
             *          and \a false otherwise.
             */
            template<std::size_t ALIGN>
            bool can_meet_request( const memory_request<ALIGN> &request ) const
            {
                static_assert( std::numeric_limits<common::uintptr>::max() >=
                              std::numeric_limits<std::size_t>::max(),
                              "This implementation cannot guarantee to work." );
                if( type != memory_type::general_purpose )
                    return false;
                
                auto aligned_address = align( virtual_start, request.alignment );
                common::uintptr request_end = aligned_address + request.size;
                
                if( (request_end - virtual_start) / pagesize <= number_of_pages )
                    return true;
                
                return false;
            }
        };
        
        /** \class memory_map
         * \brief The memory map used by the kernel
{'fraction_non_alphanumeric': 0.07618697092381303, 'fraction_numerical': 0.004692675745307324, 'mean_word_length': 1.4798083504449007, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2941858', 'n_tokens_mistral': 2710, 'n_tokens_neox': 2624, 'n_words': 925}