Commit 28e93a00 authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'x86/mm' into x86/core

parents caab36b5 ed26dbe5
#ifndef _ASM_X86_INIT_32_H
#define _ASM_X86_INIT_32_H
#ifdef CONFIG_X86_32
extern void __init early_ioremap_page_table_range_init(void);
#endif
extern unsigned long __init
kernel_physical_mapping_init(unsigned long start,
unsigned long end,
unsigned long page_size_mask);
extern unsigned long __initdata e820_table_start;
extern unsigned long __meminitdata e820_table_end;
extern unsigned long __meminitdata e820_table_top;
#endif /* _ASM_X86_INIT_32_H */
...@@ -40,14 +40,8 @@ ...@@ -40,14 +40,8 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct pgprot;
extern int page_is_ram(unsigned long pagenr); extern int page_is_ram(unsigned long pagenr);
extern int devmem_is_allowed(unsigned long pagenr); extern int devmem_is_allowed(unsigned long pagenr);
extern void map_devmem(unsigned long pfn, unsigned long size,
struct pgprot vma_prot);
extern void unmap_devmem(unsigned long pfn, unsigned long size,
struct pgprot vma_prot);
extern unsigned long max_low_pfn_mapped; extern unsigned long max_low_pfn_mapped;
extern unsigned long max_pfn_mapped; extern unsigned long max_pfn_mapped;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _ASM_X86_PAT_H #define _ASM_X86_PAT_H
#include <linux/types.h> #include <linux/types.h>
#include <asm/pgtable_types.h>
#ifdef CONFIG_X86_PAT #ifdef CONFIG_X86_PAT
extern int pat_enabled; extern int pat_enabled;
...@@ -17,5 +18,9 @@ extern int free_memtype(u64 start, u64 end); ...@@ -17,5 +18,9 @@ extern int free_memtype(u64 start, u64 end);
extern int kernel_map_sync_memtype(u64 base, unsigned long size, extern int kernel_map_sync_memtype(u64 base, unsigned long size,
unsigned long flag); unsigned long flag);
extern void map_devmem(unsigned long pfn, unsigned long size,
struct pgprot vma_prot);
extern void unmap_devmem(unsigned long pfn, unsigned long size,
struct pgprot vma_prot);
#endif /* _ASM_X86_PAT_H */ #endif /* _ASM_X86_PAT_H */
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
* area for the same reason. ;) * area for the same reason. ;)
*/ */
#define VMALLOC_OFFSET (8 * 1024 * 1024) #define VMALLOC_OFFSET (8 * 1024 * 1024)
#ifndef __ASSEMBLER__
extern bool __vmalloc_start_set; /* set once high_memory is set */
#endif
#define VMALLOC_START ((unsigned long)high_memory + VMALLOC_OFFSET) #define VMALLOC_START ((unsigned long)high_memory + VMALLOC_OFFSET)
#ifdef CONFIG_X86_PAE #ifdef CONFIG_X86_PAE
#define LAST_PKMAP 512 #define LAST_PKMAP 512
......
...@@ -273,6 +273,7 @@ typedef struct page *pgtable_t; ...@@ -273,6 +273,7 @@ typedef struct page *pgtable_t;
extern pteval_t __supported_pte_mask; extern pteval_t __supported_pte_mask;
extern int nx_enabled; extern int nx_enabled;
extern void set_nx(void);
#define pgprot_writecombine pgprot_writecombine #define pgprot_writecombine pgprot_writecombine
extern pgprot_t pgprot_writecombine(pgprot_t prot); extern pgprot_t pgprot_writecombine(pgprot_t prot);
......
...@@ -558,6 +558,19 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) ...@@ -558,6 +558,19 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
static struct mpf_intel *mpf_found; static struct mpf_intel *mpf_found;
static unsigned long __init get_mpc_size(unsigned long physptr)
{
struct mpc_table *mpc;
unsigned long size;
mpc = early_ioremap(physptr, PAGE_SIZE);
size = mpc->length;
early_iounmap(mpc, PAGE_SIZE);
apic_printk(APIC_VERBOSE, " mpc: %lx-%lx\n", physptr, physptr + size);
return size;
}
/* /*
* Scan the memory blocks for an SMP configuration block. * Scan the memory blocks for an SMP configuration block.
*/ */
...@@ -611,12 +624,16 @@ static void __init __get_smp_config(unsigned int early) ...@@ -611,12 +624,16 @@ static void __init __get_smp_config(unsigned int early)
construct_default_ISA_mptable(mpf->feature1); construct_default_ISA_mptable(mpf->feature1);
} else if (mpf->physptr) { } else if (mpf->physptr) {
struct mpc_table *mpc;
unsigned long size;
size = get_mpc_size(mpf->physptr);
mpc = early_ioremap(mpf->physptr, size);
/* /*
* Read the physical hardware table. Anything here will * Read the physical hardware table. Anything here will
* override the defaults. * override the defaults.
*/ */
if (!smp_read_mpc(phys_to_virt(mpf->physptr), early)) { if (!smp_read_mpc(mpc, early)) {
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
smp_found_config = 0; smp_found_config = 0;
#endif #endif
...@@ -624,8 +641,10 @@ static void __init __get_smp_config(unsigned int early) ...@@ -624,8 +641,10 @@ static void __init __get_smp_config(unsigned int early)
"BIOS bug, MP table errors detected!...\n"); "BIOS bug, MP table errors detected!...\n");
printk(KERN_ERR "... disabling SMP support. " printk(KERN_ERR "... disabling SMP support. "
"(tell your hw vendor)\n"); "(tell your hw vendor)\n");
early_iounmap(mpc, size);
return; return;
} }
early_iounmap(mpc, size);
if (early) if (early)
return; return;
...@@ -697,10 +716,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length, ...@@ -697,10 +716,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length,
if (!reserve) if (!reserve)
return 1; return 1;
reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE, reserve_bootmem_generic(virt_to_phys(mpf), sizeof(*mpf),
BOOTMEM_DEFAULT); BOOTMEM_DEFAULT);
if (mpf->physptr) { if (mpf->physptr) {
unsigned long size = PAGE_SIZE; unsigned long size = get_mpc_size(mpf->physptr);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
/* /*
* We cannot access to MPC table to compute * We cannot access to MPC table to compute
......
...@@ -202,7 +202,9 @@ struct ist_info ist_info; ...@@ -202,7 +202,9 @@ struct ist_info ist_info;
#endif #endif
#else #else
struct cpuinfo_x86 boot_cpu_data __read_mostly; struct cpuinfo_x86 boot_cpu_data __read_mostly = {
.x86_phys_bits = MAX_PHYSMEM_BITS,
};
EXPORT_SYMBOL(boot_cpu_data); EXPORT_SYMBOL(boot_cpu_data);
#endif #endif
......
...@@ -158,7 +158,6 @@ EXPORT_SYMBOL(kunmap); ...@@ -158,7 +158,6 @@ EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic); EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic); EXPORT_SYMBOL(kunmap_atomic);
#ifdef CONFIG_NUMA
void __init set_highmem_pages_init(void) void __init set_highmem_pages_init(void)
{ {
struct zone *zone; struct zone *zone;
...@@ -182,11 +181,3 @@ void __init set_highmem_pages_init(void) ...@@ -182,11 +181,3 @@ void __init set_highmem_pages_init(void)
} }
totalram_pages += totalhigh_pages; totalram_pages += totalhigh_pages;
} }
#else
void __init set_highmem_pages_init(void)
{
add_highpages_with_active_regions(0, highstart_pfn, highend_pfn);
totalram_pages += totalhigh_pages;
}
#endif /* CONFIG_NUMA */
#include <linux/ioport.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/e820.h>
#include <asm/init.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/page_types.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/tlbflush.h>
unsigned long __initdata e820_table_start;
unsigned long __meminitdata e820_table_end;
unsigned long __meminitdata e820_table_top;
int after_bootmem;
int direct_gbpages
#ifdef CONFIG_DIRECT_GBPAGES
= 1
#endif
;
static void __init find_early_table_space(unsigned long end, int use_pse,
int use_gbpages)
{
unsigned long puds, pmds, ptes, tables, start;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
if (use_gbpages) {
unsigned long extra;
extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
} else
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
if (use_pse) {
unsigned long extra;
extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
#ifdef CONFIG_X86_32
extra += PMD_SIZE;
#endif
ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
} else
ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
#ifdef CONFIG_X86_32
/* for fixmap */
tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
#endif
/*
* RED-PEN putting page tables only on node 0 could
* cause a hotspot and fill up ZONE_DMA. The page tables
* need roughly 0.5KB per GB.
*/
#ifdef CONFIG_X86_32
start = 0x7000;
e820_table_start = find_e820_area(start, max_pfn_mapped<<PAGE_SHIFT,
tables, PAGE_SIZE);
#else /* CONFIG_X86_64 */
start = 0x8000;
e820_table_start = find_e820_area(start, end, tables, PAGE_SIZE);
#endif
if (e820_table_start == -1UL)
panic("Cannot find space for the kernel page tables");
e820_table_start >>= PAGE_SHIFT;
e820_table_end = e820_table_start;
e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
}
struct map_range {
unsigned long start;
unsigned long end;
unsigned page_size_mask;
};
#ifdef CONFIG_X86_32
#define NR_RANGE_MR 3
#else /* CONFIG_X86_64 */
#define NR_RANGE_MR 5
#endif
static int save_mr(struct map_range *mr, int nr_range,
unsigned long start_pfn, unsigned long end_pfn,
unsigned long page_size_mask)
{
if (start_pfn < end_pfn) {
if (nr_range >= NR_RANGE_MR)
panic("run out of range for init_memory_mapping\n");
mr[nr_range].start = start_pfn<<PAGE_SHIFT;
mr[nr_range].end = end_pfn<<PAGE_SHIFT;
mr[nr_range].page_size_mask = page_size_mask;
nr_range++;
}
return nr_range;
}
#ifdef CONFIG_X86_64
static void __init init_gbpages(void)
{
if (direct_gbpages && cpu_has_gbpages)
printk(KERN_INFO "Using GB pages for direct mapping\n");
else
direct_gbpages = 0;
}
#else
static inline void init_gbpages(void)
{
}
#endif
/*
* Setup the direct mapping of the physical memory at PAGE_OFFSET.
* This runs before bootmem is initialized and gets pages directly from
* the physical memory. To access them they are temporarily mapped.
*/
unsigned long __init_refok init_memory_mapping(unsigned long start,
unsigned long end)
{
unsigned long page_size_mask = 0;
unsigned long start_pfn, end_pfn;
unsigned long pos;
unsigned long ret;
struct map_range mr[NR_RANGE_MR];
int nr_range, i;
int use_pse, use_gbpages;
printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
if (!after_bootmem)
init_gbpages();
#ifdef CONFIG_DEBUG_PAGEALLOC
/*
* For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
* This will simplify cpa(), which otherwise needs to support splitting
* large pages into small in interrupt context, etc.
*/
use_pse = use_gbpages = 0;
#else
use_pse = cpu_has_pse;
use_gbpages = direct_gbpages;
#endif
#ifdef CONFIG_X86_32
#ifdef CONFIG_X86_PAE
set_nx();
if (nx_enabled)
printk(KERN_INFO "NX (Execute Disable) protection: active\n");
#endif
/* Enable PSE if available */
if (cpu_has_pse)
set_in_cr4(X86_CR4_PSE);
/* Enable PGE if available */
if (cpu_has_pge) {
set_in_cr4(X86_CR4_PGE);
__supported_pte_mask |= _PAGE_GLOBAL;
}
#endif
if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
if (use_pse)
page_size_mask |= 1 << PG_LEVEL_2M;
memset(mr, 0, sizeof(mr));
nr_range = 0;
/* head if not big page alignment ? */
start_pfn = start >> PAGE_SHIFT;
pos = start_pfn << PAGE_SHIFT;
#ifdef CONFIG_X86_32
/*
* Don't use a large page for the first 2/4MB of memory
* because there are often fixed size MTRRs in there
* and overlapping MTRRs into large pages can cause
* slowdowns.
*/
if (pos == 0)
end_pfn = 1<<(PMD_SHIFT - PAGE_SHIFT);
else
end_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
#else /* CONFIG_X86_64 */
end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
#endif
if (end_pfn > (end >> PAGE_SHIFT))
end_pfn = end >> PAGE_SHIFT;
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
pos = end_pfn << PAGE_SHIFT;
}
/* big page (2M) range */
start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
#ifdef CONFIG_X86_32
end_pfn = (end>>PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
#else /* CONFIG_X86_64 */
end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
<< (PUD_SHIFT - PAGE_SHIFT);
if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
#endif
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask & (1<<PG_LEVEL_2M));
pos = end_pfn << PAGE_SHIFT;
}
#ifdef CONFIG_X86_64
/* big page (1G) range */
start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
<< (PUD_SHIFT - PAGE_SHIFT);
end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask &
((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
pos = end_pfn << PAGE_SHIFT;
}
/* tail is not big page (1G) alignment */
start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask & (1<<PG_LEVEL_2M));
pos = end_pfn << PAGE_SHIFT;
}
#endif
/* tail is not big page (2M) alignment */
start_pfn = pos>>PAGE_SHIFT;
end_pfn = end>>PAGE_SHIFT;
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
/* try to merge same page size and continuous */
for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
unsigned long old_start;
if (mr[i].end != mr[i+1].start ||
mr[i].page_size_mask != mr[i+1].page_size_mask)
continue;
/* move it */
old_start = mr[i].start;
memmove(&mr[i], &mr[i+1],
(nr_range - 1 - i) * sizeof(struct map_range));
mr[i--].start = old_start;
nr_range--;
}
for (i = 0; i < nr_range; i++)
printk(KERN_DEBUG " %010lx - %010lx page %s\n",
mr[i].start, mr[i].end,
(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
/*
* Find space for the kernel direct mapping tables.
*
* Later we should allocate these tables in the local node of the
* memory mapped. Unfortunately this is done currently before the
* nodes are discovered.
*/
if (!after_bootmem)
find_early_table_space(end, use_pse, use_gbpages);
#ifdef CONFIG_X86_32
for (i = 0; i < nr_range; i++)
kernel_physical_mapping_init(mr[i].start, mr[i].end,
mr[i].page_size_mask);
ret = end;
#else /* CONFIG_X86_64 */
for (i = 0; i < nr_range; i++)
ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
mr[i].page_size_mask);
#endif
#ifdef CONFIG_X86_32
early_ioremap_page_table_range_init();
load_cr3(swapper_pg_dir);
#endif
#ifdef CONFIG_X86_64
if (!after_bootmem)
mmu_cr4_features = read_cr4();
#endif
__flush_tlb_all();
if (!after_bootmem && e820_table_end > e820_table_start)
reserve_early(e820_table_start << PAGE_SHIFT,
e820_table_end << PAGE_SHIFT, "PGTABLE");
if (!after_bootmem)
early_memtest(start, end);
return ret >> PAGE_SHIFT;
}
/*
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
* is valid. The argument is a physical page number.
*
*
* On x86, access has to be given to the first megabyte of ram because that area
* contains bios code and data regions used by X and dosemu and similar apps.
* Access has to be given to non-kernel-ram areas as well, these contain the PCI
* mmio resources as well as potential bios/acpi data regions.
*/
int devmem_is_allowed(unsigned long pagenr)
{
if (pagenr <= 256)
return 1;
if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
return 0;
if (!page_is_ram(pagenr))
return 1;
return 0;
}
void free_init_pages(char *what, unsigned long begin, unsigned long end) void free_init_pages(char *what, unsigned long begin, unsigned long end)
{ {
...@@ -47,3 +384,10 @@ void free_initmem(void) ...@@ -47,3 +384,10 @@ void free_initmem(void)
(unsigned long)(&__init_begin), (unsigned long)(&__init_begin),
(unsigned long)(&__init_end)); (unsigned long)(&__init_end));
} }
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
free_init_pages("initrd memory", start, end);
}
#endif
This diff is collapsed.
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/numa.h> #include <asm/numa.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/init.h>
/* /*
* end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries. * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
...@@ -61,12 +62,6 @@ static unsigned long dma_reserve __initdata; ...@@ -61,12 +62,6 @@ static unsigned long dma_reserve __initdata;
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
int direct_gbpages
#ifdef CONFIG_DIRECT_GBPAGES
= 1
#endif
;
static int __init parse_direct_gbpages_off(char *arg) static int __init parse_direct_gbpages_off(char *arg)
{ {
direct_gbpages = 0; direct_gbpages = 0;
...@@ -87,8 +82,6 @@ early_param("gbpages", parse_direct_gbpages_on); ...@@ -87,8 +82,6 @@ early_param("gbpages", parse_direct_gbpages_on);
* around without checking the pgd every time. * around without checking the pgd every time.
*/ */
int after_bootmem;
pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP; pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP;
EXPORT_SYMBOL_GPL(__supported_pte_mask); EXPORT_SYMBOL_GPL(__supported_pte_mask);
...@@ -325,13 +318,9 @@ void __init cleanup_highmap(void) ...@@ -325,13 +318,9 @@ void __init cleanup_highmap(void)
} }
} }
static unsigned long __initdata table_start;
static unsigned long __meminitdata table_end;
static unsigned long __meminitdata table_top;
static __ref void *alloc_low_page(unsigned long *phys) static __ref void *alloc_low_page(unsigned long *phys)
{ {
unsigned long pfn = table_end++; unsigned long pfn = e820_table_end++;
void *adr; void *adr;
if (after_bootmem) { if (after_bootmem) {
...@@ -341,7 +330,7 @@ static __ref void *alloc_low_page(unsigned long *phys) ...@@ -341,7 +330,7 @@ static __ref void *alloc_low_page(unsigned long *phys)
return adr; return adr;
} }
if (pfn >= table_top) if (pfn >= e820_table_top)
panic("alloc_low_page: ran out of memory"); panic("alloc_low_page: ran out of memory");
adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE); adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
...@@ -581,56 +570,8 @@ phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end, ...@@ -581,56 +570,8 @@ phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
return phys_pud_init(pud, addr, end, page_size_mask); return phys_pud_init(pud, addr, end, page_size_mask);
} }
static void __init find_early_table_space(unsigned long end, int use_pse, unsigned long __init
int use_gbpages) kernel_physical_mapping_init(unsigned long start,
{
unsigned long puds, pmds, ptes, tables, start;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
if (use_gbpages) {
unsigned long extra;
extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
} else
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
if (use_pse) {
unsigned long extra;
extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
} else
ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
/*
* RED-PEN putting page tables only on node 0 could
* cause a hotspot and fill up ZONE_DMA. The page tables
* need roughly 0.5KB per GB.
*/
start = 0x8000;
table_start = find_e820_area(start, end, tables, PAGE_SIZE);
if (table_start == -1UL)
panic("Cannot find space for the kernel page tables");
table_start >>= PAGE_SHIFT;
table_end = table_start;
table_top = table_start + (tables >> PAGE_SHIFT);
printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
end, table_start << PAGE_SHIFT, table_top << PAGE_SHIFT);
}
static void __init init_gbpages(void)
{
if (direct_gbpages && cpu_has_gbpages)
printk(KERN_INFO "Using GB pages for direct mapping\n");
else
direct_gbpages = 0;
}
static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
unsigned long end, unsigned long end,
unsigned long page_size_mask) unsigned long page_size_mask)
{ {
...@@ -669,176 +610,6 @@ static unsigned long __meminit kernel_physical_mapping_init(unsigned long start, ...@@ -669,176 +610,6 @@ static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
return last_map_addr; return last_map_addr;
} }
struct map_range {
unsigned long start;
unsigned long end;
unsigned page_size_mask;
};
#define NR_RANGE_MR 5
static int save_mr(struct map_range *mr, int nr_range,
unsigned long start_pfn, unsigned long end_pfn,
unsigned long page_size_mask)
{
if (start_pfn < end_pfn) {
if (nr_range >= NR_RANGE_MR)
panic("run out of range for init_memory_mapping\n");
mr[nr_range].start = start_pfn<<PAGE_SHIFT;
mr[nr_range].end = end_pfn<<PAGE_SHIFT;
mr[nr_range].page_size_mask = page_size_mask;
nr_range++;
}
return nr_range;
}
/*
* Setup the direct mapping of the physical memory at PAGE_OFFSET.
* This runs before bootmem is initialized and gets pages directly from
* the physical memory. To access them they are temporarily mapped.
*/
unsigned long __init_refok init_memory_mapping(unsigned long start,
unsigned long end)
{
unsigned long last_map_addr = 0;
unsigned long page_size_mask = 0;
unsigned long start_pfn, end_pfn;
unsigned long pos;
struct map_range mr[NR_RANGE_MR];
int nr_range, i;
int use_pse, use_gbpages;
printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
/*
* Find space for the kernel direct mapping tables.
*
* Later we should allocate these tables in the local node of the
* memory mapped. Unfortunately this is done currently before the
* nodes are discovered.
*/
if (!after_bootmem)
init_gbpages();
#ifdef CONFIG_DEBUG_PAGEALLOC
/*
* For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
* This will simplify cpa(), which otherwise needs to support splitting
* large pages into small in interrupt context, etc.
*/
use_pse = use_gbpages = 0;
#else
use_pse = cpu_has_pse;
use_gbpages = direct_gbpages;
#endif
if (use_gbpages)
page_size_mask |= 1 << PG_LEVEL_1G;
if (use_pse)
page_size_mask |= 1 << PG_LEVEL_2M;
memset(mr, 0, sizeof(mr));
nr_range = 0;
/* head if not big page alignment ?*/
start_pfn = start >> PAGE_SHIFT;
pos = start_pfn << PAGE_SHIFT;
end_pfn = ((pos + (PMD_SIZE - 1)) >> PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
if (end_pfn > (end >> PAGE_SHIFT))
end_pfn = end >> PAGE_SHIFT;
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
pos = end_pfn << PAGE_SHIFT;
}
/* big page (2M) range*/
start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
end_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
<< (PUD_SHIFT - PAGE_SHIFT);
if (end_pfn > ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT)))
end_pfn = ((end>>PMD_SHIFT)<<(PMD_SHIFT - PAGE_SHIFT));
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask & (1<<PG_LEVEL_2M));
pos = end_pfn << PAGE_SHIFT;
}
/* big page (1G) range */
start_pfn = ((pos + (PUD_SIZE - 1))>>PUD_SHIFT)
<< (PUD_SHIFT - PAGE_SHIFT);
end_pfn = (end >> PUD_SHIFT) << (PUD_SHIFT - PAGE_SHIFT);
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask &
((1<<PG_LEVEL_2M)|(1<<PG_LEVEL_1G)));
pos = end_pfn << PAGE_SHIFT;
}
/* tail is not big page (1G) alignment */
start_pfn = ((pos + (PMD_SIZE - 1))>>PMD_SHIFT)
<< (PMD_SHIFT - PAGE_SHIFT);
end_pfn = (end >> PMD_SHIFT) << (PMD_SHIFT - PAGE_SHIFT);
if (start_pfn < end_pfn) {
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn,
page_size_mask & (1<<PG_LEVEL_2M));
pos = end_pfn << PAGE_SHIFT;
}
/* tail is not big page (2M) alignment */
start_pfn = pos>>PAGE_SHIFT;
end_pfn = end>>PAGE_SHIFT;
nr_range = save_mr(mr, nr_range, start_pfn, end_pfn, 0);
/* try to merge same page size and continuous */
for (i = 0; nr_range > 1 && i < nr_range - 1; i++) {
unsigned long old_start;
if (mr[i].end != mr[i+1].start ||
mr[i].page_size_mask != mr[i+1].page_size_mask)
continue;
/* move it */
old_start = mr[i].start;
memmove(&mr[i], &mr[i+1],
(nr_range - 1 - i) * sizeof (struct map_range));
mr[i--].start = old_start;
nr_range--;
}
for (i = 0; i < nr_range; i++)
printk(KERN_DEBUG " %010lx - %010lx page %s\n",
mr[i].start, mr[i].end,
(mr[i].page_size_mask & (1<<PG_LEVEL_1G))?"1G":(
(mr[i].page_size_mask & (1<<PG_LEVEL_2M))?"2M":"4k"));
if (!after_bootmem)
find_early_table_space(end, use_pse, use_gbpages);
for (i = 0; i < nr_range; i++)
last_map_addr = kernel_physical_mapping_init(
mr[i].start, mr[i].end,
mr[i].page_size_mask);
if (!after_bootmem)
mmu_cr4_features = read_cr4();
__flush_tlb_all();
if (!after_bootmem && table_end > table_start)
reserve_early(table_start << PAGE_SHIFT,
table_end << PAGE_SHIFT, "PGTABLE");
printk(KERN_INFO "last_map_addr: %lx end: %lx\n",
last_map_addr, end);
if (!after_bootmem)
early_memtest(start, end);
return last_map_addr >> PAGE_SHIFT;
}
#ifndef CONFIG_NUMA #ifndef CONFIG_NUMA
void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn) void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn)
{ {
...@@ -910,28 +681,6 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); ...@@ -910,28 +681,6 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
#endif /* CONFIG_MEMORY_HOTPLUG */ #endif /* CONFIG_MEMORY_HOTPLUG */
/*
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
* is valid. The argument is a physical page number.
*
*
* On x86, access has to be given to the first megabyte of ram because that area
* contains bios code and data regions used by X and dosemu and similar apps.
* Access has to be given to non-kernel-ram areas as well, these contain the PCI
* mmio resources as well as potential bios/acpi data regions.
*/
int devmem_is_allowed(unsigned long pagenr)
{
if (pagenr <= 256)
return 1;
if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
return 0;
if (!page_is_ram(pagenr))
return 1;
return 0;
}
static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel,
kcore_modules, kcore_vsyscall; kcore_modules, kcore_vsyscall;
...@@ -1019,13 +768,6 @@ void mark_rodata_ro(void) ...@@ -1019,13 +768,6 @@ void mark_rodata_ro(void)
#endif #endif
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
free_init_pages("initrd memory", start, end);
}
#endif
int __init reserve_bootmem_generic(unsigned long phys, unsigned long len, int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
int flags) int flags)
{ {
......
...@@ -38,8 +38,7 @@ unsigned long __phys_addr(unsigned long x) ...@@ -38,8 +38,7 @@ unsigned long __phys_addr(unsigned long x)
} else { } else {
VIRTUAL_BUG_ON(x < PAGE_OFFSET); VIRTUAL_BUG_ON(x < PAGE_OFFSET);
x -= PAGE_OFFSET; x -= PAGE_OFFSET;
VIRTUAL_BUG_ON(system_state == SYSTEM_BOOTING ? x > MAXMEM : VIRTUAL_BUG_ON(!phys_addr_valid(x));
!phys_addr_valid(x));
} }
return x; return x;
} }
...@@ -56,11 +55,9 @@ bool __virt_addr_valid(unsigned long x) ...@@ -56,11 +55,9 @@ bool __virt_addr_valid(unsigned long x)
if (x < PAGE_OFFSET) if (x < PAGE_OFFSET)
return false; return false;
x -= PAGE_OFFSET; x -= PAGE_OFFSET;
if (system_state == SYSTEM_BOOTING ? if (!phys_addr_valid(x))
x > MAXMEM : !phys_addr_valid(x)) {
return false; return false;
} }
}
return pfn_valid(x >> PAGE_SHIFT); return pfn_valid(x >> PAGE_SHIFT);
} }
...@@ -76,10 +73,9 @@ static inline int phys_addr_valid(unsigned long addr) ...@@ -76,10 +73,9 @@ static inline int phys_addr_valid(unsigned long addr)
#ifdef CONFIG_DEBUG_VIRTUAL #ifdef CONFIG_DEBUG_VIRTUAL
unsigned long __phys_addr(unsigned long x) unsigned long __phys_addr(unsigned long x)
{ {
/* VMALLOC_* aren't constants; not available at the boot time */ /* VMALLOC_* aren't constants */
VIRTUAL_BUG_ON(x < PAGE_OFFSET); VIRTUAL_BUG_ON(x < PAGE_OFFSET);
VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING && VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
is_vmalloc_addr((void *) x));
return x - PAGE_OFFSET; return x - PAGE_OFFSET;
} }
EXPORT_SYMBOL(__phys_addr); EXPORT_SYMBOL(__phys_addr);
...@@ -89,7 +85,7 @@ bool __virt_addr_valid(unsigned long x) ...@@ -89,7 +85,7 @@ bool __virt_addr_valid(unsigned long x)
{ {
if (x < PAGE_OFFSET) if (x < PAGE_OFFSET)
return false; return false;
if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x)) if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
return false; return false;
return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT); return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
} }
......
...@@ -416,10 +416,11 @@ void __init initmem_init(unsigned long start_pfn, ...@@ -416,10 +416,11 @@ void __init initmem_init(unsigned long start_pfn,
for_each_online_node(nid) for_each_online_node(nid)
propagate_e820_map_node(nid); propagate_e820_map_node(nid);
for_each_online_node(nid) for_each_online_node(nid) {
memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
}
NODE_DATA(0)->bdata = &bootmem_node_data[0];
setup_bootmem_allocator(); setup_bootmem_allocator();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment