arch/arm/mm/kasan_init.c

Source file repositories/reference/linux-study-clean/arch/arm/mm/kasan_init.c

File Facts

System
Linux kernel
Corpus path
arch/arm/mm/kasan_init.c
Extension
.c
Size
8779 bytes
Lines
306
Domain
Architecture Layer
Bucket
arch/arm
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/start_kernel.h>
#include <linux/pgtable.h>
#include <asm/cputype.h>
#include <asm/highmem.h>
#include <asm/mach/map.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/procinfo.h>
#include <asm/proc-fns.h>

#include "mm.h"

static pgd_t tmp_pgd_table[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);

pmd_t tmp_pmd_table[PTRS_PER_PMD] __page_aligned_bss;

static __init void *kasan_alloc_block_raw(size_t size)
{
	return memblock_alloc_try_nid_raw(size, size, __pa(MAX_DMA_ADDRESS),
				      MEMBLOCK_ALLOC_NOLEAKTRACE, NUMA_NO_NODE);
}

static __init void *kasan_alloc_block(size_t size)
{
	return memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
				      MEMBLOCK_ALLOC_NOLEAKTRACE, NUMA_NO_NODE);
}

static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
				      unsigned long end, bool early)
{
	unsigned long next;
	pte_t *ptep = pte_offset_kernel(pmdp, addr);

	do {
		pte_t entry;
		void *p;

		next = addr + PAGE_SIZE;

		if (!early) {
			if (!pte_none(READ_ONCE(*ptep)))
				continue;

			p = kasan_alloc_block_raw(PAGE_SIZE);
			if (!p) {
				panic("%s failed to allocate shadow page for address 0x%lx\n",
				      __func__, addr);
				return;
			}
			memset(p, KASAN_SHADOW_INIT, PAGE_SIZE);
			entry = pfn_pte(virt_to_pfn(p),
					__pgprot(pgprot_val(PAGE_KERNEL)));
		} else if (pte_none(READ_ONCE(*ptep))) {
			/*
			 * The early shadow memory is mapping all KASan
			 * operations to one and the same page in memory,
			 * "kasan_early_shadow_page" so that the instrumentation
			 * will work on a scratch area until we can set up the
			 * proper KASan shadow memory.
			 */
			entry = pfn_pte(virt_to_pfn(kasan_early_shadow_page),
					__pgprot(_L_PTE_DEFAULT | L_PTE_DIRTY | L_PTE_XN));
		} else {
			/*
			 * Early shadow mappings are PMD_SIZE aligned, so if the
			 * first entry is already set, they must all be set.
			 */
			return;
		}

		set_pte_at(&init_mm, addr, ptep, entry);
	} while (ptep++, addr = next, addr != end);
}

/*
 * The pmd (page middle directory) is only used on LPAE
 */
static void __init kasan_pmd_populate(pud_t *pudp, unsigned long addr,
				      unsigned long end, bool early)
{
	unsigned long next;
	pmd_t *pmdp = pmd_offset(pudp, addr);

	do {
		if (pmd_none(*pmdp)) {
			/*
			 * We attempt to allocate a shadow block for the PMDs
			 * used by the PTEs for this address if it isn't already
			 * allocated.

Annotation

Implementation Notes