-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
powerpc/64e: KASAN Full support for BOOK3E/64
We now have memory organised in a way that allows implementing KASAN. Unlike book3s/64, book3e always has translation active so the only thing needed to use KASAN is to setup an early zero shadow mapping just after setting a stack pointer and before calling early_setup(). The memory layout is now as follows +------------------------+ Kernel virtual map end (0xc000200000000000) | | | 16TB of KASAN map | | | +------------------------+ Kernel KASAN shadow map start | | | 16TB of IO map | | | +------------------------+ Kernel IO map start | | | 16TB of vmemmap | | | +------------------------+ Kernel vmemmap start | | | 16TB of vmap | | | +------------------------+ Kernel virt start (0xc000100000000000) | | | 64TB of linear mem | | | +------------------------+ Kernel linear (0xc.....) Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/0bef8beda27baf71e3b9e8b13e620fba6e19499b.1656427701.git.christophe.leroy@csgroup.eu
- Loading branch information
Christophe Leroy
authored and
Michael Ellerman
committed
Jun 29, 2022
1 parent
059c189
commit c7b9ed7
Showing
8 changed files
with
155 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* KASAN for 64-bit Book3e powerpc | ||
* | ||
* Copyright 2022, Christophe Leroy, CS GROUP France | ||
*/ | ||
|
||
#define DISABLE_BRANCH_PROFILING | ||
|
||
#include <linux/kasan.h> | ||
#include <linux/printk.h> | ||
#include <linux/memblock.h> | ||
#include <linux/set_memory.h> | ||
|
||
#include <asm/pgalloc.h> | ||
|
||
static inline bool kasan_pud_table(p4d_t p4d) | ||
{ | ||
return p4d_page(p4d) == virt_to_page(lm_alias(kasan_early_shadow_pud)); | ||
} | ||
|
||
static inline bool kasan_pmd_table(pud_t pud) | ||
{ | ||
return pud_page(pud) == virt_to_page(lm_alias(kasan_early_shadow_pmd)); | ||
} | ||
|
||
static inline bool kasan_pte_table(pmd_t pmd) | ||
{ | ||
return pmd_page(pmd) == virt_to_page(lm_alias(kasan_early_shadow_pte)); | ||
} | ||
|
||
static int __init kasan_map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) | ||
{ | ||
pgd_t *pgdp; | ||
p4d_t *p4dp; | ||
pud_t *pudp; | ||
pmd_t *pmdp; | ||
pte_t *ptep; | ||
|
||
pgdp = pgd_offset_k(ea); | ||
p4dp = p4d_offset(pgdp, ea); | ||
if (kasan_pud_table(*p4dp)) { | ||
pudp = memblock_alloc(PUD_TABLE_SIZE, PUD_TABLE_SIZE); | ||
memcpy(pudp, kasan_early_shadow_pud, PUD_TABLE_SIZE); | ||
p4d_populate(&init_mm, p4dp, pudp); | ||
} | ||
pudp = pud_offset(p4dp, ea); | ||
if (kasan_pmd_table(*pudp)) { | ||
pmdp = memblock_alloc(PMD_TABLE_SIZE, PMD_TABLE_SIZE); | ||
memcpy(pmdp, kasan_early_shadow_pmd, PMD_TABLE_SIZE); | ||
pud_populate(&init_mm, pudp, pmdp); | ||
} | ||
pmdp = pmd_offset(pudp, ea); | ||
if (kasan_pte_table(*pmdp)) { | ||
ptep = memblock_alloc(PTE_TABLE_SIZE, PTE_TABLE_SIZE); | ||
memcpy(ptep, kasan_early_shadow_pte, PTE_TABLE_SIZE); | ||
pmd_populate_kernel(&init_mm, pmdp, ptep); | ||
} | ||
ptep = pte_offset_kernel(pmdp, ea); | ||
|
||
__set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot), 0); | ||
|
||
return 0; | ||
} | ||
|
||
static void __init kasan_init_phys_region(void *start, void *end) | ||
{ | ||
unsigned long k_start, k_end, k_cur; | ||
void *va; | ||
|
||
if (start >= end) | ||
return; | ||
|
||
k_start = ALIGN_DOWN((unsigned long)kasan_mem_to_shadow(start), PAGE_SIZE); | ||
k_end = ALIGN((unsigned long)kasan_mem_to_shadow(end), PAGE_SIZE); | ||
|
||
va = memblock_alloc(k_end - k_start, PAGE_SIZE); | ||
for (k_cur = k_start; k_cur < k_end; k_cur += PAGE_SIZE, va += PAGE_SIZE) | ||
kasan_map_kernel_page(k_cur, __pa(va), PAGE_KERNEL); | ||
} | ||
|
||
void __init kasan_early_init(void) | ||
{ | ||
int i; | ||
unsigned long addr; | ||
pgd_t *pgd = pgd_offset_k(KASAN_SHADOW_START); | ||
pte_t zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL); | ||
|
||
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); | ||
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); | ||
|
||
for (i = 0; i < PTRS_PER_PTE; i++) | ||
__set_pte_at(&init_mm, (unsigned long)kasan_early_shadow_page, | ||
&kasan_early_shadow_pte[i], zero_pte, 0); | ||
|
||
for (i = 0; i < PTRS_PER_PMD; i++) | ||
pmd_populate_kernel(&init_mm, &kasan_early_shadow_pmd[i], | ||
kasan_early_shadow_pte); | ||
|
||
for (i = 0; i < PTRS_PER_PUD; i++) | ||
pud_populate(&init_mm, &kasan_early_shadow_pud[i], | ||
kasan_early_shadow_pmd); | ||
|
||
for (addr = KASAN_SHADOW_START; addr != KASAN_SHADOW_END; addr += PGDIR_SIZE) | ||
p4d_populate(&init_mm, p4d_offset(pgd++, addr), kasan_early_shadow_pud); | ||
} | ||
|
||
void __init kasan_init(void) | ||
{ | ||
phys_addr_t start, end; | ||
u64 i; | ||
pte_t zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL_RO); | ||
|
||
for_each_mem_range(i, &start, &end) | ||
kasan_init_phys_region((void *)start, (void *)end); | ||
|
||
if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) | ||
kasan_remove_zero_shadow((void *)VMALLOC_START, VMALLOC_SIZE); | ||
|
||
for (i = 0; i < PTRS_PER_PTE; i++) | ||
__set_pte_at(&init_mm, (unsigned long)kasan_early_shadow_page, | ||
&kasan_early_shadow_pte[i], zero_pte, 0); | ||
|
||
flush_tlb_kernel_range(KASAN_SHADOW_START, KASAN_SHADOW_END); | ||
|
||
memset(kasan_early_shadow_page, 0, PAGE_SIZE); | ||
|
||
/* Enable error messages */ | ||
init_task.kasan_depth = 0; | ||
pr_info("KASAN init done\n"); | ||
} | ||
|
||
void __init kasan_late_init(void) { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters