mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-03 09:04:21 +08:00
Merge branch 'akpm' (patches from Andrew)
Pull yet more updates from Andrew Morton: "54 patches. Subsystems affected by this patch series: lib, mm (slub, secretmem, cleanups, init, pagemap, and mremap), and debug" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (54 commits) powerpc/mm: enable HAVE_MOVE_PMD support powerpc/book3s64/mm: update flush_tlb_range to flush page walk cache mm/mremap: allow arch runtime override mm/mremap: hold the rmap lock in write mode when moving page table entries. mm/mremap: use pmd/pud_poplulate to update page table entries mm/mremap: don't enable optimized PUD move if page table levels is 2 mm/mremap: convert huge PUD move to separate helper selftest/mremap_test: avoid crash with static build selftest/mremap_test: update the test to handle pagesize other than 4K mm: rename p4d_page_vaddr to p4d_pgtable and make it return pud_t * mm: rename pud_page_vaddr to pud_pgtable and make it return pmd_t * kdump: use vmlinux_build_id to simplify buildid: fix kernel-doc notation buildid: mark some arguments const scripts/decode_stacktrace.sh: indicate 'auto' can be used for base path scripts/decode_stacktrace.sh: silence stderr messages from addr2line/nm scripts/decode_stacktrace.sh: support debuginfod x86/dumpstack: use %pSb/%pBb for backtrace printing arm64: stacktrace: use %pSb for backtrace printing module: add printk formats to add module build ID to stacktraces ...
This commit is contained in:
commit
bd9c350603
@ -125,6 +125,17 @@ used when printing stack backtraces. The specifier takes into
|
||||
consideration the effect of compiler optimisations which may occur
|
||||
when tail-calls are used and marked with the noreturn GCC attribute.
|
||||
|
||||
If the pointer is within a module, the module name and optionally build ID is
|
||||
printed after the symbol name with an extra ``b`` appended to the end of the
|
||||
specifier.
|
||||
|
||||
::
|
||||
%pS versatile_init+0x0/0x110 [module_name]
|
||||
%pSb versatile_init+0x0/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
|
||||
%pSRb versatile_init+0x9/0x110 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
|
||||
(with __builtin_extract_return_addr() translation)
|
||||
%pBb prev_fn_of_versatile_init+0x88/0x88 [module_name ed5019fdf5e53be37cb1ba7899292d7e143b259e]
|
||||
|
||||
Probed Pointers from BPF / tracing
|
||||
----------------------------------
|
||||
|
||||
|
@ -236,8 +236,10 @@ pmd_page_vaddr(pmd_t pmd)
|
||||
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> 32))
|
||||
#define pud_page(pud) (pfn_to_page(pud_val(pud) >> 32))
|
||||
|
||||
extern inline unsigned long pud_page_vaddr(pud_t pgd)
|
||||
{ return PAGE_OFFSET + ((pud_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT)); }
|
||||
extern inline pmd_t *pud_pgtable(pud_t pgd)
|
||||
{
|
||||
return (pmd_t *)(PAGE_OFFSET + ((pud_val(pgd) & _PFN_MASK) >> (32-PAGE_SHIFT)));
|
||||
}
|
||||
|
||||
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
|
||||
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
|
||||
@ -287,7 +289,7 @@ extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= __ACCESS_BITS; retu
|
||||
/* Find an entry in the second-level page table.. */
|
||||
extern inline pmd_t * pmd_offset(pud_t * dir, unsigned long address)
|
||||
{
|
||||
pmd_t *ret = (pmd_t *) pud_page_vaddr(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PAGE - 1));
|
||||
pmd_t *ret = pud_pgtable(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PAGE - 1));
|
||||
smp_rmb(); /* see above */
|
||||
return ret;
|
||||
}
|
||||
|
@ -89,10 +89,7 @@ void __init setup_arch_memory(void)
|
||||
{
|
||||
unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 };
|
||||
|
||||
init_mm.start_code = (unsigned long)_text;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
setup_initial_init_mm(_text, _etext, _edata, _end);
|
||||
|
||||
/* first page of system - kernel .vector starts here */
|
||||
min_low_pfn = virt_to_pfn(CONFIG_LINUX_RAM_BASE);
|
||||
|
@ -130,7 +130,7 @@
|
||||
flush_pmd_entry(pudp); \
|
||||
} while (0)
|
||||
|
||||
static inline pmd_t *pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
|
||||
}
|
||||
|
@ -1130,10 +1130,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
if (mdesc->reboot_mode != REBOOT_HARD)
|
||||
reboot_mode = mdesc->reboot_mode;
|
||||
|
||||
init_mm.start_code = (unsigned long) _text;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_text, _etext, _edata, _end);
|
||||
|
||||
/* populate cmd_line too for later use, preserving boot_command_line */
|
||||
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
|
@ -3,7 +3,6 @@ generic-y += early_ioremap.h
|
||||
generic-y += mcs_spinlock.h
|
||||
generic-y += qrwlock.h
|
||||
generic-y += qspinlock.h
|
||||
generic-y += set_memory.h
|
||||
generic-y += user.h
|
||||
|
||||
generated-y += cpucaps.h
|
||||
|
@ -144,12 +144,6 @@ static __always_inline void icache_inval_all_pou(void)
|
||||
dsb(ish);
|
||||
}
|
||||
|
||||
int set_memory_valid(unsigned long addr, int numpages, int enable);
|
||||
|
||||
int set_direct_map_invalid_noflush(struct page *page);
|
||||
int set_direct_map_default_noflush(struct page *page);
|
||||
bool kernel_page_present(struct page *page);
|
||||
|
||||
#include <asm-generic/cacheflush.h>
|
||||
|
||||
#endif /* __ASM_CACHEFLUSH_H */
|
||||
|
@ -8,7 +8,7 @@
|
||||
#ifndef __ASM_KFENCE_H
|
||||
#define __ASM_KFENCE_H
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
static inline bool arch_kfence_init_pool(void) { return true; }
|
||||
|
||||
|
@ -649,9 +649,9 @@ static inline phys_addr_t pud_page_paddr(pud_t pud)
|
||||
return __pud_to_phys(pud);
|
||||
}
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (unsigned long)__va(pud_page_paddr(pud));
|
||||
return (pmd_t *)__va(pud_page_paddr(pud));
|
||||
}
|
||||
|
||||
/* Find an entry in the second-level page table. */
|
||||
@ -710,9 +710,9 @@ static inline phys_addr_t p4d_page_paddr(p4d_t p4d)
|
||||
return __p4d_to_phys(p4d);
|
||||
}
|
||||
|
||||
static inline unsigned long p4d_page_vaddr(p4d_t p4d)
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return (unsigned long)__va(p4d_page_paddr(p4d));
|
||||
return (pud_t *)__va(p4d_page_paddr(p4d));
|
||||
}
|
||||
|
||||
/* Find an entry in the frst-level page table. */
|
||||
|
17
arch/arm64/include/asm/set_memory.h
Normal file
17
arch/arm64/include/asm/set_memory.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _ASM_ARM64_SET_MEMORY_H
|
||||
#define _ASM_ARM64_SET_MEMORY_H
|
||||
|
||||
#include <asm-generic/set_memory.h>
|
||||
|
||||
bool can_set_direct_map(void);
|
||||
#define can_set_direct_map can_set_direct_map
|
||||
|
||||
int set_memory_valid(unsigned long addr, int numpages, int enable);
|
||||
|
||||
int set_direct_map_invalid_noflush(struct page *page);
|
||||
int set_direct_map_default_noflush(struct page *page);
|
||||
bool kernel_page_present(struct page *page);
|
||||
|
||||
#endif /* _ASM_ARM64_SET_MEMORY_H */
|
@ -20,5 +20,6 @@
|
||||
#define __ARCH_WANT_SET_GET_RLIMIT
|
||||
#define __ARCH_WANT_TIME32_SYSCALLS
|
||||
#define __ARCH_WANT_SYS_CLONE3
|
||||
#define __ARCH_WANT_MEMFD_SECRET
|
||||
|
||||
#include <asm-generic/unistd.h>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/page-flags.h>
|
||||
#include <linux/set_memory.h>
|
||||
#include <linux/smp.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
@ -293,10 +293,7 @@ u64 cpu_logical_map(unsigned int cpu)
|
||||
|
||||
void __init __no_sanitize_address setup_arch(char **cmdline_p)
|
||||
{
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
*cmdline_p = boot_command_line;
|
||||
|
||||
|
@ -153,7 +153,7 @@ NOKPROBE_SYMBOL(walk_stackframe);
|
||||
|
||||
static void dump_backtrace_entry(unsigned long where, const char *loglvl)
|
||||
{
|
||||
printk("%s %pS\n", loglvl, (void *)where);
|
||||
printk("%s %pSb\n", loglvl, (void *)where);
|
||||
}
|
||||
|
||||
void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/set_memory.h>
|
||||
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/cputype.h>
|
||||
@ -515,8 +516,7 @@ static void __init map_mem(pgd_t *pgdp)
|
||||
*/
|
||||
BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
|
||||
|
||||
if (rodata_full || crash_mem_map || debug_pagealloc_enabled() ||
|
||||
IS_ENABLED(CONFIG_KFENCE))
|
||||
if (can_set_direct_map() || crash_mem_map || IS_ENABLED(CONFIG_KFENCE))
|
||||
flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
|
||||
|
||||
/*
|
||||
@ -1489,8 +1489,7 @@ int arch_add_memory(int nid, u64 start, u64 size,
|
||||
* KFENCE requires linear map to be mapped at page granularity, so that
|
||||
* it is possible to protect/unprotect single pages in the KFENCE pool.
|
||||
*/
|
||||
if (rodata_full || debug_pagealloc_enabled() ||
|
||||
IS_ENABLED(CONFIG_KFENCE))
|
||||
if (can_set_direct_map() || IS_ENABLED(CONFIG_KFENCE))
|
||||
flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
|
||||
|
||||
__create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
|
||||
|
@ -19,6 +19,11 @@ struct page_change_data {
|
||||
|
||||
bool rodata_full __ro_after_init = IS_ENABLED(CONFIG_RODATA_FULL_DEFAULT_ENABLED);
|
||||
|
||||
bool can_set_direct_map(void)
|
||||
{
|
||||
return rodata_full || debug_pagealloc_enabled();
|
||||
}
|
||||
|
||||
static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
|
||||
{
|
||||
struct page_change_data *cdata = data;
|
||||
@ -155,7 +160,7 @@ int set_direct_map_invalid_noflush(struct page *page)
|
||||
.clear_mask = __pgprot(PTE_VALID),
|
||||
};
|
||||
|
||||
if (!debug_pagealloc_enabled() && !rodata_full)
|
||||
if (!can_set_direct_map())
|
||||
return 0;
|
||||
|
||||
return apply_to_page_range(&init_mm,
|
||||
@ -170,7 +175,7 @@ int set_direct_map_default_noflush(struct page *page)
|
||||
.clear_mask = __pgprot(PTE_RDONLY),
|
||||
};
|
||||
|
||||
if (!debug_pagealloc_enabled() && !rodata_full)
|
||||
if (!can_set_direct_map())
|
||||
return 0;
|
||||
|
||||
return apply_to_page_range(&init_mm,
|
||||
@ -181,7 +186,7 @@ int set_direct_map_default_noflush(struct page *page)
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
if (!debug_pagealloc_enabled() && !rodata_full)
|
||||
if (!can_set_direct_map())
|
||||
return;
|
||||
|
||||
set_memory_valid((unsigned long)page_address(page), numpages, enable);
|
||||
@ -206,7 +211,7 @@ bool kernel_page_present(struct page *page)
|
||||
pte_t *ptep;
|
||||
unsigned long addr = (unsigned long)page_address(page);
|
||||
|
||||
if (!debug_pagealloc_enabled() && !rodata_full)
|
||||
if (!can_set_direct_map())
|
||||
return true;
|
||||
|
||||
pgdp = pgd_offset_k(addr);
|
||||
|
@ -78,10 +78,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
pr_info("Phys. mem: %ldMB\n",
|
||||
(unsigned long) memblock_phys_mem_size()/1024/1024);
|
||||
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
parse_early_param();
|
||||
|
||||
|
@ -95,10 +95,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) 0;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, NULL);
|
||||
|
||||
pr_notice("\r\n\nuClinux " CPU "\n");
|
||||
pr_notice("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
|
||||
|
@ -30,6 +30,7 @@ config HEXAGON
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_CPU_DEVICES
|
||||
select SET_FS
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
help
|
||||
Qualcomm Hexagon is a processor architecture designed for high
|
||||
performance and low power across a wide variety of applications.
|
||||
|
@ -38,6 +38,8 @@ SECTIONS
|
||||
.text : AT(ADDR(.text)) {
|
||||
_text = .;
|
||||
TEXT_TEXT
|
||||
IRQENTRY_TEXT
|
||||
SOFTIRQENTRY_TEXT
|
||||
SCHED_TEXT
|
||||
CPUIDLE_TEXT
|
||||
LOCK_TEXT
|
||||
@ -59,14 +61,9 @@ SECTIONS
|
||||
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
EXIT_TEXT
|
||||
EXIT_DATA
|
||||
EXIT_CALL
|
||||
}
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ ia64_phys_addr_valid (unsigned long addr)
|
||||
#define pud_bad(pud) (!ia64_phys_addr_valid(pud_val(pud)))
|
||||
#define pud_present(pud) (pud_val(pud) != 0UL)
|
||||
#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
|
||||
#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & _PFN_MASK))
|
||||
#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & _PFN_MASK))
|
||||
#define pud_page(pud) virt_to_page((pud_val(pud) + PAGE_OFFSET))
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 4
|
||||
@ -281,7 +281,7 @@ ia64_phys_addr_valid (unsigned long addr)
|
||||
#define p4d_bad(p4d) (!ia64_phys_addr_valid(p4d_val(p4d)))
|
||||
#define p4d_present(p4d) (p4d_val(p4d) != 0UL)
|
||||
#define p4d_clear(p4dp) (p4d_val(*(p4dp)) = 0UL)
|
||||
#define p4d_page_vaddr(p4d) ((unsigned long) __va(p4d_val(p4d) & _PFN_MASK))
|
||||
#define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & _PFN_MASK))
|
||||
#define p4d_page(p4d) virt_to_page((p4d_val(p4d) + PAGE_OFFSET))
|
||||
#endif
|
||||
|
||||
|
@ -131,7 +131,7 @@ static inline void pud_set(pud_t *pudp, pmd_t *pmdp)
|
||||
|
||||
#define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK))
|
||||
#define pmd_page_vaddr(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK))
|
||||
#define pud_page_vaddr(pud) ((unsigned long)__va(pud_val(pud) & _TABLE_MASK))
|
||||
#define pud_pgtable(pud) ((pmd_t *)__va(pud_val(pud) & _TABLE_MASK))
|
||||
|
||||
|
||||
#define pte_none(pte) (!pte_val(pte))
|
||||
|
@ -258,10 +258,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
}
|
||||
}
|
||||
|
||||
init_mm.start_code = PAGE_OFFSET;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
setup_initial_init_mm((void *)PAGE_OFFSET, _etext, _edata, _end);
|
||||
|
||||
#if defined(CONFIG_BOOTPARAM)
|
||||
strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE);
|
||||
|
@ -87,10 +87,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
memory_start = PAGE_ALIGN(_ramstart);
|
||||
memory_end = _ramend;
|
||||
|
||||
init_mm.start_code = (unsigned long) &_stext;
|
||||
init_mm.end_code = (unsigned long) &_etext;
|
||||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) 0;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, NULL);
|
||||
|
||||
config_BSP(&command_line[0], sizeof(command_line));
|
||||
|
||||
|
@ -209,9 +209,9 @@ static inline void p4d_clear(p4d_t *p4dp)
|
||||
p4d_val(*p4dp) = (unsigned long)invalid_pud_table;
|
||||
}
|
||||
|
||||
static inline unsigned long p4d_page_vaddr(p4d_t p4d)
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return p4d_val(p4d);
|
||||
return (pud_t *)p4d_val(p4d);
|
||||
}
|
||||
|
||||
#define p4d_phys(p4d) virt_to_phys((void *)p4d_val(p4d))
|
||||
@ -313,9 +313,9 @@ static inline void pud_clear(pud_t *pudp)
|
||||
#endif
|
||||
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return pud_val(pud);
|
||||
return (pmd_t *)pud_val(pud);
|
||||
}
|
||||
#define pud_phys(pud) virt_to_phys((void *)pud_val(pud))
|
||||
#define pud_page(pud) (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
|
||||
|
@ -294,10 +294,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
setup_cpuinfo();
|
||||
|
||||
init_mm.start_code = (unsigned long)&_stext;
|
||||
init_mm.end_code = (unsigned long)&_etext;
|
||||
init_mm.end_data = (unsigned long)&_edata;
|
||||
init_mm.brk = (unsigned long)&_end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
/* setup bootmem allocator */
|
||||
setup_memory();
|
||||
|
@ -156,10 +156,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
memory_start = memblock_start_of_DRAM();
|
||||
memory_end = memblock_end_of_DRAM();
|
||||
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
init_task.thread.kregs = &fake_regs;
|
||||
|
||||
/* Keep a copy of command line */
|
||||
|
@ -293,10 +293,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
#endif
|
||||
|
||||
/* process 1's initial memory region is the kernel code/data */
|
||||
init_mm.start_code = (unsigned long)_stext;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start == initrd_end) {
|
||||
|
@ -322,8 +322,8 @@ static inline void pmd_clear(pmd_t *pmd) {
|
||||
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 3
|
||||
#define pud_page_vaddr(pud) ((unsigned long) __va(pud_address(pud)))
|
||||
#define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud))
|
||||
#define pud_pgtable(pud) ((pmd_t *) __va(pud_address(pud)))
|
||||
#define pud_page(pud) virt_to_page((void *)pud_pgtable(pud))
|
||||
|
||||
/* For 64 bit we have three level tables */
|
||||
|
||||
|
@ -1051,8 +1051,15 @@ extern struct page *p4d_page(p4d_t p4d);
|
||||
/* Pointers in the page table tree are physical addresses */
|
||||
#define __pgtable_ptr_val(ptr) __pa(ptr)
|
||||
|
||||
#define pud_page_vaddr(pud) __va(pud_val(pud) & ~PUD_MASKED_BITS)
|
||||
#define p4d_page_vaddr(p4d) __va(p4d_val(p4d) & ~P4D_MASKED_BITS)
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return (pud_t *)__va(p4d_val(p4d) & ~P4D_MASKED_BITS);
|
||||
}
|
||||
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (pmd_t *)__va(pud_val(pud) & ~PUD_MASKED_BITS);
|
||||
}
|
||||
|
||||
#define pte_ERROR(e) \
|
||||
pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
|
||||
|
@ -64,6 +64,8 @@ extern void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end);
|
||||
extern void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, int psize);
|
||||
void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, int psize);
|
||||
extern void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long end);
|
||||
extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
|
@ -56,10 +56,14 @@
|
||||
#define p4d_none(p4d) (!p4d_val(p4d))
|
||||
#define p4d_bad(p4d) (p4d_val(p4d) == 0)
|
||||
#define p4d_present(p4d) (p4d_val(p4d) != 0)
|
||||
#define p4d_page_vaddr(p4d) (p4d_val(p4d) & ~P4D_MASKED_BITS)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return (pud_t *) (p4d_val(p4d) & ~P4D_MASKED_BITS);
|
||||
}
|
||||
|
||||
static inline void p4d_clear(p4d_t *p4dp)
|
||||
{
|
||||
*p4dp = __p4d(0);
|
||||
|
@ -162,7 +162,11 @@ static inline void pud_clear(pud_t *pudp)
|
||||
#define pud_bad(pud) (!is_kernel_addr(pud_val(pud)) \
|
||||
|| (pud_val(pud) & PUD_BAD_BITS))
|
||||
#define pud_present(pud) (pud_val(pud) != 0)
|
||||
#define pud_page_vaddr(pud) (pud_val(pud) & ~PUD_MASKED_BITS)
|
||||
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (pmd_t *)(pud_val(pud) & ~PUD_MASKED_BITS);
|
||||
}
|
||||
|
||||
extern struct page *pud_page(pud_t pud);
|
||||
|
||||
|
@ -83,5 +83,11 @@ static inline int mm_is_thread_local(struct mm_struct *mm)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define arch_supports_page_table_move arch_supports_page_table_move
|
||||
static inline bool arch_supports_page_table_move(void)
|
||||
{
|
||||
return radix_enabled();
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_POWERPC_TLB_H */
|
||||
|
@ -926,10 +926,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
klp_init_thread_info(&init_task);
|
||||
|
||||
init_mm.start_code = (unsigned long)_stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
mm_iommu_init(&init_mm);
|
||||
irqstack_early_init();
|
||||
|
@ -32,7 +32,13 @@ void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long st
|
||||
struct hstate *hstate = hstate_file(vma->vm_file);
|
||||
|
||||
psize = hstate_get_psize(hstate);
|
||||
radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
|
||||
/*
|
||||
* Flush PWC even if we get PUD_SIZE hugetlb invalidate to keep this simpler.
|
||||
*/
|
||||
if (end - start >= PUD_SIZE)
|
||||
radix__flush_tlb_pwc_range_psize(vma->vm_mm, start, end, psize);
|
||||
else
|
||||
radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -820,7 +820,7 @@ static void __meminit remove_pud_table(pud_t *pud_start, unsigned long addr,
|
||||
continue;
|
||||
}
|
||||
|
||||
pmd_base = (pmd_t *)pud_page_vaddr(*pud);
|
||||
pmd_base = pud_pgtable(*pud);
|
||||
remove_pmd_table(pmd_base, addr, next);
|
||||
free_pmd_table(pmd_base, pud);
|
||||
}
|
||||
@ -854,7 +854,7 @@ static void __meminit remove_pagetable(unsigned long start, unsigned long end)
|
||||
continue;
|
||||
}
|
||||
|
||||
pud_base = (pud_t *)p4d_page_vaddr(*p4d);
|
||||
pud_base = p4d_pgtable(*p4d);
|
||||
remove_pud_table(pud_base, addr, next);
|
||||
free_pud_table(pud_base, p4d);
|
||||
}
|
||||
@ -1105,7 +1105,7 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
pmd_t *pmd;
|
||||
int i;
|
||||
|
||||
pmd = (pmd_t *)pud_page_vaddr(*pud);
|
||||
pmd = pud_pgtable(*pud);
|
||||
pud_clear(pud);
|
||||
|
||||
flush_tlb_kernel_range(addr, addr + PUD_SIZE);
|
||||
|
@ -1111,14 +1111,13 @@ static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_
|
||||
|
||||
static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
unsigned long start, unsigned long end)
|
||||
|
||||
{
|
||||
unsigned long pid;
|
||||
unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
|
||||
unsigned long page_size = 1UL << page_shift;
|
||||
unsigned long nr_pages = (end - start) >> page_shift;
|
||||
bool fullmm = (end == TLB_FLUSH_ALL);
|
||||
bool flush_pid;
|
||||
bool flush_pid, flush_pwc = false;
|
||||
enum tlb_flush_type type;
|
||||
|
||||
pid = mm->context.id;
|
||||
@ -1137,8 +1136,16 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
flush_pid = nr_pages > tlb_single_page_flush_ceiling;
|
||||
else
|
||||
flush_pid = nr_pages > tlb_local_single_page_flush_ceiling;
|
||||
/*
|
||||
* full pid flush already does the PWC flush. if it is not full pid
|
||||
* flush check the range is more than PMD and force a pwc flush
|
||||
* mremap() depends on this behaviour.
|
||||
*/
|
||||
if (!flush_pid && (end - start) >= PMD_SIZE)
|
||||
flush_pwc = true;
|
||||
|
||||
if (!mmu_has_feature(MMU_FTR_GTSE) && type == FLUSH_TYPE_GLOBAL) {
|
||||
unsigned long type = H_RPTI_TYPE_TLB;
|
||||
unsigned long tgt = H_RPTI_TARGET_CMMU;
|
||||
unsigned long pg_sizes = psize_to_rpti_pgsize(mmu_virtual_psize);
|
||||
|
||||
@ -1146,19 +1153,20 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
pg_sizes |= psize_to_rpti_pgsize(MMU_PAGE_2M);
|
||||
if (atomic_read(&mm->context.copros) > 0)
|
||||
tgt |= H_RPTI_TARGET_NMMU;
|
||||
pseries_rpt_invalidate(pid, tgt, H_RPTI_TYPE_TLB, pg_sizes,
|
||||
start, end);
|
||||
if (flush_pwc)
|
||||
type |= H_RPTI_TYPE_PWC;
|
||||
pseries_rpt_invalidate(pid, tgt, type, pg_sizes, start, end);
|
||||
} else if (flush_pid) {
|
||||
/*
|
||||
* We are now flushing a range larger than PMD size force a RIC_FLUSH_ALL
|
||||
*/
|
||||
if (type == FLUSH_TYPE_LOCAL) {
|
||||
_tlbiel_pid(pid, RIC_FLUSH_TLB);
|
||||
_tlbiel_pid(pid, RIC_FLUSH_ALL);
|
||||
} else {
|
||||
if (cputlb_use_tlbie()) {
|
||||
if (mm_needs_flush_escalation(mm))
|
||||
_tlbie_pid(pid, RIC_FLUSH_ALL);
|
||||
else
|
||||
_tlbie_pid(pid, RIC_FLUSH_TLB);
|
||||
_tlbie_pid(pid, RIC_FLUSH_ALL);
|
||||
} else {
|
||||
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_TLB);
|
||||
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1174,6 +1182,9 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
|
||||
if (type == FLUSH_TYPE_LOCAL) {
|
||||
asm volatile("ptesync": : :"memory");
|
||||
if (flush_pwc)
|
||||
/* For PWC, only one flush is needed */
|
||||
__tlbiel_pid(pid, 0, RIC_FLUSH_PWC);
|
||||
__tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
|
||||
if (hflush)
|
||||
__tlbiel_va_range(hstart, hend, pid,
|
||||
@ -1181,6 +1192,8 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
ppc_after_tlbiel_barrier();
|
||||
} else if (cputlb_use_tlbie()) {
|
||||
asm volatile("ptesync": : :"memory");
|
||||
if (flush_pwc)
|
||||
__tlbie_pid(pid, RIC_FLUSH_PWC);
|
||||
__tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
|
||||
if (hflush)
|
||||
__tlbie_va_range(hstart, hend, pid,
|
||||
@ -1188,10 +1201,10 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
|
||||
asm volatile("eieio; tlbsync; ptesync": : :"memory");
|
||||
} else {
|
||||
_tlbiel_va_range_multicast(mm,
|
||||
start, end, pid, page_size, mmu_virtual_psize, false);
|
||||
start, end, pid, page_size, mmu_virtual_psize, flush_pwc);
|
||||
if (hflush)
|
||||
_tlbiel_va_range_multicast(mm,
|
||||
hstart, hend, pid, PMD_SIZE, MMU_PAGE_2M, false);
|
||||
hstart, hend, pid, PMD_SIZE, MMU_PAGE_2M, flush_pwc);
|
||||
}
|
||||
}
|
||||
out:
|
||||
@ -1265,9 +1278,6 @@ void radix__flush_all_lpid_guest(unsigned int lpid)
|
||||
_tlbie_lpid_guest(lpid, RIC_FLUSH_ALL);
|
||||
}
|
||||
|
||||
static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, int psize);
|
||||
|
||||
void radix__tlb_flush(struct mmu_gather *tlb)
|
||||
{
|
||||
int psize = 0;
|
||||
@ -1374,8 +1384,8 @@ void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
return __radix__flush_tlb_range_psize(mm, start, end, psize, false);
|
||||
}
|
||||
|
||||
static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, int psize)
|
||||
void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, int psize)
|
||||
{
|
||||
__radix__flush_tlb_range_psize(mm, start, end, psize, true);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ struct page *p4d_page(p4d_t p4d)
|
||||
VM_WARN_ON(!p4d_huge(p4d));
|
||||
return pte_page(p4d_pte(p4d));
|
||||
}
|
||||
return virt_to_page(p4d_page_vaddr(p4d));
|
||||
return virt_to_page(p4d_pgtable(p4d));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -115,7 +115,7 @@ struct page *pud_page(pud_t pud)
|
||||
VM_WARN_ON(!pud_huge(pud));
|
||||
return pte_page(pud_pte(pud));
|
||||
}
|
||||
return virt_to_page(pud_page_vaddr(pud));
|
||||
return virt_to_page(pud_pgtable(pud));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -102,6 +102,8 @@ config PPC_BOOK3S_64
|
||||
select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
|
||||
select ARCH_SUPPORTS_HUGETLBFS
|
||||
select ARCH_SUPPORTS_NUMA_BALANCING
|
||||
select HAVE_MOVE_PMD
|
||||
select HAVE_MOVE_PUD
|
||||
select IRQ_WORK
|
||||
select PPC_MM_SLICES
|
||||
select PPC_HAVE_KUEP
|
||||
|
@ -26,8 +26,8 @@ config RISCV
|
||||
select ARCH_HAS_KCOV
|
||||
select ARCH_HAS_MMIOWB
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_DIRECT_MAP
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_SET_DIRECT_MAP if MMU
|
||||
select ARCH_HAS_SET_MEMORY if MMU
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
|
@ -60,9 +60,9 @@ static inline void pud_clear(pud_t *pudp)
|
||||
set_pud(pudp, __pud(0));
|
||||
}
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (unsigned long)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
||||
return (pmd_t *)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
||||
}
|
||||
|
||||
static inline struct page *pud_page(pud_t pud)
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
#define __ARCH_WANT_MEMFD_SECRET
|
||||
|
||||
#include <uapi/asm/unistd.h>
|
||||
|
||||
|
@ -264,10 +264,7 @@ static void __init parse_dtb(void)
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
parse_dtb();
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_stext, _etext, _edata, _end);
|
||||
|
||||
*cmdline_p = boot_command_line;
|
||||
|
||||
|
@ -1028,10 +1028,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
ROOT_DEV = Root_RAM0;
|
||||
|
||||
init_mm.start_code = (unsigned long) _text;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_text, _etext, _edata, _end);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
|
||||
nospec_auto_detect();
|
||||
|
@ -32,9 +32,9 @@ typedef struct { unsigned long long pmd; } pmd_t;
|
||||
#define pmd_val(x) ((x).pmd)
|
||||
#define __pmd(x) ((pmd_t) { (x) } )
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return pud_val(pud);
|
||||
return (pmd_t *)pud_val(pud);
|
||||
}
|
||||
|
||||
/* only used by the stubbed out hugetlb gup code, should never be called */
|
||||
|
@ -294,10 +294,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
if (!MOUNT_ROOT_RDONLY)
|
||||
root_mountflags &= ~MS_RDONLY;
|
||||
init_mm.start_code = (unsigned long) _text;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) _end;
|
||||
setup_initial_init_mm(_text, _etext, _edata, _end);
|
||||
|
||||
code_resource.start = virt_to_phys(_text);
|
||||
code_resource.end = virt_to_phys(_etext)-1;
|
||||
|
@ -151,13 +151,13 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
||||
return (unsigned long)__nocache_va(v << 4);
|
||||
}
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
if (srmmu_device_memory(pud_val(pud))) {
|
||||
return ~0;
|
||||
return (pmd_t *)~0;
|
||||
} else {
|
||||
unsigned long v = pud_val(pud) & SRMMU_PTD_PMASK;
|
||||
return (unsigned long)__nocache_va(v << 4);
|
||||
return (pmd_t *)__nocache_va(v << 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -841,23 +841,23 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
||||
return ((unsigned long) __va(pfn << PAGE_SHIFT));
|
||||
}
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
pte_t pte = __pte(pud_val(pud));
|
||||
unsigned long pfn;
|
||||
|
||||
pfn = pte_pfn(pte);
|
||||
|
||||
return ((unsigned long) __va(pfn << PAGE_SHIFT));
|
||||
return ((pmd_t *) __va(pfn << PAGE_SHIFT));
|
||||
}
|
||||
|
||||
#define pmd_page(pmd) virt_to_page((void *)pmd_page_vaddr(pmd))
|
||||
#define pud_page(pud) virt_to_page((void *)pud_page_vaddr(pud))
|
||||
#define pud_page(pud) virt_to_page((void *)pud_pgtable(pud))
|
||||
#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL)
|
||||
#define pud_present(pud) (pud_val(pud) != 0U)
|
||||
#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
|
||||
#define p4d_page_vaddr(p4d) \
|
||||
((unsigned long) __va(p4d_val(p4d)))
|
||||
#define p4d_pgtable(p4d) \
|
||||
((pud_t *) __va(p4d_val(p4d)))
|
||||
#define p4d_present(p4d) (p4d_val(p4d) != 0U)
|
||||
#define p4d_clear(p4dp) (p4d_val(*(p4dp)) = 0UL)
|
||||
|
||||
|
@ -83,7 +83,7 @@ static inline void pud_clear (pud_t *pud)
|
||||
}
|
||||
|
||||
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
|
||||
#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
|
||||
#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & PAGE_MASK))
|
||||
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
{
|
||||
|
@ -451,3 +451,4 @@
|
||||
444 i386 landlock_create_ruleset sys_landlock_create_ruleset
|
||||
445 i386 landlock_add_rule sys_landlock_add_rule
|
||||
446 i386 landlock_restrict_self sys_landlock_restrict_self
|
||||
447 i386 memfd_secret sys_memfd_secret
|
||||
|
@ -368,6 +368,7 @@
|
||||
444 common landlock_create_ruleset sys_landlock_create_ruleset
|
||||
445 common landlock_add_rule sys_landlock_add_rule
|
||||
446 common landlock_restrict_self sys_landlock_restrict_self
|
||||
447 common memfd_secret sys_memfd_secret
|
||||
|
||||
#
|
||||
# Due to a historical design error, certain syscalls are numbered differently
|
||||
|
@ -836,9 +836,9 @@ static inline int pud_present(pud_t pud)
|
||||
return pud_flags(pud) & _PAGE_PRESENT;
|
||||
}
|
||||
|
||||
static inline unsigned long pud_page_vaddr(pud_t pud)
|
||||
static inline pmd_t *pud_pgtable(pud_t pud)
|
||||
{
|
||||
return (unsigned long)__va(pud_val(pud) & pud_pfn_mask(pud));
|
||||
return (pmd_t *)__va(pud_val(pud) & pud_pfn_mask(pud));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -877,9 +877,9 @@ static inline int p4d_present(p4d_t p4d)
|
||||
return p4d_flags(p4d) & _PAGE_PRESENT;
|
||||
}
|
||||
|
||||
static inline unsigned long p4d_page_vaddr(p4d_t p4d)
|
||||
static inline pud_t *p4d_pgtable(p4d_t p4d)
|
||||
{
|
||||
return (unsigned long)__va(p4d_val(p4d) & p4d_pfn_mask(p4d));
|
||||
return (pud_t *)__va(p4d_val(p4d) & p4d_pfn_mask(p4d));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -69,7 +69,7 @@ static void printk_stack_address(unsigned long address, int reliable,
|
||||
const char *log_lvl)
|
||||
{
|
||||
touch_nmi_watchdog();
|
||||
printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
|
||||
printk("%s %s%pBb\n", log_lvl, reliable ? "" : "? ", (void *)address);
|
||||
}
|
||||
|
||||
static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
|
||||
|
@ -847,10 +847,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
if (!boot_params.hdr.root_flags)
|
||||
root_mountflags &= ~MS_RDONLY;
|
||||
init_mm.start_code = (unsigned long) _text;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = _brk_end;
|
||||
setup_initial_init_mm(_text, _etext, _edata, (void *)_brk_end);
|
||||
|
||||
code_resource.start = __pa_symbol(_text);
|
||||
code_resource.end = __pa_symbol(_etext)-1;
|
||||
|
@ -194,8 +194,8 @@ static void sync_global_pgds_l4(unsigned long start, unsigned long end)
|
||||
spin_lock(pgt_lock);
|
||||
|
||||
if (!p4d_none(*p4d_ref) && !p4d_none(*p4d))
|
||||
BUG_ON(p4d_page_vaddr(*p4d)
|
||||
!= p4d_page_vaddr(*p4d_ref));
|
||||
BUG_ON(p4d_pgtable(*p4d)
|
||||
!= p4d_pgtable(*p4d_ref));
|
||||
|
||||
if (p4d_none(*p4d))
|
||||
set_p4d(p4d, *p4d_ref);
|
||||
|
@ -1134,7 +1134,7 @@ static void __unmap_pmd_range(pud_t *pud, pmd_t *pmd,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
if (unmap_pte_range(pmd, start, end))
|
||||
if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
|
||||
if (try_to_free_pmd_page(pud_pgtable(*pud)))
|
||||
pud_clear(pud);
|
||||
}
|
||||
|
||||
@ -1178,7 +1178,7 @@ static void unmap_pmd_range(pud_t *pud, unsigned long start, unsigned long end)
|
||||
* Try again to free the PMD page if haven't succeeded above.
|
||||
*/
|
||||
if (!pud_none(*pud))
|
||||
if (try_to_free_pmd_page((pmd_t *)pud_page_vaddr(*pud)))
|
||||
if (try_to_free_pmd_page(pud_pgtable(*pud)))
|
||||
pud_clear(pud);
|
||||
}
|
||||
|
||||
|
@ -801,7 +801,7 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
pte_t *pte;
|
||||
int i;
|
||||
|
||||
pmd = (pmd_t *)pud_page_vaddr(*pud);
|
||||
pmd = pud_pgtable(*pud);
|
||||
pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
|
||||
if (!pmd_sv)
|
||||
return 0;
|
||||
|
@ -41,7 +41,7 @@ static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
|
||||
#define __p4d(x) ((p4d_t) { __pgd(x) })
|
||||
|
||||
#define pgd_page(pgd) (p4d_page((p4d_t){ pgd }))
|
||||
#define pgd_page_vaddr(pgd) (p4d_page_vaddr((p4d_t){ pgd }))
|
||||
#define pgd_page_vaddr(pgd) ((unsigned long)(p4d_pgtable((p4d_t){ pgd })))
|
||||
|
||||
/*
|
||||
* allocating and freeing a p4d is trivial: the 1-entry p4d is
|
||||
|
@ -51,7 +51,7 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
|
||||
#define __pmd(x) ((pmd_t) { __pud(x) } )
|
||||
|
||||
#define pud_page(pud) (pmd_page((pmd_t){ pud }))
|
||||
#define pud_page_vaddr(pud) (pmd_page_vaddr((pmd_t){ pud }))
|
||||
#define pud_pgtable(pud) ((pmd_t *)(pmd_page_vaddr((pmd_t){ pud })))
|
||||
|
||||
/*
|
||||
* allocating and freeing a pmd is trivial: the 1-entry pmd is
|
||||
|
@ -49,7 +49,7 @@ static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
|
||||
#define __pud(x) ((pud_t) { __p4d(x) })
|
||||
|
||||
#define p4d_page(p4d) (pud_page((pud_t){ p4d }))
|
||||
#define p4d_page_vaddr(p4d) (pud_page_vaddr((pud_t){ p4d }))
|
||||
#define p4d_pgtable(p4d) ((pud_t *)(pud_pgtable((pud_t){ p4d })))
|
||||
|
||||
/*
|
||||
* allocating and freeing a pud is trivial: the 1-entry pud is
|
||||
|
@ -214,10 +214,10 @@ static inline struct xbc_node * __init xbc_node_get_subkey(struct xbc_node *node
|
||||
* @value: Iterated value of array entry.
|
||||
*
|
||||
* Iterate array entries of given @key under @node. Each array entry node
|
||||
* is stroed to @anode and @value. If the @node doesn't have @key node,
|
||||
* is stored to @anode and @value. If the @node doesn't have @key node,
|
||||
* it does nothing.
|
||||
* Note that even if the found key node has only one value (not array)
|
||||
* this executes block once. Hoever, if the found key node has no value
|
||||
* this executes block once. However, if the found key node has no value
|
||||
* (key-only node), this does nothing. So don't use this for testing the
|
||||
* key-value pair existence.
|
||||
*/
|
||||
|
@ -8,5 +8,13 @@
|
||||
|
||||
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
|
||||
__u32 *size);
|
||||
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size);
|
||||
|
||||
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) || IS_ENABLED(CONFIG_CRASH_CORE)
|
||||
extern unsigned char vmlinux_build_id[BUILD_ID_SIZE_MAX];
|
||||
void init_vmlinux_build_id(void);
|
||||
#else
|
||||
static inline void init_vmlinux_build_id(void) { }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -35,12 +35,12 @@ enum compact_result {
|
||||
COMPACT_CONTINUE,
|
||||
|
||||
/*
|
||||
* The full zone was compacted scanned but wasn't successfull to compact
|
||||
* The full zone was compacted scanned but wasn't successful to compact
|
||||
* suitable pages.
|
||||
*/
|
||||
COMPACT_COMPLETE,
|
||||
/*
|
||||
* direct compaction has scanned part of the zone but wasn't successfull
|
||||
* direct compaction has scanned part of the zone but wasn't successful
|
||||
* to compact suitable pages.
|
||||
*/
|
||||
COMPACT_PARTIAL_SKIPPED,
|
||||
|
@ -259,7 +259,7 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
|
||||
/**
|
||||
* for_each_cpu_wrap - iterate over every cpu in a mask, starting at a specified location
|
||||
* @cpu: the (optionally unsigned) integer iterator
|
||||
* @mask: the cpumask poiter
|
||||
* @mask: the cpumask pointer
|
||||
* @start: the start location
|
||||
*
|
||||
* The implementation does not assume any bit in @mask is set (including @start).
|
||||
|
@ -38,8 +38,12 @@ phys_addr_t paddr_vmcoreinfo_note(void);
|
||||
|
||||
#define VMCOREINFO_OSRELEASE(value) \
|
||||
vmcoreinfo_append_str("OSRELEASE=%s\n", value)
|
||||
#define VMCOREINFO_BUILD_ID(value) \
|
||||
vmcoreinfo_append_str("BUILD-ID=%s\n", value)
|
||||
#define VMCOREINFO_BUILD_ID() \
|
||||
({ \
|
||||
static_assert(sizeof(vmlinux_build_id) == 20); \
|
||||
vmcoreinfo_append_str("BUILD-ID=%20phN\n", vmlinux_build_id); \
|
||||
})
|
||||
|
||||
#define VMCOREINFO_PAGESIZE(value) \
|
||||
vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
|
||||
#define VMCOREINFO_SYMBOL(name) \
|
||||
@ -69,10 +73,6 @@ extern unsigned char *vmcoreinfo_data;
|
||||
extern size_t vmcoreinfo_size;
|
||||
extern u32 *vmcoreinfo_note;
|
||||
|
||||
/* raw contents of kernel .notes section */
|
||||
extern const void __start_notes __weak;
|
||||
extern const void __stop_notes __weak;
|
||||
|
||||
Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
|
||||
void *data, size_t data_len);
|
||||
void final_note(Elf_Word *buf);
|
||||
|
@ -18,7 +18,7 @@ enum debug_obj_state {
|
||||
struct debug_obj_descr;
|
||||
|
||||
/**
|
||||
* struct debug_obj - representaion of an tracked object
|
||||
* struct debug_obj - representation of an tracked object
|
||||
* @node: hlist node to link the object into the tracker list
|
||||
* @state: tracked object state
|
||||
* @astate: current active state
|
||||
|
@ -113,7 +113,7 @@ int hmm_range_fault(struct hmm_range *range);
|
||||
* HMM_RANGE_DEFAULT_TIMEOUT - default timeout (ms) when waiting for a range
|
||||
*
|
||||
* When waiting for mmu notifiers we need some kind of time out otherwise we
|
||||
* could potentialy wait for ever, 1000ms ie 1s sounds like a long time to
|
||||
* could potentially wait for ever, 1000ms ie 1s sounds like a long time to
|
||||
* wait already.
|
||||
*/
|
||||
#define HMM_RANGE_DEFAULT_TIMEOUT 1000
|
||||
|
@ -51,7 +51,7 @@ struct hugepage_subpool {
|
||||
long count;
|
||||
long max_hpages; /* Maximum huge pages or -1 if no maximum. */
|
||||
long used_hpages; /* Used count against maximum, includes */
|
||||
/* both alloced and reserved pages. */
|
||||
/* both allocated and reserved pages. */
|
||||
struct hstate *hstate;
|
||||
long min_hpages; /* Minimum huge pages or -1 if no minimum. */
|
||||
long rsv_hpages; /* Pages reserved against global pool to */
|
||||
@ -85,7 +85,7 @@ struct resv_map {
|
||||
* by a resv_map's lock. The set of regions within the resv_map represent
|
||||
* reservations for huge pages, or huge pages that have already been
|
||||
* instantiated within the map. The from and to elements are huge page
|
||||
* indicies into the associated mapping. from indicates the starting index
|
||||
* indices into the associated mapping. from indicates the starting index
|
||||
* of the region. to represents the first index past the end of the region.
|
||||
*
|
||||
* For example, a file region structure with from == 0 and to == 4 represents
|
||||
@ -797,7 +797,7 @@ static inline bool hugepage_migration_supported(struct hstate *h)
|
||||
* It determines whether or not a huge page should be placed on
|
||||
* movable zone or not. Movability of any huge page should be
|
||||
* required only if huge page size is supported for migration.
|
||||
* There wont be any reason for the huge page to be movable if
|
||||
* There won't be any reason for the huge page to be movable if
|
||||
* it is not migratable to start with. Also the size of the huge
|
||||
* page should be large enough to be placed under a movable zone
|
||||
* and still feasible enough to be migratable. Just the presence
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define _LINUX_KALLSYMS_H
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/mm.h>
|
||||
@ -15,8 +16,10 @@
|
||||
#include <asm/sections.h>
|
||||
|
||||
#define KSYM_NAME_LEN 128
|
||||
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \
|
||||
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1)
|
||||
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
|
||||
(KSYM_NAME_LEN - 1) + \
|
||||
2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
|
||||
(BUILD_ID_SIZE_MAX * 2) + 1)
|
||||
|
||||
struct cred;
|
||||
struct module;
|
||||
@ -91,8 +94,10 @@ const char *kallsyms_lookup(unsigned long addr,
|
||||
|
||||
/* Look up a kernel symbol and return it in a text buffer. */
|
||||
extern int sprint_symbol(char *buffer, unsigned long address);
|
||||
extern int sprint_symbol_build_id(char *buffer, unsigned long address);
|
||||
extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
|
||||
extern int sprint_backtrace(char *buffer, unsigned long address);
|
||||
extern int sprint_backtrace_build_id(char *buffer, unsigned long address);
|
||||
|
||||
int lookup_symbol_name(unsigned long addr, char *symname);
|
||||
int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
|
||||
@ -128,6 +133,12 @@ static inline int sprint_symbol(char *buffer, unsigned long addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sprint_symbol_build_id(char *buffer, unsigned long address)
|
||||
{
|
||||
*buffer = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr)
|
||||
{
|
||||
*buffer = '\0';
|
||||
@ -140,6 +151,12 @@ static inline int sprint_backtrace(char *buffer, unsigned long addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sprint_backtrace_build_id(char *buffer, unsigned long addr)
|
||||
{
|
||||
*buffer = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lookup_symbol_name(unsigned long addr, char *symname)
|
||||
{
|
||||
return -ERANGE;
|
||||
|
@ -146,7 +146,7 @@ typedef enum lru_status (*list_lru_walk_cb)(struct list_head *item,
|
||||
* @lru: the lru pointer.
|
||||
* @nid: the node id to scan from.
|
||||
* @memcg: the cgroup to scan from.
|
||||
* @isolate: callback function that is resposible for deciding what to do with
|
||||
* @isolate: callback function that is responsible for deciding what to do with
|
||||
* the item currently being scanned
|
||||
* @cb_arg: opaque type that will be passed to @isolate
|
||||
* @nr_to_walk: how many items to scan.
|
||||
@ -172,7 +172,7 @@ unsigned long list_lru_walk_one(struct list_lru *lru,
|
||||
* @lru: the lru pointer.
|
||||
* @nid: the node id to scan from.
|
||||
* @memcg: the cgroup to scan from.
|
||||
* @isolate: callback function that is resposible for deciding what to do with
|
||||
* @isolate: callback function that is responsible for deciding what to do with
|
||||
* the item currently being scanned
|
||||
* @cb_arg: opaque type that will be passed to @isolate
|
||||
* @nr_to_walk: how many items to scan.
|
||||
|
@ -32,7 +32,7 @@ This header file (and its .c file; kernel-doc of functions see there)
|
||||
Because of this later property, it is called "lru_cache".
|
||||
As it actually Tracks Objects in an Active SeT, we could also call it
|
||||
toast (incidentally that is what may happen to the data on the
|
||||
backend storage uppon next resync, if we don't get it right).
|
||||
backend storage upon next resync, if we don't get it right).
|
||||
|
||||
What for?
|
||||
|
||||
@ -152,7 +152,7 @@ struct lc_element {
|
||||
* for paranoia, and for "lc_element_to_index" */
|
||||
unsigned lc_index;
|
||||
/* if we want to track a larger set of objects,
|
||||
* it needs to become arch independend u64 */
|
||||
* it needs to become an architecture independent u64 */
|
||||
unsigned lc_number;
|
||||
/* special label when on free list */
|
||||
#define LC_FREE (~0U)
|
||||
@ -263,7 +263,7 @@ extern void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char
|
||||
*
|
||||
* Allows (expects) the set to be "dirty". Note that the reference counts and
|
||||
* order on the active and lru lists may still change. Used to serialize
|
||||
* changing transactions. Returns true if we aquired the lock.
|
||||
* changing transactions. Returns true if we acquired the lock.
|
||||
*/
|
||||
static inline int lc_try_lock_for_transaction(struct lru_cache *lc)
|
||||
{
|
||||
@ -275,7 +275,7 @@ static inline int lc_try_lock_for_transaction(struct lru_cache *lc)
|
||||
* @lc: the lru cache to operate on
|
||||
*
|
||||
* Note that the reference counts and order on the active and lru lists may
|
||||
* still change. Only works on a "clean" set. Returns true if we aquired the
|
||||
* still change. Only works on a "clean" set. Returns true if we acquired the
|
||||
* lock, which means there are no pending changes, and any further attempt to
|
||||
* change the set will not succeed until the next lc_unlock().
|
||||
*/
|
||||
|
@ -238,6 +238,9 @@ int __add_to_page_cache_locked(struct page *page, struct address_space *mapping,
|
||||
|
||||
#define lru_to_page(head) (list_entry((head)->prev, struct page, lru))
|
||||
|
||||
void setup_initial_init_mm(void *start_code, void *end_code,
|
||||
void *end_data, void *brk);
|
||||
|
||||
/*
|
||||
* Linux kernel virtual memory manager primitives.
|
||||
* The idea being to have a "virtual" mm in the same way
|
||||
|
@ -33,7 +33,7 @@ struct mmu_interval_notifier;
|
||||
*
|
||||
* @MMU_NOTIFY_SOFT_DIRTY: soft dirty accounting (still same page and same
|
||||
* access flags). User should soft dirty the page in the end callback to make
|
||||
* sure that anyone relying on soft dirtyness catch pages that might be written
|
||||
* sure that anyone relying on soft dirtiness catch pages that might be written
|
||||
* through non CPU mappings.
|
||||
*
|
||||
* @MMU_NOTIFY_RELEASE: used during mmu_interval_notifier invalidate to signal
|
||||
@ -167,7 +167,7 @@ struct mmu_notifier_ops {
|
||||
* decrease the refcount. If the refcount is decreased on
|
||||
* invalidate_range_start() then the VM can free pages as page
|
||||
* table entries are removed. If the refcount is only
|
||||
* droppped on invalidate_range_end() then the driver itself
|
||||
* dropped on invalidate_range_end() then the driver itself
|
||||
* will drop the last refcount but it must take care to flush
|
||||
* any secondary tlb before doing the final free on the
|
||||
* page. Pages will no longer be referenced by the linux
|
||||
@ -196,7 +196,7 @@ struct mmu_notifier_ops {
|
||||
* If invalidate_range() is used to manage a non-CPU TLB with
|
||||
* shared page-tables, it not necessary to implement the
|
||||
* invalidate_range_start()/end() notifiers, as
|
||||
* invalidate_range() alread catches the points in time when an
|
||||
* invalidate_range() already catches the points in time when an
|
||||
* external TLB range needs to be flushed. For more in depth
|
||||
* discussion on this see Documentation/vm/mmu_notifier.rst
|
||||
*
|
||||
@ -369,7 +369,7 @@ mmu_interval_read_retry(struct mmu_interval_notifier *interval_sub,
|
||||
* mmu_interval_read_retry() will return true.
|
||||
*
|
||||
* False is not reliable and only suggests a collision may not have
|
||||
* occured. It can be called many times and does not have to hold the user
|
||||
* occurred. It can be called many times and does not have to hold the user
|
||||
* provided lock.
|
||||
*
|
||||
* This call can be used as part of loops and other expensive operations to
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/kmod.h>
|
||||
@ -369,6 +370,11 @@ struct module {
|
||||
/* Unique handle for this module */
|
||||
char name[MODULE_NAME_LEN];
|
||||
|
||||
#ifdef CONFIG_STACKTRACE_BUILD_ID
|
||||
/* Module build ID */
|
||||
unsigned char build_id[BUILD_ID_SIZE_MAX];
|
||||
#endif
|
||||
|
||||
/* Sysfs stuff. */
|
||||
struct module_kobject mkobj;
|
||||
struct module_attribute *modinfo_attrs;
|
||||
@ -636,7 +642,7 @@ void *dereference_module_function_descriptor(struct module *mod, void *ptr);
|
||||
const char *module_address_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname,
|
||||
char **modname, const unsigned char **modbuildid,
|
||||
char *namebuf);
|
||||
int lookup_module_symbol_name(unsigned long addr, char *symname);
|
||||
int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
|
||||
@ -740,6 +746,7 @@ static inline const char *module_address_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname,
|
||||
const unsigned char **modbuildid,
|
||||
char *namebuf)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -119,7 +119,7 @@ static inline const unsigned long *__nodemask_pr_bits(const nodemask_t *m)
|
||||
* The inline keyword gives the compiler room to decide to inline, or
|
||||
* not inline a function as it sees best. However, as these functions
|
||||
* are called in both __init and non-__init functions, if they are not
|
||||
* inlined we will end up with a section mis-match error (of the type of
|
||||
* inlined we will end up with a section mismatch error (of the type of
|
||||
* freeable items not being freed). So we must use __always_inline here
|
||||
* to fix the problem. If other functions in the future also end up in
|
||||
* this situation they will also need to be annotated as __always_inline
|
||||
@ -515,7 +515,7 @@ static inline int node_random(const nodemask_t *mask)
|
||||
#define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
|
||||
|
||||
/*
|
||||
* For nodemask scrach area.
|
||||
* For nodemask scratch area.
|
||||
* NODEMASK_ALLOC(type, name) allocates an object with a specified type and
|
||||
* name.
|
||||
*/
|
||||
@ -528,7 +528,7 @@ static inline int node_random(const nodemask_t *mask)
|
||||
#define NODEMASK_FREE(m) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* A example struture for using NODEMASK_ALLOC, used in mempolicy. */
|
||||
/* Example structure for using NODEMASK_ALLOC, used in mempolicy. */
|
||||
struct nodemask_scratch {
|
||||
nodemask_t mask1;
|
||||
nodemask_t mask2;
|
||||
|
@ -412,7 +412,7 @@ do { \
|
||||
* instead.
|
||||
*
|
||||
* If there is no other protection through preempt disable and/or disabling
|
||||
* interupts then one of these RMW operations can show unexpected behavior
|
||||
* interrupts then one of these RMW operations can show unexpected behavior
|
||||
* because the execution thread was rescheduled on another processor or an
|
||||
* interrupt occurred and the same percpu variable was modified from the
|
||||
* interrupt context.
|
||||
|
@ -213,7 +213,7 @@ static inline void percpu_ref_get_many(struct percpu_ref *ref, unsigned long nr)
|
||||
* percpu_ref_get - increment a percpu refcount
|
||||
* @ref: percpu_ref to get
|
||||
*
|
||||
* Analagous to atomic_long_inc().
|
||||
* Analogous to atomic_long_inc().
|
||||
*
|
||||
* This function is safe to call as long as @ref is between init and exit.
|
||||
*/
|
||||
|
@ -106,7 +106,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
|
||||
#ifndef pmd_offset
|
||||
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
{
|
||||
return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
|
||||
return pud_pgtable(*pud) + pmd_index(address);
|
||||
}
|
||||
#define pmd_offset pmd_offset
|
||||
#endif
|
||||
@ -114,7 +114,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
#ifndef pud_offset
|
||||
static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
|
||||
{
|
||||
return (pud_t *)p4d_page_vaddr(*p4d) + pud_index(address);
|
||||
return p4d_pgtable(*p4d) + pud_index(address);
|
||||
}
|
||||
#define pud_offset pud_offset
|
||||
#endif
|
||||
|
@ -474,7 +474,7 @@ sg_page_iter_dma_address(struct sg_dma_page_iter *dma_iter)
|
||||
* Iterates over sg entries mapping page-by-page. On each successful
|
||||
* iteration, @miter->page points to the mapped page and
|
||||
* @miter->length bytes of data can be accessed at @miter->addr. As
|
||||
* long as an interation is enclosed between start and stop, the user
|
||||
* long as an iteration is enclosed between start and stop, the user
|
||||
* is free to choose control structure and when to stop.
|
||||
*
|
||||
* @miter->consumed is set to @miter->length on each iteration. It
|
||||
|
54
include/linux/secretmem.h
Normal file
54
include/linux/secretmem.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _LINUX_SECRETMEM_H
|
||||
#define _LINUX_SECRETMEM_H
|
||||
|
||||
#ifdef CONFIG_SECRETMEM
|
||||
|
||||
extern const struct address_space_operations secretmem_aops;
|
||||
|
||||
static inline bool page_is_secretmem(struct page *page)
|
||||
{
|
||||
struct address_space *mapping;
|
||||
|
||||
/*
|
||||
* Using page_mapping() is quite slow because of the actual call
|
||||
* instruction and repeated compound_head(page) inside the
|
||||
* page_mapping() function.
|
||||
* We know that secretmem pages are not compound and LRU so we can
|
||||
* save a couple of cycles here.
|
||||
*/
|
||||
if (PageCompound(page) || !PageLRU(page))
|
||||
return false;
|
||||
|
||||
mapping = (struct address_space *)
|
||||
((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
|
||||
|
||||
if (mapping != page->mapping)
|
||||
return false;
|
||||
|
||||
return mapping->a_ops == &secretmem_aops;
|
||||
}
|
||||
|
||||
bool vma_is_secretmem(struct vm_area_struct *vma);
|
||||
bool secretmem_active(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline bool vma_is_secretmem(struct vm_area_struct *vma)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool page_is_secretmem(struct page *page)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool secretmem_active(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SECRETMEM */
|
||||
|
||||
#endif /* _LINUX_SECRETMEM_H */
|
@ -28,7 +28,19 @@ static inline bool kernel_page_present(struct page *page)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */
|
||||
/*
|
||||
* Some architectures, e.g. ARM64 can disable direct map modifications at
|
||||
* boot time. Let them overrive this query.
|
||||
*/
|
||||
#ifndef can_set_direct_map
|
||||
static inline bool can_set_direct_map(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#define can_set_direct_map can_set_direct_map
|
||||
#endif
|
||||
#endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */
|
||||
|
||||
#ifndef set_mce_nospec
|
||||
static inline int set_mce_nospec(unsigned long pfn, bool unmap)
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* This struct is used to pass information from page reclaim to the shrinkers.
|
||||
* We consolidate the values for easier extention later.
|
||||
* We consolidate the values for easier extension later.
|
||||
*
|
||||
* The 'gfpmask' refers to the allocation we are currently trying to
|
||||
* fulfil.
|
||||
|
@ -1050,6 +1050,7 @@ asmlinkage long sys_landlock_create_ruleset(const struct landlock_ruleset_attr _
|
||||
asmlinkage long sys_landlock_add_rule(int ruleset_fd, enum landlock_rule_type rule_type,
|
||||
const void __user *rule_attr, __u32 flags);
|
||||
asmlinkage long sys_landlock_restrict_self(int ruleset_fd, __u32 flags);
|
||||
asmlinkage long sys_memfd_secret(unsigned int flags);
|
||||
|
||||
/*
|
||||
* Architecture-specific system calls
|
||||
|
@ -29,7 +29,7 @@ struct notifier_block; /* in notifier.h */
|
||||
#define VM_NO_HUGE_VMAP 0x00000400 /* force PAGE_SIZE pte mapping */
|
||||
|
||||
/*
|
||||
* VM_KASAN is used slighly differently depending on CONFIG_KASAN_VMALLOC.
|
||||
* VM_KASAN is used slightly differently depending on CONFIG_KASAN_VMALLOC.
|
||||
*
|
||||
* If IS_ENABLED(CONFIG_KASAN_VMALLOC), VM_KASAN is set on a vm_struct after
|
||||
* shadow memory has been mapped. It's used to handle allocation errors so that
|
||||
@ -247,7 +247,7 @@ static inline void set_vm_flush_reset_perms(void *addr)
|
||||
extern long vread(char *buf, char *addr, unsigned long count);
|
||||
|
||||
/*
|
||||
* Internals. Dont't use..
|
||||
* Internals. Don't use..
|
||||
*/
|
||||
extern struct list_head vmap_area_list;
|
||||
extern __init void vm_area_add_early(struct vm_struct *vm);
|
||||
|
@ -873,8 +873,13 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
|
||||
#define __NR_landlock_restrict_self 446
|
||||
__SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
|
||||
|
||||
#ifdef __ARCH_WANT_MEMFD_SECRET
|
||||
#define __NR_memfd_secret 447
|
||||
__SYSCALL(__NR_memfd_secret, sys_memfd_secret)
|
||||
#endif
|
||||
|
||||
#undef __NR_syscalls
|
||||
#define __NR_syscalls 447
|
||||
#define __NR_syscalls 448
|
||||
|
||||
/*
|
||||
* 32 bit systems traditionally used different
|
||||
|
@ -97,5 +97,6 @@
|
||||
#define DEVMEM_MAGIC 0x454d444d /* "DMEM" */
|
||||
#define Z3FOLD_MAGIC 0x33
|
||||
#define PPC_CMM_MAGIC 0xc7571590
|
||||
#define SECRETMEM_MAGIC 0x5345434d /* "SECM" */
|
||||
|
||||
#endif /* __LINUX_MAGIC_H__ */
|
||||
|
@ -1847,6 +1847,7 @@ config SLUB_DEBUG
|
||||
default y
|
||||
bool "Enable SLUB debugging support" if EXPERT
|
||||
depends on SLUB && SYSFS
|
||||
select STACKDEPOT if STACKTRACE_SUPPORT
|
||||
help
|
||||
SLUB has extensive debug support features. Disabling these can
|
||||
result in significant savings in code size. This also disables
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpuset.h>
|
||||
@ -913,6 +914,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
|
||||
set_task_stack_end_magic(&init_task);
|
||||
smp_setup_processor_id();
|
||||
debug_objects_early_init();
|
||||
init_vmlinux_build_id();
|
||||
|
||||
cgroup_init_early();
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com>
|
||||
*/
|
||||
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/crash_core.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/vmalloc.h>
|
||||
@ -378,53 +379,6 @@ phys_addr_t __weak paddr_vmcoreinfo_note(void)
|
||||
}
|
||||
EXPORT_SYMBOL(paddr_vmcoreinfo_note);
|
||||
|
||||
#define NOTES_SIZE (&__stop_notes - &__start_notes)
|
||||
#define BUILD_ID_MAX SHA1_DIGEST_SIZE
|
||||
#define NT_GNU_BUILD_ID 3
|
||||
|
||||
struct elf_note_section {
|
||||
struct elf_note n_hdr;
|
||||
u8 n_data[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Add build ID from .notes section as generated by the GNU ld(1)
|
||||
* or LLVM lld(1) --build-id option.
|
||||
*/
|
||||
static void add_build_id_vmcoreinfo(void)
|
||||
{
|
||||
char build_id[BUILD_ID_MAX * 2 + 1];
|
||||
int n_remain = NOTES_SIZE;
|
||||
|
||||
while (n_remain >= sizeof(struct elf_note)) {
|
||||
const struct elf_note_section *note_sec =
|
||||
&__start_notes + NOTES_SIZE - n_remain;
|
||||
const u32 n_namesz = note_sec->n_hdr.n_namesz;
|
||||
|
||||
if (note_sec->n_hdr.n_type == NT_GNU_BUILD_ID &&
|
||||
n_namesz != 0 &&
|
||||
!strcmp((char *)¬e_sec->n_data[0], "GNU")) {
|
||||
if (note_sec->n_hdr.n_descsz <= BUILD_ID_MAX) {
|
||||
const u32 n_descsz = note_sec->n_hdr.n_descsz;
|
||||
const u8 *s = ¬e_sec->n_data[n_namesz];
|
||||
|
||||
s = PTR_ALIGN(s, 4);
|
||||
bin2hex(build_id, s, n_descsz);
|
||||
build_id[2 * n_descsz] = '\0';
|
||||
VMCOREINFO_BUILD_ID(build_id);
|
||||
return;
|
||||
}
|
||||
pr_warn("Build ID is too large to include in vmcoreinfo: %u > %u\n",
|
||||
note_sec->n_hdr.n_descsz,
|
||||
BUILD_ID_MAX);
|
||||
return;
|
||||
}
|
||||
n_remain -= sizeof(struct elf_note) +
|
||||
ALIGN(note_sec->n_hdr.n_namesz, 4) +
|
||||
ALIGN(note_sec->n_hdr.n_descsz, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init crash_save_vmcoreinfo_init(void)
|
||||
{
|
||||
vmcoreinfo_data = (unsigned char *)get_zeroed_page(GFP_KERNEL);
|
||||
@ -443,7 +397,7 @@ static int __init crash_save_vmcoreinfo_init(void)
|
||||
}
|
||||
|
||||
VMCOREINFO_OSRELEASE(init_uts_ns.name.release);
|
||||
add_build_id_vmcoreinfo();
|
||||
VMCOREINFO_BUILD_ID();
|
||||
VMCOREINFO_PAGESIZE(PAGE_SIZE);
|
||||
|
||||
VMCOREINFO_SYMBOL(init_uts_ns);
|
||||
|
@ -25,7 +25,10 @@
|
||||
#include <linux/filter.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/*
|
||||
* These will be re-linked against their real values
|
||||
@ -297,21 +300,14 @@ int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
|
||||
get_symbol_pos(addr, symbolsize, offset);
|
||||
return 1;
|
||||
}
|
||||
return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
|
||||
return !!module_address_lookup(addr, symbolsize, offset, NULL, NULL, namebuf) ||
|
||||
!!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup an address
|
||||
* - modname is set to NULL if it's in the kernel.
|
||||
* - We guarantee that the returned name is valid until we reschedule even if.
|
||||
* It resides in a module.
|
||||
* - We also guarantee that modname will be valid until rescheduled.
|
||||
*/
|
||||
const char *kallsyms_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname, char *namebuf)
|
||||
static const char *kallsyms_lookup_buildid(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset, char **modname,
|
||||
const unsigned char **modbuildid, char *namebuf)
|
||||
{
|
||||
const char *ret;
|
||||
|
||||
@ -327,6 +323,8 @@ const char *kallsyms_lookup(unsigned long addr,
|
||||
namebuf, KSYM_NAME_LEN);
|
||||
if (modname)
|
||||
*modname = NULL;
|
||||
if (modbuildid)
|
||||
*modbuildid = NULL;
|
||||
|
||||
ret = namebuf;
|
||||
goto found;
|
||||
@ -334,7 +332,7 @@ const char *kallsyms_lookup(unsigned long addr,
|
||||
|
||||
/* See if it's in a module or a BPF JITed image. */
|
||||
ret = module_address_lookup(addr, symbolsize, offset,
|
||||
modname, namebuf);
|
||||
modname, modbuildid, namebuf);
|
||||
if (!ret)
|
||||
ret = bpf_address_lookup(addr, symbolsize,
|
||||
offset, modname, namebuf);
|
||||
@ -348,6 +346,22 @@ found:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup an address
|
||||
* - modname is set to NULL if it's in the kernel.
|
||||
* - We guarantee that the returned name is valid until we reschedule even if.
|
||||
* It resides in a module.
|
||||
* - We also guarantee that modname will be valid until rescheduled.
|
||||
*/
|
||||
const char *kallsyms_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname, char *namebuf)
|
||||
{
|
||||
return kallsyms_lookup_buildid(addr, symbolsize, offset, modname,
|
||||
NULL, namebuf);
|
||||
}
|
||||
|
||||
int lookup_symbol_name(unsigned long addr, char *symname)
|
||||
{
|
||||
int res;
|
||||
@ -404,15 +418,17 @@ found:
|
||||
|
||||
/* Look up a kernel symbol and return it in a text buffer. */
|
||||
static int __sprint_symbol(char *buffer, unsigned long address,
|
||||
int symbol_offset, int add_offset)
|
||||
int symbol_offset, int add_offset, int add_buildid)
|
||||
{
|
||||
char *modname;
|
||||
const unsigned char *buildid;
|
||||
const char *name;
|
||||
unsigned long offset, size;
|
||||
int len;
|
||||
|
||||
address += symbol_offset;
|
||||
name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
|
||||
name = kallsyms_lookup_buildid(address, &size, &offset, &modname, &buildid,
|
||||
buffer);
|
||||
if (!name)
|
||||
return sprintf(buffer, "0x%lx", address - symbol_offset);
|
||||
|
||||
@ -424,8 +440,19 @@ static int __sprint_symbol(char *buffer, unsigned long address,
|
||||
if (add_offset)
|
||||
len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
|
||||
|
||||
if (modname)
|
||||
len += sprintf(buffer + len, " [%s]", modname);
|
||||
if (modname) {
|
||||
len += sprintf(buffer + len, " [%s", modname);
|
||||
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
|
||||
if (add_buildid && buildid) {
|
||||
/* build ID should match length of sprintf */
|
||||
#if IS_ENABLED(CONFIG_MODULES)
|
||||
static_assert(sizeof(typeof_member(struct module, build_id)) == 20);
|
||||
#endif
|
||||
len += sprintf(buffer + len, " %20phN", buildid);
|
||||
}
|
||||
#endif
|
||||
len += sprintf(buffer + len, "]");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -443,10 +470,27 @@ static int __sprint_symbol(char *buffer, unsigned long address,
|
||||
*/
|
||||
int sprint_symbol(char *buffer, unsigned long address)
|
||||
{
|
||||
return __sprint_symbol(buffer, address, 0, 1);
|
||||
return __sprint_symbol(buffer, address, 0, 1, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sprint_symbol);
|
||||
|
||||
/**
|
||||
* sprint_symbol_build_id - Look up a kernel symbol and return it in a text buffer
|
||||
* @buffer: buffer to be stored
|
||||
* @address: address to lookup
|
||||
*
|
||||
* This function looks up a kernel symbol with @address and stores its name,
|
||||
* offset, size, module name and module build ID to @buffer if possible. If no
|
||||
* symbol was found, just saves its @address as is.
|
||||
*
|
||||
* This function returns the number of bytes stored in @buffer.
|
||||
*/
|
||||
int sprint_symbol_build_id(char *buffer, unsigned long address)
|
||||
{
|
||||
return __sprint_symbol(buffer, address, 0, 1, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sprint_symbol_build_id);
|
||||
|
||||
/**
|
||||
* sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
|
||||
* @buffer: buffer to be stored
|
||||
@ -460,7 +504,7 @@ EXPORT_SYMBOL_GPL(sprint_symbol);
|
||||
*/
|
||||
int sprint_symbol_no_offset(char *buffer, unsigned long address)
|
||||
{
|
||||
return __sprint_symbol(buffer, address, 0, 0);
|
||||
return __sprint_symbol(buffer, address, 0, 0, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
|
||||
|
||||
@ -480,7 +524,27 @@ EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
|
||||
*/
|
||||
int sprint_backtrace(char *buffer, unsigned long address)
|
||||
{
|
||||
return __sprint_symbol(buffer, address, -1, 1);
|
||||
return __sprint_symbol(buffer, address, -1, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* sprint_backtrace_build_id - Look up a backtrace symbol and return it in a text buffer
|
||||
* @buffer: buffer to be stored
|
||||
* @address: address to lookup
|
||||
*
|
||||
* This function is for stack backtrace and does the same thing as
|
||||
* sprint_symbol() but with modified/decreased @address. If there is a
|
||||
* tail-call to the function marked "noreturn", gcc optimized out code after
|
||||
* the call so that the stack-saved return address could point outside of the
|
||||
* caller. This function ensures that kallsyms will find the original caller
|
||||
* by decreasing @address. This function also appends the module build ID to
|
||||
* the @buffer if @address is within a kernel module.
|
||||
*
|
||||
* This function returns the number of bytes stored in @buffer.
|
||||
*/
|
||||
int sprint_backtrace_build_id(char *buffer, unsigned long address)
|
||||
{
|
||||
return __sprint_symbol(buffer, address, -1, 1, 1);
|
||||
}
|
||||
|
||||
/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/trace_events.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sysfs.h>
|
||||
@ -1465,6 +1466,13 @@ resolve_symbol_wait(struct module *mod,
|
||||
return ksym;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
static inline bool sect_empty(const Elf_Shdr *sect)
|
||||
{
|
||||
return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* /sys/module/foo/sections stuff
|
||||
* J. Corbet <corbet@lwn.net>
|
||||
@ -1472,11 +1480,6 @@ resolve_symbol_wait(struct module *mod,
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
static inline bool sect_empty(const Elf_Shdr *sect)
|
||||
{
|
||||
return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0;
|
||||
}
|
||||
|
||||
struct module_sect_attr {
|
||||
struct bin_attribute battr;
|
||||
unsigned long address;
|
||||
@ -2797,6 +2800,26 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
|
||||
}
|
||||
#endif /* CONFIG_KALLSYMS */
|
||||
|
||||
#if IS_ENABLED(CONFIG_KALLSYMS) && IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
|
||||
static void init_build_id(struct module *mod, const struct load_info *info)
|
||||
{
|
||||
const Elf_Shdr *sechdr;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < info->hdr->e_shnum; i++) {
|
||||
sechdr = &info->sechdrs[i];
|
||||
if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE &&
|
||||
!build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id,
|
||||
sechdr->sh_size))
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void init_build_id(struct module *mod, const struct load_info *info)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num)
|
||||
{
|
||||
if (!debug)
|
||||
@ -4021,6 +4044,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
||||
goto free_arch_cleanup;
|
||||
}
|
||||
|
||||
init_build_id(mod, info);
|
||||
dynamic_debug_setup(mod, info->debug, info->num_debug);
|
||||
|
||||
/* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
|
||||
@ -4254,6 +4278,7 @@ const char *module_address_lookup(unsigned long addr,
|
||||
unsigned long *size,
|
||||
unsigned long *offset,
|
||||
char **modname,
|
||||
const unsigned char **modbuildid,
|
||||
char *namebuf)
|
||||
{
|
||||
const char *ret = NULL;
|
||||
@ -4264,6 +4289,13 @@ const char *module_address_lookup(unsigned long addr,
|
||||
if (mod) {
|
||||
if (modname)
|
||||
*modname = mod->name;
|
||||
if (modbuildid) {
|
||||
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
|
||||
*modbuildid = mod->build_id;
|
||||
#else
|
||||
*modbuildid = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = find_kallsyms_symbol(mod, addr, size, offset);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/secretmem.h>
|
||||
#include <trace/events/power.h>
|
||||
|
||||
#include "power.h"
|
||||
@ -81,7 +82,9 @@ void hibernate_release(void)
|
||||
|
||||
bool hibernation_available(void)
|
||||
{
|
||||
return nohibernate == 0 && !security_locked_down(LOCKDOWN_HIBERNATION);
|
||||
return nohibernate == 0 &&
|
||||
!security_locked_down(LOCKDOWN_HIBERNATION) &&
|
||||
!secretmem_active();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -358,6 +358,8 @@ COND_SYSCALL(pkey_mprotect);
|
||||
COND_SYSCALL(pkey_alloc);
|
||||
COND_SYSCALL(pkey_free);
|
||||
|
||||
/* memfd_secret */
|
||||
COND_SYSCALL(memfd_secret);
|
||||
|
||||
/*
|
||||
* Architecture specific weak syscall entries.
|
||||
|
@ -35,6 +35,17 @@ config PRINTK_CALLER
|
||||
no option to enable/disable at the kernel command line parameter or
|
||||
sysfs interface.
|
||||
|
||||
config STACKTRACE_BUILD_ID
|
||||
bool "Show build ID information in stacktraces"
|
||||
depends on PRINTK
|
||||
help
|
||||
Selecting this option adds build ID information for symbols in
|
||||
stacktraces printed with the printk format '%p[SR]b'.
|
||||
|
||||
This option is intended for distros where debuginfo is not easily
|
||||
accessible but can be downloaded given the build ID of the vmlinux or
|
||||
kernel module where the function is located.
|
||||
|
||||
config CONSOLE_LOGLEVEL_DEFAULT
|
||||
int "Default console loglevel (1-15)"
|
||||
range 1 15
|
||||
@ -1282,7 +1293,7 @@ config PROVE_RAW_LOCK_NESTING
|
||||
option expect lockdep splats until these problems have been fully
|
||||
addressed which is work in progress. This config switch allows to
|
||||
identify and analyze these problems. It will be removed and the
|
||||
check permanentely enabled once the main issues have been fixed.
|
||||
check permanently enabled once the main issues have been fixed.
|
||||
|
||||
If unsure, select N.
|
||||
|
||||
@ -1448,7 +1459,7 @@ config DEBUG_LOCKING_API_SELFTESTS
|
||||
Say Y here if you want the kernel to run a short self-test during
|
||||
bootup. The self-test checks whether common types of locking bugs
|
||||
are detected by debugging mechanisms or not. (if you disable
|
||||
lock debugging then those bugs wont be detected of course.)
|
||||
lock debugging then those bugs won't be detected of course.)
|
||||
The following locking APIs are covered: spinlocks, rwlocks,
|
||||
mutexes and rwsems.
|
||||
|
||||
@ -1928,7 +1939,7 @@ config FAIL_IO_TIMEOUT
|
||||
thus exercising the error handling.
|
||||
|
||||
Only works with drivers that use the generic timeout handling,
|
||||
for others it wont do anything.
|
||||
for others it won't do anything.
|
||||
|
||||
config FAIL_FUTEX
|
||||
bool "Fault-injection capability for futexes"
|
||||
|
@ -181,7 +181,7 @@ EXPORT_SYMBOL_GPL(asn1_encode_oid);
|
||||
/**
|
||||
* asn1_encode_length() - encode a length to follow an ASN.1 tag
|
||||
* @data: pointer to encode at
|
||||
* @data_len: pointer to remaning length (adjusted by routine)
|
||||
* @data_len: pointer to remaining length (adjusted by routine)
|
||||
* @len: length to encode
|
||||
*
|
||||
* This routine can encode lengths up to 65535 using the ASN.1 rules.
|
||||
|
@ -1,36 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/cache.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
#define BUILD_ID 3
|
||||
|
||||
/*
|
||||
* Parse build id from the note segment. This logic can be shared between
|
||||
* 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are
|
||||
* identical.
|
||||
*/
|
||||
static inline int parse_build_id(void *page_addr,
|
||||
unsigned char *build_id,
|
||||
__u32 *size,
|
||||
void *note_start,
|
||||
Elf32_Word note_size)
|
||||
static int parse_build_id_buf(unsigned char *build_id,
|
||||
__u32 *size,
|
||||
const void *note_start,
|
||||
Elf32_Word note_size)
|
||||
{
|
||||
Elf32_Word note_offs = 0, new_offs;
|
||||
|
||||
/* check for overflow */
|
||||
if (note_start < page_addr || note_start + note_size < note_start)
|
||||
return -EINVAL;
|
||||
|
||||
/* only supports note that fits in the first page */
|
||||
if (note_start + note_size > page_addr + PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
while (note_offs + sizeof(Elf32_Nhdr) < note_size) {
|
||||
Elf32_Nhdr *nhdr = (Elf32_Nhdr *)(note_start + note_offs);
|
||||
|
||||
if (nhdr->n_type == BUILD_ID &&
|
||||
nhdr->n_namesz == sizeof("GNU") &&
|
||||
!strcmp((char *)(nhdr + 1), "GNU") &&
|
||||
nhdr->n_descsz > 0 &&
|
||||
nhdr->n_descsz <= BUILD_ID_SIZE_MAX) {
|
||||
memcpy(build_id,
|
||||
@ -49,11 +44,29 @@ static inline int parse_build_id(void *page_addr,
|
||||
break;
|
||||
note_offs = new_offs;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int parse_build_id(const void *page_addr,
|
||||
unsigned char *build_id,
|
||||
__u32 *size,
|
||||
const void *note_start,
|
||||
Elf32_Word note_size)
|
||||
{
|
||||
/* check for overflow */
|
||||
if (note_start < page_addr || note_start + note_size < note_start)
|
||||
return -EINVAL;
|
||||
|
||||
/* only supports note that fits in the first page */
|
||||
if (note_start + note_size > page_addr + PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
return parse_build_id_buf(build_id, size, note_start, note_size);
|
||||
}
|
||||
|
||||
/* Parse build ID from 32-bit ELF */
|
||||
static int get_build_id_32(void *page_addr, unsigned char *build_id,
|
||||
static int get_build_id_32(const void *page_addr, unsigned char *build_id,
|
||||
__u32 *size)
|
||||
{
|
||||
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)page_addr;
|
||||
@ -78,7 +91,7 @@ static int get_build_id_32(void *page_addr, unsigned char *build_id,
|
||||
}
|
||||
|
||||
/* Parse build ID from 64-bit ELF */
|
||||
static int get_build_id_64(void *page_addr, unsigned char *build_id,
|
||||
static int get_build_id_64(const void *page_addr, unsigned char *build_id,
|
||||
__u32 *size)
|
||||
{
|
||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)page_addr;
|
||||
@ -108,7 +121,7 @@ static int get_build_id_64(void *page_addr, unsigned char *build_id,
|
||||
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
|
||||
* @size: returns actual build id size in case of success
|
||||
*
|
||||
* Returns 0 on success, otherwise error (< 0).
|
||||
* Return: 0 on success, -EINVAL otherwise
|
||||
*/
|
||||
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
|
||||
__u32 *size)
|
||||
@ -147,3 +160,32 @@ out:
|
||||
put_page(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* build_id_parse_buf - Get build ID from a buffer
|
||||
* @buf: Elf note section(s) to parse
|
||||
* @buf_size: Size of @buf in bytes
|
||||
* @build_id: Build ID parsed from @buf, at least BUILD_ID_SIZE_MAX long
|
||||
*
|
||||
* Return: 0 on success, -EINVAL otherwise
|
||||
*/
|
||||
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size)
|
||||
{
|
||||
return parse_build_id_buf(build_id, NULL, buf, buf_size);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) || IS_ENABLED(CONFIG_CRASH_CORE)
|
||||
unsigned char vmlinux_build_id[BUILD_ID_SIZE_MAX] __ro_after_init;
|
||||
|
||||
/**
|
||||
* init_vmlinux_build_id - Compute and stash the running kernel's build ID
|
||||
*/
|
||||
void __init init_vmlinux_build_id(void)
|
||||
{
|
||||
extern const void __start_notes __weak;
|
||||
extern const void __stop_notes __weak;
|
||||
unsigned int size = &__stop_notes - &__start_notes;
|
||||
|
||||
build_id_parse_buf(&__start_notes, vmlinux_build_id, size);
|
||||
}
|
||||
#endif
|
||||
|
@ -355,7 +355,7 @@ static void pcim_iomap_release(struct device *gendev, void *res)
|
||||
* detach.
|
||||
*
|
||||
* This function might sleep when the table is first allocated but can
|
||||
* be safely called without context and guaranteed to succed once
|
||||
* be safely called without context and guaranteed to succeed once
|
||||
* allocated.
|
||||
*/
|
||||
void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/buildid.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/debug.h>
|
||||
@ -36,6 +37,14 @@ void __init dump_stack_set_arch_desc(const char *fmt, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)
|
||||
#define BUILD_ID_FMT " %20phN"
|
||||
#define BUILD_ID_VAL vmlinux_build_id
|
||||
#else
|
||||
#define BUILD_ID_FMT "%s"
|
||||
#define BUILD_ID_VAL ""
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dump_stack_print_info - print generic debug info for dump_stack()
|
||||
* @log_lvl: log level
|
||||
@ -45,13 +54,13 @@ void __init dump_stack_set_arch_desc(const char *fmt, ...)
|
||||
*/
|
||||
void dump_stack_print_info(const char *log_lvl)
|
||||
{
|
||||
printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s\n",
|
||||
printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n",
|
||||
log_lvl, raw_smp_processor_id(), current->pid, current->comm,
|
||||
kexec_crash_loaded() ? "Kdump: loaded " : "",
|
||||
print_tainted(),
|
||||
init_utsname()->release,
|
||||
(int)strcspn(init_utsname()->version, " "),
|
||||
init_utsname()->version);
|
||||
init_utsname()->version, BUILD_ID_VAL);
|
||||
|
||||
if (dump_stack_arch_desc_str[0] != '\0')
|
||||
printk("%sHardware name: %s\n",
|
||||
|
@ -991,7 +991,7 @@ static int ddebug_dyndbg_param_cb(char *param, char *val,
|
||||
|
||||
ddebug_exec_queries((val ? val : "+p"), modname);
|
||||
|
||||
return 0; /* query failure shouldnt stop module load */
|
||||
return 0; /* query failure shouldn't stop module load */
|
||||
}
|
||||
|
||||
/* handle both dyndbg and $module.dyndbg params at boot */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user