/*
 * Copyright (c) 2026, Chloe M.
 * Provided under the BSD-3 clause.
 *
 * Description:  Virtual memory management
 * Author:       Chloe M.
 */

#ifndef _MM_VM_H_
#define _MM_VM_H_ 1

#include <ke/bpal.h>
#include <hal/vas.h>
#include <hal/mmu.h>
#include <ptapi/ptmm.h>
#include <ptdef.h>

/*
 * Virtual memory allocation region. This is outside the
 * higher half direct map and thus cannot be converted with
 * PMA_TO_VMA() / VMA_TO_PMA()
 */
#define VALLOC_BASE 0xFFFF804000000000

/*
 * Used to convert physical addresses to virtual addresses
 * and vice versa only when they are within the higher half
 * direct map.
 */
#define PMA_TO_VMA(PMA) \
    PTR_OFFSET((VOID *)PMA, KeBpalLoadBase())
#define VMA_TO_PMA(VMA) \
    (UPTR)PTR_NOFFSET(VMA, KeBpalLoadBase())

/*
 * Represents a virtual memory range
 *
 * @VirtualBase:    Virtual address base
 * @PhysicalBase:   Physical address base
 * @Length:         Length of memory range
 */
typedef struct {
    UPTR VirtualBase;
    UPTR PhysicalBase;
    USIZE Length;
} MM_RANGE;

/* Obtain a pointer from an &MM_RANGE pointer */
#define RANGE_PTR(RANGE_P) \
    ((VOID *)((RANGE_P)->VirtualBase))

/*
 * Unmap a virtual memory range
 *
 * @Vas:        Virtual address space to unmap
 * @Range:      Range to unmap
 * @PageSize:   Page size to unmap
 */
PT_STATUS MmUnmapRange(MMU_VAS *Vas, const MM_RANGE *Range, MMU_PAGESIZE PageSize);

/*
 * Map a virtual memory range
 *
 * @Vas:        Virtual address space to map within
 * @Range:      Range to map
 * @Prot:       Protection flags to map with
 * @PageSize:   Page size to map
 */
PT_STATUS MmMapRange(
    MMU_VAS *Vas, const MM_RANGE *Range,
    MM_PROT Prot, MMU_PAGESIZE PageSize
);

/*
 * Allocate one or more pages
 *
 * @Count:  Number of pages to allocate
 * @Result: Result is written back here
 */
PT_STATUS MmAllocatePages(USIZE Count, MM_RANGE *Result);

/*
 * Initialize virtual memory
 */
VOID MmVmInit(VOID);

#endif  /* !_MM_VM_H_ */
