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

Quelle  pmsa-v8.c   Sprache: C

 
/*
 * Based on linux/arch/arm/pmsa-v7.c
 *
 * ARM PMSAv8 supporting functions.
 */


#include <linux/memblock.h>
#include <linux/range.h>

#include <asm/cp15.h>
#include <asm/cputype.h>
#include <asm/mpu.h>

#include <asm/page.h>
#include <asm/sections.h>

#include "mm.h"

#ifndef CONFIG_CPU_V7M

#define PRSEL __ACCESS_CP15(c6, 0, c2, 1)
#define PRBAR __ACCESS_CP15(c6, 0, c3, 0)
#define PRLAR __ACCESS_CP15(c6, 0, c3, 1)

static inline u32 prlar_read(void)
{
 return read_sysreg(PRLAR);
}

static inline u32 prbar_read(void)
{
 return read_sysreg(PRBAR);
}

static inline void prsel_write(u32 v)
{
 write_sysreg(v, PRSEL);
}

static inline void prbar_write(u32 v)
{
 write_sysreg(v, PRBAR);
}

static inline void prlar_write(u32 v)
{
 write_sysreg(v, PRLAR);
}
#else

static inline u32 prlar_read(void)
{
 return readl_relaxed(BASEADDR_V7M_SCB + PMSAv8_RLAR);
}

static inline u32 prbar_read(void)
{
 return readl_relaxed(BASEADDR_V7M_SCB + PMSAv8_RBAR);
}

static inline void prsel_write(u32 v)
{
 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RNR);
}

static inline void prbar_write(u32 v)
{
 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RBAR);
}

static inline void prlar_write(u32 v)
{
 writel_relaxed(v, BASEADDR_V7M_SCB + PMSAv8_RLAR);
}

#endif

static struct range __initdata io[MPU_MAX_REGIONS];
static struct range __initdata mem[MPU_MAX_REGIONS];

static unsigned int __initdata mpu_max_regions;

static __init bool is_region_fixed(int number)
{
 switch (number) {
 case PMSAv8_XIP_REGION:
 case PMSAv8_KERNEL_REGION:
  return true;
 default:
  return false;
 }
}

void __init pmsav8_adjust_lowmem_bounds(void)
{
 phys_addr_t mem_end;
 phys_addr_t reg_start, reg_end;
 bool first = true;
 u64 i;

 for_each_mem_range(i, ®_start, ®_end) {
  if (first) {
   phys_addr_t phys_offset = PHYS_OFFSET;

   /*
 * Initially only use memory continuous from
 * PHYS_OFFSET */

   if (reg_start != phys_offset)
    panic("First memory bank must be contiguous from PHYS_OFFSET");
   mem_end = reg_end;
   first = false;
  } else {
   /*
 * memblock auto merges contiguous blocks, remove
 * all blocks afterwards in one go (we can't remove
 * blocks separately while iterating)
 */

   pr_notice("Ignoring RAM after %pa, memory at %pa ignored\n",
      &mem_end, ®_start);
   memblock_remove(reg_start, 0 - reg_start);
   break;
  }
 }
}

static int __init __mpu_max_regions(void)
{
 static int max_regions;
 u32 mpuir;

 if (max_regions)
  return max_regions;

 mpuir = read_cpuid_mputype();

 max_regions  = (mpuir & MPUIR_DREGION_SZMASK) >> MPUIR_DREGION;

 return max_regions;
}

static int __init __pmsav8_setup_region(unsigned int number, u32 bar, u32 lar)
{
 if (number > mpu_max_regions
     || number >= MPU_MAX_REGIONS)
  return -ENOENT;

 dsb();
 prsel_write(number);
 isb();
 prbar_write(bar);
 prlar_write(lar);

 mpu_rgn_info.rgns[number].prbar = bar;
 mpu_rgn_info.rgns[number].prlar = lar;

 mpu_rgn_info.used++;

 return 0;
}

static int __init pmsav8_setup_ram(unsigned int number, phys_addr_t start,phys_addr_t end)
{
 u32 bar, lar;

 if (is_region_fixed(number))
  return -EINVAL;

 bar = start;
 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);

 bar |= PMSAv8_AP_PL1RW_PL0RW | PMSAv8_RGN_SHARED;
 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;

 return __pmsav8_setup_region(number, bar, lar);
}

static int __init pmsav8_setup_io(unsigned int number, phys_addr_t start,phys_addr_t end)
{
 u32 bar, lar;

 if (is_region_fixed(number))
  return -EINVAL;

 bar = start;
 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);

 bar |= PMSAv8_AP_PL1RW_PL0RW | PMSAv8_RGN_SHARED | PMSAv8_BAR_XN;
 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_DEVICE_nGnRnE) | PMSAv8_LAR_EN;

 return __pmsav8_setup_region(number, bar, lar);
}

static int __init pmsav8_setup_fixed(unsigned int number, phys_addr_t start,phys_addr_t end)
{
 u32 bar, lar;

 if (!is_region_fixed(number))
  return -EINVAL;

 bar = start;
 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);

 bar |= PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED;
 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;

 prsel_write(number);
 isb();

 if (prbar_read() != bar || prlar_read() != lar)
  return -EINVAL;

 /* Reserved region was set up early, we just need a record for secondaries */
 mpu_rgn_info.rgns[number].prbar = bar;
 mpu_rgn_info.rgns[number].prlar = lar;

 mpu_rgn_info.used++;

 return 0;
}

#ifndef CONFIG_CPU_V7M
static int __init pmsav8_setup_vector(unsigned int number, phys_addr_t start,phys_addr_t end)
{
 u32 bar, lar;

 if (number == PMSAv8_KERNEL_REGION)
  return -EINVAL;

 bar = start;
 lar = (end - 1) & ~(PMSAv8_MINALIGN - 1);

 bar |= PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED;
 lar |= PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN;

 return __pmsav8_setup_region(number, bar, lar);
}
#endif

void __init pmsav8_setup(void)
{
 int i, err = 0;
 int region = PMSAv8_KERNEL_REGION;

 /* How many regions are supported ? */
 mpu_max_regions = __mpu_max_regions();

 /* RAM: single chunk of memory */
 add_range(mem,  ARRAY_SIZE(mem), 0,  memblock.memory.regions[0].base,
    memblock.memory.regions[0].base + memblock.memory.regions[0].size);

 /* IO: cover full 4G range */
 add_range(io, ARRAY_SIZE(io), 0, 0, 0xffffffff);

 /* RAM and IO: exclude kernel */
 subtract_range(mem, ARRAY_SIZE(mem), __pa(KERNEL_START), __pa(KERNEL_END));
 subtract_range(io, ARRAY_SIZE(io),  __pa(KERNEL_START), __pa(KERNEL_END));

#ifdef CONFIG_XIP_KERNEL
 /* RAM and IO: exclude xip */
 subtract_range(mem, ARRAY_SIZE(mem), CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
 subtract_range(io, ARRAY_SIZE(io), CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
#endif

#ifndef CONFIG_CPU_V7M
 /* RAM and IO: exclude vectors */
 subtract_range(mem, ARRAY_SIZE(mem),  vectors_base, vectors_base + 2 * PAGE_SIZE);
 subtract_range(io, ARRAY_SIZE(io),  vectors_base, vectors_base + 2 * PAGE_SIZE);
#endif
 /* IO: exclude RAM */
 for (i = 0; i < ARRAY_SIZE(mem); i++)
  subtract_range(io, ARRAY_SIZE(io), mem[i].start, mem[i].end);

 /* Now program MPU */

#ifdef CONFIG_XIP_KERNEL
 /* ROM */
 err |= pmsav8_setup_fixed(PMSAv8_XIP_REGION, CONFIG_XIP_PHYS_ADDR, __pa(_exiprom));
#endif
 /* Kernel */
 err |= pmsav8_setup_fixed(region++, __pa(KERNEL_START), __pa(KERNEL_END));


 /* IO */
 for (i = 0; i < ARRAY_SIZE(io); i++) {
  if (!io[i].end)
   continue;

  err |= pmsav8_setup_io(region++, io[i].start, io[i].end);
 }

 /* RAM */
 for (i = 0; i < ARRAY_SIZE(mem); i++) {
  if (!mem[i].end)
   continue;

  err |= pmsav8_setup_ram(region++, mem[i].start, mem[i].end);
 }

 /* Vectors */
#ifndef CONFIG_CPU_V7M
 err |= pmsav8_setup_vector(region++, vectors_base, vectors_base + 2 * PAGE_SIZE);
#endif
 if (err)
  pr_warn("MPU region initialization failure! %d", err);
 else
  pr_info("Using ARM PMSAv8 Compliant MPU. Used %d of %d regions\n",
   mpu_rgn_info.used, mpu_max_regions);
}

Messung V0.5
C=95 H=88 G=91

¤ Dauer der Verarbeitung: 0.12 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.