Patchwork [3.5.y.z,extended,stable] Patch "mm/vmemmap: fix wrong use of virt_to_page" has been added to staging queue

mail settings
Submitter Herton Ronaldo Krzesinski
Date Dec. 10, 2012, 5 p.m.
Message ID <>
Download mbox | patch
Permalink /patch/204983/
State New
Headers show


Herton Ronaldo Krzesinski - Dec. 10, 2012, 5 p.m.
This is a note to let you know that I have just added a patch titled

    mm/vmemmap: fix wrong use of virt_to_page

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From 3ad38b8b7ca21206cd0453a148da39fd3f3d3f89 Mon Sep 17 00:00:00 2001
From: Jianguo Wu <>
Date: Thu, 29 Nov 2012 13:54:21 -0800
Subject: [PATCH] mm/vmemmap: fix wrong use of virt_to_page

commit ae64ffcac35de0db628ba9631edf8ff34c5cd7ac upstream.

memory hotremove, there is a kernel BUG at arch/x86/mm/physaddr.c:20.

It is caused by free_section_usemap()->virt_to_page(), virt_to_page() is
only used for kernel direct mapping address, but sparse-vmemmap uses
vmemmap address, so it is going wrong here.

  ------------[ cut here ]------------
  kernel BUG at arch/x86/mm/physaddr.c:20!
  invalid opcode: 0000 [#1] SMP
  Modules linked in: acpihp_drv acpihp_slot edd cpufreq_conservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf fuse vfat fat loop dm_mod coretemp kvm crc32c_intel ipv6 ixgbe igb iTCO_wdt i7core_edac edac_core pcspkr iTCO_vendor_support ioatdma microcode joydev sr_mod i2c_i801 dca lpc_ich mfd_core mdio tpm_tis i2c_core hid_generic tpm cdrom sg tpm_bios rtc_cmos button ext3 jbd mbcache usbhid hid uhci_hcd ehci_hcd usbcore usb_common sd_mod crc_t10dif processor thermal_sys hwmon scsi_dh_alua scsi_dh_hp_sw scsi_dh_rdac scsi_dh_emc scsi_dh ata_generic ata_piix libata megaraid_sas scsi_mod
  CPU 39
  Pid: 6454, comm: sh Not tainted 3.7.0-rc1-acpihp-final+ #45 QCI QSSC-S4R/QSSC-S4R
  RIP: 0010:[<ffffffff8103c908>]  [<ffffffff8103c908>] __phys_addr+0x88/0x90
  RSP: 0018:ffff8804440d7c08  EFLAGS: 00010006
  RAX: 0000000000000006 RBX: ffffea0012000000 RCX: 000000000000002c

Signed-off-by: Jianguo Wu <>
Signed-off-by: Jiang Liu <>
Reviewd-by: Wen Congyang <>
Acked-by: Johannes Weiner <>
Reviewed-by: Yasuaki Ishimatsu <>
Reviewed-by: Michal Hocko <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>
Signed-off-by: Herton Ronaldo Krzesinski <>
 mm/sparse.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)



diff --git a/mm/sparse.c b/mm/sparse.c
index 950981f..0abadaf 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -629,7 +629,7 @@  static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 	return; /* XXX: Not implemented yet */
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
@@ -670,10 +670,11 @@  static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 			   get_order(sizeof(struct page) * nr_pages));

-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 	unsigned long maps_section_nr, removing_section_nr, i;
 	unsigned long magic;
+	struct page *page = virt_to_page(memmap);

 	for (i = 0; i < nr_pages; i++, page++) {
 		magic = (unsigned long) page->;
@@ -722,13 +723,10 @@  static void free_section_usemap(struct page *memmap, unsigned long *usemap)

 	if (memmap) {
-		struct page *memmap_page;
-		memmap_page = virt_to_page(memmap);
 		nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
 			>> PAGE_SHIFT;

-		free_map_bootmem(memmap_page, nr_pages);
+		free_map_bootmem(memmap, nr_pages);