mirror of https://gitee.com/openkylin/linux.git
x86-64: Fix accounting in kernel_physical_mapping_init()
When finding a present and acceptable 2M/1G mapping, the number of pages mapped this way shouldn't be incremented (as it was already incremented when the earlier part of the mapping was established). Instead, last_map_addr needs to be updated in this case. Further, address increments were wrong in one place each in both phys_pmd_init() and phys_pud_init() (lacking the aligning down to the respective page boundary). As we're now doing the same calculation several times, fold it into a single instance using a local variable (matching how kernel_physical_mapping_init() itself does it at the PGD level). Observed during code inspection, not because of an actual problem. Signed-off-by: Jan Beulich <jbeulich@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/4FB3C27202000078000841A0@nat28.tlf.novell.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
3e7f3db001
commit
20167d3421
|
@ -408,12 +408,12 @@ static unsigned long __meminit
|
|||
phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
|
||||
unsigned long page_size_mask, pgprot_t prot)
|
||||
{
|
||||
unsigned long pages = 0;
|
||||
unsigned long pages = 0, next;
|
||||
unsigned long last_map_addr = end;
|
||||
|
||||
int i = pmd_index(address);
|
||||
|
||||
for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
|
||||
for (; i < PTRS_PER_PMD; i++, address = next) {
|
||||
unsigned long pte_phys;
|
||||
pmd_t *pmd = pmd_page + pmd_index(address);
|
||||
pte_t *pte;
|
||||
|
@ -427,6 +427,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
|
|||
break;
|
||||
}
|
||||
|
||||
next = (address & PMD_MASK) + PMD_SIZE;
|
||||
|
||||
if (pmd_val(*pmd)) {
|
||||
if (!pmd_large(*pmd)) {
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
|
@ -450,7 +452,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
|
|||
* attributes.
|
||||
*/
|
||||
if (page_size_mask & (1 << PG_LEVEL_2M)) {
|
||||
pages++;
|
||||
last_map_addr = next;
|
||||
continue;
|
||||
}
|
||||
new_prot = pte_pgprot(pte_clrhuge(*(pte_t *)pmd));
|
||||
|
@ -463,7 +465,7 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
|
|||
pfn_pte(address >> PAGE_SHIFT,
|
||||
__pgprot(pgprot_val(prot) | _PAGE_PSE)));
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
last_map_addr = (address & PMD_MASK) + PMD_SIZE;
|
||||
last_map_addr = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -483,11 +485,11 @@ static unsigned long __meminit
|
|||
phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
|
||||
unsigned long page_size_mask)
|
||||
{
|
||||
unsigned long pages = 0;
|
||||
unsigned long pages = 0, next;
|
||||
unsigned long last_map_addr = end;
|
||||
int i = pud_index(addr);
|
||||
|
||||
for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE) {
|
||||
for (; i < PTRS_PER_PUD; i++, addr = next) {
|
||||
unsigned long pmd_phys;
|
||||
pud_t *pud = pud_page + pud_index(addr);
|
||||
pmd_t *pmd;
|
||||
|
@ -496,8 +498,9 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
|
|||
if (addr >= end)
|
||||
break;
|
||||
|
||||
if (!after_bootmem &&
|
||||
!e820_any_mapped(addr, addr+PUD_SIZE, 0)) {
|
||||
next = (addr & PUD_MASK) + PUD_SIZE;
|
||||
|
||||
if (!after_bootmem && !e820_any_mapped(addr, next, 0)) {
|
||||
set_pud(pud, __pud(0));
|
||||
continue;
|
||||
}
|
||||
|
@ -524,7 +527,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
|
|||
* attributes.
|
||||
*/
|
||||
if (page_size_mask & (1 << PG_LEVEL_1G)) {
|
||||
pages++;
|
||||
last_map_addr = next;
|
||||
continue;
|
||||
}
|
||||
prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud));
|
||||
|
@ -536,7 +539,7 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
|
|||
set_pte((pte_t *)pud,
|
||||
pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
last_map_addr = (addr & PUD_MASK) + PUD_SIZE;
|
||||
last_map_addr = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue