Skip to content

Commit cf387d9

Browse files
kvaneeshdjbw
authored andcommitted
libnvdimm/altmap: Track namespace boundaries in altmap
With PFN_MODE_PMEM namespace, the memmap area is allocated from the device area. Some architectures map the memmap area with large page size. On architectures like ppc64, 16MB page for memap mapping can map 262144 pfns. This maps a namespace size of 16G. When populating memmap region with 16MB page from the device area, make sure the allocated space is not used to map resources outside this namespace. Such usage of device area will prevent a namespace destroy. Add resource end pnf in altmap and use that to check if the memmap area allocation can map pfn outside the namespace. On ppc64 in such case we fallback to allocation from memory. This fix kernel crash reported below: [ 132.034989] WARNING: CPU: 13 PID: 13719 at mm/memremap.c:133 devm_memremap_pages_release+0x2d8/0x2e0 [ 133.464754] BUG: Unable to handle kernel data access at 0xc00c00010b204000 [ 133.464760] Faulting instruction address: 0xc00000000007580c [ 133.464766] Oops: Kernel access of bad area, sig: 11 [#1] [ 133.464771] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries ..... [ 133.464901] NIP [c00000000007580c] vmemmap_free+0x2ac/0x3d0 [ 133.464906] LR [c0000000000757f8] vmemmap_free+0x298/0x3d0 [ 133.464910] Call Trace: [ 133.464914] [c000007cbfd0f7b0] [c0000000000757f8] vmemmap_free+0x298/0x3d0 (unreliable) [ 133.464921] [c000007cbfd0f8d0] [c000000000370a44] section_deactivate+0x1a4/0x240 [ 133.464928] [c000007cbfd0f980] [c000000000386270] __remove_pages+0x3a0/0x590 [ 133.464935] [c000007cbfd0fa50] [c000000000074158] arch_remove_memory+0x88/0x160 [ 133.464942] [c000007cbfd0fae0] [c0000000003be8c0] devm_memremap_pages_release+0x150/0x2e0 [ 133.464949] [c000007cbfd0fb70] [c000000000738ea0] devm_action_release+0x30/0x50 [ 133.464955] [c000007cbfd0fb90] [c00000000073a5a4] release_nodes+0x344/0x400 [ 133.464961] [c000007cbfd0fc40] [c00000000073378c] device_release_driver_internal+0x15c/0x250 [ 133.464968] [c000007cbfd0fc80] [c00000000072fd14] unbind_store+0x104/0x110 [ 133.464973] [c000007cbfd0fcd0] [c00000000072ee24] drv_attr_store+0x44/0x70 [ 133.464981] [c000007cbfd0fcf0] [c0000000004a32bc] sysfs_kf_write+0x6c/0xa0 [ 133.464987] [c000007cbfd0fd10] [c0000000004a1dfc] kernfs_fop_write+0x17c/0x250 [ 133.464993] [c000007cbfd0fd60] [c0000000003c348c] __vfs_write+0x3c/0x70 [ 133.464999] [c000007cbfd0fd80] [c0000000003c75d0] vfs_write+0xd0/0x250 djbw: Aneesh notes that this crash can likely be triggered in any kernel that supports 'papr_scm', so flagging that commit for -stable consideration. Fixes: b5beae5 ("powerpc/pseries: Add driver for PAPR SCM regions") Cc: <[email protected]> Reported-by: Sachin Sant <[email protected]> Signed-off-by: Aneesh Kumar K.V <[email protected]> Reviewed-by: Pankaj Gupta <[email protected]> Tested-by: Santosh Sivaraj <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent 86aa666 commit cf387d9

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

arch/powerpc/mm/init_64.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ static __meminit void vmemmap_list_populate(unsigned long phys,
172172
vmemmap_list = vmem_back;
173173
}
174174

175+
static bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long start,
176+
unsigned long page_size)
177+
{
178+
unsigned long nr_pfn = page_size / sizeof(struct page);
179+
unsigned long start_pfn = page_to_pfn((struct page *)start);
180+
181+
if ((start_pfn + nr_pfn) > altmap->end_pfn)
182+
return true;
183+
184+
if (start_pfn < altmap->base_pfn)
185+
return true;
186+
187+
return false;
188+
}
189+
175190
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
176191
struct vmem_altmap *altmap)
177192
{
@@ -194,7 +209,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
194209
* fail due to alignment issues when using 16MB hugepages, so
195210
* fall back to system memory if the altmap allocation fail.
196211
*/
197-
if (altmap) {
212+
if (altmap && !altmap_cross_boundary(altmap, start, page_size)) {
198213
p = altmap_alloc_block_buf(page_size, altmap);
199214
if (!p)
200215
pr_debug("altmap block allocation failed, falling back to system memory");

drivers/nvdimm/pfn_devs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,9 +672,11 @@ static int __nvdimm_setup_pfn(struct nd_pfn *nd_pfn, struct dev_pagemap *pgmap)
672672
struct nd_namespace_common *ndns = nd_pfn->ndns;
673673
struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
674674
resource_size_t base = nsio->res.start + start_pad;
675+
resource_size_t end = nsio->res.end - end_trunc;
675676
struct vmem_altmap __altmap = {
676677
.base_pfn = init_altmap_base(base),
677678
.reserve = init_altmap_reserve(base),
679+
.end_pfn = PHYS_PFN(end),
678680
};
679681

680682
memcpy(res, &nsio->res, sizeof(*res));

include/linux/memremap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct device;
1717
*/
1818
struct vmem_altmap {
1919
const unsigned long base_pfn;
20+
const unsigned long end_pfn;
2021
const unsigned long reserve;
2122
unsigned long free;
2223
unsigned long align;

0 commit comments

Comments
 (0)