in mm/init_64.c [2275:2461]
void __init paging_init(void)
{
unsigned long end_pfn, shift, phys_base;
unsigned long real_end, i;
setup_page_offset();
/* These build time checkes make sure that the dcache_dirty_cpu()
* page->flags usage will work.
*
* When a page gets marked as dcache-dirty, we store the
* cpu number starting at bit 32 in the page->flags. Also,
* functions like clear_dcache_dirty_cpu use the cpu mask
* in 13-bit signed-immediate instruction fields.
*/
/*
* Page flags must not reach into upper 32 bits that are used
* for the cpu number
*/
BUILD_BUG_ON(NR_PAGEFLAGS > 32);
/*
* The bit fields placed in the high range must not reach below
* the 32 bit boundary. Otherwise we cannot place the cpu field
* at the 32 bit boundary.
*/
BUILD_BUG_ON(SECTIONS_WIDTH + NODES_WIDTH + ZONES_WIDTH +
ilog2(roundup_pow_of_two(NR_CPUS)) > 32);
BUILD_BUG_ON(NR_CPUS > 4096);
kern_base = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB;
kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
/* Invalidate both kernel TSBs. */
memset(swapper_tsb, 0x40, sizeof(swapper_tsb));
#ifndef CONFIG_DEBUG_PAGEALLOC
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
#endif
/* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde
* bit on M7 processor. This is a conflicting usage of the same
* bit. Enabling TTE.cv on M7 would turn on Memory Corruption
* Detection error on all pages and this will lead to problems
* later. Kernel does not run with MCD enabled and hence rest
* of the required steps to fully configure memory corruption
* detection are not taken. We need to ensure TTE.mcde is not
* set on M7 processor. Compute the value of cacheability
* flag for use later taking this into consideration.
*/
switch (sun4v_chip_type) {
case SUN4V_CHIP_SPARC_M7:
case SUN4V_CHIP_SPARC_M8:
case SUN4V_CHIP_SPARC_SN:
page_cache4v_flag = _PAGE_CP_4V;
break;
default:
page_cache4v_flag = _PAGE_CACHE_4V;
break;
}
if (tlb_type == hypervisor)
sun4v_pgprot_init();
else
sun4u_pgprot_init();
if (tlb_type == cheetah_plus ||
tlb_type == hypervisor) {
tsb_phys_patch();
ktsb_phys_patch();
}
if (tlb_type == hypervisor)
sun4v_patch_tlb_handlers();
/* Find available physical memory...
*
* Read it twice in order to work around a bug in openfirmware.
* The call to grab this table itself can cause openfirmware to
* allocate memory, which in turn can take away some space from
* the list of available memory. Reading it twice makes sure
* we really do get the final value.
*/
read_obp_translations();
read_obp_memory("reg", &pall[0], &pall_ents);
read_obp_memory("available", &pavail[0], &pavail_ents);
read_obp_memory("available", &pavail[0], &pavail_ents);
phys_base = 0xffffffffffffffffUL;
for (i = 0; i < pavail_ents; i++) {
phys_base = min(phys_base, pavail[i].phys_addr);
memblock_add(pavail[i].phys_addr, pavail[i].reg_size);
}
memblock_reserve(kern_base, kern_size);
find_ramdisk(phys_base);
if (cmdline_memory_size)
reduce_memory(cmdline_memory_size);
memblock_allow_resize();
memblock_dump_all();
set_bit(0, mmu_context_bmap);
shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE);
real_end = (unsigned long)_end;
num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << ILOG2_4MB);
printk("Kernel: Using %d locked TLB entries for main kernel image.\n",
num_kernel_image_mappings);
/* Set kernel pgd to upper alias so physical page computations
* work.
*/
init_mm.pgd += ((shift) / (sizeof(pgd_t)));
memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
inherit_prom_mappings();
/* Ok, we can use our TLB miss and window trap handlers safely. */
setup_tba();
__flush_tlb_all();
prom_build_devicetree();
of_populate_present_mask();
#ifndef CONFIG_SMP
of_fill_in_cpu_data();
#endif
if (tlb_type == hypervisor) {
sun4v_mdesc_init();
mdesc_populate_present_mask(cpu_all_mask);
#ifndef CONFIG_SMP
mdesc_fill_in_cpu_data(cpu_all_mask);
#endif
mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask);
sun4v_linear_pte_xor_finalize();
sun4v_ktsb_init();
sun4v_ktsb_register();
} else {
unsigned long impl, ver;
cpu_pgsz_mask = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
__asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
impl = ((ver >> 32) & 0xffff);
if (impl == PANTHER_IMPL)
cpu_pgsz_mask |= (HV_PGSZ_MASK_32MB |
HV_PGSZ_MASK_256MB);
sun4u_linear_pte_xor_finalize();
}
/* Flush the TLBs and the 4M TSB so that the updated linear
* pte XOR settings are realized for all mappings.
*/
__flush_tlb_all();
#ifndef CONFIG_DEBUG_PAGEALLOC
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
#endif
__flush_tlb_all();
/* Setup bootmem... */
last_valid_pfn = end_pfn = bootmem_init(phys_base);
kernel_physical_mapping_init();
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
max_zone_pfns[ZONE_NORMAL] = end_pfn;
free_area_init(max_zone_pfns);
}
printk("Booting Linux...\n");
}