-/*
+/*
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "mem_user.h"
#include "uml_uaccess.h"
#include "os.h"
-
-extern char __binary_start;
+#include "linux/types.h"
+#include "linux/string.h"
+#include "init.h"
+#include "kern_constants.h"
/* Changed during early boot */
unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL;
-pgd_t swapper_pg_dir[1024];
-unsigned long highmem;
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
+unsigned long long highmem;
int kmalloc_ok = 0;
static unsigned long brk_end;
}
#ifdef CONFIG_HIGHMEM
-static void setup_highmem(unsigned long highmem_start,
+static void setup_highmem(unsigned long highmem_start,
unsigned long highmem_len)
{
struct page *page;
unsigned long highmem_pfn;
int i;
- highmem_start_page = virt_to_page(highmem_start);
-
highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
page = &mem_map[highmem_pfn + i];
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
- set_page_count(page, 1);
+ init_page_count(page);
__free_page(page);
}
}
void mem_init(void)
{
- unsigned long start;
-
max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT;
-#ifdef CONFIG_HIGHMEM
- highmem_start_page = phys_page(__pa(high_physmem));
-#endif
/* clear the zero-page */
memset((void *) empty_zero_page, 0, PAGE_SIZE);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
- /* Fill in any hole at the start of the binary */
- start = (unsigned long) &__binary_start;
- if(uml_physmem != start){
- map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem,
- 1, 1, 0);
- }
-
/* this will put all low memory onto the freelists */
totalram_pages = free_all_bootmem();
+#ifdef CONFIG_HIGHMEM
totalhigh_pages = highmem >> PAGE_SHIFT;
totalram_pages += totalhigh_pages;
+#endif
num_physpages = totalram_pages;
max_pfn = totalram_pages;
printk(KERN_INFO "Memory: %luk available\n",
#endif
}
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+ if (pmd_none(*pmd)) {
+ pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ (unsigned long) __pa(pte)));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+ if (pmd_table != pmd_offset(pud, 0))
+ BUG();
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
int i, j;
unsigned long vaddr;
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
- pmd = (pmd_t *)pgd;
+ pud = pud_offset(pgd, vaddr);
+ if (pud_none(*pud))
+ one_md_table_init(pud);
+ pmd = pmd_offset(pud, vaddr);
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- if (pmd_none(*pmd)) {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE +
- (unsigned long) __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
+ one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
j = 0;
}
}
-#if CONFIG_HIGHMEM
+#ifdef CONFIG_HIGHMEM
pte_t *kmap_pte;
pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \
- pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
+ (vaddr)), (vaddr))
-void __init kmap_init(void)
+static void __init kmap_init(void)
{
unsigned long kmap_vstart;
static void init_highmem(void)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long vaddr;
fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir);
pgd = swapper_pg_dir + pgd_index(vaddr);
- pmd = pmd_offset(pgd, vaddr);
+ pud = pud_offset(pgd, vaddr);
+ pmd = pmd_offset(pud, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte;
}
#endif /* CONFIG_HIGHMEM */
+static void __init fixaddr_user_init( void)
+{
+#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
+ long size = FIXADDR_USER_END - FIXADDR_USER_START;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long paddr, vaddr = FIXADDR_USER_START;
+
+ if ( ! size )
+ return;
+
+ fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
+ paddr = (unsigned long)alloc_bootmem_low_pages( size);
+ memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
+ paddr = __pa(paddr);
+ for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
+ pgd = swapper_pg_dir + pgd_index(vaddr);
+ pud = pud_offset(pgd, vaddr);
+ pmd = pmd_offset(pud, vaddr);
+ pte = pte_offset_kernel(pmd, vaddr);
+ pte_set_val( (*pte), paddr, PAGE_READONLY);
+ }
+#endif
+}
+
void paging_init(void)
{
unsigned long zones_size[MAX_NR_ZONES], vaddr;
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
- for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
+ for(i = 0; i < ARRAY_SIZE(zones_size); i++)
zones_size[i] = 0;
- zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
- zones_size[2] = highmem >> PAGE_SHIFT;
+
+ zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+ (uml_physmem >> PAGE_SHIFT);
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
+#endif
free_area_init(zones_size);
/*
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
+ fixaddr_user_init();
+
#ifdef CONFIG_HIGHMEM
init_highmem();
#endif
}
-struct page *arch_validate(struct page *page, int mask, int order)
+struct page *arch_validate(struct page *page, gfp_t mask, int order)
{
unsigned long addr, zero = 0;
int i;
addr = (unsigned long) page_address(page);
for(i = 0; i < (1 << order); i++){
current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void *) addr, &zero,
+ if(__do_copy_to_user((void __user *) addr, &zero,
sizeof(zero),
¤t->thread.fault_addr,
¤t->thread.fault_catcher)){
}
addr += PAGE_SIZE;
}
+
if(i == (1 << order)) return(page);
page = alloc_pages(mask, order);
goto again;
(end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
- set_page_count(virt_to_page(start), 1);
+ init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}
{
pte_t *pte;
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
- if (pte)
- clear_page(pte);
+ pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
{
struct page *pte;
- pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
- if (pte)
- clear_highpage(pte);
+ pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
+extern int parse_iomem(char *str, int *add) __init;
+
+__uml_setup("iomem=", parse_iomem,
+"iomem=<name>,<file>\n"
+" Configure <file> as an IO memory region named <name>.\n\n"
+);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically