2019-06-01 08:08:55 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2016-05-27 05:48:59 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016, Rashmica Gupta, IBM Corp.
|
|
|
|
*
|
|
|
|
* This traverses the kernel pagetables and dumps the
|
|
|
|
* information about the used sections of memory to
|
|
|
|
* /sys/kernel/debug/kernel_pagetables.
|
|
|
|
*
|
|
|
|
* Derived from the arm64 implementation:
|
|
|
|
* Copyright (c) 2014, The Linux Foundation, Laura Abbott.
|
|
|
|
* (C) Copyright 2008 Intel Corporation, Arjan van de Ven.
|
|
|
|
*/
|
|
|
|
#include <linux/debugfs.h>
|
|
|
|
#include <linux/fs.h>
|
2017-05-16 10:42:53 +00:00
|
|
|
#include <linux/hugetlb.h>
|
2016-05-27 05:48:59 +00:00
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/mm.h>
|
2018-11-26 01:59:16 +00:00
|
|
|
#include <linux/highmem.h>
|
2016-05-27 05:48:59 +00:00
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
#include <asm/fixmap.h>
|
|
|
|
#include <linux/const.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/pgalloc.h>
|
2020-05-19 05:48:55 +00:00
|
|
|
#include <asm/hugetlb.h>
|
2016-05-27 05:48:59 +00:00
|
|
|
|
2020-01-14 07:14:40 +00:00
|
|
|
#include <mm/mmu_decl.h>
|
|
|
|
|
2019-02-18 12:28:36 +00:00
|
|
|
#include "ptdump.h"
|
2018-10-09 13:51:58 +00:00
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
/*
|
|
|
|
* To visualise what is happening,
|
|
|
|
*
|
|
|
|
* - PTRS_PER_P** = how many entries there are in the corresponding P**
|
|
|
|
* - P**_SHIFT = how many bits of the address we use to index into the
|
|
|
|
* corresponding P**
|
|
|
|
* - P**_SIZE is how much memory we can access through the table - not the
|
|
|
|
* size of the table itself.
|
|
|
|
* P**={PGD, PUD, PMD, PTE}
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Each entry of the PGD points to a PUD. Each entry of a PUD points to a
|
|
|
|
* PMD. Each entry of a PMD points to a PTE. And every PTE entry points to
|
|
|
|
* a page.
|
|
|
|
*
|
|
|
|
* In the case where there are only 3 levels, the PUD is folded into the
|
|
|
|
* PGD: every PUD has only one entry which points to the PMD.
|
|
|
|
*
|
|
|
|
* The page dumper groups page table entries of the same type into a single
|
|
|
|
* description. It uses pg_state to track the range information while
|
|
|
|
* iterating over the PTE entries. When the continuity is broken it then
|
|
|
|
* dumps out a description of the range - ie PTEs that are virtually contiguous
|
|
|
|
* with the same PTE flags are chunked together. This is to make it clear how
|
|
|
|
* different areas of the kernel virtual memory are used.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
struct pg_state {
|
|
|
|
struct seq_file *seq;
|
|
|
|
const struct addr_marker *marker;
|
|
|
|
unsigned long start_address;
|
2017-03-31 01:37:49 +00:00
|
|
|
unsigned long start_pa;
|
|
|
|
unsigned long last_pa;
|
2020-05-19 05:48:54 +00:00
|
|
|
unsigned long page_size;
|
2016-05-27 05:48:59 +00:00
|
|
|
unsigned int level;
|
|
|
|
u64 current_flags;
|
2019-05-02 07:39:47 +00:00
|
|
|
bool check_wx;
|
|
|
|
unsigned long wx_pages;
|
2016-05-27 05:48:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct addr_marker {
|
|
|
|
unsigned long start_address;
|
|
|
|
const char *name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct addr_marker address_markers[] = {
|
|
|
|
{ 0, "Start of kernel VM" },
|
|
|
|
{ 0, "vmalloc() Area" },
|
|
|
|
{ 0, "vmalloc() End" },
|
2017-04-18 06:20:13 +00:00
|
|
|
#ifdef CONFIG_PPC64
|
2016-05-27 05:48:59 +00:00
|
|
|
{ 0, "isa I/O start" },
|
|
|
|
{ 0, "isa I/O end" },
|
|
|
|
{ 0, "phb I/O start" },
|
|
|
|
{ 0, "phb I/O end" },
|
|
|
|
{ 0, "I/O remap start" },
|
|
|
|
{ 0, "I/O remap end" },
|
|
|
|
{ 0, "vmemmap start" },
|
2017-04-18 06:20:13 +00:00
|
|
|
#else
|
|
|
|
{ 0, "Early I/O remap start" },
|
|
|
|
{ 0, "Early I/O remap end" },
|
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
|
|
{ 0, "Highmem PTEs start" },
|
|
|
|
{ 0, "Highmem PTEs end" },
|
|
|
|
#endif
|
|
|
|
{ 0, "Fixmap start" },
|
|
|
|
{ 0, "Fixmap end" },
|
2019-04-26 16:23:32 +00:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_KASAN
|
|
|
|
{ 0, "kasan shadow mem start" },
|
|
|
|
{ 0, "kasan shadow mem end" },
|
2017-04-18 06:20:13 +00:00
|
|
|
#endif
|
2016-05-27 05:48:59 +00:00
|
|
|
{ -1, NULL },
|
|
|
|
};
|
|
|
|
|
2019-05-02 07:39:46 +00:00
|
|
|
#define pt_dump_seq_printf(m, fmt, args...) \
|
|
|
|
({ \
|
|
|
|
if (m) \
|
|
|
|
seq_printf(m, fmt, ##args); \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define pt_dump_seq_putc(m, c) \
|
|
|
|
({ \
|
|
|
|
if (m) \
|
|
|
|
seq_putc(m, c); \
|
|
|
|
})
|
|
|
|
|
2020-05-19 05:48:52 +00:00
|
|
|
void pt_dump_size(struct seq_file *m, unsigned long size)
|
|
|
|
{
|
|
|
|
static const char units[] = "KMGTPE";
|
|
|
|
const char *unit = units;
|
|
|
|
|
|
|
|
/* Work out what appropriate unit to use */
|
|
|
|
while (!(size & 1023) && unit[1]) {
|
|
|
|
size >>= 10;
|
|
|
|
unit++;
|
|
|
|
}
|
|
|
|
pt_dump_seq_printf(m, "%9lu%c ", size, *unit);
|
|
|
|
}
|
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
static void dump_flag_info(struct pg_state *st, const struct flag_info
|
|
|
|
*flag, u64 pte, int num)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++, flag++) {
|
|
|
|
const char *s = NULL;
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
/* flag not defined so don't check it */
|
|
|
|
if (flag->mask == 0)
|
|
|
|
continue;
|
|
|
|
/* Some 'flags' are actually values */
|
|
|
|
if (flag->is_val) {
|
|
|
|
val = pte & flag->val;
|
|
|
|
if (flag->shift)
|
|
|
|
val = val >> flag->shift;
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, " %s:%llx", flag->set, val);
|
2016-05-27 05:48:59 +00:00
|
|
|
} else {
|
|
|
|
if ((pte & flag->mask) == flag->val)
|
|
|
|
s = flag->set;
|
|
|
|
else
|
|
|
|
s = flag->clear;
|
|
|
|
if (s)
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, " %s", s);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
st->current_flags &= ~flag->mask;
|
|
|
|
}
|
|
|
|
if (st->current_flags != 0)
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, " unknown flags:%llx", st->current_flags);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_addr(struct pg_state *st, unsigned long addr)
|
|
|
|
{
|
|
|
|
unsigned long delta;
|
|
|
|
|
2017-04-13 12:41:40 +00:00
|
|
|
#ifdef CONFIG_PPC64
|
2019-02-18 12:25:20 +00:00
|
|
|
#define REG "0x%016lx"
|
2017-04-13 12:41:40 +00:00
|
|
|
#else
|
2019-02-18 12:25:20 +00:00
|
|
|
#define REG "0x%08lx"
|
2017-04-13 12:41:40 +00:00
|
|
|
#endif
|
2017-03-31 01:37:49 +00:00
|
|
|
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, REG "-" REG " ", st->start_address, addr - 1);
|
2020-05-19 05:48:54 +00:00
|
|
|
if (st->start_pa == st->last_pa && st->start_address + st->page_size != addr) {
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, "[" REG "]", st->start_pa);
|
2020-05-19 05:48:54 +00:00
|
|
|
delta = st->page_size >> 10;
|
2019-02-18 12:25:20 +00:00
|
|
|
} else {
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, " " REG " ", st->start_pa);
|
2019-02-18 12:25:20 +00:00
|
|
|
delta = (addr - st->start_address) >> 10;
|
|
|
|
}
|
2020-05-19 05:48:52 +00:00
|
|
|
pt_dump_size(st->seq, delta);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
|
2019-05-02 07:39:47 +00:00
|
|
|
static void note_prot_wx(struct pg_state *st, unsigned long addr)
|
|
|
|
{
|
2020-01-14 08:13:09 +00:00
|
|
|
pte_t pte = __pte(st->current_flags);
|
|
|
|
|
2019-08-14 12:36:12 +00:00
|
|
|
if (!IS_ENABLED(CONFIG_PPC_DEBUG_WX) || !st->check_wx)
|
2019-05-02 07:39:47 +00:00
|
|
|
return;
|
|
|
|
|
2020-01-14 08:13:09 +00:00
|
|
|
if (!pte_write(pte) || !pte_exec(pte))
|
2019-05-02 07:39:47 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
WARN_ONCE(1, "powerpc/mm: Found insecure W+X mapping at address %p/%pS\n",
|
|
|
|
(void *)st->start_address, (void *)st->start_address);
|
|
|
|
|
|
|
|
st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
|
|
|
|
}
|
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
static void note_page(struct pg_state *st, unsigned long addr,
|
2020-05-19 05:48:54 +00:00
|
|
|
unsigned int level, u64 val, unsigned long page_size)
|
2016-05-27 05:48:59 +00:00
|
|
|
{
|
|
|
|
u64 flag = val & pg_level[level].mask;
|
2017-03-31 01:37:49 +00:00
|
|
|
u64 pa = val & PTE_RPN_MASK;
|
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
/* At first no level is set */
|
|
|
|
if (!st->level) {
|
|
|
|
st->level = level;
|
|
|
|
st->current_flags = flag;
|
|
|
|
st->start_address = addr;
|
2017-03-31 01:37:49 +00:00
|
|
|
st->start_pa = pa;
|
|
|
|
st->last_pa = pa;
|
2020-05-19 05:48:54 +00:00
|
|
|
st->page_size = page_size;
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
|
2016-05-27 05:48:59 +00:00
|
|
|
/*
|
|
|
|
* Dump the section of virtual memory when:
|
|
|
|
* - the PTE flags from one entry to the next differs.
|
|
|
|
* - we change levels in the tree.
|
|
|
|
* - the address is in a different section of memory and is thus
|
|
|
|
* used for a different purpose, regardless of the flags.
|
2017-03-31 01:37:49 +00:00
|
|
|
* - the pa of this page is not adjacent to the last inspected page
|
2016-05-27 05:48:59 +00:00
|
|
|
*/
|
|
|
|
} else if (flag != st->current_flags || level != st->level ||
|
2017-03-31 01:37:49 +00:00
|
|
|
addr >= st->marker[1].start_address ||
|
2020-05-19 05:48:54 +00:00
|
|
|
(pa != st->last_pa + st->page_size &&
|
2019-02-18 12:25:20 +00:00
|
|
|
(pa != st->start_pa || st->start_pa != st->last_pa))) {
|
2016-05-27 05:48:59 +00:00
|
|
|
|
|
|
|
/* Check the PTE flags */
|
|
|
|
if (st->current_flags) {
|
2019-05-02 07:39:47 +00:00
|
|
|
note_prot_wx(st, addr);
|
2016-05-27 05:48:59 +00:00
|
|
|
dump_addr(st, addr);
|
|
|
|
|
|
|
|
/* Dump all the flags */
|
|
|
|
if (pg_level[st->level].flag)
|
|
|
|
dump_flag_info(st, pg_level[st->level].flag,
|
|
|
|
st->current_flags,
|
|
|
|
pg_level[st->level].num);
|
|
|
|
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_putc(st->seq, '\n');
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Address indicates we have passed the end of the
|
|
|
|
* current section of virtual memory
|
|
|
|
*/
|
|
|
|
while (addr >= st->marker[1].start_address) {
|
|
|
|
st->marker++;
|
2019-05-02 07:39:46 +00:00
|
|
|
pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
st->start_address = addr;
|
2017-03-31 01:37:49 +00:00
|
|
|
st->start_pa = pa;
|
|
|
|
st->last_pa = pa;
|
2020-05-19 05:48:54 +00:00
|
|
|
st->page_size = page_size;
|
2016-05-27 05:48:59 +00:00
|
|
|
st->current_flags = flag;
|
|
|
|
st->level = level;
|
2017-03-31 01:37:49 +00:00
|
|
|
} else {
|
|
|
|
st->last_pa = pa;
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
|
|
|
|
{
|
|
|
|
pte_t *pte = pte_offset_kernel(pmd, 0);
|
|
|
|
unsigned long addr;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
|
|
|
|
addr = start + i * PAGE_SIZE;
|
2020-05-19 05:48:54 +00:00
|
|
|
note_page(st, addr, 4, pte_val(*pte), PAGE_SIZE);
|
2016-05-27 05:48:59 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 05:48:55 +00:00
|
|
|
static void walk_hugepd(struct pg_state *st, hugepd_t *phpd, unsigned long start,
|
|
|
|
int pdshift, int level)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_ARCH_HAS_HUGEPD
|
|
|
|
unsigned int i;
|
|
|
|
int shift = hugepd_shift(*phpd);
|
|
|
|
int ptrs_per_hpd = pdshift - shift > 0 ? 1 << (pdshift - shift) : 1;
|
|
|
|
|
|
|
|
if (start & ((1 << shift) - 1))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < ptrs_per_hpd; i++) {
|
|
|
|
unsigned long addr = start + (i << shift);
|
|
|
|
pte_t *pte = hugepte_offset(*phpd, addr, pdshift);
|
|
|
|
|
|
|
|
note_page(st, addr, level + 1, pte_val(*pte), 1 << shift);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
|
|
|
|
{
|
|
|
|
pmd_t *pmd = pmd_offset(pud, 0);
|
|
|
|
unsigned long addr;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
|
|
|
|
addr = start + i * PMD_SIZE;
|
2019-05-14 06:03:00 +00:00
|
|
|
if (!pmd_none(*pmd) && !pmd_is_leaf(*pmd))
|
2016-05-27 05:48:59 +00:00
|
|
|
/* pmd exists */
|
|
|
|
walk_pte(st, pmd, addr);
|
|
|
|
else
|
2020-05-19 05:48:54 +00:00
|
|
|
note_page(st, addr, 3, pmd_val(*pmd), PMD_SIZE);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 23:46:44 +00:00
|
|
|
static void walk_pud(struct pg_state *st, p4d_t *p4d, unsigned long start)
|
2016-05-27 05:48:59 +00:00
|
|
|
{
|
2020-06-04 23:46:44 +00:00
|
|
|
pud_t *pud = pud_offset(p4d, 0);
|
2016-05-27 05:48:59 +00:00
|
|
|
unsigned long addr;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
|
|
|
|
addr = start + i * PUD_SIZE;
|
2019-05-14 06:03:00 +00:00
|
|
|
if (!pud_none(*pud) && !pud_is_leaf(*pud))
|
2016-05-27 05:48:59 +00:00
|
|
|
/* pud exists */
|
|
|
|
walk_pmd(st, pud, addr);
|
|
|
|
else
|
2020-05-19 05:48:54 +00:00
|
|
|
note_page(st, addr, 2, pud_val(*pud), PUD_SIZE);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void walk_pagetables(struct pg_state *st)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
2019-08-14 12:36:10 +00:00
|
|
|
unsigned long addr = st->start_address & PGDIR_MASK;
|
|
|
|
pgd_t *pgd = pgd_offset_k(addr);
|
2018-08-15 11:29:45 +00:00
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
/*
|
|
|
|
* Traverse the linux pagetable structure and dump pages that are in
|
|
|
|
* the hash pagetable.
|
|
|
|
*/
|
2019-08-14 12:36:10 +00:00
|
|
|
for (i = pgd_index(addr); i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
|
2020-06-04 23:46:44 +00:00
|
|
|
p4d_t *p4d = p4d_offset(pgd, 0);
|
|
|
|
|
powerpc updates for 5.8
- Support for userspace to send requests directly to the on-chip GZIP
accelerator on Power9.
- Rework of our lockless page table walking (__find_linux_pte()) to make it
safe against parallel page table manipulations without relying on an IPI for
serialisation.
- A series of fixes & enhancements to make our machine check handling more
robust.
- Lots of plumbing to add support for "prefixed" (64-bit) instructions on
Power10.
- Support for using huge pages for the linear mapping on 8xx (32-bit).
- Remove obsolete Xilinx PPC405/PPC440 support, and an associated sound driver.
- Removal of some obsolete 40x platforms and associated cruft.
- Initial support for booting on Power10.
- Lots of other small features, cleanups & fixes.
Thanks to:
Alexey Kardashevskiy, Alistair Popple, Andrew Donnellan, Andrey Abramov,
Aneesh Kumar K.V, Balamuruhan S, Bharata B Rao, Bulent Abali, Cédric Le
Goater, Chen Zhou, Christian Zigotzky, Christophe JAILLET, Christophe Leroy,
Dmitry Torokhov, Emmanuel Nicolet, Erhard F., Gautham R. Shenoy, Geoff Levand,
George Spelvin, Greg Kurz, Gustavo A. R. Silva, Gustavo Walbon, Haren Myneni,
Hari Bathini, Joel Stanley, Jordan Niethe, Kajol Jain, Kees Cook, Leonardo
Bras, Madhavan Srinivasan., Mahesh Salgaonkar, Markus Elfring, Michael
Neuling, Michal Simek, Nathan Chancellor, Nathan Lynch, Naveen N. Rao,
Nicholas Piggin, Oliver O'Halloran, Paul Mackerras, Pingfan Liu, Qian Cai, Ram
Pai, Raphael Moreira Zinsly, Ravi Bangoria, Sam Bobroff, Sandipan Das, Segher
Boessenkool, Stephen Rothwell, Sukadev Bhattiprolu, Tyrel Datwyler, Wolfram
Sang, Xiongfeng Wang.
-----BEGIN PGP SIGNATURE-----
iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAl7aYZ8THG1wZUBlbGxl
cm1hbi5pZC5hdQAKCRBR6+o8yOGlgPiKD/9zNCuZLFMAFrIdbm0HlYA2RGYZFT75
GUHsqYyei1pxA7PgM3KwJiXELVODsBv0eQbgNh1tbecKrxPRegN/cywd1KLjPZ7I
v5/qweQP8MvR0RhzjbhvUcO0jq/f8u2LbJr5mUfVzjU6tAvrvcWo3oZqDElsekCS
kgyOH3r1vZ2PLTMiGFhb0gWi2iqc+6BHU1AFCGPCMjB1Vu5d5+54VvZ/6lllGsOF
yg9CBXmmVvQ+Bn6tH4zdEB78FYxnAIwBqlbmL79i5ca+HQJ0Sw6HuPRy9XYq35p6
2EiXS4Wrgp7i7+1TN3HO362u5Onb8TSyQU7NS6yCFPoJ6JQxcJMBIw6mHhnXOPuZ
CrjgcdwUMjx8uDoKmX1Epbfuex2w+AysW+4yBHPFiSgl3klKC3D0wi95mR485w2F
rN8uzJtrDeFKcYZJG7IoB/cgFCCPKGf9HaXr8q0S/jBKMffx91ul3cfzlfdIXOCw
FDNw/+ZX7UD6ddFEG12ZTO+vdL8yf1uCRT/DIZwUiDMIA0+M6F4nc7j3lfyZfoO1
65f9UlhoLxScq7VH2fKH4UtZatO9cPID2z1CmiY4UbUIPtFDepSuYClgLF+Duf4b
rkfxhKU0+Ja1zNH5XNc+L+Bc5/W4lFiJXz02dYIjtHoUpWkc1aToOETVwzggYFNM
G3PXIBOI0jRgRw==
=o0WU
-----END PGP SIGNATURE-----
Merge tag 'powerpc-5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman:
- Support for userspace to send requests directly to the on-chip GZIP
accelerator on Power9.
- Rework of our lockless page table walking (__find_linux_pte()) to
make it safe against parallel page table manipulations without
relying on an IPI for serialisation.
- A series of fixes & enhancements to make our machine check handling
more robust.
- Lots of plumbing to add support for "prefixed" (64-bit) instructions
on Power10.
- Support for using huge pages for the linear mapping on 8xx (32-bit).
- Remove obsolete Xilinx PPC405/PPC440 support, and an associated sound
driver.
- Removal of some obsolete 40x platforms and associated cruft.
- Initial support for booting on Power10.
- Lots of other small features, cleanups & fixes.
Thanks to: Alexey Kardashevskiy, Alistair Popple, Andrew Donnellan,
Andrey Abramov, Aneesh Kumar K.V, Balamuruhan S, Bharata B Rao, Bulent
Abali, Cédric Le Goater, Chen Zhou, Christian Zigotzky, Christophe
JAILLET, Christophe Leroy, Dmitry Torokhov, Emmanuel Nicolet, Erhard F.,
Gautham R. Shenoy, Geoff Levand, George Spelvin, Greg Kurz, Gustavo A.
R. Silva, Gustavo Walbon, Haren Myneni, Hari Bathini, Joel Stanley,
Jordan Niethe, Kajol Jain, Kees Cook, Leonardo Bras, Madhavan
Srinivasan., Mahesh Salgaonkar, Markus Elfring, Michael Neuling, Michal
Simek, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin,
Oliver O'Halloran, Paul Mackerras, Pingfan Liu, Qian Cai, Ram Pai,
Raphael Moreira Zinsly, Ravi Bangoria, Sam Bobroff, Sandipan Das, Segher
Boessenkool, Stephen Rothwell, Sukadev Bhattiprolu, Tyrel Datwyler,
Wolfram Sang, Xiongfeng Wang.
* tag 'powerpc-5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (299 commits)
powerpc/pseries: Make vio and ibmebus initcalls pseries specific
cxl: Remove dead Kconfig options
powerpc: Add POWER10 architected mode
powerpc/dt_cpu_ftrs: Add MMA feature
powerpc/dt_cpu_ftrs: Enable Prefixed Instructions
powerpc/dt_cpu_ftrs: Advertise support for ISA v3.1 if selected
powerpc: Add support for ISA v3.1
powerpc: Add new HWCAP bits
powerpc/64s: Don't set FSCR bits in INIT_THREAD
powerpc/64s: Save FSCR to init_task.thread.fscr after feature init
powerpc/64s: Don't let DT CPU features set FSCR_DSCR
powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
powerpc/32s: Fix another build failure with CONFIG_PPC_KUAP_DEBUG
powerpc/module_64: Use special stub for _mcount() with -mprofile-kernel
powerpc/module_64: Simplify check for -mprofile-kernel ftrace relocations
powerpc/module_64: Consolidate ftrace code
powerpc/32: Disable KASAN with pages bigger than 16k
powerpc/uaccess: Don't set KUEP by default on book3s/32
powerpc/uaccess: Don't set KUAP by default on book3s/32
powerpc/8xx: Reduce time spent in allow_user_access() and friends
...
2020-06-05 19:39:30 +00:00
|
|
|
if (p4d_none(*p4d) || p4d_is_leaf(*p4d))
|
|
|
|
note_page(st, addr, 1, p4d_val(*p4d), PGDIR_SIZE);
|
|
|
|
else if (is_hugepd(__hugepd(p4d_val(*p4d))))
|
|
|
|
walk_hugepd(st, (hugepd_t *)p4d, addr, PGDIR_SHIFT, 1);
|
2016-05-27 05:48:59 +00:00
|
|
|
else
|
powerpc updates for 5.8
- Support for userspace to send requests directly to the on-chip GZIP
accelerator on Power9.
- Rework of our lockless page table walking (__find_linux_pte()) to make it
safe against parallel page table manipulations without relying on an IPI for
serialisation.
- A series of fixes & enhancements to make our machine check handling more
robust.
- Lots of plumbing to add support for "prefixed" (64-bit) instructions on
Power10.
- Support for using huge pages for the linear mapping on 8xx (32-bit).
- Remove obsolete Xilinx PPC405/PPC440 support, and an associated sound driver.
- Removal of some obsolete 40x platforms and associated cruft.
- Initial support for booting on Power10.
- Lots of other small features, cleanups & fixes.
Thanks to:
Alexey Kardashevskiy, Alistair Popple, Andrew Donnellan, Andrey Abramov,
Aneesh Kumar K.V, Balamuruhan S, Bharata B Rao, Bulent Abali, Cédric Le
Goater, Chen Zhou, Christian Zigotzky, Christophe JAILLET, Christophe Leroy,
Dmitry Torokhov, Emmanuel Nicolet, Erhard F., Gautham R. Shenoy, Geoff Levand,
George Spelvin, Greg Kurz, Gustavo A. R. Silva, Gustavo Walbon, Haren Myneni,
Hari Bathini, Joel Stanley, Jordan Niethe, Kajol Jain, Kees Cook, Leonardo
Bras, Madhavan Srinivasan., Mahesh Salgaonkar, Markus Elfring, Michael
Neuling, Michal Simek, Nathan Chancellor, Nathan Lynch, Naveen N. Rao,
Nicholas Piggin, Oliver O'Halloran, Paul Mackerras, Pingfan Liu, Qian Cai, Ram
Pai, Raphael Moreira Zinsly, Ravi Bangoria, Sam Bobroff, Sandipan Das, Segher
Boessenkool, Stephen Rothwell, Sukadev Bhattiprolu, Tyrel Datwyler, Wolfram
Sang, Xiongfeng Wang.
-----BEGIN PGP SIGNATURE-----
iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAl7aYZ8THG1wZUBlbGxl
cm1hbi5pZC5hdQAKCRBR6+o8yOGlgPiKD/9zNCuZLFMAFrIdbm0HlYA2RGYZFT75
GUHsqYyei1pxA7PgM3KwJiXELVODsBv0eQbgNh1tbecKrxPRegN/cywd1KLjPZ7I
v5/qweQP8MvR0RhzjbhvUcO0jq/f8u2LbJr5mUfVzjU6tAvrvcWo3oZqDElsekCS
kgyOH3r1vZ2PLTMiGFhb0gWi2iqc+6BHU1AFCGPCMjB1Vu5d5+54VvZ/6lllGsOF
yg9CBXmmVvQ+Bn6tH4zdEB78FYxnAIwBqlbmL79i5ca+HQJ0Sw6HuPRy9XYq35p6
2EiXS4Wrgp7i7+1TN3HO362u5Onb8TSyQU7NS6yCFPoJ6JQxcJMBIw6mHhnXOPuZ
CrjgcdwUMjx8uDoKmX1Epbfuex2w+AysW+4yBHPFiSgl3klKC3D0wi95mR485w2F
rN8uzJtrDeFKcYZJG7IoB/cgFCCPKGf9HaXr8q0S/jBKMffx91ul3cfzlfdIXOCw
FDNw/+ZX7UD6ddFEG12ZTO+vdL8yf1uCRT/DIZwUiDMIA0+M6F4nc7j3lfyZfoO1
65f9UlhoLxScq7VH2fKH4UtZatO9cPID2z1CmiY4UbUIPtFDepSuYClgLF+Duf4b
rkfxhKU0+Ja1zNH5XNc+L+Bc5/W4lFiJXz02dYIjtHoUpWkc1aToOETVwzggYFNM
G3PXIBOI0jRgRw==
=o0WU
-----END PGP SIGNATURE-----
Merge tag 'powerpc-5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc updates from Michael Ellerman:
- Support for userspace to send requests directly to the on-chip GZIP
accelerator on Power9.
- Rework of our lockless page table walking (__find_linux_pte()) to
make it safe against parallel page table manipulations without
relying on an IPI for serialisation.
- A series of fixes & enhancements to make our machine check handling
more robust.
- Lots of plumbing to add support for "prefixed" (64-bit) instructions
on Power10.
- Support for using huge pages for the linear mapping on 8xx (32-bit).
- Remove obsolete Xilinx PPC405/PPC440 support, and an associated sound
driver.
- Removal of some obsolete 40x platforms and associated cruft.
- Initial support for booting on Power10.
- Lots of other small features, cleanups & fixes.
Thanks to: Alexey Kardashevskiy, Alistair Popple, Andrew Donnellan,
Andrey Abramov, Aneesh Kumar K.V, Balamuruhan S, Bharata B Rao, Bulent
Abali, Cédric Le Goater, Chen Zhou, Christian Zigotzky, Christophe
JAILLET, Christophe Leroy, Dmitry Torokhov, Emmanuel Nicolet, Erhard F.,
Gautham R. Shenoy, Geoff Levand, George Spelvin, Greg Kurz, Gustavo A.
R. Silva, Gustavo Walbon, Haren Myneni, Hari Bathini, Joel Stanley,
Jordan Niethe, Kajol Jain, Kees Cook, Leonardo Bras, Madhavan
Srinivasan., Mahesh Salgaonkar, Markus Elfring, Michael Neuling, Michal
Simek, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin,
Oliver O'Halloran, Paul Mackerras, Pingfan Liu, Qian Cai, Ram Pai,
Raphael Moreira Zinsly, Ravi Bangoria, Sam Bobroff, Sandipan Das, Segher
Boessenkool, Stephen Rothwell, Sukadev Bhattiprolu, Tyrel Datwyler,
Wolfram Sang, Xiongfeng Wang.
* tag 'powerpc-5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (299 commits)
powerpc/pseries: Make vio and ibmebus initcalls pseries specific
cxl: Remove dead Kconfig options
powerpc: Add POWER10 architected mode
powerpc/dt_cpu_ftrs: Add MMA feature
powerpc/dt_cpu_ftrs: Enable Prefixed Instructions
powerpc/dt_cpu_ftrs: Advertise support for ISA v3.1 if selected
powerpc: Add support for ISA v3.1
powerpc: Add new HWCAP bits
powerpc/64s: Don't set FSCR bits in INIT_THREAD
powerpc/64s: Save FSCR to init_task.thread.fscr after feature init
powerpc/64s: Don't let DT CPU features set FSCR_DSCR
powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
powerpc/32s: Fix another build failure with CONFIG_PPC_KUAP_DEBUG
powerpc/module_64: Use special stub for _mcount() with -mprofile-kernel
powerpc/module_64: Simplify check for -mprofile-kernel ftrace relocations
powerpc/module_64: Consolidate ftrace code
powerpc/32: Disable KASAN with pages bigger than 16k
powerpc/uaccess: Don't set KUEP by default on book3s/32
powerpc/uaccess: Don't set KUAP by default on book3s/32
powerpc/8xx: Reduce time spent in allow_user_access() and friends
...
2020-06-05 19:39:30 +00:00
|
|
|
/* p4d exists */
|
|
|
|
walk_pud(st, p4d, addr);
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void populate_markers(void)
|
|
|
|
{
|
2017-04-18 06:20:13 +00:00
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
address_markers[i++].start_address = PAGE_OFFSET;
|
|
|
|
address_markers[i++].start_address = VMALLOC_START;
|
|
|
|
address_markers[i++].start_address = VMALLOC_END;
|
|
|
|
#ifdef CONFIG_PPC64
|
|
|
|
address_markers[i++].start_address = ISA_IO_BASE;
|
|
|
|
address_markers[i++].start_address = ISA_IO_END;
|
|
|
|
address_markers[i++].start_address = PHB_IO_BASE;
|
|
|
|
address_markers[i++].start_address = PHB_IO_END;
|
|
|
|
address_markers[i++].start_address = IOREMAP_BASE;
|
|
|
|
address_markers[i++].start_address = IOREMAP_END;
|
2019-04-17 12:59:14 +00:00
|
|
|
/* What is the ifdef about? */
|
2017-10-19 04:08:43 +00:00
|
|
|
#ifdef CONFIG_PPC_BOOK3S_64
|
2019-04-17 12:59:14 +00:00
|
|
|
address_markers[i++].start_address = H_VMEMMAP_START;
|
2016-05-27 05:48:59 +00:00
|
|
|
#else
|
2017-04-18 06:20:13 +00:00
|
|
|
address_markers[i++].start_address = VMEMMAP_BASE;
|
|
|
|
#endif
|
|
|
|
#else /* !CONFIG_PPC64 */
|
|
|
|
address_markers[i++].start_address = ioremap_bot;
|
|
|
|
address_markers[i++].start_address = IOREMAP_TOP;
|
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
|
|
address_markers[i++].start_address = PKMAP_BASE;
|
|
|
|
address_markers[i++].start_address = PKMAP_ADDR(LAST_PKMAP);
|
2016-05-27 05:48:59 +00:00
|
|
|
#endif
|
2017-04-18 06:20:13 +00:00
|
|
|
address_markers[i++].start_address = FIXADDR_START;
|
|
|
|
address_markers[i++].start_address = FIXADDR_TOP;
|
2019-04-26 16:23:32 +00:00
|
|
|
#ifdef CONFIG_KASAN
|
|
|
|
address_markers[i++].start_address = KASAN_SHADOW_START;
|
|
|
|
address_markers[i++].start_address = KASAN_SHADOW_END;
|
|
|
|
#endif
|
2017-04-18 06:20:13 +00:00
|
|
|
#endif /* CONFIG_PPC64 */
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ptdump_show(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
struct pg_state st = {
|
|
|
|
.seq = m,
|
|
|
|
.marker = address_markers,
|
2019-08-14 12:36:11 +00:00
|
|
|
.start_address = PAGE_OFFSET,
|
2016-05-27 05:48:59 +00:00
|
|
|
};
|
2018-08-15 11:29:45 +00:00
|
|
|
|
2019-08-14 12:36:11 +00:00
|
|
|
#ifdef CONFIG_PPC64
|
|
|
|
if (!radix_enabled())
|
2018-08-15 11:29:45 +00:00
|
|
|
st.start_address = KERN_VIRT_START;
|
2019-08-14 12:36:11 +00:00
|
|
|
#endif
|
2018-08-15 11:29:45 +00:00
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
/* Traverse kernel page tables */
|
|
|
|
walk_pagetables(&st);
|
2020-05-19 05:48:54 +00:00
|
|
|
note_page(&st, 0, 0, 0, 0);
|
2016-05-27 05:48:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int ptdump_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
return single_open(file, ptdump_show, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations ptdump_fops = {
|
|
|
|
.open = ptdump_open,
|
|
|
|
.read = seq_read,
|
|
|
|
.llseek = seq_lseek,
|
|
|
|
.release = single_release,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void build_pgtable_complete_mask(void)
|
|
|
|
{
|
|
|
|
unsigned int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(pg_level); i++)
|
|
|
|
if (pg_level[i].flag)
|
|
|
|
for (j = 0; j < pg_level[i].num; j++)
|
|
|
|
pg_level[i].mask |= pg_level[i].flag[j].mask;
|
|
|
|
}
|
|
|
|
|
2019-05-02 07:39:47 +00:00
|
|
|
#ifdef CONFIG_PPC_DEBUG_WX
|
|
|
|
void ptdump_check_wx(void)
|
|
|
|
{
|
|
|
|
struct pg_state st = {
|
|
|
|
.seq = NULL,
|
|
|
|
.marker = address_markers,
|
|
|
|
.check_wx = true,
|
2019-08-14 12:36:11 +00:00
|
|
|
.start_address = PAGE_OFFSET,
|
2019-05-02 07:39:47 +00:00
|
|
|
};
|
|
|
|
|
2019-08-14 12:36:11 +00:00
|
|
|
#ifdef CONFIG_PPC64
|
|
|
|
if (!radix_enabled())
|
2019-05-02 07:39:47 +00:00
|
|
|
st.start_address = KERN_VIRT_START;
|
2019-08-14 12:36:11 +00:00
|
|
|
#endif
|
2019-05-02 07:39:47 +00:00
|
|
|
|
|
|
|
walk_pagetables(&st);
|
|
|
|
|
|
|
|
if (st.wx_pages)
|
|
|
|
pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found\n",
|
|
|
|
st.wx_pages);
|
|
|
|
else
|
|
|
|
pr_info("Checked W+X mappings: passed, no W+X pages found\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-05-27 05:48:59 +00:00
|
|
|
static int ptdump_init(void)
|
|
|
|
{
|
|
|
|
populate_markers();
|
|
|
|
build_pgtable_complete_mask();
|
2020-02-09 10:58:59 +00:00
|
|
|
debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
|
|
|
|
&ptdump_fops);
|
|
|
|
return 0;
|
2016-05-27 05:48:59 +00:00
|
|
|
}
|
|
|
|
device_initcall(ptdump_init);
|