mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
vmap: fix wrong mmu setting in check sp funciton [1/1]
PD#TV-9668 Problem: If sp address is in linear mapping range, check_sp_fault_again function in vmap fault handler will still map a new page for it. This will cause some data in R/W section polluted. Solution: Avoid map page if sp is in linear range. Verify: TL1 x301 Change-Id: I0e02a2048b586854c528cd3eeafb725751b9dc82 Signed-off-by: Tao Zeng <tao.zeng@amlogic.com>
This commit is contained in:
@@ -52,6 +52,8 @@
|
||||
static unsigned long stack_shrink_jiffies;
|
||||
static unsigned char vmap_shrink_enable;
|
||||
static atomic_t vmap_stack_size;
|
||||
static atomic_t vmap_fault_count;
|
||||
static atomic_t vmap_pre_handle_count;
|
||||
static struct aml_vmap *avmap;
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
@@ -454,6 +456,18 @@ static void check_sp_fault_again(struct pt_regs *regs)
|
||||
#endif
|
||||
addr = sp - sizeof(*regs);
|
||||
|
||||
/*
|
||||
* When we handle vmap stack fault, we are in pre-allcated
|
||||
* per-cpu vmap stack. But if sp is near bottom of a page and we
|
||||
* return to normal handler, sp may down grow to another page
|
||||
* to cause a vmap fault again. So we need map next page for
|
||||
* stack before page-fault happen.
|
||||
*
|
||||
* But we need check sp is realy in vmap stack range.
|
||||
*/
|
||||
if (!is_vmap_addr(addr)) /* addr may in linear mapping */
|
||||
return;
|
||||
|
||||
if (sp && ((addr & PAGE_MASK) != (sp & PAGE_MASK))) {
|
||||
/*
|
||||
* will fault when we copy back context, so handle
|
||||
@@ -477,6 +491,7 @@ static void check_sp_fault_again(struct pt_regs *regs)
|
||||
mod_delayed_work(system_highpri_wq, &avmap->mwork, 0);
|
||||
|
||||
D("map page:%5lx for addr:%lx\n", page_to_pfn(page), addr);
|
||||
atomic_inc(&vmap_pre_handle_count);
|
||||
#if DEBUG
|
||||
show_fault_stack(addr, regs);
|
||||
#endif
|
||||
@@ -557,6 +572,7 @@ int handle_vmap_fault(unsigned long addr, unsigned int esr,
|
||||
if (cache <= (VMAP_CACHE_PAGE / 2))
|
||||
mod_delayed_work(system_highpri_wq, &avmap->mwork, 0);
|
||||
|
||||
atomic_inc(&vmap_fault_count);
|
||||
D("map page:%5lx for addr:%lx\n", page_to_pfn(page), addr);
|
||||
#if DEBUG
|
||||
show_fault_stack(addr, regs);
|
||||
@@ -586,6 +602,20 @@ static int shrink_vm_stack(unsigned long low, unsigned long high)
|
||||
return pages;
|
||||
}
|
||||
|
||||
void arch_report_meminfo(struct seq_file *m)
|
||||
{
|
||||
unsigned long kb = 1 << (PAGE_SHIFT - 10);
|
||||
unsigned long tmp1, tmp2, tmp3;
|
||||
|
||||
tmp1 = kb * atomic_read(&vmap_stack_size);
|
||||
tmp2 = kb * atomic_read(&vmap_fault_count);
|
||||
tmp3 = kb * atomic_read(&vmap_pre_handle_count);
|
||||
|
||||
seq_printf(m, "VmapStack: %8ld kB\n", tmp1);
|
||||
seq_printf(m, "VmapFault: %8ld kB\n", tmp2);
|
||||
seq_printf(m, "VmapPfault: %8ld kB\n", tmp3);
|
||||
}
|
||||
|
||||
static unsigned long get_task_stack_floor(unsigned long sp)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
#ifdef CONFIG_CMA
|
||||
#include <linux/cma.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
#include <linux/amlogic/vmap_stack.h>
|
||||
#endif
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include "internal.h"
|
||||
@@ -156,9 +153,6 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
|
||||
show_val_kb(m, "CmaFree: ",
|
||||
global_page_state(NR_FREE_CMA_PAGES));
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
show_val_kb(m, "VmapStack: ", get_vmap_stack_size());
|
||||
#endif
|
||||
|
||||
hugetlb_report_meminfo(m);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user