|
@@ -2308,18 +2308,9 @@ unsigned long _PAGE_CACHE __read_mostly;
|
|
|
EXPORT_SYMBOL(_PAGE_CACHE);
|
|
|
|
|
|
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
|
|
-unsigned long vmemmap_table[VMEMMAP_SIZE];
|
|
|
-
|
|
|
-static long __meminitdata addr_start, addr_end;
|
|
|
-static int __meminitdata node_start;
|
|
|
-
|
|
|
int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
|
|
|
int node)
|
|
|
{
|
|
|
- unsigned long phys_start = (vstart - VMEMMAP_BASE);
|
|
|
- unsigned long phys_end = (vend - VMEMMAP_BASE);
|
|
|
- unsigned long addr = phys_start & VMEMMAP_CHUNK_MASK;
|
|
|
- unsigned long end = VMEMMAP_ALIGN(phys_end);
|
|
|
unsigned long pte_base;
|
|
|
|
|
|
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U |
|
|
@@ -2330,47 +2321,52 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
|
|
|
_PAGE_CP_4V | _PAGE_CV_4V |
|
|
|
_PAGE_P_4V | _PAGE_W_4V);
|
|
|
|
|
|
- for (; addr < end; addr += VMEMMAP_CHUNK) {
|
|
|
- unsigned long *vmem_pp =
|
|
|
- vmemmap_table + (addr >> VMEMMAP_CHUNK_SHIFT);
|
|
|
- void *block;
|
|
|
+ pte_base |= _PAGE_PMD_HUGE;
|
|
|
|
|
|
- if (!(*vmem_pp & _PAGE_VALID)) {
|
|
|
- block = vmemmap_alloc_block(1UL << ILOG2_4MB, node);
|
|
|
- if (!block)
|
|
|
+ vstart = vstart & PMD_MASK;
|
|
|
+ vend = ALIGN(vend, PMD_SIZE);
|
|
|
+ for (; vstart < vend; vstart += PMD_SIZE) {
|
|
|
+ pgd_t *pgd = pgd_offset_k(vstart);
|
|
|
+ unsigned long pte;
|
|
|
+ pud_t *pud;
|
|
|
+ pmd_t *pmd;
|
|
|
+
|
|
|
+ if (pgd_none(*pgd)) {
|
|
|
+ pud_t *new = vmemmap_alloc_block(PAGE_SIZE, node);
|
|
|
+
|
|
|
+ if (!new)
|
|
|
return -ENOMEM;
|
|
|
+ pgd_populate(&init_mm, pgd, new);
|
|
|
+ }
|
|
|
|
|
|
- *vmem_pp = pte_base | __pa(block);
|
|
|
+ pud = pud_offset(pgd, vstart);
|
|
|
+ if (pud_none(*pud)) {
|
|
|
+ pmd_t *new = vmemmap_alloc_block(PAGE_SIZE, node);
|
|
|
|
|
|
- /* check to see if we have contiguous blocks */
|
|
|
- if (addr_end != addr || node_start != node) {
|
|
|
- if (addr_start)
|
|
|
- printk(KERN_DEBUG " [%lx-%lx] on node %d\n",
|
|
|
- addr_start, addr_end-1, node_start);
|
|
|
- addr_start = addr;
|
|
|
- node_start = node;
|
|
|
- }
|
|
|
- addr_end = addr + VMEMMAP_CHUNK;
|
|
|
+ if (!new)
|
|
|
+ return -ENOMEM;
|
|
|
+ pud_populate(&init_mm, pud, new);
|
|
|
}
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
-void __meminit vmemmap_populate_print_last(void)
|
|
|
-{
|
|
|
- if (addr_start) {
|
|
|
- printk(KERN_DEBUG " [%lx-%lx] on node %d\n",
|
|
|
- addr_start, addr_end-1, node_start);
|
|
|
- addr_start = 0;
|
|
|
- addr_end = 0;
|
|
|
- node_start = 0;
|
|
|
+ pmd = pmd_offset(pud, vstart);
|
|
|
+
|
|
|
+ pte = pmd_val(*pmd);
|
|
|
+ if (!(pte & _PAGE_VALID)) {
|
|
|
+ void *block = vmemmap_alloc_block(PMD_SIZE, node);
|
|
|
+
|
|
|
+ if (!block)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ pmd_val(*pmd) = pte_base | __pa(block);
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void vmemmap_free(unsigned long start, unsigned long end)
|
|
|
{
|
|
|
}
|
|
|
-
|
|
|
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
|
|
|
|
|
|
static void prot_init_common(unsigned long page_none,
|