Messages in this thread | | | Date | Sat, 28 Jun 2008 21:40:42 -0700 | From | "Yinghai Lu" <> | Subject | Re: [PATCH] x86: fix init_memory_mapping over boundary v4 |
| |
On Sat, Jun 28, 2008 at 7:22 PM, Jeremy Fitzhardinge <jeremy@goop.org> wrote: > Yinghai Lu wrote: >> >> some end boundary is only page alignment, instead of 2M alignment, >> so call ker_phycial_mapping_init three times. >> then don't overmap above the max_low_pfn >> >> v2: make init_memory_mapping more solid: start could be any value other >> than 0 >> v3: fix NON PAE by handling left over in kernel_physical_mapping >> v4: revert back to v2, and use PMD_SHIFT to calculate boundary >> also adjust size for pre-allocated table size >> >> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> >> >> --- >> arch/x86/mm/init_32.c | 101 >> +++++++++++++++++++++++++++++++++++++------------- >> 1 file changed, 75 insertions(+), 26 deletions(-) >> >> Index: linux-2.6/arch/x86/mm/init_32.c >> =================================================================== >> --- linux-2.6.orig/arch/x86/mm/init_32.c >> +++ linux-2.6/arch/x86/mm/init_32.c >> @@ -184,8 +184,9 @@ static inline int is_kernel_text(unsigne >> * PAGE_OFFSET: >> */ >> static void __init kernel_physical_mapping_init(pgd_t *pgd_base, >> - unsigned long start, >> - unsigned long end) >> + unsigned long start_pfn, >> + unsigned long end_pfn, >> + int use_pse) >> { >> int pgd_idx, pmd_idx, pte_ofs; >> unsigned long pfn; >> @@ -193,32 +194,33 @@ static void __init kernel_physical_mappi >> pmd_t *pmd; >> pte_t *pte; >> unsigned pages_2m = 0, pages_4k = 0; >> - unsigned limit_pfn = end >> PAGE_SHIFT; >> - pgd_idx = pgd_index(PAGE_OFFSET); >> - pgd = pgd_base + pgd_idx; >> - pfn = start >> PAGE_SHIFT; >> + if (!cpu_has_pse) >> + use_pse = 0; >> + pfn = start_pfn; >> + pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); >> + pgd = pgd_base + pgd_idx; >> for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { >> pmd = one_md_table_init(pgd); >> - if (pfn >= limit_pfn) >> - continue; >> - for (pmd_idx = 0; >> - pmd_idx < PTRS_PER_PMD && pfn < limit_pfn; >> + if (pfn >= end_pfn) >> + continue; >> +#ifdef CONFIG_X86_PAE >> + pmd_idx = pmd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); >> + pmd += pmd_idx; >> +#else >> + pmd_idx = 0; >> +#endif >> > > We should really define X_index() to return 0 for folded pagetable level X. > I've had to put similar #ifdefs in other code. Also, for the purposes of > making this code more unifiable, it's probably better to test for "#if > PAGETABLE_LEVELS >= 3" rather than for PAE specifically.
does all cpu support >=3?
> >> + for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn; >> pmd++, pmd_idx++) { >> unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET; >> /* >> * Map with big pages if possible, otherwise >> * create normal page tables: >> - * >> - * Don't use a large page for the first 2/4MB of >> memory >> - * because there are often fixed size MTRRs in >> there >> - * and overlapping MTRRs into large pages can >> cause >> - * slowdowns. >> */ >> - if (cpu_has_pse && !(pgd_idx == 0 && pmd_idx == >> 0)) { >> + if (use_pse) { >> unsigned int addr2; >> pgprot_t prot = PAGE_KERNEL_LARGE; >> @@ -233,13 +235,13 @@ static void __init kernel_physical_mappi >> set_pmd(pmd, pfn_pmd(pfn, prot)); >> pfn += PTRS_PER_PTE; >> - max_pfn_mapped = pfn; >> continue; >> } >> pte = one_page_table_init(pmd); >> - for (pte_ofs = 0; >> - pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; >> + pte_ofs = pte_index((pfn<<PAGE_SHIFT) + >> PAGE_OFFSET); >> + pte += pte_ofs; >> + for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn; >> pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) { >> pgprot_t prot = PAGE_KERNEL; >> @@ -249,7 +251,6 @@ static void __init kernel_physical_mappi >> pages_4k++; >> set_pte(pte, pfn_pte(pfn, prot)); >> } >> - max_pfn_mapped = pfn; >> } >> } >> update_page_count(PG_LEVEL_2M, pages_2m); >> @@ -729,7 +730,7 @@ void __init setup_bootmem_allocator(void >> static void __init find_early_table_space(unsigned long end) >> { >> - unsigned long puds, pmds, tables, start; >> + unsigned long puds, pmds, ptes, tables, start; >> puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; >> tables = PAGE_ALIGN(puds * sizeof(pud_t)); >> @@ -737,10 +738,19 @@ static void __init find_early_table_spac >> pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; >> tables += PAGE_ALIGN(pmds * sizeof(pmd_t)); >> - if (!cpu_has_pse) { >> - int ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; >> - tables += PAGE_ALIGN(ptes * sizeof(pte_t)); >> - } >> + if (cpu_has_pse) { >> + unsigned long extra; >> + >> + extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); left over at tail >> + extra += PMD_SIZE; head... >> > > Is this the same as "extra = (end + PMD_SIZE + 1) & PMD_MASK"?
extra = end & PMD_MASK; extra+ = PMD_SIZE; ; > >> + ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; >> + } else >> + ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; >> + >> + tables += PAGE_ALIGN(ptes * sizeof(pte_t)); >> + >> + /* for fixmap */ >> + tables += PAGE_SIZE * 2; >> > > Why not correct for fixmaps by putting "ptes += __end_of_fixed_addresses;" > above?
yes
YH
| |