Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/x86/mm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  ident_map.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Helper routines for building identity mapping page tables. This is
 * included by both the compressed kernel and the regular kernel.
 */


static void free_pte(struct x86_mapping_info *info, pmd_t *pmd)
{
 pte_t *pte = pte_offset_kernel(pmd, 0);

 info->free_pgt_page(pte, info->context);
}

static void free_pmd(struct x86_mapping_info *info, pud_t *pud)
{
 pmd_t *pmd = pmd_offset(pud, 0);
 int i;

 for (i = 0; i < PTRS_PER_PMD; i++) {
  if (!pmd_present(pmd[i]))
   continue;

  if (pmd_leaf(pmd[i]))
   continue;

  free_pte(info, &pmd[i]);
 }

 info->free_pgt_page(pmd, info->context);
}

static void free_pud(struct x86_mapping_info *info, p4d_t *p4d)
{
 pud_t *pud = pud_offset(p4d, 0);
 int i;

 for (i = 0; i < PTRS_PER_PUD; i++) {
  if (!pud_present(pud[i]))
   continue;

  if (pud_leaf(pud[i]))
   continue;

  free_pmd(info, &pud[i]);
 }

 info->free_pgt_page(pud, info->context);
}

static void free_p4d(struct x86_mapping_info *info, pgd_t *pgd)
{
 p4d_t *p4d = p4d_offset(pgd, 0);
 int i;

 for (i = 0; i < PTRS_PER_P4D; i++) {
  if (!p4d_present(p4d[i]))
   continue;

  free_pud(info, &p4d[i]);
 }

 if (pgtable_l5_enabled())
  info->free_pgt_page(p4d, info->context);
}

void kernel_ident_mapping_free(struct x86_mapping_info *info, pgd_t *pgd)
{
 int i;

 for (i = 0; i < PTRS_PER_PGD; i++) {
  if (!pgd_present(pgd[i]))
   continue;

  free_p4d(info, &pgd[i]);
 }

 info->free_pgt_page(pgd, info->context);
}

static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
      unsigned long addr, unsigned long end)
{
 addr &= PMD_MASK;
 for (; addr < end; addr += PMD_SIZE) {
  pmd_t *pmd = pmd_page + pmd_index(addr);

  if (pmd_present(*pmd))
   continue;

  set_pmd(pmd, __pmd((addr - info->offset) | info->page_flag));
 }
}

static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
     unsigned long addr, unsigned long end)
{
 unsigned long next;

 for (; addr < end; addr = next) {
  pud_t *pud = pud_page + pud_index(addr);
  pmd_t *pmd;
  bool use_gbpage;

  next = pud_addr_end(addr, end);

  /* if this is already a gbpage, this portion is already mapped */
  if (pud_leaf(*pud))
   continue;

  /* Is using a gbpage allowed? */
  use_gbpage = info->direct_gbpages;

  /* Don't use gbpage if it maps more than the requested region. */
  /* at the begining: */
  use_gbpage &= ((addr & ~PUD_MASK) == 0);
  /* ... or at the end: */
  use_gbpage &= ((next & ~PUD_MASK) == 0);

  /* Never overwrite existing mappings */
  use_gbpage &= !pud_present(*pud);

  if (use_gbpage) {
   pud_t pudval;

   pudval = __pud((addr - info->offset) | info->page_flag);
   set_pud(pud, pudval);
   continue;
  }

  if (pud_present(*pud)) {
   pmd = pmd_offset(pud, 0);
   ident_pmd_init(info, pmd, addr, next);
   continue;
  }
  pmd = (pmd_t *)info->alloc_pgt_page(info->context);
  if (!pmd)
   return -ENOMEM;
  ident_pmd_init(info, pmd, addr, next);
  set_pud(pud, __pud(__pa(pmd) | info->kernpg_flag));
 }

 return 0;
}

static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
     unsigned long addr, unsigned long end)
{
 unsigned long next;
 int result;

 for (; addr < end; addr = next) {
  p4d_t *p4d = p4d_page + p4d_index(addr);
  pud_t *pud;

  next = p4d_addr_end(addr, end);
  if (p4d_present(*p4d)) {
   pud = pud_offset(p4d, 0);
   result = ident_pud_init(info, pud, addr, next);
   if (result)
    return result;

   continue;
  }
  pud = (pud_t *)info->alloc_pgt_page(info->context);
  if (!pud)
   return -ENOMEM;

  result = ident_pud_init(info, pud, addr, next);
  if (result)
   return result;

  set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag | _PAGE_NOPTISHADOW));
 }

 return 0;
}

int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
         unsigned long pstart, unsigned long pend)
{
 unsigned long addr = pstart + info->offset;
 unsigned long end = pend + info->offset;
 unsigned long next;
 int result;

 /* Set the default pagetable flags if not supplied */
 if (!info->kernpg_flag)
  info->kernpg_flag = _KERNPG_TABLE;

 /* Filter out unsupported __PAGE_KERNEL_* bits: */
 info->kernpg_flag &= __default_kernel_pte_mask;

 for (; addr < end; addr = next) {
  pgd_t *pgd = pgd_page + pgd_index(addr);
  p4d_t *p4d;

  next = pgd_addr_end(addr, end);
  if (pgd_present(*pgd)) {
   p4d = p4d_offset(pgd, 0);
   result = ident_p4d_init(info, p4d, addr, next);
   if (result)
    return result;
   continue;
  }

  p4d = (p4d_t *)info->alloc_pgt_page(info->context);
  if (!p4d)
   return -ENOMEM;
  result = ident_p4d_init(info, p4d, addr, next);
  if (result)
   return result;
  if (pgtable_l5_enabled()) {
   set_pgd(pgd, __pgd(__pa(p4d) | info->kernpg_flag | _PAGE_NOPTISHADOW));
  } else {
   /*
 * With p4d folded, pgd is equal to p4d.
 * The pgd entry has to point to the pud page table in this case.
 */

   pud_t *pud = pud_offset(p4d, 0);
   set_pgd(pgd, __pgd(__pa(pud) | info->kernpg_flag | _PAGE_NOPTISHADOW));
  }
 }

 return 0;
}

Messung V0.5
C=96 H=86 G=90

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.