
This patch ports the feature Kernel Address SANitizer (KASAN). Note: The start address of shadow memory is at the beginning of kernel space, which is 2^64 - (2^39 / 2) in SV39. The size of the kernel space is 2^38 bytes so the size of shadow memory should be 2^38 / 8. Thus, the shadow memory would not overlap with the fixmap area. There are currently two limitations in this port, 1. RV64 only: KASAN need large address space for extra shadow memory region. 2. KASAN can't debug the modules since the modules are allocated in VMALLOC area. We mapped the shadow memory, which corresponding to VMALLOC area, to the kasan_early_shadow_page because we don't have enough physical space for all the shadow memory corresponding to VMALLOC area. Signed-off-by: Nick Hu <nickhu@andestech.com> Reported-by: Greentime Hu <green.hu@gmail.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
87 lines
1.9 KiB
C
87 lines
1.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2012 Regents of the University of California
|
|
*/
|
|
|
|
#ifndef _ASM_RISCV_PGTABLE_64_H
|
|
#define _ASM_RISCV_PGTABLE_64_H
|
|
|
|
#include <linux/const.h>
|
|
|
|
#define PGDIR_SHIFT 30
|
|
/* Size of region mapped by a page global directory */
|
|
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
|
|
#define PGDIR_MASK (~(PGDIR_SIZE - 1))
|
|
|
|
#define PMD_SHIFT 21
|
|
/* Size of region mapped by a page middle directory */
|
|
#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
|
|
#define PMD_MASK (~(PMD_SIZE - 1))
|
|
|
|
/* Page Middle Directory entry */
|
|
typedef struct {
|
|
unsigned long pmd;
|
|
} pmd_t;
|
|
|
|
#define pmd_val(x) ((x).pmd)
|
|
#define __pmd(x) ((pmd_t) { (x) })
|
|
|
|
#define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t))
|
|
|
|
static inline int pud_present(pud_t pud)
|
|
{
|
|
return (pud_val(pud) & _PAGE_PRESENT);
|
|
}
|
|
|
|
static inline int pud_none(pud_t pud)
|
|
{
|
|
return (pud_val(pud) == 0);
|
|
}
|
|
|
|
static inline int pud_bad(pud_t pud)
|
|
{
|
|
return !pud_present(pud);
|
|
}
|
|
|
|
static inline void set_pud(pud_t *pudp, pud_t pud)
|
|
{
|
|
*pudp = pud;
|
|
}
|
|
|
|
static inline void pud_clear(pud_t *pudp)
|
|
{
|
|
set_pud(pudp, __pud(0));
|
|
}
|
|
|
|
static inline unsigned long pud_page_vaddr(pud_t pud)
|
|
{
|
|
return (unsigned long)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
|
}
|
|
|
|
static inline struct page *pud_page(pud_t pud)
|
|
{
|
|
return pfn_to_page(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
|
}
|
|
|
|
#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
|
|
|
|
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
|
{
|
|
return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
|
|
}
|
|
|
|
static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
return __pmd((pfn << _PAGE_PFN_SHIFT) | pgprot_val(prot));
|
|
}
|
|
|
|
static inline unsigned long _pmd_pfn(pmd_t pmd)
|
|
{
|
|
return pmd_val(pmd) >> _PAGE_PFN_SHIFT;
|
|
}
|
|
|
|
#define pmd_ERROR(e) \
|
|
pr_err("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
|
|
|
|
#endif /* _ASM_RISCV_PGTABLE_64_H */
|