Skip to content

Commit 36ddc5a

Browse files
wildea01torvalds
authored andcommitted
lib/ioremap: ensure phys_addr actually corresponds to a physical address
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. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]> Tested-by: Sean Christopherson <[email protected]> Reviewed-by: Sean Christopherson <[email protected]> Cc: Chintan Pandya <[email protected]> Cc: Toshi Kani <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 48e178a commit 36ddc5a

File tree

1 file changed

+12
-16
lines changed

1 file changed

+12
-16
lines changed

lib/ioremap.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,18 @@ static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
101101
pmd_t *pmd;
102102
unsigned long next;
103103

104-
phys_addr -= addr;
105104
pmd = pmd_alloc(&init_mm, pud, addr);
106105
if (!pmd)
107106
return -ENOMEM;
108107
do {
109108
next = pmd_addr_end(addr, end);
110109

111-
if (ioremap_try_huge_pmd(pmd, addr, next, phys_addr + addr, prot))
110+
if (ioremap_try_huge_pmd(pmd, addr, next, phys_addr, prot))
112111
continue;
113112

114-
if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
113+
if (ioremap_pte_range(pmd, addr, next, phys_addr, prot))
115114
return -ENOMEM;
116-
} while (pmd++, addr = next, addr != end);
115+
} while (pmd++, phys_addr += (next - addr), addr = next, addr != end);
117116
return 0;
118117
}
119118

@@ -142,19 +141,18 @@ static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
142141
pud_t *pud;
143142
unsigned long next;
144143

145-
phys_addr -= addr;
146144
pud = pud_alloc(&init_mm, p4d, addr);
147145
if (!pud)
148146
return -ENOMEM;
149147
do {
150148
next = pud_addr_end(addr, end);
151149

152-
if (ioremap_try_huge_pud(pud, addr, next, phys_addr + addr, prot))
150+
if (ioremap_try_huge_pud(pud, addr, next, phys_addr, prot))
153151
continue;
154152

155-
if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
153+
if (ioremap_pmd_range(pud, addr, next, phys_addr, prot))
156154
return -ENOMEM;
157-
} while (pud++, addr = next, addr != end);
155+
} while (pud++, phys_addr += (next - addr), addr = next, addr != end);
158156
return 0;
159157
}
160158

@@ -164,7 +162,6 @@ static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
164162
p4d_t *p4d;
165163
unsigned long next;
166164

167-
phys_addr -= addr;
168165
p4d = p4d_alloc(&init_mm, pgd, addr);
169166
if (!p4d)
170167
return -ENOMEM;
@@ -173,14 +170,14 @@ static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr,
173170

174171
if (ioremap_p4d_enabled() &&
175172
((next - addr) == P4D_SIZE) &&
176-
IS_ALIGNED(phys_addr + addr, P4D_SIZE)) {
177-
if (p4d_set_huge(p4d, phys_addr + addr, prot))
173+
IS_ALIGNED(phys_addr, P4D_SIZE)) {
174+
if (p4d_set_huge(p4d, phys_addr, prot))
178175
continue;
179176
}
180177

181-
if (ioremap_pud_range(p4d, addr, next, phys_addr + addr, prot))
178+
if (ioremap_pud_range(p4d, addr, next, phys_addr, prot))
182179
return -ENOMEM;
183-
} while (p4d++, addr = next, addr != end);
180+
} while (p4d++, phys_addr += (next - addr), addr = next, addr != end);
184181
return 0;
185182
}
186183

@@ -196,14 +193,13 @@ int ioremap_page_range(unsigned long addr,
196193
BUG_ON(addr >= end);
197194

198195
start = addr;
199-
phys_addr -= addr;
200196
pgd = pgd_offset_k(addr);
201197
do {
202198
next = pgd_addr_end(addr, end);
203-
err = ioremap_p4d_range(pgd, addr, next, phys_addr+addr, prot);
199+
err = ioremap_p4d_range(pgd, addr, next, phys_addr, prot);
204200
if (err)
205201
break;
206-
} while (pgd++, addr = next, addr != end);
202+
} while (pgd++, phys_addr += (next - addr), addr = next, addr != end);
207203

208204
flush_cache_vmap(start, end);
209205

0 commit comments

Comments
 (0)