Skip to contentSkip to conversation

x86/mm: Fix slow_virt_to_phys() for X86_PAE again]

[email protected]: Ingo Molnar 2 participants 2 messages Mar 8, 2016 – Mar 12, 2016

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

hi Greg,

Please apply this fix (bf70e5513dfea) on top of v4.4. v4.3 does not have the bug.
v4.5 and later has the fix already.

Thanks,

Ingo

----- Forwarded message from tip-bot for Dexuan Cui <[email protected]> -----

Date: Thu, 25 Feb 2016 10:57:39 -0800
From: tip-bot for Dexuan Cui <[email protected]>
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected],
[email protected]
Subject: [tip:x86/urgent] x86/mm: Fix slow_virt_to_phys() for X86_PAE again

Commit-ID:  bf70e5513dfea29c3682e7eb3dbb45f0723bac09
Gitweb:     http://git.kernel.org/tip/bf70e5513dfea29c3682e7eb3dbb45f0723bac09
Author:     Dexuan Cui <[email protected]>
AuthorDate: Thu, 25 Feb 2016 01:58:12 -0800
Committer:  Thomas Gleixner <[email protected]>
CommitDate: Thu, 25 Feb 2016 19:53:15 +0100

x86/mm: Fix slow_virt_to_phys() for X86_PAE again

"d1cd12108346: x86, pageattr: Prevent overflow in slow_virt_to_phys() for X86_PAE" was unintentionally removed by the recent "34437e67a672: x86/mm: Fix slow_virt_to_phys() to handle large PAT bit".

And, the variable 'phys_addr' was defined as "unsigned long" by mistake -- it should be "phys_addr_t".

As a result, Hyper-V network driver in 32-PAE Linux guest can't work again.

Fixes commit 34437e67a672: "x86/mm: Fix slow_virt_to_phys() to handle large PAT bit"
Cc Andrew Morton <[email protected]>
Cc K. Y. Srinivasan <[email protected]>
Cc Haiyang Zhang <[email protected]>
---
 arch/x86/mm/pageattr.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
arch/x86/mm/pageattr.c +10 -4
index 2440814..9cf96d8 100644
@@ -419,24 +419,30 @@ pmd_t *lookup_pmd_address(unsigned long address)
 phys_addr_t slow_virt_to_phys(void *__virt_addr)
 {
 	unsigned long virt_addr = (unsigned long)__virt_addr;
-	unsigned long phys_addr, offset;
+	phys_addr_t phys_addr;
+	unsigned long offset;
 	enum pg_level level;
 	pte_t *pte;
 
 	pte = lookup_address(virt_addr, &level);
 	BUG_ON(!pte);
 
+	/*
+	 * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t
+	 * before being left-shifted PAGE_SHIFT bits -- this trick is to
+	 * make 32-PAE kernel work correctly.
+	 */
 	switch (level) {
 	case PG_LEVEL_1G:
-		phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
+		phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
 		offset = virt_addr & ~PUD_PAGE_MASK;
 		break;
 	case PG_LEVEL_2M:
-		phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
+		phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
 		offset = virt_addr & ~PMD_PAGE_MASK;
 		break;
 	default:
-		phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
+		phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
 		offset = virt_addr & ~PAGE_MASK;
 	}
 

----- End forwarded message -----

#1 lore raw
Quoted 5 lines · Ingo Molnar

hi Greg,

Please apply this fix (bf70e5513dfea) on top of v4.4. v4.3 does not have the bug.
v4.5 and later has the fix already.

Now queued up, thanks.

greg k-h