cregit-Linux how code gets into the kernel

Release 4.14 arch/metag/mm/init.c

Directory: arch/metag/mm
// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 2005,2006,2007,2008,2009,2010 Imagination Technologies
 *
 */

#include <linux/export.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/pagemap.h>
#include <linux/percpu.h>
#include <linux/memblock.h>
#include <linux/initrd.h>
#include <linux/sched/task.h>

#include <asm/setup.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/mmu.h>
#include <asm/mmu_context.h>
#include <asm/sections.h>
#include <asm/tlb.h>
#include <asm/user_gateway.h>
#include <asm/mmzone.h>
#include <asm/fixmap.h>


unsigned long pfn_base;

EXPORT_SYMBOL(pfn_base);


pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data;


unsigned long empty_zero_page;

EXPORT_SYMBOL(empty_zero_page);

extern char __user_gateway_start;
extern char __user_gateway_end;


void *gateway_page;

/*
 * Insert the gateway page into a set of page tables, creating the
 * page tables if necessary.
 */

static void insert_gateway_page(pgd_t *pgd, unsigned long address) { pud_t *pud; pmd_t *pmd; pte_t *pte; BUG_ON(!pgd_present(*pgd)); pud = pud_offset(pgd, address); BUG_ON(!pud_present(*pud)); pmd = pmd_offset(pud, address); if (!pmd_present(*pmd)) { pte = alloc_bootmem_pages(PAGE_SIZE); set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))); } pte = pte_offset_kernel(pmd, address); set_pte(pte, pfn_pte(__pa(gateway_page) >> PAGE_SHIFT, PAGE_READONLY)); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan123100.00%1100.00%
Total123100.00%1100.00%

/* Alloc and map a page in a known location accessible to userspace. */
static void __init user_gateway_init(void) { unsigned long address = USER_GATEWAY_PAGE; int offset = pgd_index(address); pgd_t *pgd; gateway_page = alloc_bootmem_pages(PAGE_SIZE); pgd = swapper_pg_dir + offset; insert_gateway_page(pgd, address); #ifdef CONFIG_METAG_META12 /* * Insert the gateway page into our current page tables even * though we've already inserted it into our reference page * table (swapper_pg_dir). This is because with a META1 mmu we * copy just the user address range and not the gateway page * entry on context switch, see switch_mmu(). */ pgd = (pgd_t *)mmu_get_base() + offset; insert_gateway_page(pgd, address); #endif /* CONFIG_METAG_META12 */ BUG_ON((&__user_gateway_end - &__user_gateway_start) > PAGE_SIZE); gateway_page += (address & ~PAGE_MASK); memcpy(gateway_page, &__user_gateway_start, &__user_gateway_end - &__user_gateway_start); /* * We don't need to flush the TLB here, there should be no mapping * present at boot for this address and only valid mappings are in * the TLB (apart from on Meta 1.x, but those cached invalid * mappings should be impossible to hit here). * * We don't flush the code cache here even though we have written * code through the data cache and they may not be coherent. At * this point we assume there is no stale data in the code cache * for this address so there is no need to flush. */ }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan109100.00%1100.00%
Total109100.00%1100.00%


static void __init allocate_pgdat(unsigned int nid) { unsigned long start_pfn, end_pfn; #ifdef CONFIG_NEED_MULTIPLE_NODES unsigned long phys; #endif get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); #ifdef CONFIG_NEED_MULTIPLE_NODES phys = __memblock_alloc_base(sizeof(struct pglist_data), SMP_CACHE_BYTES, end_pfn << PAGE_SHIFT); /* Retry with all of system memory */ if (!phys) phys = __memblock_alloc_base(sizeof(struct pglist_data), SMP_CACHE_BYTES, memblock_end_of_DRAM()); if (!phys) panic("Can't allocate pgdat for node %d\n", nid); NODE_DATA(nid) = __va(phys); memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; #endif NODE_DATA(nid)->node_start_pfn = start_pfn; NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan152100.00%1100.00%
Total152100.00%1100.00%


static void __init bootmem_init_one_node(unsigned int nid) { unsigned long total_pages, paddr; unsigned long end_pfn; struct pglist_data *p; p = NODE_DATA(nid); /* Nothing to do.. */ if (!p->node_spanned_pages) return; end_pfn = pgdat_end_pfn(p); #ifdef CONFIG_HIGHMEM if (end_pfn > max_low_pfn) end_pfn = max_low_pfn; #endif total_pages = bootmem_bootmap_pages(end_pfn - p->node_start_pfn); paddr = memblock_alloc(total_pages << PAGE_SHIFT, PAGE_SIZE); if (!paddr) panic("Can't allocate bootmap for nid[%d]\n", nid); init_bootmem_node(p, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn); free_bootmem_with_active_regions(nid, end_pfn); /* * XXX Handle initial reservations for the system memory node * only for the moment, we'll refactor this later for handling * reservations in other nodes. */ if (nid == 0) { struct memblock_region *reg; /* Reserve the sections we're already using. */ for_each_memblock(reserved, reg) { unsigned long size = reg->size; #ifdef CONFIG_HIGHMEM /* ...but not highmem */ if (PFN_DOWN(reg->base) >= highstart_pfn) continue; if (PFN_UP(reg->base + size) > highstart_pfn) size = (highstart_pfn - PFN_DOWN(reg->base)) << PAGE_SHIFT; #endif reserve_bootmem(reg->base, size, BOOTMEM_DEFAULT); } } sparse_memory_present_with_active_regions(nid); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan21098.59%150.00%
Xishi Qiu31.41%150.00%
Total213100.00%2100.00%


static void __init do_init_bootmem(void) { struct memblock_region *reg; int i; /* Add active regions with valid PFNs. */ for_each_memblock(memory, reg) { unsigned long start_pfn, end_pfn; start_pfn = memblock_region_memory_base_pfn(reg); end_pfn = memblock_region_memory_end_pfn(reg); memblock_set_node(PFN_PHYS(start_pfn), PFN_PHYS(end_pfn - start_pfn), &memblock.memory, 0); } /* All of system RAM sits in node 0 for the non-NUMA case */ allocate_pgdat(0); node_set_online(0); soc_mem_setup(); for_each_online_node(i) bootmem_init_one_node(i); sparse_init(); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan8994.68%150.00%
Tang Chen55.32%150.00%
Total94100.00%2100.00%

extern char _heap_start[];
static void __init init_and_reserve_mem(void) { unsigned long start_pfn, heap_start; u64 base = min_low_pfn << PAGE_SHIFT; u64 size = (max_low_pfn << PAGE_SHIFT) - base; heap_start = (unsigned long) &_heap_start; memblock_add(base, size); /* * Partially used pages are not usable - thus * we are rounding upwards: */ start_pfn = PFN_UP(__pa(heap_start)); /* * Reserve the kernel text. */ memblock_reserve(base, (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - base); #ifdef CONFIG_HIGHMEM /* * Add & reserve highmem, so page structures are initialised. */ base = highstart_pfn << PAGE_SHIFT; size = (highend_pfn << PAGE_SHIFT) - base; if (size) { memblock_add(base, size); memblock_reserve(base, size); } #endif }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan121100.00%1100.00%
Total121100.00%1100.00%

#ifdef CONFIG_HIGHMEM /* * Ensure we have allocated page tables in swapper_pg_dir for the * fixed mappings range from 'start' to 'end'. */
static void __init allocate_pgtables(unsigned long start, unsigned long end) { pgd_t *pgd; pmd_t *pmd; pte_t *pte; int i, j; unsigned long vaddr; vaddr = start; i = pgd_index(vaddr); j = pmd_index(vaddr); pgd = swapper_pg_dir + i; for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { pmd = (pmd_t *)pgd; for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { vaddr += PMD_SIZE; if (!pmd_none(*pmd)) continue; pte = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); pmd_populate_kernel(&init_mm, pmd, pte); } j = 0; } }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan153100.00%1100.00%
Total153100.00%1100.00%


static void __init fixedrange_init(void) { unsigned long vaddr, end; pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; /* * Fixed mappings: */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK; allocate_pgtables(vaddr, end); /* * Permanent kmaps: */ vaddr = PKMAP_BASE; allocate_pgtables(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP); pgd = swapper_pg_dir + pgd_index(vaddr); pud = pud_offset(pgd, vaddr); pmd = pmd_offset(pud, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan118100.00%1100.00%
Total118100.00%1100.00%

#endif /* CONFIG_HIGHMEM */ /* * paging_init() continues the virtual memory environment setup which * was begun by the code in arch/metag/kernel/setup.c. */
void __init paging_init(unsigned long mem_end) { unsigned long max_zone_pfns[MAX_NR_ZONES]; int nid; init_and_reserve_mem(); memblock_allow_resize(); memblock_dump_all(); nodes_clear(node_online_map); init_new_context(&init_task, &init_mm); memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); do_init_bootmem(); mmu_init(mem_end); #ifdef CONFIG_HIGHMEM fixedrange_init(); kmap_init(); #endif /* Initialize the zero page to a bootmem page, already zeroed. */ empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); user_gateway_init(); memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); for_each_online_node(nid) { pg_data_t *pgdat = NODE_DATA(nid); unsigned long low, start_pfn; start_pfn = pgdat->bdata->node_min_pfn; low = pgdat->bdata->node_low_pfn; if (max_zone_pfns[ZONE_NORMAL] < low) max_zone_pfns[ZONE_NORMAL] = low; #ifdef CONFIG_HIGHMEM max_zone_pfns[ZONE_HIGHMEM] = highend_pfn; #endif pr_info("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", nid, start_pfn, low); } free_area_init_nodes(max_zone_pfns); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan182100.00%1100.00%
Total182100.00%1100.00%


void __init mem_init(void) { #ifdef CONFIG_HIGHMEM unsigned long tmp; /* * Explicitly reset zone->managed_pages because highmem pages are * freed before calling free_all_bootmem(); */ reset_all_zones_managed_pages(); for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) free_highmem_page(pfn_to_page(tmp)); #endif /* CONFIG_HIGHMEM */ free_all_bootmem(); mem_init_print_info(NULL); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan4180.39%120.00%
Jiang Liu1019.61%480.00%
Total51100.00%5100.00%


void free_initmem(void) { free_initmem_default(POISON_FREE_INITMEM); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan1083.33%150.00%
Jiang Liu216.67%150.00%
Total12100.00%2100.00%

#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end) { free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM, "initrd"); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan1959.38%133.33%
Jiang Liu1340.62%266.67%
Total32100.00%3100.00%

#endif

Overall Contributors

PersonTokensPropCommitsCommitProp
James Hogan144297.50%216.67%
Jiang Liu251.69%650.00%
Tang Chen50.34%18.33%
Xishi Qiu30.20%18.33%
Ingo Molnar30.20%18.33%
Greg Kroah-Hartman10.07%18.33%
Total1479100.00%12100.00%
Directory: arch/metag/mm
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.