LCOV - code coverage report
Current view: top level - arch/um/kernel - mem.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 51 64 79.7 %
Date: 2022-12-09 01:23:36 Functions: 6 8 75.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       4             :  */
       5             : 
       6             : #include <linux/stddef.h>
       7             : #include <linux/module.h>
       8             : #include <linux/memblock.h>
       9             : #include <linux/highmem.h>
      10             : #include <linux/mm.h>
      11             : #include <linux/swap.h>
      12             : #include <linux/slab.h>
      13             : #include <asm/fixmap.h>
      14             : #include <asm/page.h>
      15             : #include <as-layout.h>
      16             : #include <init.h>
      17             : #include <kern.h>
      18             : #include <kern_util.h>
      19             : #include <mem_user.h>
      20             : #include <os.h>
      21             : 
      22             : /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
      23             : unsigned long *empty_zero_page = NULL;
      24             : EXPORT_SYMBOL(empty_zero_page);
      25             : 
      26             : /*
      27             :  * Initialized during boot, and readonly for initializing page tables
      28             :  * afterwards
      29             :  */
      30             : pgd_t swapper_pg_dir[PTRS_PER_PGD];
      31             : 
      32             : /* Initialized at boot time, and readonly after that */
      33             : unsigned long long highmem;
      34             : EXPORT_SYMBOL(highmem);
      35             : int kmalloc_ok = 0;
      36             : 
      37             : /* Used during early boot */
      38             : static unsigned long brk_end;
      39             : 
      40           1 : void __init mem_init(void)
      41             : {
      42             :         /* clear the zero-page */
      43           1 :         memset(empty_zero_page, 0, PAGE_SIZE);
      44             : 
      45             :         /* Map in the area just after the brk now that kmalloc is about
      46             :          * to be turned on.
      47             :          */
      48           1 :         brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
      49           2 :         map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
      50           1 :         memblock_free((void *)brk_end, uml_reserved - brk_end);
      51           1 :         uml_reserved = brk_end;
      52             : 
      53             :         /* this will put all low memory onto the freelists */
      54           1 :         memblock_free_all();
      55           1 :         max_low_pfn = totalram_pages();
      56           1 :         max_pfn = max_low_pfn;
      57           1 :         kmalloc_ok = 1;
      58           1 : }
      59             : 
      60             : /*
      61             :  * Create a page table and place a pointer to it in a middle page
      62             :  * directory entry.
      63             :  */
      64           1 : static void __init one_page_table_init(pmd_t *pmd)
      65             : {
      66           1 :         if (pmd_none(*pmd)) {
      67           1 :                 pte_t *pte = (pte_t *) memblock_alloc_low(PAGE_SIZE,
      68             :                                                           PAGE_SIZE);
      69           1 :                 if (!pte)
      70           0 :                         panic("%s: Failed to allocate %lu bytes align=%lx\n",
      71             :                               __func__, PAGE_SIZE, PAGE_SIZE);
      72             : 
      73           2 :                 set_pmd(pmd, __pmd(_KERNPG_TABLE +
      74             :                                            (unsigned long) __pa(pte)));
      75           1 :                 BUG_ON(pte != pte_offset_kernel(pmd, 0));
      76             :         }
      77           1 : }
      78             : 
      79           1 : static void __init one_md_table_init(pud_t *pud)
      80             : {
      81             : #ifdef CONFIG_3_LEVEL_PGTABLES
      82           1 :         pmd_t *pmd_table = (pmd_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
      83           1 :         if (!pmd_table)
      84           0 :                 panic("%s: Failed to allocate %lu bytes align=%lx\n",
      85             :                       __func__, PAGE_SIZE, PAGE_SIZE);
      86             : 
      87           2 :         set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
      88           1 :         BUG_ON(pmd_table != pmd_offset(pud, 0));
      89             : #endif
      90           1 : }
      91             : 
      92           1 : static void __init fixrange_init(unsigned long start, unsigned long end,
      93             :                                  pgd_t *pgd_base)
      94             : {
      95             :         pgd_t *pgd;
      96             :         p4d_t *p4d;
      97             :         pud_t *pud;
      98             :         pmd_t *pmd;
      99             :         int i, j;
     100             :         unsigned long vaddr;
     101             : 
     102           1 :         vaddr = start;
     103           1 :         i = pgd_index(vaddr);
     104           1 :         j = pmd_index(vaddr);
     105           1 :         pgd = pgd_base + i;
     106             : 
     107           2 :         for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
     108           1 :                 p4d = p4d_offset(pgd, vaddr);
     109           1 :                 pud = pud_offset(p4d, vaddr);
     110           1 :                 if (pud_none(*pud))
     111           1 :                         one_md_table_init(pud);
     112           1 :                 pmd = pmd_offset(pud, vaddr);
     113           2 :                 for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
     114           1 :                         one_page_table_init(pmd);
     115           1 :                         vaddr += PMD_SIZE;
     116             :                 }
     117           1 :                 j = 0;
     118             :         }
     119           1 : }
     120             : 
     121             : static void __init fixaddr_user_init( void)
     122             : {
     123             : #ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA
     124             :         long size = FIXADDR_USER_END - FIXADDR_USER_START;
     125             :         pte_t *pte;
     126             :         phys_t p;
     127             :         unsigned long v, vaddr = FIXADDR_USER_START;
     128             : 
     129             :         if (!size)
     130             :                 return;
     131             : 
     132             :         fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
     133             :         v = (unsigned long) memblock_alloc_low(size, PAGE_SIZE);
     134             :         if (!v)
     135             :                 panic("%s: Failed to allocate %lu bytes align=%lx\n",
     136             :                       __func__, size, PAGE_SIZE);
     137             : 
     138             :         memcpy((void *) v , (void *) FIXADDR_USER_START, size);
     139             :         p = __pa(v);
     140             :         for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
     141             :                       p += PAGE_SIZE) {
     142             :                 pte = virt_to_kpte(vaddr);
     143             :                 pte_set_val(*pte, p, PAGE_READONLY);
     144             :         }
     145             : #endif
     146             : }
     147             : 
     148           1 : void __init paging_init(void)
     149             : {
     150           1 :         unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
     151             :         unsigned long vaddr;
     152             : 
     153           1 :         empty_zero_page = (unsigned long *) memblock_alloc_low(PAGE_SIZE,
     154             :                                                                PAGE_SIZE);
     155           1 :         if (!empty_zero_page)
     156           0 :                 panic("%s: Failed to allocate %lu bytes align=%lx\n",
     157             :                       __func__, PAGE_SIZE, PAGE_SIZE);
     158             : 
     159           1 :         max_zone_pfn[ZONE_NORMAL] = end_iomem >> PAGE_SHIFT;
     160           1 :         free_area_init(max_zone_pfn);
     161             : 
     162             :         /*
     163             :          * Fixed mappings, only the page table structure has to be
     164             :          * created - mappings will be set by set_fixmap():
     165             :          */
     166           1 :         vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
     167           1 :         fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir);
     168             : 
     169             :         fixaddr_user_init();
     170           1 : }
     171             : 
     172             : /*
     173             :  * This can't do anything because nothing in the kernel image can be freed
     174             :  * since it's not in kernel physical memory.
     175             :  */
     176             : 
     177           0 : void free_initmem(void)
     178             : {
     179           0 : }
     180             : 
     181             : /* Allocate and free page tables. */
     182             : 
     183           0 : pgd_t *pgd_alloc(struct mm_struct *mm)
     184             : {
     185           0 :         pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
     186             : 
     187           0 :         if (pgd) {
     188           0 :                 memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
     189           0 :                 memcpy(pgd + USER_PTRS_PER_PGD,
     190           0 :                        swapper_pg_dir + USER_PTRS_PER_PGD,
     191           0 :                        (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
     192             :         }
     193           0 :         return pgd;
     194             : }
     195             : 
     196           4 : void *uml_kmalloc(int size, int flags)
     197             : {
     198           8 :         return kmalloc(size, flags);
     199             : }

Generated by: LCOV version 1.14