[E820_PMEM] = "PMEM"
};
+/*
+ * E820 type based bitmask for deciding how to round entries to page
+ * boundaries: A set bit means the type relates to a resource managed by
+ * Mini-OS (e.g. RAM), so rounding needs to be done to only include pages
+ * completely of the related type (narrowing). All other types need to be
+ * rounded to include all pages with parts of that type (widening).
+ */
+#define E820_NARROW ((1U << E820_RAM) | (1U << E820_NVS) | (1 << E820_PMEM))
+
+/* Private type used to mark a range temporarily as reserved (lowest prio). */
+#define E820_TMP_RESERVED 0
+
+static void e820_remove_entry(int idx)
+{
+ int i;
+
+ e820_entries--;
+ for ( i = idx; i < e820_entries; i++ )
+ e820_map[i] = e820_map[i + 1];
+}
+
+static void e820_insert_entry_at(int idx, unsigned long addr,
+ unsigned long size, unsigned int type)
+{
+ int i;
+
+ if ( e820_entries == E820_MAX )
+ {
+ xprintk("E820 memory map overflow\n");
+ do_exit();
+ }
+
+ e820_entries++;
+ for ( i = e820_entries - 1; i > idx; i-- )
+ e820_map[i] = e820_map[i - 1];
+
+ e820_map[idx].addr = addr;
+ e820_map[idx].size = size;
+ e820_map[idx].type = type;
+}
+
+static void e820_insert_entry(unsigned long addr, unsigned long size,
+ unsigned int type)
+{
+ int i;
+
+ for ( i = 0; i < e820_entries && addr > e820_map[i].addr; i++ );
+
+ e820_insert_entry_at(i, addr, size, type);
+}
+
+static void e820_swap_entries(int idx1, int idx2)
+{
+ struct e820entry entry;
+
+ entry = e820_map[idx1];
+ e820_map[idx1] = e820_map[idx2];
+ e820_map[idx2] = entry;
+}
+
+/*
+ * Do a memory map sanitizing sweep:
+ * - sort the entries by start address
+ * - remove overlaps of entries (higher type value wins)
+ * - merge adjacent entries of same type
+ */
+static void e820_process_entries(void)
+{
+ int i, j;
+ unsigned long end, start;
+ unsigned int type;
+
+ /* Sort entries. */
+ for ( i = 1; i < e820_entries; i++ )
+ for ( j = i; j > 0 && e820_map[j - 1].addr > e820_map[j].addr; j-- )
+ e820_swap_entries(j - 1, j);
+
+ /* Handle overlapping entries (higher type values win). */
+ for ( i = 1; i < e820_entries; i++ )
+ {
+ if ( e820_map[i - 1].addr + e820_map[i - 1].size <= e820_map[i].addr )
+ continue;
+ if ( e820_map[i - 1].addr < e820_map[i].addr )
+ {
+ e820_insert_entry_at(i - 1, e820_map[i - 1].addr,
+ e820_map[i].addr - e820_map[i - 1].addr,
+ e820_map[i - 1].type);
+ e820_map[i].addr += e820_map[i - 1].size;
+ e820_map[i].size -= e820_map[i - 1].size;
+ i++;
+ }
+ if ( e820_map[i - 1].type < e820_map[i].type )
+ e820_swap_entries(i - 1, i);
+ if ( e820_map[i - 1].size >= e820_map[i].size )
+ {
+ e820_remove_entry(i);
+ i--;
+ }
+ else
+ {
+ start = e820_map[i].addr + e820_map[i - 1].size;
+ end = e820_map[i].addr + e820_map[i].size;
+ type = e820_map[i].type;
+ e820_remove_entry(i);
+ e820_insert_entry(start, end - start, type);
+ }
+ }
+
+ /* Merge adjacent entries. */
+ for ( i = 0; i < e820_entries - 1; i++ )
+ {
+ if ( e820_map[i].type == e820_map[i + 1].type &&
+ e820_map[i].addr + e820_map[i].size >= e820_map[i + 1].addr )
+ {
+ if ( e820_map[i].addr + e820_map[i].size <
+ e820_map[i + 1].addr + e820_map[i + 1].size )
+ {
+ e820_map[i].size = e820_map[i + 1].addr - e820_map[i].addr +
+ e820_map[i + 1].size;
+ }
+ e820_remove_entry(i + 1);
+ i--;
+ }
+ }
+}
+
+/*
+ * Transform memory map into a well sorted map without any overlaps.
+ * - sort map entries by start address
+ * - handle overlaps
+ * - merge adjacent entries of same type (possibly removing boundary in the
+ * middle of a page)
+ * - trim entries to page boundaries (depending on type either expanding
+ * the entry or narrowing it down)
+ * - repeat first 3 sanitizing steps
+ * - make remaining temporarily reserved entries permanently reserved
+ */
+static void e820_sanitize(void)
+{
+ int i;
+ unsigned long end, start;
+
+ /* Sanitize memory map in current form. */
+ e820_process_entries();
+
+ /* Adjust map entries to page boundaries. */
+ for ( i = 0; i < e820_entries; i++ )
+ {
+ start = e820_map[i].addr;
+ end = start + e820_map[i].size;
+ if ( (1U << e820_map[i].type) & E820_NARROW )
+ {
+ if ( start & (PAGE_SIZE - 1) )
+ {
+ start = round_pgup(start);
+ e820_insert_entry_at(i, start - PAGE_SIZE, PAGE_SIZE,
+ E820_TMP_RESERVED);
+ i++;
+ }
+ if ( end & (PAGE_SIZE - 1) )
+ {
+ end = round_pgdown(end);
+ e820_insert_entry_at(i + 1, end, PAGE_SIZE, E820_TMP_RESERVED);
+ i++;
+ }
+ }
+ else
+ {
+ start = round_pgdown(start);
+ end = round_pgup(end);
+ }
+ e820_map[i].addr = start;
+ e820_map[i].size = end - start;
+ }
+
+ /* Sanitize memory map (again). */
+ e820_process_entries();
+
+ /* Make remaining temporarily reserved entries permanently reserved. */
+ for ( i = 0; i < e820_entries; i++ )
+ if ( e820_map[i].type == E820_TMP_RESERVED )
+ e820_map[i].type = E820_RESERVED;
+}
+
static void e820_get_memmap(void)
{
long ret;
do_exit();
}
e820_entries = memmap.nr_entries;
+
+ e820_sanitize();
}
void arch_print_memmap(void)