cregit-Linux how code gets into the kernel

Release 4.13 arch/arm64/mm/hugetlbpage.c

Directory: arch/arm64/mm
/*
 * arch/arm64/mm/hugetlbpage.c
 *
 * Copyright (C) 2013 Linaro Ltd.
 *
 * Based on arch/x86/mm/hugetlbpage.c.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/err.h>
#include <linux/sysctl.h>
#include <asm/mman.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>


int pmd_huge(pmd_t pmd) { return pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT); }

Contributors

PersonTokensPropCommitsCommitProp
Steve Capper1979.17%150.00%
Christoffer Dall520.83%150.00%
Total24100.00%2100.00%


int pud_huge(pud_t pud) { #ifndef __PAGETABLE_PMD_FOLDED return pud_val(pud) && !(pud_val(pud) & PUD_TABLE_BIT); #else return 0; #endif }

Contributors

PersonTokensPropCommitsCommitProp
Steve Capper1955.88%133.33%
Mark Salter1029.41%133.33%
Christoffer Dall514.71%133.33%
Total34100.00%3100.00%


static int find_num_contig(struct mm_struct *mm, unsigned long addr, pte_t *ptep, size_t *pgsize) { pgd_t *pgd = pgd_offset(mm, addr); pud_t *pud; pmd_t *pmd; *pgsize = PAGE_SIZE; pud = pud_offset(pgd, addr); pmd = pmd_offset(pud, addr); if ((pte_t *)pmd == ptep) { *pgsize = PMD_SIZE; return CONT_PMDS; } return CONT_PTES; }

Contributors

PersonTokensPropCommitsCommitProp
David Woods88100.00%1100.00%
Total88100.00%1100.00%


void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { size_t pgsize; int i; int ncontig; unsigned long pfn; pgprot_t hugeprot; if (!pte_cont(pte)) { set_pte_at(mm, addr, ptep, pte); return; } ncontig = find_num_contig(mm, addr, ptep, &pgsize); pfn = pte_pfn(pte); hugeprot = __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte)); for (i = 0; i < ncontig; i++) { pr_debug("%s: set pte %p to 0x%llx\n", __func__, ptep, pte_val(pfn_pte(pfn, hugeprot))); set_pte_at(mm, addr, ptep, pfn_pte(pfn, hugeprot)); ptep++; pfn += pgsize >> PAGE_SHIFT; addr += pgsize; } }

Contributors

PersonTokensPropCommitsCommitProp
David Woods14788.55%150.00%
Steve Capper1911.45%150.00%
Total166100.00%2100.00%


pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) { pgd_t *pgd; pud_t *pud; pte_t *pte = NULL; pr_debug("%s: addr:0x%lx sz:0x%lx\n", __func__, addr, sz); pgd = pgd_offset(mm, addr); pud = pud_alloc(mm, pgd, addr); if (!pud) return NULL; if (sz == PUD_SIZE) { pte = (pte_t *)pud; } else if (sz == (PAGE_SIZE * CONT_PTES)) { pmd_t *pmd = pmd_alloc(mm, pud, addr); WARN_ON(addr & (sz - 1)); /* * Note that if this code were ever ported to the * 32-bit arm platform then it will cause trouble in * the case where CONFIG_HIGHPTE is set, since there * will be no pte_unmap() to correspond with this * pte_alloc_map(). */ pte = pte_alloc_map(mm, pmd, addr); } else if (sz == PMD_SIZE) { if (IS_ENABLED(CONFIG_ARCH_WANT_HUGE_PMD_SHARE) && pud_none(*pud)) pte = huge_pmd_share(mm, addr, pud); else pte = (pte_t *)pmd_alloc(mm, pud, addr); } else if (sz == (PMD_SIZE * CONT_PMDS)) { pmd_t *pmd; pmd = pmd_alloc(mm, pud, addr); WARN_ON(addr & (sz - 1)); return (pte_t *)pmd; } pr_debug("%s: addr:0x%lx sz:0x%lx ret pte=%p/0x%llx\n", __func__, addr, sz, pte, pte_val(*pte)); return pte; }

Contributors

PersonTokensPropCommitsCommitProp
David Woods254100.00%1100.00%
Total254100.00%1100.00%


pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, unsigned long sz) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pgd = pgd_offset(mm, addr); pr_debug("%s: addr:0x%lx pgd:%p\n", __func__, addr, pgd); if (!pgd_present(*pgd)) return NULL; pud = pud_offset(pgd, addr); if (pud_none(*pud)) return NULL; /* swap or huge page */ if (!pud_present(*pud) || pud_huge(*pud)) return (pte_t *)pud; /* table; check the next level */ pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) return NULL; if (!pmd_present(*pmd) || pmd_huge(*pmd)) return (pte_t *)pmd; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
David Woods13488.16%133.33%
Punit Agrawal1811.84%266.67%
Total152100.00%3100.00%


pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma, struct page *page, int writable) { size_t pagesize = huge_page_size(hstate_vma(vma)); if (pagesize == CONT_PTE_SIZE) { entry = pte_mkcont(entry); } else if (pagesize == CONT_PMD_SIZE) { entry = pmd_pte(pmd_mkcont(pte_pmd(entry))); } else if (pagesize != PUD_SIZE && pagesize != PMD_SIZE) { pr_warn("%s: unrecognized huge page size 0x%lx\n", __func__, pagesize); } return entry; }

Contributors

PersonTokensPropCommitsCommitProp
David Woods94100.00%1100.00%
Total94100.00%1100.00%


pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t pte; if (pte_cont(*ptep)) { int ncontig, i; size_t pgsize; bool is_dirty = false; ncontig = find_num_contig(mm, addr, ptep, &pgsize); /* save the 1st pte to return */ pte = ptep_get_and_clear(mm, addr, ptep); for (i = 1, addr += pgsize; i < ncontig; ++i, addr += pgsize) { /* * If HW_AFDBM is enabled, then the HW could * turn on the dirty bit for any of the page * in the set, so check them all. */ ++ptep; if (pte_dirty(ptep_get_and_clear(mm, addr, ptep))) is_dirty = true; } if (is_dirty) return pte_mkdirty(pte); else return pte; } else { return ptep_get_and_clear(mm, addr, ptep); } }

Contributors

PersonTokensPropCommitsCommitProp
David Woods13091.55%133.33%
Huang Shijie85.63%133.33%
Steve Capper42.82%133.33%
Total142100.00%3100.00%


int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty) { if (pte_cont(pte)) { int ncontig, i, changed = 0; size_t pgsize = 0; unsigned long pfn = pte_pfn(pte); /* Select all bits except the pfn */ pgprot_t hugeprot = __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte)); pfn = pte_pfn(pte); ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize); for (i = 0; i < ncontig; ++i, ++ptep, addr += pgsize) { changed |= ptep_set_access_flags(vma, addr, ptep, pfn_pte(pfn, hugeprot), dirty); pfn += pgsize >> PAGE_SHIFT; } return changed; } else { return ptep_set_access_flags(vma, addr, ptep, pte, dirty); } }

Contributors

PersonTokensPropCommitsCommitProp
David Woods16394.77%125.00%
Huang Shijie52.91%250.00%
Steve Capper42.33%125.00%
Total172100.00%4100.00%


void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { if (pte_cont(*ptep)) { int ncontig, i; size_t pgsize = 0; ncontig = find_num_contig(mm, addr, ptep, &pgsize); for (i = 0; i < ncontig; ++i, ++ptep, addr += pgsize) ptep_set_wrprotect(mm, addr, ptep); } else { ptep_set_wrprotect(mm, addr, ptep); } }

Contributors

PersonTokensPropCommitsCommitProp
David Woods8692.47%133.33%
Huang Shijie44.30%133.33%
Steve Capper33.23%133.33%
Total93100.00%3100.00%


void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { if (pte_cont(*ptep)) { int ncontig, i; size_t pgsize = 0; ncontig = find_num_contig(vma->vm_mm, addr, ptep, &pgsize); for (i = 0; i < ncontig; ++i, ++ptep, addr += pgsize) ptep_clear_flush(vma, addr, ptep); } else { ptep_clear_flush(vma, addr, ptep); } }

Contributors

PersonTokensPropCommitsCommitProp
David Woods8892.63%133.33%
Huang Shijie44.21%133.33%
Steve Capper33.16%133.33%
Total95100.00%3100.00%


static __init int setup_hugepagesz(char *opt) { unsigned long ps = memparse(opt, &opt); if (ps == PMD_SIZE) { hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT); } else if (ps == PUD_SIZE) { hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT); } else { hugetlb_bad_size(); pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10); return 0; } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Steve Capper7093.33%133.33%
Vaishali Thakkar34.00%133.33%
David Woods22.67%133.33%
Total75100.00%3100.00%

__setup("hugepagesz=", setup_hugepagesz);

Overall Contributors

PersonTokensPropCommitsCommitProp
David Woods118682.94%18.33%
Steve Capper18112.66%325.00%
Huang Shijie211.47%216.67%
Punit Agrawal181.26%216.67%
Christoffer Dall100.70%18.33%
Mark Salter100.70%18.33%
Vaishali Thakkar30.21%18.33%
JiSheng Zhang10.07%18.33%
Total1430100.00%12100.00%
Directory: arch/arm64/mm
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.