dmc: fix panic problem when show memory in highmem [1/1]

PD#SWPL-2767

Problem:
If DMC violation address is in highmem, then it will panic
when show memory using page_address();

Solution:
map violation address for highmem

Verify:
p212

Change-Id: Ib6213eaab42b129c8c0a381511a0b3376b0d3e66
Signed-off-by: Tao Zeng <tao.zeng@amlogic.com>
This commit is contained in:
Tao Zeng
2018-12-27 14:31:29 +08:00
committed by Luke Go
parent 3d29868fd0
commit 52d4640db5
2 changed files with 46 additions and 20 deletions

View File

@@ -29,6 +29,7 @@
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/cpu.h>
#include <linux/smp.h>
@@ -76,12 +77,31 @@ static size_t g12_dmc_dump_reg(char *buf)
return sz;
}
static void show_violation_mem(unsigned long addr)
{
struct page *page;
unsigned long *p, *q;
if (!pfn_valid(__phys_to_pfn(addr)))
return;
page = phys_to_page(addr);
p = kmap_atomic(page);
if (!p)
return;
q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p));
pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n",
(unsigned long)q, *q, page->flags & 0xffffffff,
page->mapping,
(void *)get_page_trace(page));
kunmap_atomic(p);
}
static void check_violation(struct dmc_monitor *mon)
{
int i, port, subport;
unsigned long addr, status;
struct page *page;
unsigned long *p;
char id_str[4];
char off1 = 21, off2 = 10;
@@ -112,14 +132,7 @@ static void check_violation(struct dmc_monitor *mon)
pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n",
addr, status, to_ports(port),
to_sub_ports(port, subport, id_str), mon->same_page);
if (pfn_valid(__phys_to_pfn(addr))) {
page = phys_to_page(addr);
p = (page_address(page) + (addr & (PAGE_SIZE - 1)));
pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n",
addr, *p, page->flags & 0xffffffff,
page->mapping,
(void *)get_page_trace(page));
}
show_violation_mem(addr);
if (!port) /* dump stack for CPU write */
dump_stack();

View File

@@ -29,6 +29,7 @@
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/cpu.h>
#include <linux/smp.h>
@@ -80,12 +81,31 @@ static size_t gx_dmc_dump_reg(char *buf)
return sz;
}
static void show_violation_mem(unsigned long addr)
{
struct page *page;
unsigned long *p, *q;
if (!pfn_valid(__phys_to_pfn(addr)))
return;
page = phys_to_page(addr);
p = kmap_atomic(page);
if (!p)
return;
q = p + ((addr & (PAGE_SIZE - 1)) / sizeof(*p));
pr_info(DMC_TAG "[%08lx]:%016lx, f:%8lx, m:%p, a:%ps\n",
(unsigned long)q, *q, page->flags & 0xffffffff,
page->mapping,
(void *)get_page_trace(page));
kunmap_atomic(p);
}
static void check_violation(struct dmc_monitor *mon)
{
int i, port, subport;
unsigned long addr, status;
struct page *page;
unsigned long *p;
char id_str[4];
for (i = 1; i < 8; i += 2) {
@@ -109,14 +129,7 @@ static void check_violation(struct dmc_monitor *mon)
pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n",
addr, status, to_ports(port),
to_sub_ports(port, subport, id_str), mon->same_page);
if (pfn_valid(__phys_to_pfn(addr))) {
page = phys_to_page(addr);
p = (page_address(page) + (addr & (PAGE_SIZE - 1)));
pr_info(DMC_TAG" [%08lx]:%016lx, f:%8lx, m:%p, a:%pf\n",
addr, *p, page->flags & 0xffffffff,
page->mapping,
(void *)get_page_trace(page));
}
show_violation_mem(addr);
if (!port) /* dump stack for CPU write */
dump_stack();