mm: kmemleak: avoid using __va() on addresses that don't have a lowmem mapping

Some of the kmemleak_*() callbacks in memblock, bootmem, CMA convert a
physical address to a virtual one using __va().  However, such physical
addresses may sometimes be located in highmem and using __va() is
incorrect, leading to inconsistent object tracking in kmemleak.

The following functions have been added to the kmemleak API and they take
a physical address as the object pointer.  They only perform the
corresponding action if the address has a lowmem mapping:

kmemleak_alloc_phys
kmemleak_free_part_phys
kmemleak_not_leak_phys
kmemleak_ignore_phys

The affected calling places have been updated to use the new kmemleak
API.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Catalin Marinas <[email protected]>
Reported-by: Vignesh R <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
Catalin Marinas 2016-10-11 13:55:11 -07:00 • committed by Linus Torvalds
commit 9099daed9c
7 changed files with 83 additions and 9 deletions

View file

@ -155,7 +155,7 @@ void __init free_bootmem_late(unsigned long physaddr, unsigned long size)
{
unsigned long cursor, end;
kmemleak_free_part(__va(physaddr), size);
kmemleak_free_part_phys(physaddr, size);
cursor = PFN_UP(physaddr);
end = PFN_DOWN(physaddr + size);
@ -399,7 +399,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
{
unsigned long start, end;
kmemleak_free_part(__va(physaddr), size);
kmemleak_free_part_phys(physaddr, size);
start = PFN_UP(physaddr);
end = PFN_DOWN(physaddr + size);
@ -420,7 +420,7 @@ void __init free_bootmem(unsigned long physaddr, unsigned long size)
{
unsigned long start, end;
kmemleak_free_part(__va(physaddr), size);
kmemleak_free_part_phys(physaddr, size);
start = PFN_UP(physaddr);
end = PFN_DOWN(physaddr + size);