* [PATCH] Rewrite of EFI memory map walk code
@ 2005-01-08 0:00 Khalid Aziz
0 siblings, 0 replies; only message in thread
From: Khalid Aziz @ 2005-01-08 0:00 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 2166 bytes --]
In an attempt to simplify EFI emmory range management and EFI memory map
walk, I have rewritten how EFI memory map is managed in the kernel. Here
is how I have approached this code. I am walking the EFI memory map and
from there I am constructing a linked list of valid memory ranges for
kernel to use. To find space to store this linked list in, from within
reserve_memory(), I walk the EFI memory map and look for the smallest
granule aligned block that will be sufficient to hold the linked list.
Amount of space I am allocating for linked list is the number of entries
in efi_memmap + another few for safety margin. I then mark this memory
reserved.
I have added two new functions - efi_gather_memory() which walks the EFI
memory map and builds a linked list of kernel usable memory map, and
efi_trim_memory() which applies the "max_addr=" and "mem=" restrictions
by splitting the linked list of kernel uable memory ranges
appropriately. Each node in this linked list has a field called
"ignore". To trim a memory range, I can split the list at approrpiate
point and mark every node in the list from that point onwards as ignored
by setting this field.
I rewrote efi_memmap_walk() to use the new kern_memmap list. I have also
replaced occurences of "md->num_pages << EFI_PAGE_SHIFT" with a macro.
One issue I have not been able to come up with a good solution for is
what to do if I fail to allocate memory for the linked list of memory
ranges. The only time this will happen is if I can not find a single
memory range that is larger than granule size. If that were to happen, I
do not see how the machine will boot even if we did not need space for
EFI memory map. So for now I have shelved this issue and simply do a
machine_restart() if this were to happen ever.
Tony, please apply.
--
Khalid
====================================================================
Khalid Aziz Linux and Open Source Lab
(970)898-9214 Hewlett-Packard
khalid_aziz@hp.com Fort Collins, CO
"The Linux kernel is subject to relentless development"
- Alessandro Rubini
[-- Attachment #2: efi_memmapwalk_rewrite.patch --]
[-- Type: text/x-patch, Size: 20375 bytes --]
diff -urNp linux-2.6.10/arch/ia64/kernel/efi.c linux-2.6.10-efimemmap/arch/ia64/kernel/efi.c
--- linux-2.6.10/arch/ia64/kernel/efi.c 2004-12-24 14:33:50.000000000 -0700
+++ linux-2.6.10-efimemmap/arch/ia64/kernel/efi.c 2005-01-07 16:49:31.212763442 -0700
@@ -17,6 +17,10 @@
*
* Goutham Rao: <goutham.rao@intel.com>
* Skip non-WB memory and ignore empty memory ranges.
+ *
+ * Rewrote efi_memap_walk() to create a linked list of available
+ * memory regions instead of editing EFI memory map in place
+ * - Khalid Aziz <khalid.aziz@hp.com>
*/
#include <linux/config.h>
#include <linux/module.h>
@@ -35,12 +39,17 @@
#define EFI_DEBUG 0
+#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT)
+
extern efi_status_t efi_call_phys (void *, ...);
struct efi efi;
EXPORT_SYMBOL(efi);
static efi_runtime_services_t *runtime;
static unsigned long mem_limit = ~0UL, max_addr = ~0UL;
+static kern_memdesc_t *kern_memmap = NULL;
+static unsigned long efi_total_mem = 0UL;
+kern_memdesc_t *memdesc_area, *memdesc_end;
#define efi_call_virt(f, args...) (*(f))(args)
@@ -222,60 +231,43 @@ efi_gettimeofday (struct timespec *ts)
ts->tv_nsec = tm.nanosecond;
}
-static int
-is_available_memory (efi_memory_desc_t *md)
-{
- if (!(md->attribute & EFI_MEMORY_WB))
- return 0;
-
- switch (md->type) {
- case EFI_LOADER_CODE:
- case EFI_LOADER_DATA:
- case EFI_BOOT_SERVICES_CODE:
- case EFI_BOOT_SERVICES_DATA:
- case EFI_CONVENTIONAL_MEMORY:
- return 1;
- }
- return 0;
-}
-
/*
* Trim descriptor MD so its starts at address START_ADDR. If the descriptor covers
* memory that is normally available to the kernel, issue a warning that some memory
* is being ignored.
*/
static void
-trim_bottom (efi_memory_desc_t *md, u64 start_addr)
+granule_align_bottom (kern_memdesc_t *md, u64 start_addr)
{
u64 num_skipped_pages;
- if (md->phys_addr >= start_addr || !md->num_pages)
+ if (md->start >= start_addr || !md->num_pages)
return;
- num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
+ num_skipped_pages = (start_addr - md->start) >> EFI_PAGE_SHIFT;
if (num_skipped_pages > md->num_pages)
num_skipped_pages = md->num_pages;
if (is_available_memory(md))
- printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
- "at 0x%lx\n", __FUNCTION__,
- (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
- md->phys_addr, start_addr - IA64_GRANULE_SIZE);
+ printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at "
+ "0x%lx due to granule hole at 0x%lx\n", __FUNCTION__,
+ (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
+ md->start, start_addr - IA64_GRANULE_SIZE);
/*
- * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
- * descriptor list to become unsorted. In such a case, md->num_pages will be
- * zero, so the Right Thing will happen.
+ * NOTE: Don't set md->start to start_addr because that could
+ * cause the memory descriptor list to become unsorted. In such
+ * a case, md->num_pages will be zero, so the Right Thing will happen.
*/
- md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
+ md->start += num_skipped_pages << EFI_PAGE_SHIFT;
md->num_pages -= num_skipped_pages;
}
static void
-trim_top (efi_memory_desc_t *md, u64 end_addr)
+granule_align_top (kern_memdesc_t *md, u64 end_addr)
{
u64 num_dropped_pages, md_end_addr;
- md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+ md_end_addr = md->start + efi_md_size(md);
if (md_end_addr <= end_addr || !md->num_pages)
return;
@@ -288,124 +280,228 @@ trim_top (efi_memory_desc_t *md, u64 end
printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
"at 0x%lx\n", __FUNCTION__,
(num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
- md->phys_addr, end_addr);
+ md->start, end_addr);
md->num_pages -= num_dropped_pages;
}
+/*
+ * Allocate a node for kernel memory descriptor. These allocations are never
+ * freed.
+ */
+static kern_memdesc_t *
+memdesc_alloc (void)
+{
+ if (memdesc_area >= memdesc_end)
+ return(-1UL);
+ return(memdesc_area++);
+}
+
/*
- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
- * has memory that is available for OS use.
+ * Walks the EFI memory map and calls CALLBACK once for each EFI
+ * memory descriptor that has memory that is available for OS use.
*/
void
efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
{
- int prev_valid = 0;
- struct range {
- u64 start;
- u64 end;
- } prev, curr;
+ kern_memdesc_t *memnode;
+ u64 start, end;
+
+ memnode = kern_memmap;
+
+ while (memnode != NULL) {
+ if (!is_available_memory(memnode) || memnode->ignore) {
+ memnode = memnode->next;
+ continue;
+ }
+ start = PAGE_OFFSET + memnode->start;
+ end = (start + efi_md_size(memnode)) & PAGE_MASK;
+
+ if ((*callback)(start, end, arg) < 0)
+ return;
+ memnode = memnode->next;
+ }
+}
+
+/*
+ * Trim memory size in accordance with "mem=" and "max_addr=" parameters
+ */
+void
+efi_trim_memory (void)
+{
+ kern_memdesc_t *memnode, *newnode;
+ unsigned long total_mem = 0UL;
+ unsigned long new_pages;
+
+ /* Do we have a memory size limit? If not, we are done */
+ if ((mem_limit == ~0UL) && (max_addr == ~0UL))
+ return;
+
+ /*
+ * walk the memory map to find where the limit kicks in
+ */
+ memnode = kern_memmap;
+ while (memnode != NULL) {
+ total_mem += efi_md_size(memnode);
+
+ if (memnode->start + efi_md_size(memnode) > max_addr) {
+ new_pages = (max_addr - memnode->start) >> EFI_PAGE_SHIFT;
+ break;
+ }
+ if (total_mem > mem_limit) {
+ new_pages = memnode->num_pages -
+ ((total_mem - mem_limit) >> EFI_PAGE_SHIFT);
+ break;
+ }
+ memnode = memnode->next;
+ }
+
+ /* Check for the case where the limit is larger than available mem */
+ if (memnode == NULL)
+ return;
+
+ if (new_pages == 0) {
+ memnode->ignore = 1; /* trim the whole range */
+ memnode = memnode->next;
+ }
+ else {
+ /* Allocate a new node that will hold split range */
+ if ((newnode = memdesc_alloc()) == -1UL) {
+ /*
+ * Print an error message and throw away the split
+ * range. Not the best option, but we do not have
+ * many choices here.
+ */
+ printk(KERN_ERR "ERROR: Failed to allocate space to split memory map for max_addr/mem\n");
+ memnode->num_pages = new_pages;
+ memnode = memnode->next;
+ }
+ else {
+ newnode->start = memnode->start + (new_pages << EFI_PAGE_SHIFT);
+ newnode->num_pages = memnode->num_pages - new_pages;
+ newnode->type = memnode->type;
+ newnode->ignore = 1;
+ memnode->num_pages = new_pages;
+ newnode->prev = memnode;
+ newnode->next = memnode->next;
+ memnode->next = newnode;
+ newnode->next->prev = newnode;
+ memnode = newnode->next;
+ }
+ }
+
+ /* Now walk the rest of the ranges and mark them ignored */
+ while (memnode != NULL) {
+ memnode->ignore = 1;
+ memnode = memnode->next;
+ }
+}
+
+/*
+ * Walk the EFI memory map and gather all memory available for kernel
+ * to use.
+ */
+void
+efi_gather_memory (void)
+{
void *efi_map_start, *efi_map_end, *p, *q;
efi_memory_desc_t *md, *check_md;
- u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
- unsigned long total_mem = 0;
+ u64 efi_desc_size, granule_addr, last_granule_addr, prev_end;
+ u64 first_non_wb_addr = 0;
+ int no_allocate = 0;
+ kern_memdesc_t *newnode, *prevnode;
efi_map_start = __va(ia64_boot_param->efi_memmap);
efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
efi_desc_size = ia64_boot_param->efi_memdesc_size;
+ prevnode = newnode = NULL;
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
- /* skip over non-WB memory descriptors; that's all we're interested in... */
if (!(md->attribute & EFI_MEMORY_WB))
continue;
+ if (!no_allocate && (newnode = memdesc_alloc()) == NULL) {
+ printk(KERN_ERR "ERROR: Failed to allocate node for kernel memory descriptor\n");
+ printk(KERN_ERR " Continuing with limited memory\n");
+ break;
+ }
+ newnode->type = md->type;
+ newnode->ignore = 0;
+ newnode->start = md->phys_addr;
+ newnode->num_pages = md->num_pages;
+ newnode->next = newnode->prev = NULL;
+ if (kern_memmap == NULL)
+ kern_memmap = newnode;
+
/*
+ * Do we need to granule align?
* granule_addr is the base of md's first granule.
* [granule_addr - first_non_wb_addr) is guaranteed to
* be contiguous WB memory.
*/
- granule_addr = GRANULEROUNDDOWN(md->phys_addr);
+ granule_addr = GRANULEROUNDDOWN(newnode->start);
first_non_wb_addr = max(first_non_wb_addr, granule_addr);
- if (first_non_wb_addr < md->phys_addr) {
- trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
- granule_addr = GRANULEROUNDDOWN(md->phys_addr);
+ if (first_non_wb_addr < newnode->start) {
+ granule_align_bottom(newnode, granule_addr + IA64_GRANULE_SIZE);
+ granule_addr = GRANULEROUNDDOWN(newnode->start);
first_non_wb_addr = max(first_non_wb_addr, granule_addr);
}
- for (q = p; q < efi_map_end; q += efi_desc_size) {
+ if (newnode->start == first_non_wb_addr)
+ first_non_wb_addr += efi_md_size(newnode);
+
+ for (q = p+efi_desc_size; q < efi_map_end; q += efi_desc_size) {
check_md = q;
if ((check_md->attribute & EFI_MEMORY_WB) &&
- (check_md->phys_addr == first_non_wb_addr))
- first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
+ (check_md->phys_addr == first_non_wb_addr)) {
+ first_non_wb_addr += efi_md_size(check_md);
+ }
else
- break; /* non-WB or hole */
+ break; /* non-WB or hole */
}
last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
- if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
- trim_top(md, last_granule_addr);
+ if (last_granule_addr < newnode->start + efi_md_size(newnode))
+ granule_align_top(newnode, last_granule_addr);
- if (is_available_memory(md)) {
- if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
- if (md->phys_addr >= max_addr)
- continue;
- md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
- first_non_wb_addr = max_addr;
- }
-
- if (total_mem >= mem_limit)
- continue;
-
- if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
- unsigned long limit_addr = md->phys_addr;
- limit_addr += mem_limit - total_mem;
- limit_addr = GRANULEROUNDDOWN(limit_addr);
-
- if (md->phys_addr > limit_addr)
- continue;
-
- md->num_pages = (limit_addr - md->phys_addr) >>
- EFI_PAGE_SHIFT;
- first_non_wb_addr = max_addr = md->phys_addr +
- (md->num_pages << EFI_PAGE_SHIFT);
- }
- total_mem += (md->num_pages << EFI_PAGE_SHIFT);
+ /*
+ * Are we left with any pages after all the alignment?
+ * If not, we will simply reuse the node we just allocated
+ * and not allocate a new one.
+ */
+ if (!newnode->num_pages) {
+ no_allocate = 1;
+ continue;
+ } else
+ no_allocate = 0;
- if (md->num_pages == 0)
+ /*
+ * Can we coalesce this memory range with previous one
+ */
+ if (prevnode) {
+ prev_end = prevnode->start + efi_md_size(prevnode);
+ if ((prev_end == newnode->start) &&
+ (is_available_memory(newnode)) &&
+ (is_available_memory(prevnode))) {
+ prevnode->num_pages += newnode->num_pages;
+ no_allocate = 1;
+ efi_total_mem += efi_md_size(newnode);
continue;
-
- curr.start = PAGE_OFFSET + md->phys_addr;
- curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
-
- if (!prev_valid) {
- prev = curr;
- prev_valid = 1;
- } else {
- if (curr.start < prev.start)
- printk(KERN_ERR "Oops: EFI memory table not ordered!\n");
-
- if (prev.end == curr.start) {
- /* merge two consecutive memory ranges */
- prev.end = curr.end;
- } else {
- start = PAGE_ALIGN(prev.start);
- end = prev.end & PAGE_MASK;
- if ((end > start) && (*callback)(start, end, arg) < 0)
- return;
- prev = curr;
- }
}
}
- }
- if (prev_valid) {
- start = PAGE_ALIGN(prev.start);
- end = prev.end & PAGE_MASK;
- if (end > start)
- (*callback)(start, end, arg);
+ if (is_available_memory(newnode))
+ efi_total_mem += efi_md_size(newnode);
+
+ /* Link this node in the list */
+ if (prevnode != NULL) {
+ newnode->prev = prevnode;
+ prevnode->next = newnode;
+ }
+ prevnode = newnode;
}
}
@@ -464,14 +560,14 @@ efi_map_pal_code (void)
continue;
}
- if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE)
+ if (efi_md_size(md) > IA64_GRANULE_SIZE)
panic("Woah! PAL code size bigger than a granule!");
mask = ~((1 << IA64_GRANULE_SHIFT) - 1);
#if EFI_DEBUG
printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
smp_processor_id(), md->phys_addr,
- md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
+ md->phys_addr + efi_md_size(md),
vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
#endif
@@ -604,7 +700,7 @@ efi_init (void)
md = p;
printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
i, md->type, md->attribute, md->phys_addr,
- md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
+ md->phys_addr + efi_md_size(md),
md->num_pages >> (20 - EFI_PAGE_SHIFT));
}
}
@@ -725,7 +821,7 @@ efi_mem_type (unsigned long phys_addr)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
- if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
+ if (phys_addr - md->phys_addr < efi_md_size(md))
return md->type;
}
return 0;
@@ -745,7 +841,7 @@ efi_mem_attributes (unsigned long phys_a
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
- if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
+ if (phys_addr - md->phys_addr < efi_md_size(md))
return md->attribute;
}
return 0;
@@ -765,12 +861,12 @@ valid_phys_addr_range (unsigned long phy
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
- if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) {
+ if (phys_addr - md->phys_addr < efi_md_size(md)) {
if (!(md->attribute & EFI_MEMORY_WB))
return 0;
- if (*size > md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr)
- *size = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr;
+ if (*size > md->phys_addr + efi_md_size(md) - phys_addr)
+ *size = md->phys_addr + efi_md_size(md) - phys_addr;
return 1;
}
}
diff -urNp linux-2.6.10/arch/ia64/kernel/setup.c linux-2.6.10-efimemmap/arch/ia64/kernel/setup.c
--- linux-2.6.10/arch/ia64/kernel/setup.c 2004-12-24 14:34:00.000000000 -0700
+++ linux-2.6.10-efimemmap/arch/ia64/kernel/setup.c 2005-01-07 16:49:43.859247662 -0700
@@ -74,6 +74,9 @@ EXPORT_SYMBOL(ia64_iobase);
struct io_space io_space[MAX_IO_SPACES];
EXPORT_SYMBOL(io_space);
unsigned int num_io_spaces;
+extern kern_memdesc_t *memdesc_area;
+extern kern_memdesc_t *memdesc_end;
+
unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */
@@ -156,6 +159,79 @@ sort_regions (struct rsvd_region *rsvd_r
}
}
+#define MEM_DESC_SAFETY_MARGIN 8
+
+static int
+find_memmap_space (int *marker)
+{
+ void *efi_map_start, *efi_map_end, *p, *q;
+ u64 efi_desc_size, space_needed;
+ u64 smallest_block = UINT_MAX;
+ u64 small_block_addr, block_size;
+ efi_memory_desc_t *md, *check_md;
+
+ /*
+ * Look for the first granule aligned memory descriptor memory
+ * that is big enough to hold EFI memory map. Make sure this
+ * descriptor is atleast granule sized so it does not get trimmed
+ */
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ /*
+ * We will allocate enough memory to hold as many nodes as
+ * there are in EFI memory map. We will then allocate another
+ * MEM_DESC_SAFETY_MARGIN for safety margin in case we have to
+ * split some of the memory ranges and thus create new nodes
+ */
+ space_needed = sizeof(kern_memdesc_t)*(ia64_boot_param->efi_memmap_size/efi_desc_size + MEM_DESC_SAFETY_MARGIN);
+
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ md = p;
+
+ /* skip over non-WB and non-available memory descriptors */
+ if ((!(md->attribute & EFI_MEMORY_WB)) ||
+ (!is_available_memory(md)))
+ continue;
+ block_size = md->num_pages << EFI_PAGE_SHIFT;
+
+ /* Look for any contiguous blocks of memory */
+ for (q = p+efi_desc_size; q < efi_map_end; q += efi_desc_size) {
+ check_md = q;
+
+ if ((check_md->attribute & EFI_MEMORY_WB) &&
+ (check_md->phys_addr == md->phys_addr+block_size) &&
+ is_available_memory(check_md)) {
+ block_size += check_md->num_pages << EFI_PAGE_SHIFT;
+ p += efi_desc_size;
+ }
+ else
+ break;
+ }
+
+ if ((block_size < smallest_block) &&
+ (block_size >= space_needed &&
+ (block_size >= IA64_GRANULE_SIZE))) {
+ smallest_block = block_size;
+ small_block_addr = md->phys_addr;
+ }
+
+ }
+
+ /*
+ * We will allocate a chunk of memory from the smallest block
+ * of memory we found.
+ */
+ rsvd_region[*marker].start = small_block_addr;
+ rsvd_region[*marker].end = memdesc_end =
+ small_block_addr + space_needed;
+ memdesc_area = __va(small_block_addr);
+ memdesc_end = memdesc_area + space_needed;
+ (*marker)++;
+ return 0;
+}
+
/**
* reserve_memory - setup reserved memory areas
*
@@ -196,6 +272,11 @@ reserve_memory (void)
}
#endif
+ if (find_memmap_space(&n) != 0) {
+ printk(KERN_EMERG "Failed to find space to build kernel EFI memory map");
+ machine_restart(NULL);
+ }
+
/* end of memory marker */
rsvd_region[n].start = ~0UL;
rsvd_region[n].end = ~0UL;
diff -urNp linux-2.6.10/arch/ia64/mm/contig.c linux-2.6.10-efimemmap/arch/ia64/mm/contig.c
--- linux-2.6.10/arch/ia64/mm/contig.c 2004-12-24 14:34:30.000000000 -0700
+++ linux-2.6.10-efimemmap/arch/ia64/mm/contig.c 2005-01-05 09:14:15.000000000 -0700
@@ -146,6 +146,9 @@ find_memory (void)
reserve_memory();
+ efi_gather_memory();
+ efi_trim_memory();
+
/* first find highest page frame number */
max_pfn = 0;
efi_memmap_walk(find_max_pfn, &max_pfn);
diff -urNp linux-2.6.10/arch/ia64/mm/discontig.c linux-2.6.10-efimemmap/arch/ia64/mm/discontig.c
--- linux-2.6.10/arch/ia64/mm/discontig.c 2004-12-24 14:35:25.000000000 -0700
+++ linux-2.6.10-efimemmap/arch/ia64/mm/discontig.c 2005-01-05 09:14:15.000000000 -0700
@@ -429,6 +429,9 @@ void __init find_memory(void)
reserve_memory();
+ efi_gather_memory();
+ efi_trim_memory();
+
if (numnodes == 0) {
printk(KERN_ERR "node info missing!\n");
numnodes = 1;
diff -urNp linux-2.6.10/include/asm-ia64/meminit.h linux-2.6.10-efimemmap/include/asm-ia64/meminit.h
--- linux-2.6.10/include/asm-ia64/meminit.h 2004-12-24 14:34:30.000000000 -0700
+++ linux-2.6.10-efimemmap/include/asm-ia64/meminit.h 2005-01-07 15:20:01.000000000 -0700
@@ -16,10 +16,11 @@
* - initrd (optional)
* - command line string
* - kernel code & data
+ * - Kernel memory map built from EFI memory map
*
* More could be added if necessary
*/
-#define IA64_MAX_RSVD_REGIONS 5
+#define IA64_MAX_RSVD_REGIONS 6
struct rsvd_region {
unsigned long start; /* virtual address of beginning of element */
@@ -29,6 +30,14 @@ struct rsvd_region {
extern struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
extern int num_rsvd_regions;
+typedef struct kern_memdesc {
+ u32 ignore;
+ u32 type;
+ u64 start;
+ u64 num_pages;
+ struct kern_memdesc *next, *prev;
+} kern_memdesc_t;
+
extern void find_memory (void);
extern void reserve_memory (void);
extern void find_initrd (void);
@@ -57,4 +66,10 @@ extern int filter_rsvd_memory (unsigned
extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
#endif
+#define is_available_memory(md) ((md->type == EFI_LOADER_CODE)? 1: \
+ ((md->type == EFI_LOADER_DATA)? 1: \
+ ((md->type == EFI_BOOT_SERVICES_CODE)? 1: \
+ ((md->type == EFI_BOOT_SERVICES_DATA)? 1: \
+ ((md->type == EFI_CONVENTIONAL_MEMORY)? 1:0)))))
+
#endif /* meminit_h */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-01-08 0:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-08 0:00 [PATCH] Rewrite of EFI memory map walk code Khalid Aziz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox