diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2016-08-25 14:12:06 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2016-08-25 14:12:06 +1000 |
commit | 8ef060f03472920a5bb26d59877db62594d007d1 (patch) | |
tree | 5b64b41ada77f5104a7ed83d99a5c90e61314c84 | |
parent | 895fc9e7f48a12095a2713f5311c08d9011d946a (diff) | |
parent | 152869a2980e5c92d19e252129115a01807bb9bf (diff) | |
download | linux-next-8ef060f03472920a5bb26d59877db62594d007d1.tar.gz |
Merge branch 'akpm/master'
-rw-r--r-- | Documentation/dev-tools/kmemleak.rst | 9 | ||||
-rw-r--r-- | arch/x86/kernel/machine_kexec_64.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/dvm/calib.c | 3 | ||||
-rw-r--r-- | include/linux/kexec.h | 6 | ||||
-rw-r--r-- | include/linux/kmemleak.h | 18 | ||||
-rw-r--r-- | include/linux/mlx5/device.h | 2 | ||||
-rw-r--r-- | mm/bootmem.c | 6 | ||||
-rw-r--r-- | mm/cma.c | 2 | ||||
-rw-r--r-- | mm/kmemleak.c | 47 | ||||
-rw-r--r-- | mm/memblock.c | 8 | ||||
-rw-r--r-- | mm/nobootmem.c | 2 |
11 files changed, 93 insertions, 13 deletions
diff --git a/Documentation/dev-tools/kmemleak.rst b/Documentation/dev-tools/kmemleak.rst index 1788722d5495..b2391b829169 100644 --- a/Documentation/dev-tools/kmemleak.rst +++ b/Documentation/dev-tools/kmemleak.rst @@ -162,6 +162,15 @@ See the include/linux/kmemleak.h header for the functions prototype. - ``kmemleak_alloc_recursive`` - as kmemleak_alloc but checks the recursiveness - ``kmemleak_free_recursive`` - as kmemleak_free but checks the recursiveness +The following functions take a physical address as the object pointer +and 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`` + Dealing with false positives/negatives -------------------------------------- diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index fc3389fc47a2..b1f15a2dab65 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -338,6 +338,9 @@ void arch_crash_save_vmcoreinfo(void) vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); VMCOREINFO_PHYS_BASE(phys_base); + VMCOREINFO_PAGE_OFFSET(PAGE_OFFSET); + VMCOREINFO_VMALLOC_START(VMALLOC_START); + VMCOREINFO_VMEMMAP_START(VMEMMAP_START); } /* arch-dependent functionality related to kexec file-based syscall */ diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c index e9cef9de9ed8..c96f9b1d948a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c @@ -900,8 +900,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = - min(abs(delta_g), - (s32) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); + min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) /* diff --git a/include/linux/kexec.h b/include/linux/kexec.h index d3ae4292931b..cd3874c21b3c 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -261,6 +261,12 @@ phys_addr_t paddr_vmcoreinfo_note(void); vmcoreinfo_append_str("CONFIG_%s=y\n", #name) #define VMCOREINFO_PHYS_BASE(value) \ vmcoreinfo_append_str("PHYS_BASE=%lx\n", (unsigned long)value) +#define VMCOREINFO_PAGE_OFFSET(value) \ + vmcoreinfo_append_str("PAGE_OFFSET=%lx\n", (unsigned long)value) +#define VMCOREINFO_VMALLOC_START(value) \ + vmcoreinfo_append_str("VMALLOC_START=%lx\n", (unsigned long)value) +#define VMCOREINFO_VMEMMAP_START(value) \ + vmcoreinfo_append_str("VMEMMAP_START=%lx\n", (unsigned long)value) extern struct kimage *kexec_image; extern struct kimage *kexec_crash_image; diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h index 4894c6888bc6..1c2a32829620 100644 --- a/include/linux/kmemleak.h +++ b/include/linux/kmemleak.h @@ -38,6 +38,11 @@ extern void kmemleak_not_leak(const void *ptr) __ref; extern void kmemleak_ignore(const void *ptr) __ref; extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref; extern void kmemleak_no_scan(const void *ptr) __ref; +extern void kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count, + gfp_t gfp) __ref; +extern void kmemleak_free_part_phys(phys_addr_t phys, size_t size) __ref; +extern void kmemleak_not_leak_phys(phys_addr_t phys) __ref; +extern void kmemleak_ignore_phys(phys_addr_t phys) __ref; static inline void kmemleak_alloc_recursive(const void *ptr, size_t size, int min_count, unsigned long flags, @@ -106,6 +111,19 @@ static inline void kmemleak_erase(void **ptr) static inline void kmemleak_no_scan(const void *ptr) { } +static inline void kmemleak_alloc_phys(phys_addr_t phys, size_t size, + int min_count, gfp_t gfp) +{ +} +static inline void kmemleak_free_part_phys(phys_addr_t phys, size_t size) +{ +} +static inline void kmemleak_not_leak_phys(phys_addr_t phys) +{ +} +static inline void kmemleak_ignore_phys(phys_addr_t phys) +{ +} #endif /* CONFIG_DEBUG_KMEMLEAK */ diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 77c141797152..37a130eff270 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -93,8 +93,6 @@ __mlx5_mask(typ, fld)) }) #define MLX5_SET64(typ, p, fld, v) do { \ - BUILD_BUG_ON(__mlx5_bit_sz(typ, fld) != 64); \ - BUILD_BUG_ON(__mlx5_bit_off(typ, fld) % 64); \ *((__be64 *)(p) + __mlx5_64_off(typ, fld)) = cpu_to_be64(v); \ } while (0) diff --git a/mm/bootmem.c b/mm/bootmem.c index 0aa7dda52402..80f1d70bad2d 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -158,7 +158,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); @@ -402,7 +402,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); @@ -423,7 +423,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); @@ -336,7 +336,7 @@ int __init cma_declare_contiguous(phys_addr_t base, * kmemleak scans/reads tracked objects for pointers to other * objects but this address isn't mapped and accessible */ - kmemleak_ignore(phys_to_virt(addr)); + kmemleak_ignore_phys(addr); base = addr; } diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 086292f7c59d..a5e453cf05c4 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -90,6 +90,8 @@ #include <linux/cache.h> #include <linux/percpu.h> #include <linux/hardirq.h> +#include <linux/bootmem.h> +#include <linux/pfn.h> #include <linux/mmzone.h> #include <linux/slab.h> #include <linux/thread_info.h> @@ -1121,6 +1123,51 @@ void __ref kmemleak_no_scan(const void *ptr) } EXPORT_SYMBOL(kmemleak_no_scan); +/** + * kmemleak_alloc_phys - similar to kmemleak_alloc but taking a physical + * address argument + */ +void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count, + gfp_t gfp) +{ + if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_alloc(__va(phys), size, min_count, gfp); +} +EXPORT_SYMBOL(kmemleak_alloc_phys); + +/** + * kmemleak_free_part_phys - similar to kmemleak_free_part but taking a + * physical address argument + */ +void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size) +{ + if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_free_part(__va(phys), size); +} +EXPORT_SYMBOL(kmemleak_free_part_phys); + +/** + * kmemleak_not_leak_phys - similar to kmemleak_not_leak but taking a physical + * address argument + */ +void __ref kmemleak_not_leak_phys(phys_addr_t phys) +{ + if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_not_leak(__va(phys)); +} +EXPORT_SYMBOL(kmemleak_not_leak_phys); + +/** + * kmemleak_ignore_phys - similar to kmemleak_ignore but taking a physical + * address argument + */ +void __ref kmemleak_ignore_phys(phys_addr_t phys) +{ + if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) + kmemleak_ignore(__va(phys)); +} +EXPORT_SYMBOL(kmemleak_ignore_phys); + /* * Update an object's checksum and return true if it was modified. */ diff --git a/mm/memblock.c b/mm/memblock.c index 483197ef613f..30ecea7b45d1 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -723,7 +723,7 @@ int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size) (unsigned long long)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + kmemleak_free_part_phys(base, size); return memblock_remove_range(&memblock.reserved, base, size); } @@ -1152,7 +1152,7 @@ static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size, * The min_count is set to 0 so that memblock allocations are * never reported as leaks. */ - kmemleak_alloc(__va(found), size, 0, 0); + kmemleak_alloc_phys(found, size, 0, 0); return found; } return 0; @@ -1399,7 +1399,7 @@ void __init __memblock_free_early(phys_addr_t base, phys_addr_t size) memblock_dbg("%s: [%#016llx-%#016llx] %pF\n", __func__, (u64)base, (u64)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + kmemleak_free_part_phys(base, size); memblock_remove_range(&memblock.reserved, base, size); } @@ -1419,7 +1419,7 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) memblock_dbg("%s: [%#016llx-%#016llx] %pF\n", __func__, (u64)base, (u64)base + size - 1, (void *)_RET_IP_); - kmemleak_free_part(__va(base), size); + kmemleak_free_part_phys(base, size); cursor = PFN_UP(base); end = PFN_DOWN(base + size); diff --git a/mm/nobootmem.c b/mm/nobootmem.c index bd05a70f44b9..a056d31dff7e 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -81,7 +81,7 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size) { unsigned long cursor, end; - kmemleak_free_part(__va(addr), size); + kmemleak_free_part_phys(addr, size); cursor = PFN_UP(addr); end = PFN_DOWN(addr + size); |