<commit_before>
#include <tilck/common/basic_defs.h>
#include <tilck/common/string_util.h>
#include <tilck/common/utils.h>

#include <tilck/kernel/system_mmap.h>
#include <tilck/kernel/paging.h>
#include <tilck/kernel/sort.h>
#include <tilck/kernel/elf_utils.h>

u32 __mem_lower_kb;
u32 __mem_upper_kb;

memory_region_t mem_regions[MAX_MEM_REGIONS];
int mem_regions_count;

STATIC void append_mem_region(memory_region_t r)
{
   if (mem_regions_count >= (int)ARRAY_SIZE(mem_regions))
      panic("Too many memory regions (limit: %u)", ARRAY_SIZE(mem_regions));

   mem_regions[mem_regions_count++] = r;
}

STATIC int less_than_cmp_mem_region(const void *a, const void *b)
{
   const memory_region_t *m1 = a;
   const memory_region_t *m2 = b;

   if (m1->addr < m2->addr)
      return -1;

   if (m1->addr == m2->addr)
      return 0;

   return 1;
}

STATIC void sort_mem_regions(void)
{
   insertion_sort_generic(mem_regions,
                          sizeof(memory_region_t),
                          mem_regions_count,
                          less_than_cmp_mem_region);
}

void system_mmap_add_ramdisk(uptr start_paddr, uptr end_paddr)
{
   append_mem_region((memory_region_t) {
      .addr = start_paddr,
      .len = end_paddr - start_paddr,
      .type = MULTIBOOT_MEMORY_RESERVED,
      .extra = MEM_REG_EXTRA_RAMDISK
   });

   sort_mem_regions();
}

void *system_mmap_get_ramdisk_vaddr(int ramdisk_index)
{
   int rd_count = 0;

   for (int i = 0; i < mem_regions_count; i++) {

      memory_region_t *m = mem_regions + i;

      if (m->extra & MEM_REG_EXTRA_RAMDISK) {
         if (rd_count == ramdisk_index)
            return KERNEL_PA_TO_VA((uptr)m->addr);

         rd_count++;
      }
   }

   return NULL;
}

STATIC void remove_mem_region(int i)
{
   memory_region_t *ma = mem_regions + i;
   const int rem = mem_regions_count - i - 1;

   memcpy(ma, ma + 1, rem * sizeof(memory_region_t));
   mem_regions_count--; /* decrease the number of memory regions */
}

STATIC void swap_mem_regions(int i, int j)
{
   ASSERT(0 <= i && i < mem_regions_count);
   ASSERT(0 <= j && j < mem_regions_count);

   memory_region_t temp = mem_regions[i];
   mem_regions[i] = mem_regions[j];
   mem_regions[j] = temp;
}

STATIC void remove_mem_region_by_swap_with_last(int i)
{
   ASSERT(0 <= i && i < mem_regions_count);
   swap_mem_regions(i, mem_regions_count - 1);
   mem_regions_count--;
}

STATIC void align_mem_regions_to_page_boundary(void)
{
   for (int i = 0; i < mem_regions_count; i++) {

      memory_region_t *ma = mem_regions + i;

      /*
       * Unfortunately, in general we cannot rely on the memory regions to be
       * page-aligned (while they will be in most of the cases). Therefore,
       * we have to forcibly approximate the regions at page-boundaries.
       */
      const u64 ma_end = round_up_at64(ma->addr + ma->len, PAGE_SIZE);
      ma->addr &= PAGE_MASK;
      ma->len = ma_end - ma->addr;
   }
}

STATIC void merge_adj_mem_regions(void)
{
   for (int i = 0; i < mem_regions_count - 1; i++) {

      memory_region_t *ma = mem_regions + i;
      memory_region_t *ma_next = ma + 1;

      if (ma_next->type != ma->type || ma_next->extra != ma->extra)
         continue;

      if (ma_next->addr != ma->addr + ma->len)
         continue;

      /* If we got here, we hit two adjacent regions having the same type */

      ma->len += ma_next->len;
      remove_mem_region(i + 1);<commit_msg>[system_mmap] Fix a nasty bug (32 vs 64 bit)<commit_after>
#include <tilck/common/basic_defs.h>
#include <tilck/common/string_util.h>
#include <tilck/common/utils.h>

#include <tilck/kernel/system_mmap.h>
#include <tilck/kernel/paging.h>
#include <tilck/kernel/sort.h>
#include <tilck/kernel/elf_utils.h>

u32 __mem_lower_kb;
u32 __mem_upper_kb;

memory_region_t mem_regions[MAX_MEM_REGIONS];
int mem_regions_count;

STATIC void append_mem_region(memory_region_t r)
{
   if (mem_regions_count >= (int)ARRAY_SIZE(mem_regions))
      panic("Too many memory regions (limit: %u)", ARRAY_SIZE(mem_regions));

   mem_regions[mem_regions_count++] = r;
}

STATIC int less_than_cmp_mem_region(const void *a, const void *b)
{
   const memory_region_t *m1 = a;
   const memory_region_t *m2 = b;

   if (m1->addr < m2->addr)
      return -1;

   if (m1->addr == m2->addr)
      return 0;

   return 1;
}

STATIC void sort_mem_regions(void)
{
   insertion_sort_generic(mem_regions,
                          sizeof(memory_region_t),
                          mem_regions_count,
                          less_than_cmp_mem_region);
}

void system_mmap_add_ramdisk(uptr start_paddr, uptr end_paddr)
{
   append_mem_region((memory_region_t) {
      .addr = start_paddr,
      .len = end_paddr - start_paddr,
      .type = MULTIBOOT_MEMORY_RESERVED,
      .extra = MEM_REG_EXTRA_RAMDISK
   });

   sort_mem_regions();
}

void *system_mmap_get_ramdisk_vaddr(int ramdisk_index)
{
   int rd_count = 0;

   for (int i = 0; i < mem_regions_count; i++) {

      memory_region_t *m = mem_regions + i;

      if (m->extra & MEM_REG_EXTRA_RAMDISK) {
         if (rd_count == ramdisk_index)
            return KERNEL_PA_TO_VA((uptr)m->addr);

         rd_count++;
      }
   }

   return NULL;
}

STATIC void remove_mem_region(int i)
{
   memory_region_t *ma = mem_regions + i;
   const int rem = mem_regions_count - i - 1;

   memcpy(ma, ma + 1, rem * sizeof(memory_region_t));
   mem_regions_count--; /* decrease the number of memory regions */
}

STATIC void swap_mem_regions(int i, int j)
{
   ASSERT(0 <= i && i < mem_regions_count);
   ASSERT(0 <= j && j < mem_regions_count);

   memory_region_t temp = mem_regions[i];
   mem_regions[i] = mem_regions[j];
   mem_regions[j] = temp;
}

STATIC void remove_mem_region_by_swap_with_last(int i)
{
   ASSERT(0 <= i && i < mem_regions_count);
   swap_mem_regions(i, mem_regions_count - 1);
   mem_regions_count--;
}

STATIC void align_mem_regions_to_page_boundary(void)
{
   for (int i = 0; i < mem_regions_count; i++) {

      memory_region_t *ma = mem_regions + i;

      /*
       * Unfortunately, in general we cannot rely on the memory regions to be
       * page-aligned (while they will be in most of the cases). Therefore,
       * we have to forcibly approximate the regions at page-boundaries.
       */
      const u64 ma_end = round_up_at64(ma->addr + ma->len, PAGE_SIZE);
      ma->addr &= ~((u64)PAGE_SIZE - 1); /* Don't use PAGE_MASK here: it causes
                                            truncation on 32-bit systems */
      ma->len = ma_end - ma->addr;
   }
}

STATIC void merge_adj_mem_regions(void)
{
   for (int i = 0; i < mem_regions_count - 1; i++) {

      memory_region_t *ma = mem_regions + i;
      memory_region_t *ma_next = ma + 1;

      if (ma_next->type != ma->type || ma_next->extra != ma->extra)
         continue;

      if (ma_next->addr != ma->addr + ma->len)
         continue;

      /* If we got here, we hit two adjacent regions having the same type */

      ma->len += ma_next->len;
      remove_mem_region(i + 1);
{'fraction_non_alphanumeric': 0.11626248216833096, 'fraction_numerical': 0.009843081312410842, 'mean_word_length': 2.9498591549295776, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7114021', 'n_tokens_mistral': 2689, 'n_tokens_neox': 2507, 'n_words': 582}