diff mbox series

[v4,4/5] lib/ioremap: Ensure phys_addr actually corresponds to a physical address

Message ID 1543252067-30831-5-git-send-email-will.deacon@arm.com
State Superseded
Headers show
Series Clean up huge vmap and ioremap code | expand

Commit Message

Will Deacon Nov. 26, 2018, 5:07 p.m. UTC
The current ioremap() code uses a phys_addr variable at each level of
page table, which is confusingly offset by subtracting the base virtual
address being mapped so that adding the current virtual address back on
when iterating through the page table entries gives back the corresponding
physical address.

This is fairly confusing and results in all users of phys_addr having to
add the current virtual address back on. Instead, this patch just updates
phys_addr when iterating over the page table entries, ensuring that it's
always up-to-date and doesn't require explicit offsetting.

Cc: Chintan Pandya <cpandya@codeaurora.org>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

---
 lib/ioremap.c | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

-- 
2.1.4

Comments

Sean Christopherson Nov. 26, 2018, 7 p.m. UTC | #1
On Mon, Nov 26, 2018 at 05:07:46PM +0000, Will Deacon wrote:
> The current ioremap() code uses a phys_addr variable at each level of

> page table, which is confusingly offset by subtracting the base virtual

> address being mapped so that adding the current virtual address back on

> when iterating through the page table entries gives back the corresponding

> physical address.

> 

> This is fairly confusing and results in all users of phys_addr having to

> add the current virtual address back on. Instead, this patch just updates

> phys_addr when iterating over the page table entries, ensuring that it's

> always up-to-date and doesn't require explicit offsetting.

> 

> Cc: Chintan Pandya <cpandya@codeaurora.org>

> Cc: Toshi Kani <toshi.kani@hpe.com>

> Cc: Thomas Gleixner <tglx@linutronix.de>

> Cc: Michal Hocko <mhocko@suse.com>

> Cc: Andrew Morton <akpm@linux-foundation.org>

> Cc: Sean Christopherson <sean.j.christopherson@intel.com>

> Signed-off-by: Will Deacon <will.deacon@arm.com>


Tested-by: Sean Christopherson <sean.j.christopherson@intel.com>

Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Will Deacon Nov. 27, 2018, 12:12 p.m. UTC | #2
On Mon, Nov 26, 2018 at 11:00:10AM -0800, Sean Christopherson wrote:
> On Mon, Nov 26, 2018 at 05:07:46PM +0000, Will Deacon wrote:

> > The current ioremap() code uses a phys_addr variable at each level of

> > page table, which is confusingly offset by subtracting the base virtual

> > address being mapped so that adding the current virtual address back on

> > when iterating through the page table entries gives back the corresponding

> > physical address.

> > 

> > This is fairly confusing and results in all users of phys_addr having to

> > add the current virtual address back on. Instead, this patch just updates

> > phys_addr when iterating over the page table entries, ensuring that it's

> > always up-to-date and doesn't require explicit offsetting.

> > 

> > Cc: Chintan Pandya <cpandya@codeaurora.org>

> > Cc: Toshi Kani <toshi.kani@hpe.com>

> > Cc: Thomas Gleixner <tglx@linutronix.de>

> > Cc: Michal Hocko <mhocko@suse.com>

> > Cc: Andrew Morton <akpm@linux-foundation.org>

> > Cc: Sean Christopherson <sean.j.christopherson@intel.com>

> > Signed-off-by: Will Deacon <will.deacon@arm.com>

> 

> Tested-by: Sean Christopherson <sean.j.christopherson@intel.com>

> Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>


Thanks, Sean. I think Andrew can queue these now.

Will
diff mbox series

Patch

diff --git a/lib/ioremap.c b/lib/ioremap.c
index 6c72764af19c..10d7c5485c39 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -101,19 +101,18 @@  static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
 	pmd_t *pmd;
 	unsigned long next;
 
-	phys_addr -= addr;
 	pmd = pmd_alloc(&init_mm, pud, addr);
 	if (!pmd)
 		return -ENOMEM;
 	do {
 		next = pmd_addr_end(addr, end);
 
-		if (ioremap_try_huge_pmd(pmd, addr, next, phys_addr + addr, prot))
+		if (ioremap_try_huge_pmd(pmd, addr, next, phys_addr, prot))
 			continue;
 
-		if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
+		if (ioremap_pte_range(pmd, addr, next, phys_addr, prot))
 			return -ENOMEM;
-	} while (pmd++, addr = next, addr != end);
+	} while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
 	return 0;
 }
 
@@ -142,19 +141,18 @@  static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
 	pud_t *pud;
 	unsigned long next;
 
-	phys_addr -= addr;
 	pud = pud_alloc(&init_mm, p4d, addr);
 	if (!pud)
 		return -ENOMEM;
 	do {
 		next = pud_addr_end(addr, end);
 
-		if (ioremap_try_huge_pud(pud, addr, next, phys_addr + addr, prot))
+		if (ioremap_try_huge_pud(pud, addr, next, phys_addr, prot))
 			continue;
 
-		if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
+		if (ioremap_pmd_range(pud, addr, next, phys_addr, prot))
 			return -ENOMEM;
-	} while (pud++, addr = next, addr != end);
+	} while (pud++, phys_addr += (next - addr), addr = next, addr != end);
 	return 0;
 }
 
@@ -164,7 +162,6 @@  static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
 	p4d_t *p4d;
 	unsigned long next;
 
-	phys_addr -= addr;
 	p4d = p4d_alloc(&init_mm, pgd, addr);
 	if (!p4d)
 		return -ENOMEM;
@@ -173,14 +170,14 @@  static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
 
 		if (ioremap_p4d_enabled() &&
 		    ((next - addr) == P4D_SIZE) &&
-		    IS_ALIGNED(phys_addr + addr, P4D_SIZE)) {
-			if (p4d_set_huge(p4d, phys_addr + addr, prot))
+		    IS_ALIGNED(phys_addr, P4D_SIZE)) {
+			if (p4d_set_huge(p4d, phys_addr, prot))
 				continue;
 		}
 
-		if (ioremap_pud_range(p4d, addr, next, phys_addr + addr, prot))
+		if (ioremap_pud_range(p4d, addr, next, phys_addr, prot))
 			return -ENOMEM;
-	} while (p4d++, addr = next, addr != end);
+	} while (p4d++, phys_addr += (next - addr), addr = next, addr != end);
 	return 0;
 }
 
@@ -196,14 +193,13 @@  int ioremap_page_range(unsigned long addr,
 	BUG_ON(addr >= end);
 
 	start = addr;
-	phys_addr -= addr;
 	pgd = pgd_offset_k(addr);
 	do {
 		next = pgd_addr_end(addr, end);
-		err = ioremap_p4d_range(pgd, addr, next, phys_addr+addr, prot);
+		err = ioremap_p4d_range(pgd, addr, next, phys_addr, prot);
 		if (err)
 			break;
-	} while (pgd++, addr = next, addr != end);
+	} while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
 
 	flush_cache_vmap(start, end);