#pragma once

#include <stdint.h>

//in paging.asm
extern "C" [[noreturn]] void switch_to_kernel_p4(void (*and_then_jump_to)());

namespace hilbert::kernel::paging {

  void mark_all_pram_used();
  void mark_all_vram_free();

  void mark_pram_region_free(uint64_t start_addr, uint64_t end_addr);
  void mark_vram_region_used(uint64_t start_addr, uint64_t end_addr);

  uint64_t find_unmapped_vram_region(uint64_t page_count);

  uint64_t encode_pte(uint64_t addr, bool user, bool write, bool execute);

  void init_kernel_page_tables(uint64_t kernel_offset);

  uint64_t take_pram_page();

  void map_kernel_stacks();

  void map_kernel_page(
    uint64_t paddr, uint64_t vaddr, bool write, bool execute);

  void unmap_kernel_page(uint64_t vaddr);

  //maps writable and not executable
  void *map_new_kernel_pages(uint64_t count);

  //maps writable and not executable
  void map_new_kernel_page(uint64_t &vaddr_out, uint64_t &paddr_out);

  uint64_t get_used_vram_page_count();
  uint64_t get_free_pram_page_count();

  extern uint64_t kernel_p4e;

}
