d38c07afc3
- A large series from Nick for 64-bit to further rework our exception vectors, and rewrite portions of the syscall entry/exit and interrupt return in C. The result is much easier to follow code that is also faster in general. - Cleanup of our ptrace code to split various parts out that had become badly intertwined with #ifdefs over the years. - Changes to our NUMA setup under the PowerVM hypervisor which should hopefully avoid non-sensical topologies which can lead to warnings from the workqueue code and other problems. - MAINTAINERS updates to remove some of our old orphan entries and update the status of others. - Quite a few other small changes and fixes all over the map. Thanks to: Abdul Haleem, afzal mohammed, Alexey Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Balamuruhan S, Cédric Le Goater, Chen Zhou, Christophe JAILLET, Christophe Leroy, Christoph Hellwig, Clement Courbet, Daniel Axtens, David Gibson, Douglas Miller, Fabiano Rosas, Fangrui Song, Ganesh Goudar, Gautham R. Shenoy, Greg Kroah-Hartman, Greg Kurz, Gustavo Luiz Duarte, Hari Bathini, Ilie Halip, Jan Kara, Joe Lawrence, Joe Perches, Kajol Jain, Larry Finger, Laurentiu Tudor, Leonardo Bras, Libor Pechacek, Madhavan Srinivasan, Mahesh Salgaonkar, Masahiro Yamada, Masami Hiramatsu, Mauricio Faria de Oliveira, Michael Neuling, Michal Suchanek, Mike Rapoport, Nageswara R Sastry, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nick Desaulniers, Oliver O'Halloran, Po-Hsu Lin, Pratik Rajesh Sampat, Rasmus Villemoes, Ravi Bangoria, Roman Bolshakov, Sam Bobroff, Sandipan Das, Santosh S, Sedat Dilek, Segher Boessenkool, Shilpasri G Bhat, Sourabh Jain, Srikar Dronamraju, Stephen Rothwell, Tyrel Datwyler, Vaibhav Jain, YueHaibing. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAl6JypATHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgOTyD/0U90tXb3VXlQcc4OFIb8vWIj76k4Zn ZSZ7RyOuvb5pCISBZjSK79XkR9eMHT77qagX4V41q64k4yQl8nbgLeVnwL76hLLc IJCs23f4nsO0uqX/MhSCc5dfOOOS2i8V+OQYtsYWsH5QaG95v0cHIqVaHHMlfQxu 507GO/W5W6KTd4x008b5unQOuE51zMKlKvqEJXkT59obQFpaa2S5Wn7OzhsnarCH YSRNxaC7vtgBKLA9wUnFh8UUbh0FbOwXBCaq4OhHMhgRihdteVBCzlcR/6c+IRbt EoZxKzfQ0hI1z5f++kJNaRXMtUbSpM8D1HdKKHgiWjpdBSD0eu2X106KQT2R2ZOF qhX8xPLWNzdBglA6L43AaZUu+4ayd3QrrJIkjDv/K1rCHZjfGOzSQfoZgTEBNLFA tC0crhEfw8m98e4EwhCtekGQxdczRdLS9YvtC/h6mU2xkpA35yNSwB1/iuVQdkYD XyrEqImAQ1PJla7NL0hxSy5ZxrBtMeKT4WZZ0BNgKXryemldg8Tuv3AEyach3BHz eU0pIwpbnPm1JAPyrpDQ1yEf7QsD77gTPfEvilEci60R9DhvIMGAY+pt0qfME3yX wOLp2yVBEXlRmvHk/y/+r+m4aCsmwSrikbWwmLLwAAA6JehtzFOWxTEfNpACP23V mZyyZznsHIIE3Q== =ARdm -----END PGP SIGNATURE----- Merge tag 'powerpc-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Michael Ellerman: "Slightly late as I had to rebase mid-week to insert a bug fix: - A large series from Nick for 64-bit to further rework our exception vectors, and rewrite portions of the syscall entry/exit and interrupt return in C. The result is much easier to follow code that is also faster in general. - Cleanup of our ptrace code to split various parts out that had become badly intertwined with #ifdefs over the years. - Changes to our NUMA setup under the PowerVM hypervisor which should hopefully avoid non-sensical topologies which can lead to warnings from the workqueue code and other problems. - MAINTAINERS updates to remove some of our old orphan entries and update the status of others. - Quite a few other small changes and fixes all over the map. Thanks to: Abdul Haleem, afzal mohammed, Alexey Kardashevskiy, Andrew Donnellan, Aneesh Kumar K.V, Balamuruhan S, Cédric Le Goater, Chen Zhou, Christophe JAILLET, Christophe Leroy, Christoph Hellwig, Clement Courbet, Daniel Axtens, David Gibson, Douglas Miller, Fabiano Rosas, Fangrui Song, Ganesh Goudar, Gautham R. Shenoy, Greg Kroah-Hartman, Greg Kurz, Gustavo Luiz Duarte, Hari Bathini, Ilie Halip, Jan Kara, Joe Lawrence, Joe Perches, Kajol Jain, Larry Finger, Laurentiu Tudor, Leonardo Bras, Libor Pechacek, Madhavan Srinivasan, Mahesh Salgaonkar, Masahiro Yamada, Masami Hiramatsu, Mauricio Faria de Oliveira, Michael Neuling, Michal Suchanek, Mike Rapoport, Nageswara R Sastry, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nick Desaulniers, Oliver O'Halloran, Po-Hsu Lin, Pratik Rajesh Sampat, Rasmus Villemoes, Ravi Bangoria, Roman Bolshakov, Sam Bobroff, Sandipan Das, Santosh S, Sedat Dilek, Segher Boessenkool, Shilpasri G Bhat, Sourabh Jain, Srikar Dronamraju, Stephen Rothwell, Tyrel Datwyler, Vaibhav Jain, YueHaibing" * tag 'powerpc-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (158 commits) powerpc: Make setjmp/longjmp signature standard powerpc/cputable: Remove unnecessary copy of cpu_spec->oprofile_type powerpc: Suppress .eh_frame generation powerpc: Drop -fno-dwarf2-cfi-asm powerpc/32: drop unused ISA_DMA_THRESHOLD powerpc/powernv: Add documentation for the opal sensor_groups sysfs interfaces selftests/powerpc: Fix try-run when source tree is not writable powerpc/vmlinux.lds: Explicitly retain .gnu.hash powerpc/ptrace: move ptrace_triggered() into hw_breakpoint.c powerpc/ptrace: create ppc_gethwdinfo() powerpc/ptrace: create ptrace_get_debugreg() powerpc/ptrace: split out ADV_DEBUG_REGS related functions. powerpc/ptrace: move register viewing functions out of ptrace.c powerpc/ptrace: split out TRANSACTIONAL_MEM related functions. powerpc/ptrace: split out SPE related functions. powerpc/ptrace: split out ALTIVEC related functions. powerpc/ptrace: split out VSX related functions. powerpc/ptrace: drop PARAMETER_SAVE_AREA_OFFSET powerpc/ptrace: drop unnecessary #ifdefs CONFIG_PPC64 powerpc/ptrace: remove unused header includes ...
213 lines
5.4 KiB
C
213 lines
5.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#define DISABLE_BRANCH_PROFILING
|
|
|
|
#include <linux/kasan.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/memblock.h>
|
|
#include <linux/moduleloader.h>
|
|
#include <linux/sched/task.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <asm/pgalloc.h>
|
|
#include <asm/code-patching.h>
|
|
#include <mm/mmu_decl.h>
|
|
|
|
static pgprot_t __init kasan_prot_ro(void)
|
|
{
|
|
if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
|
return PAGE_READONLY;
|
|
|
|
return PAGE_KERNEL_RO;
|
|
}
|
|
|
|
static void __init kasan_populate_pte(pte_t *ptep, pgprot_t prot)
|
|
{
|
|
unsigned long va = (unsigned long)kasan_early_shadow_page;
|
|
phys_addr_t pa = __pa(kasan_early_shadow_page);
|
|
int i;
|
|
|
|
for (i = 0; i < PTRS_PER_PTE; i++, ptep++)
|
|
__set_pte_at(&init_mm, va, ptep, pfn_pte(PHYS_PFN(pa), prot), 0);
|
|
}
|
|
|
|
static int __init kasan_init_shadow_page_tables(unsigned long k_start, unsigned long k_end)
|
|
{
|
|
pmd_t *pmd;
|
|
unsigned long k_cur, k_next;
|
|
pte_t *new = NULL;
|
|
|
|
pmd = pmd_ptr_k(k_start);
|
|
|
|
for (k_cur = k_start; k_cur != k_end; k_cur = k_next, pmd++) {
|
|
k_next = pgd_addr_end(k_cur, k_end);
|
|
if ((void *)pmd_page_vaddr(*pmd) != kasan_early_shadow_pte)
|
|
continue;
|
|
|
|
if (!new)
|
|
new = memblock_alloc(PTE_FRAG_SIZE, PTE_FRAG_SIZE);
|
|
|
|
if (!new)
|
|
return -ENOMEM;
|
|
kasan_populate_pte(new, PAGE_KERNEL);
|
|
|
|
smp_wmb(); /* See comment in __pte_alloc */
|
|
|
|
spin_lock(&init_mm.page_table_lock);
|
|
/* Has another populated it ? */
|
|
if (likely((void *)pmd_page_vaddr(*pmd) == kasan_early_shadow_pte)) {
|
|
pmd_populate_kernel(&init_mm, pmd, new);
|
|
new = NULL;
|
|
}
|
|
spin_unlock(&init_mm.page_table_lock);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int __init kasan_init_region(void *start, size_t size)
|
|
{
|
|
unsigned long k_start = (unsigned long)kasan_mem_to_shadow(start);
|
|
unsigned long k_end = (unsigned long)kasan_mem_to_shadow(start + size);
|
|
unsigned long k_cur;
|
|
int ret;
|
|
void *block;
|
|
|
|
ret = kasan_init_shadow_page_tables(k_start, k_end);
|
|
if (ret)
|
|
return ret;
|
|
|
|
block = memblock_alloc(k_end - k_start, PAGE_SIZE);
|
|
|
|
for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) {
|
|
pmd_t *pmd = pmd_ptr_k(k_cur);
|
|
void *va = block + k_cur - k_start;
|
|
pte_t pte = pfn_pte(PHYS_PFN(__pa(va)), PAGE_KERNEL);
|
|
|
|
if (!va)
|
|
return -ENOMEM;
|
|
|
|
__set_pte_at(&init_mm, k_cur, pte_offset_kernel(pmd, k_cur), pte, 0);
|
|
}
|
|
flush_tlb_kernel_range(k_start, k_end);
|
|
return 0;
|
|
}
|
|
|
|
static void __init kasan_remap_early_shadow_ro(void)
|
|
{
|
|
pgprot_t prot = kasan_prot_ro();
|
|
unsigned long k_start = KASAN_SHADOW_START;
|
|
unsigned long k_end = KASAN_SHADOW_END;
|
|
unsigned long k_cur;
|
|
phys_addr_t pa = __pa(kasan_early_shadow_page);
|
|
|
|
kasan_populate_pte(kasan_early_shadow_pte, prot);
|
|
|
|
for (k_cur = k_start & PAGE_MASK; k_cur != k_end; k_cur += PAGE_SIZE) {
|
|
pmd_t *pmd = pmd_ptr_k(k_cur);
|
|
pte_t *ptep = pte_offset_kernel(pmd, k_cur);
|
|
|
|
if ((pte_val(*ptep) & PTE_RPN_MASK) != pa)
|
|
continue;
|
|
|
|
__set_pte_at(&init_mm, k_cur, ptep, pfn_pte(PHYS_PFN(pa), prot), 0);
|
|
}
|
|
flush_tlb_kernel_range(KASAN_SHADOW_START, KASAN_SHADOW_END);
|
|
}
|
|
|
|
static void __init kasan_unmap_early_shadow_vmalloc(void)
|
|
{
|
|
unsigned long k_start = (unsigned long)kasan_mem_to_shadow((void *)VMALLOC_START);
|
|
unsigned long k_end = (unsigned long)kasan_mem_to_shadow((void *)VMALLOC_END);
|
|
unsigned long k_cur;
|
|
phys_addr_t pa = __pa(kasan_early_shadow_page);
|
|
|
|
for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) {
|
|
pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(k_cur), k_cur), k_cur);
|
|
pte_t *ptep = pte_offset_kernel(pmd, k_cur);
|
|
|
|
if ((pte_val(*ptep) & PTE_RPN_MASK) != pa)
|
|
continue;
|
|
|
|
__set_pte_at(&init_mm, k_cur, ptep, __pte(0), 0);
|
|
}
|
|
flush_tlb_kernel_range(k_start, k_end);
|
|
}
|
|
|
|
void __init kasan_mmu_init(void)
|
|
{
|
|
int ret;
|
|
struct memblock_region *reg;
|
|
|
|
if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE) ||
|
|
IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
|
|
ret = kasan_init_shadow_page_tables(KASAN_SHADOW_START, KASAN_SHADOW_END);
|
|
|
|
if (ret)
|
|
panic("kasan: kasan_init_shadow_page_tables() failed");
|
|
}
|
|
|
|
for_each_memblock(memory, reg) {
|
|
phys_addr_t base = reg->base;
|
|
phys_addr_t top = min(base + reg->size, total_lowmem);
|
|
|
|
if (base >= top)
|
|
continue;
|
|
|
|
ret = kasan_init_region(__va(base), top - base);
|
|
if (ret)
|
|
panic("kasan: kasan_init_region() failed");
|
|
}
|
|
}
|
|
|
|
void __init kasan_init(void)
|
|
{
|
|
kasan_remap_early_shadow_ro();
|
|
|
|
clear_page(kasan_early_shadow_page);
|
|
|
|
/* At this point kasan is fully initialized. Enable error messages */
|
|
init_task.kasan_depth = 0;
|
|
pr_info("KASAN init done\n");
|
|
}
|
|
|
|
void __init kasan_late_init(void)
|
|
{
|
|
if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
|
|
kasan_unmap_early_shadow_vmalloc();
|
|
}
|
|
|
|
#ifdef CONFIG_PPC_BOOK3S_32
|
|
u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
|
|
|
|
static void __init kasan_early_hash_table(void)
|
|
{
|
|
unsigned int hash = __pa(early_hash);
|
|
|
|
modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
|
|
modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
|
|
|
|
Hash = (struct hash_pte *)early_hash;
|
|
}
|
|
#else
|
|
static void __init kasan_early_hash_table(void) {}
|
|
#endif
|
|
|
|
void __init kasan_early_init(void)
|
|
{
|
|
unsigned long addr = KASAN_SHADOW_START;
|
|
unsigned long end = KASAN_SHADOW_END;
|
|
unsigned long next;
|
|
pmd_t *pmd = pmd_ptr_k(addr);
|
|
|
|
BUILD_BUG_ON(KASAN_SHADOW_START & ~PGDIR_MASK);
|
|
|
|
kasan_populate_pte(kasan_early_shadow_pte, PAGE_KERNEL);
|
|
|
|
do {
|
|
next = pgd_addr_end(addr, end);
|
|
pmd_populate_kernel(&init_mm, pmd, kasan_early_shadow_pte);
|
|
} while (pmd++, addr = next, addr != end);
|
|
|
|
if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
|
kasan_early_hash_table();
|
|
}
|