The system I am concerned with, likewise many MIPS based systems have 256MB RAM + 256MB I/O in lowmem area. Additional RAM is placed at top of this area, starting or could even be beyond 2000_0000. My {quick, dirty, naïve} hack to support HIGHMEM in this case, would be to - .1 during bootmem_init, (we need EFI), move highstart_pfn as RAM gets added beyond lowmem area. .2 add I/O space into ZONE_NORMAL (marked reserved later on) .3 add Non-RAM pages into ZONE_NORMAL (see below #4) .4 reset ZONE_NORMAL num. pages to zero, at the end of free_area_init At the end zone table looks like - ZONE_DMA = 256MB ZONE_NORMAL = 0 ZONE_HIGHMEM= 256MB (additional RAM for example) Of course with this approach there will be an overhead of reserved pages. But then again it also has an use. Consider this, MIPS/UML can make use of these reserved pages of I/O space (of course marking them un-cached) through kmap for temporary access or through /dev/kmem for process-term access. For example, the mmap call on /dev/kmem with offset hint of physical address 1000_0000 where all I/O begins, sets vma->vm_pgoff which in turn extracts an already reserved page for this frame. The user application (driver?) has access to I/O space. Is it possible? On 7/5/06 10:13 PM, "Atsushi Nemoto" <anemo@xxxxxxxxxxxxx> wrote: > With SPARSEMEM, the single node can contains some holes so there might > be many invalid pages. For example, with two 256M memory and one 256M > hole, some variables (num_physpage, totalpages, nr_kernel_pages, > nr_all_pages, etc.) will indicate that there are 768MB on this system. > This is not desired because, for example, alloc_large_system_hash() > allocates too many entries. > > Use free_area_init_node() with counted zholes_size[] instead of > free_area_init(). > > For num_physpages, use number of ram pages instead of max_low_pfn. > > Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx> > > diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c > index 802bdd3..d41dee5 100644 > --- a/arch/mips/mm/init.c > +++ b/arch/mips/mm/init.c > @@ -139,10 +139,36 @@ #endif /* CONFIG_HIGHMEM */ > #ifndef CONFIG_NEED_MULTIPLE_NODES > extern void pagetable_init(void); > > +static int __init page_is_ram(unsigned long pagenr) > +{ > + int i; > + > + for (i = 0; i < boot_mem_map.nr_map; i++) { > + unsigned long addr, end; > + > + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) > + /* not usable memory */ > + continue; > + > + addr = PFN_UP(boot_mem_map.map[i].addr); > + end = PFN_DOWN(boot_mem_map.map[i].addr + > + boot_mem_map.map[i].size); > + > + if (pagenr >= addr && pagenr < end) > + return 1; > + } > + > + return 0; > +} > + > void __init paging_init(void) > { > - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; > + unsigned long zones_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 }; > unsigned long max_dma, high, low; > +#ifdef CONFIG_SPARSEMEM > + unsigned long zholes_size[] = { [0 ... MAX_NR_ZONES - 1] = 0 }; > + unsigned long i, j, pfn; > +#endif > > pagetable_init(); > > @@ -174,29 +200,17 @@ #ifdef CONFIG_HIGHMEM > zones_size[ZONE_HIGHMEM] = high - low; > #endif > > +#ifdef CONFIG_SPARSEMEM > + pfn = 0; > + for (i = 0; i < MAX_NR_ZONES; i++) > + for (j = 0; j < zones_size[i]; j++, pfn++) > + if (!page_is_ram(pfn)) > + zholes_size[i]++; > + free_area_init_node(0, NODE_DATA(0), zones_size, > + __pa(PAGE_OFFSET), zholes_size); > +#else > free_area_init(zones_size); > -} > - > -static inline int page_is_ram(unsigned long pagenr) > -{ > - int i; > - > - for (i = 0; i < boot_mem_map.nr_map; i++) { > - unsigned long addr, end; > - > - if (boot_mem_map.map[i].type != BOOT_MEM_RAM) > - /* not usable memory */ > - continue; > - > - addr = PFN_UP(boot_mem_map.map[i].addr); > - end = PFN_DOWN(boot_mem_map.map[i].addr + > - boot_mem_map.map[i].size); > - > - if (pagenr >= addr && pagenr < end) > - return 1; > - } > - > - return 0; > +#endif > } > > static struct kcore_list kcore_mem, kcore_vmalloc; > @@ -213,9 +227,9 @@ #ifdef CONFIG_HIGHMEM > #ifdef CONFIG_DISCONTIGMEM > #error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" > #endif > - max_mapnr = num_physpages = highend_pfn; > + max_mapnr = highend_pfn; > #else > - max_mapnr = num_physpages = max_low_pfn; > + max_mapnr = max_low_pfn; > #endif > high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); > > @@ -229,6 +243,7 @@ #endif > if (PageReserved(pfn_to_page(tmp))) > reservedpages++; > } > + num_physpages = ram; > > #ifdef CONFIG_HIGHMEM > for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { > @@ -247,6 +262,7 @@ #endif > totalhigh_pages++; > } > totalram_pages += totalhigh_pages; > + num_physpages += totalhigh_pages; > #endif > > codesize = (unsigned long) &_etext - (unsigned long) &_text; > -- First of all - I am an Engineer. I care less for Copyrights/Patents, at least I have none of my own! I love software development & it pays me to run my family. I try to dedicate some time thinking about Open Source movement & sometime contributing to it actually. I often get paid by claiming knowledge in software developed by Open Source community. Lots of things I know today & still learning are due to Open Source community.