Skip to contentSkip to conversation

mm/page_alloc: Call kernel_map_pages in unset_migrateype_isolate

PATCH In review Laura Abbott 3 participants 3 messages Mar 16, 2015 – Mar 17, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mm/page_alloc: Call kernel_map_pages in unset_migrateype_isolate

Commit 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock") changed the logic of unset_migratetype_isolate to check the buddy allocator and explicitly call __free_pages to merge. The page that is being freed in this path never had prep_new_page called so set_page_refcounted is called explicitly but there is no call to kernel_map_pages. With the default kernel_map_pages this is mostly harmless but if kernel_map_pages does any manipulation of the page tables (unmapping or setting pages to read only) this may trigger a fault:

    alloc_contig_range test_pages_isolated(ceb00, ced00) failed
    Unable to handle kernel paging request at virtual address ffffffc0cec00000
    pgd = ffffffc045fc4000
    [ffffffc0cec00000] *pgd=0000000000000000
    Internal error: Oops: 9600004f [#1] PREEMPT SMP
    Modules linked in: exfatfs
    CPU: 1 PID: 23237 Comm: TimedEventQueue Not tainted 3.10.49-gc72ad36-dirty #1
    task: ffffffc03de52100 ti: ffffffc015388000 task.ti: ffffffc015388000
    PC is at memset+0xc8/0x1c0
    LR is at kernel_map_pages+0x1ec/0x244

Fix this by calling kernel_map_pages to ensure the page is set in the page table properly

Fixes 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock")
Cc Naoya Horiguchi <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Yasuaki Ishimatsu <[email protected]>
Cc Zhang Yanfei <[email protected]>
Cc Xishi Qiu <[email protected]>
Cc Vladimir Davydov <[email protected]>
Cc Joonsoo Kim <[email protected]>
Cc Gioh Kim <[email protected]>
Cc Michal Nazarewicz <[email protected]>
Cc Marek Szyprowski <[email protected]>
Cc Vlastimil Babka <[email protected]>

---
Note this was found on a backport to 3.10 and the code to make kernel_map_pages change the page table state is currently out of tree. The original had stable, so this may need to go into stable as well.

---
 mm/page_isolation.c | 1 +
 1 file changed, 1 insertion(+)
mm/page_isolation.c +1 -0
index 72f5ac3..755a42c 100644
@@ -103,6 +103,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
 
 			if (!is_migrate_isolate_page(buddy)) {
 				__isolate_free_page(page, order);
+				kernel_map_pages(page, (1 << order), 1);
 				set_page_refcounted(page);
 				isolated_page = page;
 			}
Signature · 10 lines
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
This e-mail address will be inactive after March 20, 2015
Please contact privately for follow up after that date.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Acked-by on v1 1/1
#1 lore raw
Quoted 37 lines · Laura Abbott

Commit 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock") changed the logic of unset_migratetype_isolate to check the buddy allocator and explicitly call __free_pages to merge. The page that is being freed in this path never had prep_new_page called so set_page_refcounted is called explicitly but there is no call to kernel_map_pages. With the default kernel_map_pages this is mostly harmless but if kernel_map_pages does any manipulation of the page tables (unmapping or setting pages to read only) this may trigger a fault:

    alloc_contig_range test_pages_isolated(ceb00, ced00) failed
    Unable to handle kernel paging request at virtual address ffffffc0cec00000
    pgd = ffffffc045fc4000
    [ffffffc0cec00000] *pgd=0000000000000000
    Internal error: Oops: 9600004f [#1] PREEMPT SMP
    Modules linked in: exfatfs
    CPU: 1 PID: 23237 Comm: TimedEventQueue Not tainted 3.10.49-gc72ad36-dirty #1
    task: ffffffc03de52100 ti: ffffffc015388000 task.ti: ffffffc015388000
    PC is at memset+0xc8/0x1c0
    LR is at kernel_map_pages+0x1ec/0x244

Fix this by calling kernel_map_pages to ensure the page is set in the page table properly

Fixes 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock")
Cc Naoya Horiguchi <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Yasuaki Ishimatsu <[email protected]>
Cc Zhang Yanfei <[email protected]>
Cc Xishi Qiu <[email protected]>
Cc Vladimir Davydov <[email protected]>
Cc Joonsoo Kim <[email protected]>
Cc Gioh Kim <[email protected]>
Cc Michal Nazarewicz <[email protected]>
Cc Marek Szyprowski <[email protected]>
Cc Vlastimil Babka <[email protected]>
Quoted 4 lines

---
Note this was found on a backport to 3.10 and the code to make kernel_map_pages change the page table state is currently out of tree. The original had stable, so this may need to go into stable as well.

I found that some implementation of kernel_map_pages() in mainline also require this change. Some implementation doesn't check previous state of page table, but some others check previous state of page table when calling kernel_map_pages().

Thanks.

Quoted 27 lines
---
 mm/page_isolation.c | 1 +
 1 file changed, 1 insertion(+)
mm/page_isolation.c +1 -0
index 72f5ac3..755a42c 100644
@@ -103,6 +103,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
 
 			if (!is_migrate_isolate_page(buddy)) {
 				__isolate_free_page(page, order);
+				kernel_map_pages(page, (1 << order), 1);
 				set_page_refcounted(page);
 				isolated_page = page;
 			}
Signature · 10 lines
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
This e-mail address will be inactive after March 20, 2015
Please contact privately for follow up after that date.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by on v1 1/1
#2 lore raw
In reply to Laura Abbott
Quoted 20 lines · Laura Abbott

Commit 3c605096d315 ("mm/page_alloc: restrict max order of merging on isolated pageblock") changed the logic of unset_migratetype_isolate to check the buddy allocator and explicitly call __free_pages to merge. The page that is being freed in this path never had prep_new_page called so set_page_refcounted is called explicitly but there is no call to kernel_map_pages. With the default kernel_map_pages this is mostly harmless but if kernel_map_pages does any manipulation of the page tables (unmapping or setting pages to read only) this may trigger a fault:

    alloc_contig_range test_pages_isolated(ceb00, ced00) failed
    Unable to handle kernel paging request at virtual address ffffffc0cec00000
    pgd = ffffffc045fc4000
    [ffffffc0cec00000] *pgd=0000000000000000
    Internal error: Oops: 9600004f [#1] PREEMPT SMP
    Modules linked in: exfatfs
    CPU: 1 PID: 23237 Comm: TimedEventQueue Not tainted 3.10.49-gc72ad36-dirty #1
    task: ffffffc03de52100 ti: ffffffc015388000 task.ti: ffffffc015388000
    PC is at memset+0xc8/0x1c0
    LR is at kernel_map_pages+0x1ec/0x244
Quoted 2 lines

Fix this by calling kernel_map_pages to ensure the page is set in the page table properly

Signature · 7 lines
All rights reversed

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>