[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[microblaze-uclinux] [patch] memory management initialisation cleanup
Hi folks,
Attached is a trial patch that cleans up the so-called bootmem-debacle,
and other memory initialisations that go on before the kernel boots.
Basically I've just lifted the mechanism used in arm/armnommu kernels.
They take a clean approach to the whole thing.
Why do this? Well, as many people have seen the present setup makes it
quite clumsy to change things like physical memory ranges etc, and hard
to do in a bug-free manner.
Secondly, the present approach can't support discontiguous memory
models. "What's that?" I hear you ask.. Well, There are lots of good
reasons why we might wish to give the kernel memory allocator control
over, say, fast BRAM in the microblaze's memory space, or some other
area of physical memory that is not contiguous with the main chunk of
DDR or SDRAM or whatever. To do this properly requires discontigmem
support.
This patch reverts the link scripts (mbvanilla.ld and suzaku.ld) to page
align the __init_end, as discussed in my previous email. Yashi (and
anyone else who's interested), can you please give this a try and let me
know if it works for you?
Thanks,
John
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/kernel/setup.c ./arch/microblaze/kernel/setup.c
--- /opt/src/uClinux-2.4.x/arch/microblaze/kernel/setup.c 2004-07-08 16:07:01.000000000 +1000
+++ ./arch/microblaze/kernel/setup.c 2004-07-30 14:45:03.000000000 +1000
@@ -26,8 +26,13 @@
#include <asm/irq.h>
#include "mach.h"
+#include "asm/setup.h"
-extern void paging_init(void);
+static struct meminfo meminfo __initdata= { 0, };
+
+extern void bootmem_init(struct meminfo *);
+extern void paging_init(struct meminfo *);
+extern unsigned long _ramstart;
#ifndef CONFIG_REGISTER_TASK_PTR
struct task_struct *current;
@@ -81,13 +86,25 @@
console_verbose ();
- init_mm.start_code = (unsigned long) &_stext;
- init_mm.end_code = (unsigned long) &_etext;
+ init_mm.start_code = (unsigned long) &_stext;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) _ramstart;
+ init_mm.brk = (unsigned long) _ramstart;
+#if 0
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_kram_end;
+#endif
+ /* Provide default meminfo configuration */
+ if(meminfo.nr_banks == 0)
+ {
+ meminfo.nr_banks = 1;
+ meminfo.bank[0].start = PAGE_OFFSET;
+ meminfo.bank[0].size = ERAM_SIZE;
+ }
/* ... and tell the kernel about it. */
- paging_init ();
+ bootmem_init(&meminfo);
+ paging_init (&meminfo);
/* do machine-specific setups. */
mach_setup (cmdline);
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/Makefile ./arch/microblaze/Makefile
--- /opt/src/uClinux-2.4.x/arch/microblaze/Makefile 2004-07-08 16:07:01.000000000 +1000
+++ ./arch/microblaze/Makefile 2004-07-30 15:08:36.000000000 +1000
@@ -64,9 +64,11 @@
#kernel linker script
-LINKFLAGS = -T linux.ld --defsym _STACK_SIZE=0x00
-$(LINUX) : linux.ld
-linux.ld: $(ARCH_DIR)/linux.ld.in
+LD_SCRIPT := linux.ld
+
+LINKFLAGS = -T $(LD_SCRIPT) --defsym _STACK_SIZE=0x00
+$(LINUX) : $(LD_SCRIPT)
+$(LD_SCRIPT): $(ARCH_DIR)/linux.ld.in
$(CPP) -P -x assembler-with-cpp $(AFLAGS) $< > $@
@@ -86,6 +88,7 @@
archdep:
archclean:
+ rm -f $(LD_SCRIPT)
rm -f $(LINUX)
rm -f $(ARCH_DIR)/kernel/microblaze_defs.h $(ARCH_DIR)/kernel/microblaze_defs.d
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/mbvanilla.ld ./arch/microblaze/mbvanilla.ld
--- /opt/src/uClinux-2.4.x/arch/microblaze/mbvanilla.ld 2004-07-10 04:24:17.000000000 +1000
+++ ./arch/microblaze/mbvanilla.ld 2004-07-30 14:45:22.000000000 +1000
@@ -131,6 +131,7 @@
*(.initcall.init)
. = ALIGN (4) ;
__initcall_end = . ;
+ . = ALIGN(4096);
__init_end = . ;
_init_end = . ;
/* Untouchable kernel ram ends here */
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/mm/init.c ./arch/microblaze/mm/init.c
--- /opt/src/uClinux-2.4.x/arch/microblaze/mm/init.c 2004-07-10 04:24:17.000000000 +1000
+++ ./arch/microblaze/mm/init.c 2004-07-30 14:45:03.000000000 +1000
@@ -1,8 +1,10 @@
/*
* arch/microblaze/mm/init.c
*
+ * Copyright (C) 2004 John Williams
* Copyright (C) 2004 Atmark Techno, Inc.
*
+ * John Williams <jwilliams@itee.uq.edu.au>
* Yasushi SHOJI <yashi@atmark-techno.com>
*
* Based on
@@ -23,7 +25,17 @@
#include <linux/mm.h>
#include <linux/bootmem.h>
+#include <asm/pgalloc.h>
#include <asm/machdep.h>
+#include <asm/setup.h>
+#include <asm/map.h>
+
+/* Locally used struct to describe the memory nodes */
+struct node_info {
+ unsigned int start;
+ unsigned int end;
+ int bootmap_pages;
+};
/* these function prototypes are taken form arch/microblaze/kernel/mach.h */
extern void mach_reserve_bootmem (void) __attribute__ ((__weak__));
@@ -35,10 +47,14 @@
/* erase following when we port to 2.6, include <asm/sections.h> instead */
extern char _text[], _stext[], _etext[];
extern char _data[], _sdata[], _edata[];
+extern char _end[];
+
extern char __bss_start[], __bss_stop[];
extern char __init_begin[], __init_end[];
extern char _sinittext[], _einittext[];
+extern unsigned long _ramstart;
+
/* Physical System RAM. */
static unsigned long ram_start = 0, ram_len = 0;
@@ -46,6 +62,28 @@
#define ADDR_TO_PAGE(x) (((unsigned long)x) >> PAGE_SHIFT)
#define PAGE_TO_ADDR(x) (((unsigned long)x) << PAGE_SHIFT)
+#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x))
+
+#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
+#define V_PFN_UP(x) O_PFN_UP(__pa(x))
+
+#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
+#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
+ (((unsigned long)(s)) & PAGE_MASK))
+
+
+#ifndef CONFIG_DISCONTIGMEM
+#define NR_NODES 1
+#else
+#define NR_NODES 4
+#endif
+
+/* Somewhere to store "local" copy of meminfo structure. */
+static struct meminfo meminfo __initdata = { 0, };
+
+struct page *empty_zero_page;
+
/* Memory not used by the kernel. */
/* for 2.4, declare totalram_pages here. for 2.6, totalram_pages is
@@ -53,139 +91,424 @@
* linux/swap.h, instead. - yashi Apr 10, 2004 */
static unsigned long totalram_pages;
-void __init mem_init (void)
+static inline void free_memmap(int node, unsigned long start, unsigned long end)
{
- max_mapnr = MAP_NR (ram_start + ram_len);
+ unsigned long pg, pgend;
+
+ start = __phys_to_virt(start);
+ end = __phys_to_virt(end);
+
+ pg = PAGE_ALIGN((unsigned long)(virt_to_page(start)));
+ pgend = ((unsigned long)(virt_to_page(end))) & PAGE_MASK;
+
+ start = __virt_to_phys(pg);
+ end = __virt_to_phys(pgend);
- num_physpages = ADDR_TO_PAGE (ram_len);
+ free_bootmem_node(NODE_DATA(node), start, end - start);
+}
+
+static inline void free_unused_memmap_node(int node, struct meminfo *mi)
+{
+ unsigned long bank_start, prev_bank_end = 0;
+ unsigned int i;
- totalram_pages = free_all_bootmem ();
+ /*
+ * [FIXME] This relies on each bank being in address order. This
+ * may not be the case, especially if the user has provided the
+ * information on the command line.
+ */
+ for (i = 0; i < mi->nr_banks; i++) {
+ if (mi->bank[i].size == 0 || mi->bank[i].node != node)
+ continue;
+
+ bank_start = mi->bank[i].start & PAGE_MASK;
+
+ /*
+ * If we had a previous bank, and there is a space
+ * between the current bank and the previous, free it.
+ */
+ if (prev_bank_end && prev_bank_end != bank_start)
+ free_memmap(node, prev_bank_end, bank_start);
- printk (KERN_INFO
- "Memory: %luK/%luK available"
- " (%luK kernel code, %luK data)\n",
- PAGE_TO_ADDR (nr_free_pages()) / 1024,
- ram_len / 1024,
- ((unsigned long)_etext - (unsigned long)_stext) / 1024,
- ((unsigned long)__bss_stop - (unsigned long)_sdata) / 1024);
+ prev_bank_end = PAGE_ALIGN(mi->bank[i].start +
+ mi->bank[i].size);
+ }
}
-void free_initmem (void)
+/*
+ * The mem_map array can get very big. Free
+ * the unused area of the memory map.
+ */
+void __init create_memmap_holes(struct meminfo *mi)
{
- unsigned long ram_end = ram_start + ram_len;
- unsigned long start = (unsigned long)(__init_begin);
+ int node;
- if (start >= ram_start && start < ram_end) {
- unsigned long addr;
- unsigned long end = (unsigned long)(__init_end);
+ for (node = 0; node < numnodes; node++)
+ free_unused_memmap_node(node, mi);
+}
- if (end > ram_end)
- end = ram_end;
+/*
+ * mem_init() marks the free areas in the mem_map and tells us how much
+ * memory is free. This is done after various parts of the system have
+ * claimed their memory after the kernel image.
+ */
+void __init mem_init(void)
+{
+ unsigned int codepages, datapages, initpages;
+ int i, node;
- printk("Freeing unused kernel memory: %ldK freed\n",
- (end - start) / 1024);
+ codepages = (unsigned long)&_etext - (unsigned long)&_stext;
+ datapages = _ramstart - ((unsigned int)&_etext);
+ initpages = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+
+ high_memory = (void *)__va(meminfo.end);
+ max_mapnr = virt_to_page(high_memory) - mem_map;
+
+ /*
+ * We may have non-contiguous memory.
+ */
+ if (meminfo.nr_banks != 1)
+ create_memmap_holes(&meminfo);
+
+ /* this will put all unused low memory onto the freelists */
+ for (node = 0; node < numnodes; node++)
+ totalram_pages += free_all_bootmem_node(NODE_DATA(node));
+
+ // SetPageReserved(virt_to_page(PAGE_OFFSET));
+ /*
+ * Since our memory may not be contiguous, calculate the
+ * real number of pages we have in this system
+ */
+ printk(KERN_INFO "Memory:");
+
+ num_physpages = 0;
+ for (i = 0; i < meminfo.nr_banks; i++) {
+ num_physpages += meminfo.bank[i].size >> PAGE_SHIFT;
+ printk(" %ldMB", meminfo.bank[i].size >> 20);
+ }
- for (addr = start; addr < end; addr += PAGE_SIZE) {
- mem_map_t *page = virt_to_page (addr);
- ClearPageReserved (page);
- set_page_count (page, 1);
- __free_page (page);
- totalram_pages++;
- }
+ printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
+ printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
+ "%dK data, %dK init)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ codepages >> 10, datapages >> 10, initpages >> 10);
+
+ if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
+ extern int sysctl_overcommit_memory;
+ /*
+ * On a machine this small we won't get
+ * anywhere without overcommit, so turn
+ * it on by default.
+ */
+ sysctl_overcommit_memory = 1;
}
}
-/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify
- what RAM may be used. */
-static void __init bootmem_init (unsigned long ram_start, unsigned long ram_len)
+/*
+ * Free memory area area bounded by the range (addr, end)
+ */
+static inline void free_area(unsigned long addr, unsigned long end, char *s)
{
- extern unsigned long _ramstart;
+ unsigned int size = (end - addr) >> 10;
+
+ for (; addr < end; addr += PAGE_SIZE) {
+ struct page *page = virt_to_page(addr);
+ ClearPageReserved(page);
+ set_page_count(page, 1);
+ free_page(addr);
+ totalram_pages++;
+ }
+
+ if (size)
+ printk("Freeing %s memory: %dK\n", s, size);
+}
+
+void free_initmem(void)
+{
+ free_area((unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end),
+ "init");
+}
+
+/*
+ * Scan the memory info structure and pull out:
+ * - the end of memory
+ * - the number of nodes
+ * - the pfn range of each node
+ * - the number of bootmem bitmap pages
+ */
+static unsigned int __init
+find_memend_and_nodes(struct meminfo *mi, struct node_info *np)
+{
+ unsigned int i, bootmem_pages = 0, memend_pfn = 0;
+
+ for (i = 0; i < NR_NODES; i++) {
+ np[i].start = -1U;
+ np[i].end = 0;
+ np[i].bootmap_pages = 0;
+ }
+
+ for (i = 0; i < mi->nr_banks; i++) {
+ unsigned long start, end;
+ int node;
+
+ if (mi->bank[i].size == 0) {
+ /*
+ * Mark this bank with an invalid node number
+ */
+ mi->bank[i].node = -1;
+ continue;
+ }
+
+ node = mi->bank[i].node;
+
+ if (node >= numnodes) {
+ numnodes = node + 1;
+
+ /*
+ * Make sure we haven't exceeded the maximum number
+ * of nodes that we have in this configuration. If
+ * we have, we're in trouble. (maybe we ought to
+ * limit, instead of bugging?)
+ */
+ if (numnodes > NR_NODES)
+ BUG();
+ }
+
+ /*
+ * Get the start and end pfns for this bank
+ */
+ start = O_PFN_UP(mi->bank[i].start);
+ end = O_PFN_DOWN(mi->bank[i].start + mi->bank[i].size);
+
+ if (np[node].start > start)
+ np[node].start = start;
+
+ if (np[node].end < end)
+ np[node].end = end;
- /* The part of the kernel that's in the same managed RAM space
- used for general allocation. */
- unsigned long kram_start = (unsigned long)&_kram_start;
- unsigned long kram_end = (unsigned long)&_kram_end;
+ if (memend_pfn < end)
+ memend_pfn = end;
+ }
+
+ /*
+ * Calculate the number of pages we require to
+ * store the bootmem bitmaps.
+ */
+ for (i = 0; i < numnodes; i++) {
+ if (np[i].end == 0)
+ continue;
+
+ np[i].bootmap_pages = bootmem_bootmap_pages(np[i].end -
+ np[i].start);
+ bootmem_pages += np[i].bootmap_pages;
+ }
- /* End of the managed RAM space. */
- unsigned long ram_end = ram_start + ram_len;
+ /*
+ * This doesn't seem to be used by the Linux memory
+ * manager any more. If we can get rid of it, we
+ * also get rid of some of the stuff above as well.
+ */
+ /* HACK! */
+ #define PHYS_OFFSET (PAGE_OFFSET)
+ max_low_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET);
+// max_pfn = memend_pfn - O_PFN_DOWN(PHYS_OFFSET);
+ mi->end = memend_pfn << PAGE_SHIFT;
- /* Address range of the interrupt vector table. */
- unsigned long intv_start = 0; //(unsigned long)&_intv_start;
- unsigned long intv_end = 0x20; //(unsigned long)&_intv_end;
+ return bootmem_pages;
+}
- /* True if the interrupt vectors are in the managed RAM area. */
- int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
+/*
+ * Reserve the various regions of node 0
+ */
+static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
+{
+ /* Handle to Node 0*/
+ pg_data_t *pgdat = NODE_DATA(0);
- /* True if the interrupt vectors are inside the kernel's RAM. */
- int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
+ unsigned long kram_start = (unsigned long )&_kram_start;
+ unsigned long kram_end = (unsigned long )&_kram_end;
/* Machine specific bootmem reserve function */
void (*volatile mrb) (void) = mach_reserve_bootmem;
- /* The bootmem allocator's allocation bitmap. */
- unsigned long bootmap = _ramstart;
- unsigned long bootmap_len;
-
- /* Round bootmap location up to next page. */
- bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
-
- /* Initialize bootmem allocator. */
- bootmap_len = init_bootmem_node (NODE_DATA (0),
- ADDR_TO_PAGE (bootmap),
- ADDR_TO_PAGE (PAGE_OFFSET),
- ADDR_TO_PAGE (ram_end));
-
- /* Now make the RAM actually allocatable (it starts out `reserved'). */
- free_bootmem (ram_start, ram_len);
-
- if (kram_end > kram_start)
- /* Reserve the RAM part of the kernel's address space, so it
- doesn't get allocated. */
- reserve_bootmem (kram_start, kram_end - kram_start);
-
- if (intv_in_ram && !intv_in_kram)
- /* Reserve the interrupt vector space. */
- reserve_bootmem (intv_start, intv_end - intv_start);
-
- if (bootmap >= ram_start && bootmap < ram_end)
- /* Reserve the bootmap space. */
- reserve_bootmem (bootmap, bootmap_len);
+ /*
+ * Register the kernel text and data with bootmem.
+ * Note that this can only be in node 0.
+ */
+ if(kram_end > kram_start)
+ reserve_bootmem_node(pgdat, __pa(kram_start),
+ (kram_end-kram_start));
/* Reserve space for the bss segment. Also save space for
* rootfs as well. because bss and romfs is contiguous, we
* reserve from start of bss to end of romfs which is
* _ramstart */
- reserve_bootmem((unsigned long)__bss_start, _ramstart - (unsigned long)__bss_start);
+ reserve_bootmem_node(pgdat, __pa(__bss_start),
+ _ramstart - (unsigned long)__bss_start);
+
+ /*
+ * And don't forget to reserve the allocator bitmap,
+ * which will be freed later.
+ */
+ reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT,
+ bootmap_pages << PAGE_SHIFT);
/* Let the platform-dependent code reserve some too. */
if (mrb)
(*mrb) ();
}
+/*
+ * FIXME: We really want to avoid allocating the bootmap bitmap
+ * over the top of the initrd. Hopefully, this is located towards
+ * the start of a bank, so if we allocate the bootmap bitmap at
+ * the end, we won't clash.
+ */
+static unsigned int __init
+find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages)
+{
+ unsigned int start_pfn, bank, bootmap_pfn;
+
+ start_pfn = V_PFN_UP(_ramstart);
+ bootmap_pfn = 0;
+
+ for (bank = 0; bank < mi->nr_banks; bank ++) {
+ unsigned int start, end;
+
+ if (mi->bank[bank].node != node)
+ continue;
+
+ start = O_PFN_UP(mi->bank[bank].start);
+ end = O_PFN_DOWN(mi->bank[bank].size +
+ mi->bank[bank].start);
+
+ if (end < start_pfn)
+ continue;
+
+ if (start < start_pfn)
+ start = start_pfn;
+
+ if (end <= start)
+ continue;
+
+ if (end - start >= bootmap_pages) {
+ bootmap_pfn = start;
+ break;
+ }
+ }
+
+ if (bootmap_pfn == 0)
+ BUG();
+
+ return bootmap_pfn;
+}
+
+/*
+ * Register all available RAM in this node with the bootmem allocator.
+ */
+static inline void free_bootmem_node_bank(int node, struct meminfo *mi)
+{
+ pg_data_t *pgdat = NODE_DATA(node);
+ int bank;
+
+ for (bank = 0; bank < mi->nr_banks; bank++)
+ if (mi->bank[bank].node == node)
+ free_bootmem_node(pgdat, mi->bank[bank].start,
+ mi->bank[bank].size);
+}
+
+
+/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify
+ what RAM may be used. */
+void __init bootmem_init (struct meminfo *mi)
+{
+ struct node_info node_info[NR_NODES], *np = node_info;
+ unsigned int bootmap_pages, bootmap_pfn, map_pg;
+ int node, initrd_node;
+
+ bootmap_pages = find_memend_and_nodes(mi,np);
+ bootmap_pfn = find_bootmap_pfn(0, mi, bootmap_pages);
+ initrd_node = 0; /*check_initrd(mi); */
+
+ map_pg = bootmap_pfn;
+
+ np += numnodes - 1;
+ for (node = numnodes - 1; node >= 0; node--, np--)
+ {
+ if(np->end == 0)
+ {
+ if(node == 0)
+ BUG();
+ continue;
+ }
+
+ init_bootmem_node(NODE_DATA(node), map_pg, np->start, np->end);
+ free_bootmem_node_bank(node, mi);
+ map_pg += np->bootmap_pages;
+
+ if(node == 0)
+ reserve_node_zero(bootmap_pfn, bootmap_pages);
+ }
+
+ if(map_pg != bootmap_pfn + bootmap_pages)
+ BUG();
+
+}
+
/* Setup memory zone. We don't have no page table to warry about.
* Initialize memory zone and call free_area_init_node().
*
* Note: One we get discon mem support, we need to chage the function
*/
-void __init paging_init (void)
+void __init paging_init (struct meminfo *mi)
{
unsigned i;
unsigned long zones_size[MAX_NR_ZONES];
+ void *zero_page;
+ int node;
+
+ /* Copy the meminfo struct locally */
+ memcpy(&meminfo, mi, sizeof(meminfo));
+
+ zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+
+ for (node = 0; node < numnodes; node++)
+ {
+ unsigned long zone_size[MAX_NR_ZONES];
+ unsigned long zhole_size[MAX_NR_ZONES];
+ struct bootmem_data *bdata;
+ pg_data_t *pgdat;
+ int i;
+
+ for(i=0; i < MAX_NR_ZONES; i++)
+ {
+ zone_size[i] = 0;
+ zhole_size[i] = 0;
+ }
- /* Find out what mem this machine has. */
- mach_get_physical_ram (&ram_start, &ram_len);
+ pgdat = NODE_DATA(node);
+ bdata = pgdat->bdata;
- bootmem_init (ram_start, ram_len);
+ zone_size[0] = bdata->node_low_pfn -
+ (bdata->node_boot_start >> PAGE_SHIFT);
+
+ zhole_size[0] = zone_size[0];
+ for (i=0; i < mi->nr_banks; i++)
+ {
+ if (mi->bank[i].node != node)
+ continue;
- for (i = 0; i < MAX_NR_ZONES; i++)
- zones_size[i] = 0;
+ zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
+ }
- /* We stuff all the memory into one area, which includes the
- initial gap from PAGE_OFFSET to ram_start. */
- zones_size[ZONE_DMA]
- = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
+ free_area_init_node(node, pgdat, 0, zone_size,
+ bdata->node_boot_start, zhole_size);
+ }
- free_area_init_node (0, 0, 0, zones_size, PAGE_OFFSET, 0);
+ memset(zero_page, 0, PAGE_SIZE);
+ empty_zero_page = virt_to_page(zero_page);
+ flush_dcache_page(empty_zero_page);
}
/* For 2.6, remove this function. mm/page_alloc.c has generic one. */
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/mm/Makefile ./arch/microblaze/mm/Makefile
--- /opt/src/uClinux-2.4.x/arch/microblaze/mm/Makefile 2004-07-08 16:07:01.000000000 +1000
+++ ./arch/microblaze/mm/Makefile 2004-07-30 15:04:57.000000000 +1000
@@ -11,9 +11,10 @@
O_TARGET := mm.o
-obj-y := init.o
+obj-y := init.o
obj-m :=
obj-n :=
obj- :=
+export-objs :=
include $(TOPDIR)/Rules.make
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/arch/microblaze/suzaku.ld ./arch/microblaze/suzaku.ld
--- /opt/src/uClinux-2.4.x/arch/microblaze/suzaku.ld 2004-07-10 04:24:17.000000000 +1000
+++ ./arch/microblaze/suzaku.ld 2004-07-30 15:04:35.000000000 +1000
@@ -129,6 +129,7 @@
*(.initcall.init)
. = ALIGN (4) ;
__initcall_end = . ;
+ . = ALIGN(4096) ;
__init_end = . ;
_init_end = . ;
/* Untouchable kernel ram ends here */
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/include/asm-microblaze/map.h ./include/asm-microblaze/map.h
--- /opt/src/uClinux-2.4.x/include/asm-microblaze/map.h 1970-01-01 10:00:00.000000000 +1000
+++ ./include/asm-microblaze/map.h 2004-07-30 14:48:46.000000000 +1000
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-microblaze/map.h
+ *
+ * Copyright (C) 1999-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Page table mapping constructs and function prototypes
+ */
+struct map_desc {
+ unsigned long virtual;
+ unsigned long physical;
+ unsigned long length;
+ int domain:4,
+ prot_read:1,
+ prot_write:1,
+ cacheable:1,
+ bufferable:1,
+ last:1;
+};
+
+#define LAST_DESC \
+ { last: 1 }
+
+struct meminfo;
+
+extern void create_memmap_holes(struct meminfo *);
+extern void memtable_init(struct meminfo *);
+extern void iotable_init(struct map_desc *);
+extern void setup_io_desc(void);
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/include/asm-microblaze/pgtable.h ./include/asm-microblaze/pgtable.h
--- /opt/src/uClinux-2.4.x/include/asm-microblaze/pgtable.h 2004-07-08 16:08:28.000000000 +1000
+++ ./include/asm-microblaze/pgtable.h 2004-07-30 14:45:03.000000000 +1000
@@ -13,7 +13,7 @@
#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
-extern void paging_init(void);
+extern void paging_init(struct meminfo *);
#define pgtable_cache_init() ((void)0)
diff -Naur -x '*CVS*' /opt/src/uClinux-2.4.x/include/asm-microblaze/setup.h ./include/asm-microblaze/setup.h
--- /opt/src/uClinux-2.4.x/include/asm-microblaze/setup.h 2004-07-08 16:08:28.000000000 +1000
+++ ./include/asm-microblaze/setup.h 2004-07-30 14:45:03.000000000 +1000
@@ -16,4 +16,22 @@
#ifndef __MICROBLAZE_SETUP_H__
#define __MICROBLAZE_SETUP_H__
+/*
+ * Memory map description
+ */
+#define NR_BANKS 8
+
+struct meminfo {
+ int nr_banks;
+ unsigned long end;
+ struct {
+ unsigned long start;
+ unsigned long size;
+ int node;
+ } bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
+
+
#endif /* __MICROBLAZE_SETUP_H__ */