| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/arch/x86_64/mm/init.c | |||
| 3 | * | |||
| 4 | * Copyright (C) 1995 Linus Torvalds | |||
| 5 | * Copyright (C) 2000 Pavel Machek <pavel@suse.cz> | |||
| 6 | * Copyright (C) 2002,2003 Andi Kleen <ak@suse.de> | |||
| 7 | */ | |||
| 8 | ||||
| 9 | #include <linux/config.h> | |||
| 10 | #include <linux/signal.h> | |||
| 11 | #include <linux/sched.h> | |||
| 12 | #include <linux/kernel.h> | |||
| 13 | #include <linux/errno.h> | |||
| 14 | #include <linux/string.h> | |||
| 15 | #include <linux/types.h> | |||
| 16 | #include <linux/ptrace.h> | |||
| 17 | #include <linux/mman.h> | |||
| 18 | #include <linux/mm.h> | |||
| 19 | #include <linux/swap.h> | |||
| 20 | #include <linux/smp.h> | |||
| 21 | #include <linux/init.h> | |||
| 22 | #include <linux/pagemap.h> | |||
| 23 | #include <linux/bootmem.h> | |||
| 24 | #include <linux/proc_fs.h> | |||
| 25 | #include <linux/pci.h> | |||
| 26 | #include <linux/dma-mapping.h> | |||
| 27 | #include <linux/module.h> | |||
| 28 | #include <linux/memory_hotplug.h> | |||
| 29 | ||||
| 30 | #include <asm/processor.h> | |||
| 31 | #include <asm/system.h> | |||
| 32 | #include <asm/uaccess.h> | |||
| 33 | #include <asm/pgtable.h> | |||
| 34 | #include <asm/pgalloc.h> | |||
| 35 | #include <asm/dma.h> | |||
| 36 | #include <asm/fixmap.h> | |||
| 37 | #include <asm/e820.h> | |||
| 38 | #include <asm/apic.h> | |||
| 39 | #include <asm/tlb.h> | |||
| 40 | #include <asm/mmu_context.h> | |||
| 41 | #include <asm/proto.h> | |||
| 42 | #include <asm/smp.h> | |||
| 43 | #include <asm/sections.h> | |||
| 44 | #include <asm/dma-mapping.h> | |||
| 45 | #include <asm/swiotlb.h> | |||
| 46 | ||||
| 47 | #ifndef Dprintk | |||
| 48 | #define Dprintk(x...) | |||
| 49 | #endif | |||
| 50 | ||||
| 51 | struct dma_mapping_ops* dma_ops; | |||
| 52 | EXPORT_SYMBOL(dma_ops); | |||
| 53 | ||||
| 54 | static unsigned long dma_reserve __initdata; | |||
| 55 | ||||
| 56 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | |||
| 57 | ||||
| 58 | /* | |||
| 59 | * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the | |||
| 60 | * physical space so we can cache the place of the first one and move | |||
| 61 | * around without checking the pgd every time. | |||
| 62 | */ | |||
| 63 | ||||
| 10 | 10 | 64 | void show_mem(void) | |
| 65 | { | |||
| 66 | long i, total = 0, reserved = 0; | |||
| 67 | long shared = 0, cached = 0; | |||
| 68 | pg_data_t *pgdat; | |||
| 69 | struct page *page; | |||
| 70 | ||||
| 71 | printk(KERN_INFO "Mem-info:\n"); | |||
| 72 | show_free_areas(); | |||
| 73 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | |||
| 74 | ||||
| 10 | 10 | 75 | for_each_pgdat(pgdat) { | |
| 1308E3 | 10 | 76 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { | |
| 77 | page = pfn_to_page(pgdat->node_start_pfn + i); | |||
| 78 | total++; | |||
| 91820 | 1216E3 | 79 | if (PageReserved(page)) | |
| 1308E3 | 0 | - | 79 | ternary-?: __builtin_constant_p ( 10 ) |
| 80 | reserved++; | |||
| 60 | 1216E3 | 81 | else if (PageSwapCache(page)) | |
| 1216E3 | 0 | - | 81 | ternary-?: __builtin_constant_p ( 15 ) |
| 82 | cached++; | |||
| 1202E3 | 13294 | 83 | else if (page_count(page)) | |
| 84 | shared += page_count(page) - 1; | |||
| 85 | } | |||
| 86 | } | |||
| 87 | printk(KERN_INFO "%lu pages of RAM\n", total); | |||
| 88 | printk(KERN_INFO "%lu reserved pages\n",reserved); | |||
| 89 | printk(KERN_INFO "%lu pages shared\n",shared); | |||
| 90 | printk(KERN_INFO "%lu pages swap cached\n",cached); | |||
| 91 | } | |||
| 92 | ||||
| 93 | /* References to section boundaries */ | |||
| 94 | ||||
| 95 | int after_bootmem; | |||
| 96 | ||||
| 18 | 0 | 97 | static void *spp_getpage(void) | |
| 98 | { | |||
| 99 | void *ptr; | |||
| 6 | 12 | 100 | if (after_bootmem) | |
| 101 | ptr = (void *) get_zeroed_page(GFP_ATOMIC); | |||
| 102 | else | |||
| 103 | ptr = alloc_bootmem_pages(PAGE_SIZE); | |||
| 0 | 12 | - | 103 | ternary-?: ( ( unsigned long ) ( ( ( unsigne.. |
| 0 | 18 | - | 104 | if (!ptr || ((unsigned long)ptr & ~PAGE_MASK)) |
| 0 | - | 104 | T || (_) | |
| 0 | - | 104 | F || (T) | |
| 18 | 104 | F || (F) | ||
| 105 | panic("set_pte_phys: cannot allocate page data %s\n", after_bootmem?"after bootmem":""); | |||
| 0 | 0 | - | 105 | ternary-?: after_bootmem |
| 106 | ||||
| 107 | Dprintk("spp_getpage %p\n", ptr); | |||
| 18 | 108 | return ptr; | ||
| 109 | } | |||
| 110 | ||||
| 30 | 30 | 111 | static void set_pte_phys(unsigned long vaddr, | |
| 112 | unsigned long phys, pgprot_t prot) | |||
| 113 | { | |||
| 114 | pgd_t *pgd; | |||
| 115 | pud_t *pud; | |||
| 116 | pmd_t *pmd; | |||
| 117 | pte_t *pte, new_pte; | |||
| 118 | ||||
| 119 | Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys); | |||
| 120 | ||||
| 121 | pgd = pgd_offset_k(vaddr); | |||
| 0 | 30 | - | 122 | if (pgd_none(*pgd)) { |
| 123 | printk("PGD FIXMAP MISSING, it should be setup in head.S!\n"); | |||
| 0 | - | 124 | return; | |
| 125 | } | |||
| 126 | pud = pud_offset(pgd, vaddr); | |||
| 6 | 24 | 127 | if (pud_none(*pud)) { | |
| 128 | pmd = (pmd_t *) spp_getpage(); | |||
| 129 | set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); | |||
| 0 | 6 | - | 130 | if (pmd != pmd_offset(pud, 0)) { |
| 131 | printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0)); | |||
| 0 | - | 132 | return; | |
| 133 | } | |||
| 134 | } | |||
| 135 | pmd = pmd_offset(pud, vaddr); | |||
| 12 | 18 | 136 | if (pmd_none(*pmd)) { | |
| 137 | pte = (pte_t *) spp_getpage(); | |||
| 138 | set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); | |||
| 0 | 12 | - | 139 | if (pte != pte_offset_kernel(pmd, 0)) { |
| 140 | printk("PAGETABLE BUG #02!\n"); | |||
| 0 | - | 141 | return; | |
| 142 | } | |||
| 143 | } | |||
| 144 | new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); | |||
| 145 | ||||
| 146 | pte = pte_offset_kernel(pmd, vaddr); | |||
| 147 | if (!pte_none(*pte) && | |||
| 0 | 30 | - | 148 | pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) |
| 0 | - | 148 | !(!(T)) && T | |
| 12 | 148 | !(!(T)) && F | ||
| 18 | 148 | !(!(F)) && _ | ||
| 149 | pte_ERROR(*pte); | |||
| 150 | set_pte(pte, new_pte); | |||
| 151 | ||||
| 152 | /* | |||
| 153 | * It's enough to flush this one mapping. | |||
| 154 | * (PGE mappings get flushed as well) | |||
| 155 | */ | |||
| 156 | __flush_tlb_one(vaddr); | |||
| 157 | } | |||
| 158 | ||||
| 159 | /* NOTE: this is meant to be run only at boot */ | |||
| 30 | 30 | 160 | void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot) | |
| 161 | { | |||
| 162 | unsigned long address = __fix_to_virt(idx); | |||
| 163 | ||||
| 0 | 30 | - | 164 | if (idx >= __end_of_fixed_addresses) { |
| 165 | printk("Invalid __set_fixmap\n"); | |||
| 0 | - | 166 | return; | |
| 167 | } | |||
| 168 | set_pte_phys(address, phys, prot); | |||
| 169 | } | |||
| 170 | ||||
| 171 | unsigned long __initdata table_start, table_end; | |||
| 172 | ||||
| 173 | extern pmd_t temp_boot_pmds[]; | |||
| 174 | ||||
| 175 | static struct temp_map { | |||
| 176 | pmd_t *pmd; | |||
| 177 | void *address; | |||
| 178 | int allocated; | |||
| 179 | } temp_mappings[] __initdata = { | |||
| 180 | { &temp_boot_pmds[0], (void *)(40UL * 1024 * 1024) }, | |||
| 181 | { &temp_boot_pmds[1], (void *)(42UL * 1024 * 1024) }, | |||
| 182 | {} | |||
| 183 | }; | |||
| 184 | ||||
| 18 | 0 | 185 | static __meminit void *alloc_low_page(int *index, unsigned long *phys) | |
| 186 | { | |||
| 187 | struct temp_map *ti; | |||
| 188 | int i; | |||
| 189 | unsigned long pfn = table_end++, paddr; | |||
| 190 | void *adr; | |||
| 191 | ||||
| 0 | 18 | - | 192 | if (after_bootmem) { |
| 193 | adr = (void *)get_zeroed_page(GFP_ATOMIC); | |||
| 194 | *phys = __pa(adr); | |||
| 0 | 0 | - | 194 | ternary-?: ( ( unsigned long ) ( adr ) >= 0x.. |
| 0 | - | 195 | return adr; | |
| 196 | } | |||
| 197 | ||||
| 0 | 18 | - | 198 | if (pfn >= end_pfn) |
| 199 | panic("alloc_low_page: ran out of memory"); | |||
| 12 | 18 | 200 | for (i = 0; temp_mappings[i].allocated; i++) { | |
| 0 | 12 | - | 201 | if (!temp_mappings[i].pmd) |
| 202 | panic("alloc_low_page: ran out of temp mappings"); | |||
| 203 | } | |||
| 204 | ti = &temp_mappings[i]; | |||
| 205 | paddr = (pfn << PAGE_SHIFT) & PMD_MASK; | |||
| 206 | set_pmd(ti->pmd, __pmd(paddr | _KERNPG_TABLE | _PAGE_PSE)); | |||
| 207 | ti->allocated = 1; | |||
| 208 | __flush_tlb(); | |||
| 0 | 18 | - | 208 | do-while (0) |
| 209 | adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); | |||
| 210 | memset(adr, 0, PAGE_SIZE); | |||
| 211 | *index = i; | |||
| 212 | *phys = pfn * PAGE_SIZE; | |||
| 18 | 213 | return adr; | ||
| 214 | } | |||
| 215 | ||||
| 18 | 18 | 216 | static __meminit void unmap_low_page(int i) | |
| 217 | { | |||
| 218 | struct temp_map *ti; | |||
| 219 | ||||
| 0 | 18 | - | 220 | if (after_bootmem) |
| 0 | - | 221 | return; | |
| 222 | ||||
| 223 | ti = &temp_mappings[i]; | |||
| 224 | set_pmd(ti->pmd, __pmd(0)); | |||
| 225 | ti->allocated = 0; | |||
| 226 | } | |||
| 227 | ||||
| 228 | static void __meminit | |||
| 12 | 12 | 229 | phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) | |
| 230 | { | |||
| 231 | int i; | |||
| 232 | ||||
| 6144 | 12 | 233 | for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { | |
| 234 | unsigned long entry; | |||
| 235 | ||||
| 0 | 6144 | - | 236 | if (address > end) { |
| 0 | 0 | - | 237 | for (; i < PTRS_PER_PMD; i++, pmd++) |
| 238 | set_pmd(pmd, __pmd(0)); | |||
| 0 | - | 239 | break; | |
| 240 | } | |||
| 241 | entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; | |||
| 242 | entry &= __supported_pte_mask; | |||
| 243 | set_pmd(pmd, __pmd(entry)); | |||
| 244 | } | |||
| 245 | } | |||
| 246 | ||||
| 247 | static void __meminit | |||
| 0 | 0 | - | 248 | phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) |
| 249 | { | |||
| 250 | pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address)); | |||
| 251 | ||||
| 0 | 0 | - | 252 | if (pmd_none(*pmd)) { |
| 253 | spin_lock(&init_mm.page_table_lock); | |||
| 253 | do | |||
| 0 | 0 | - | 253 | do-while (0) |
| 0 | 0 | - | 253 | do-while (0) |
| 254 | phys_pmd_init(pmd, address, end); | |||
| 255 | spin_unlock(&init_mm.page_table_lock); | |||
| 255 | do | |||
| 0 | 0 | - | 255 | do-while (0) |
| 0 | 0 | - | 255 | do-while (0) |
| 256 | __flush_tlb_all(); | |||
| 0 | 0 | - | 256 | do-while (0) |
| 257 | } | |||
| 258 | } | |||
| 259 | ||||
| 6 | 6 | 260 | static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) | |
| 261 | { | |||
| 262 | long i = pud_index(address); | |||
| 263 | ||||
| 264 | pud = pud + i; | |||
| 265 | ||||
| 0 | 6 | - | 266 | if (after_bootmem && pud_val(*pud)) { |
| 0 | - | 266 | T && (T) | |
| 0 | - | 266 | T && (F) | |
| 6 | 266 | F && (_) | ||
| 267 | phys_pmd_update(pud, address, end); | |||
| 0 | - | 268 | return; | |
| 269 | } | |||
| 270 | ||||
| 30 | 0 | - | 271 | for (; i < PTRS_PER_PUD; pud++, i++) { |
| 272 | int map; | |||
| 273 | unsigned long paddr, pmd_phys; | |||
| 274 | pmd_t *pmd; | |||
| 275 | ||||
| 276 | paddr = (address & PGDIR_MASK) + i*PUD_SIZE; | |||
| 6 | 24 | 277 | if (paddr >= end) | |
| 6 | 278 | break; | ||
| 279 | ||||
| 12 | 12 | 280 | if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) { | |
| 12 | 280 | T && T | ||
| 12 | 280 | T && F | ||
| 0 | - | 280 | F && _ | |
| 281 | set_pud(pud, __pud(0)); | |||
| 12 | 282 | continue; | ||
| 283 | } | |||
| 284 | ||||
| 285 | pmd = alloc_low_page(&map, &pmd_phys); | |||
| 286 | spin_lock(&init_mm.page_table_lock); | |||
| 286 | do | |||
| 0 | 12 | - | 286 | do-while (0) |
| 0 | 12 | - | 286 | do-while (0) |
| 287 | set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); | |||
| 288 | phys_pmd_init(pmd, paddr, end); | |||
| 289 | spin_unlock(&init_mm.page_table_lock); | |||
| 289 | do | |||
| 0 | 12 | - | 289 | do-while (0) |
| 0 | 12 | - | 289 | do-while (0) |
| 290 | unmap_low_page(map); | |||
| 291 | } | |||
| 292 | __flush_tlb(); | |||
| 0 | 6 | - | 292 | do-while (0) |
| 293 | } | |||
| 294 | ||||
| 6 | 6 | 295 | static void __init find_early_table_space(unsigned long end) | |
| 296 | { | |||
| 297 | unsigned long puds, pmds, tables, start; | |||
| 298 | ||||
| 299 | puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; | |||
| 300 | pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; | |||
| 301 | tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) + | |||
| 302 | round_up(pmds * sizeof(pmd_t), PAGE_SIZE); | |||
| 303 | ||||
| 304 | /* RED-PEN putting page tables only on node 0 could | |||
| 305 | cause a hotspot and fill up ZONE_DMA. The page tables | |||
| 306 | need roughly 0.5KB per GB. */ | |||
| 307 | start = 0x8000; | |||
| 308 | table_start = find_e820_area(start, end, tables); | |||
| 0 | 6 | - | 309 | if (table_start == -1UL) |
| 310 | panic("Cannot find space for the kernel page tables"); | |||
| 311 | ||||
| 312 | table_start >>= PAGE_SHIFT; | |||
| 313 | table_end = table_start; | |||
| 314 | ||||
| 315 | early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", | |||
| 316 | end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT); | |||
| 317 | } | |||
| 318 | ||||
| 319 | /* Setup the direct mapping of the physical memory at PAGE_OFFSET. | |||
| 320 | This runs before bootmem is initialized and gets pages directly from the | |||
| 321 | physical memory. To access them they are temporarily mapped. */ | |||
| 6 | 6 | 322 | void __meminit init_memory_mapping(unsigned long start, unsigned long end) | |
| 323 | { | |||
| 324 | unsigned long next; | |||
| 325 | ||||
| 326 | Dprintk("init_memory_mapping\n"); | |||
| 327 | ||||
| 328 | /* | |||
| 329 | * Find space for the kernel direct mapping tables. | |||
| 330 | * Later we should allocate these tables in the local node of the memory | |||
| 331 | * mapped. Unfortunately this is done currently before the nodes are | |||
| 332 | * discovered. | |||
| 333 | */ | |||
| 6 | 0 | - | 334 | if (!after_bootmem) |
| 335 | find_early_table_space(end); | |||
| 336 | ||||
| 337 | start = (unsigned long)__va(start); | |||
| 338 | end = (unsigned long)__va(end); | |||
| 339 | ||||
| 6 | 6 | 340 | for (; start < end; start = next) { | |
| 341 | int map; | |||
| 342 | unsigned long pud_phys; | |||
| 343 | pgd_t *pgd = pgd_offset_k(start); | |||
| 344 | pud_t *pud; | |||
| 345 | ||||
| 0 | 6 | - | 346 | if (after_bootmem) |
| 347 | pud = pud_offset_k(pgd, __PAGE_OFFSET); | |||
| 348 | else | |||
| 349 | pud = alloc_low_page(&map, &pud_phys); | |||
| 350 | ||||
| 351 | next = start + PGDIR_SIZE; | |||
| 6 | 0 | - | 352 | if (next > end) |
| 353 | next = end; | |||
| 354 | phys_pud_init(pud, __pa(start), __pa(next)); | |||
| 0 | 6 | - | 354 | ternary-?: ( ( unsigned long ) ( start ) >= .. |
| 0 | 6 | - | 354 | ternary-?: ( ( unsigned long ) ( next ) >= 0.. |
| 6 | 0 | - | 355 | if (!after_bootmem) |
| 356 | set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); | |||
| 357 | unmap_low_page(map); | |||
| 358 | } | |||
| 359 | ||||
| 6 | 0 | - | 360 | if (!after_bootmem) |
| 361 | asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); | |||
| 362 | __flush_tlb_all(); | |||
| 0 | 6 | - | 362 | do-while (0) |
| 363 | } | |||
| 364 | ||||
| 6 | 6 | 365 | void __cpuinit zap_low_mappings(int cpu) | |
| 366 | { | |||
| 6 | 0 | - | 367 | if (cpu == 0) { |
| 368 | pgd_t *pgd = pgd_offset_k(0UL); | |||
| 369 | pgd_clear(pgd); | |||
| 370 | } else { | |||
| 371 | /* | |||
| 372 | * For AP's, zap the low identity mappings by changing the cr3 | |||
| 373 | * to init_level4_pgt and doing local flush tlb all | |||
| 374 | */ | |||
| 375 | asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt))); | |||
| 376 | } | |||
| 377 | __flush_tlb_all(); | |||
| 0 | 6 | - | 377 | do-while (0) |
| 378 | } | |||
| 379 | ||||
| 380 | /* Compute zone sizes for the DMA and DMA32 zones in a node. */ | |||
| 381 | __init void | |||
| 6 | 6 | 382 | size_zones(unsigned long *z, unsigned long *h, | |
| 383 | unsigned long start_pfn, unsigned long end_pfn) | |||
| 384 | { | |||
| 385 | int i; | |||
| 386 | unsigned long w; | |||
| 387 | ||||
| 24 | 6 | 388 | for (i = 0; i < MAX_NR_ZONES; i++) | |
| 389 | z[i] = 0; | |||
| 390 | ||||
| 6 | 0 | - | 391 | if (start_pfn < MAX_DMA_PFN) |
| 392 | z[ZONE_DMA] = MAX_DMA_PFN - start_pfn; | |||
| 6 | 0 | - | 393 | if (start_pfn < MAX_DMA32_PFN) { |
| 394 | unsigned long dma32_pfn = MAX_DMA32_PFN; | |||
| 6 | 0 | - | 395 | if (dma32_pfn > end_pfn) |
| 396 | dma32_pfn = end_pfn; | |||
| 397 | z[ZONE_DMA32] = dma32_pfn - start_pfn; | |||
| 398 | } | |||
| 399 | z[ZONE_NORMAL] = end_pfn - start_pfn; | |||
| 400 | ||||
| 401 | /* Remove lower zones from higher ones. */ | |||
| 402 | w = 0; | |||
| 24 | 6 | 403 | for (i = 0; i < MAX_NR_ZONES; i++) { | |
| 18 | 6 | 404 | if (z[i]) | |
| 405 | z[i] -= w; | |||
| 406 | w += z[i]; | |||
| 407 | } | |||
| 408 | ||||
| 409 | /* Compute holes */ | |||
| 410 | w = start_pfn; | |||
| 24 | 6 | 411 | for (i = 0; i < MAX_NR_ZONES; i++) { | |
| 412 | unsigned long s = w; | |||
| 413 | w += z[i]; | |||
| 414 | h[i] = e820_hole_size(s, w); | |||
| 415 | } | |||
| 416 | ||||
| 417 | /* Add the space pace needed for mem_map to the holes too. */ | |||
| 24 | 6 | 418 | for (i = 0; i < MAX_NR_ZONES; i++) | |
| 419 | h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE; | |||
| 420 | ||||
| 421 | /* The 16MB DMA zone has the kernel and other misc mappings. | |||
| 422 | Account them too */ | |||
| 6 | 0 | - | 423 | if (h[ZONE_DMA]) { |
| 424 | h[ZONE_DMA] += dma_reserve; | |||
| 0 | 6 | - | 425 | if (h[ZONE_DMA] >= z[ZONE_DMA]) { |
| 426 | printk(KERN_WARNING | |||
| 427 | "Kernel too large and filling up ZONE_DMA?\n"); | |||
| 428 | h[ZONE_DMA] = z[ZONE_DMA]; | |||
| 429 | } | |||
| 430 | } | |||
| 431 | } | |||
| 432 | ||||
| 433 | #ifndef CONFIG_NUMA | |||
| 6 | 6 | 434 | void __init paging_init(void) | |
| 435 | { | |||
| 436 | unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; | |||
| 437 | ||||
| 438 | memory_present(0, 0, end_pfn); | |||
| 439 | sparse_init(); | |||
| 0 | 6 | - | 439 | do-while (0) |
| 440 | size_zones(zones, holes, 0, end_pfn); | |||
| 441 | free_area_init_node(0, NODE_DATA(0), zones, | |||
| 442 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); | |||
| 0 | 6 | - | 442 | ternary-?: ( ( unsigned long ) ( ( ( unsigned .. |
| 443 | } | |||
| 444 | #endif | |||
| 445 | ||||
| 446 | /* Unmap a kernel mapping if it exists. This is useful to avoid prefetches | |||
| 447 | from the CPU leading to inconsistent cache lines. address and size | |||
| 448 | must be aligned to 2MB boundaries. | |||
| 449 | Does nothing when the mapping doesn't exist. */ | |||
| 0 | 0 | - | 450 | void __init clear_kernel_mapping(unsigned long address, unsigned long size) |
| 451 | { | |||
| 452 | unsigned long end = address + size; | |||
| 453 | ||||
| 454 | BUG_ON(address & ~LARGE_PAGE_MASK); | |||
| 0 | 0 | - | 454 | if (__builtin_expect ( ! ! ( ( address & ~ (.. |
| 0 | 0 | - | 454 | do-while (0) |
| 455 | BUG_ON(size & ~LARGE_PAGE_MASK); | |||
| 0 | 0 | - | 455 | if (__builtin_expect ( ! ! ( ( size & ~ ( ~ .. |
| 0 | 0 | - | 455 | do-while (0) |
| 456 | ||||
| 0 | 0 | - | 457 | for (; address < end; address += LARGE_PAGE_SIZE) { |
| 458 | pgd_t *pgd = pgd_offset_k(address); | |||
| 459 | pud_t *pud; | |||
| 460 | pmd_t *pmd; | |||
| 0 | 0 | - | 461 | if (pgd_none(*pgd)) |
| 0 | - | 462 | continue; | |
| 463 | pud = pud_offset(pgd, address); | |||
| 0 | 0 | - | 464 | if (pud_none(*pud)) |
| 0 | - | 465 | continue; | |
| 466 | pmd = pmd_offset(pud, address); | |||
| 0 | 0 | - | 467 | if (!pmd || pmd_none(*pmd)) |
| 0 | - | 467 | T || (!(_)) | |
| 0 | - | 467 | F || (!(F)) | |
| 0 | - | 467 | F || (!(T)) | |
| 0 | - | 468 | continue; | |
| 0 | 0 | - | 469 | if (0 == (pmd_val(*pmd) & _PAGE_PSE)) { |
| 470 | /* Could handle this, but it should not happen currently. */ | |||
| 471 | printk(KERN_ERR | |||
| 472 | "clear_kernel_mapping: mapping has been split. will leak memory\n"); | |||
| 473 | pmd_ERROR(*pmd); | |||
| 474 | } | |||
| 475 | set_pmd(pmd, __pmd(0)); | |||
| 476 | } | |||
| 477 | __flush_tlb_all(); | |||
| 0 | 0 | - | 477 | do-while (0) |
| 478 | } | |||
| 479 | ||||
| 480 | /* | |||
| 481 | * Memory hotplug specific functions | |||
| 482 | * These are only for non-NUMA machines right now. | |||
| 483 | */ | |||
| 484 | #ifdef CONFIG_MEMORY_HOTPLUG | |||
| 485 | ||||
| 486 | void online_page(struct page *page) | |||
| 487 | { | |||
| 488 | ClearPageReserved(page); | |||
| 489 | set_page_count(page, 1); | |||
| 490 | __free_page(page); | |||
| 491 | totalram_pages++; | |||
| 492 | num_physpages++; | |||
| 493 | } | |||
| 494 | ||||
| 495 | int add_memory(u64 start, u64 size) | |||
| 496 | { | |||
| 497 | ||||