Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dec7305d authored by Max Filippov's avatar Max Filippov
Browse files

xtensa: allow fixmap and kmap span more than one page table



To support aliasing cache both kmap region sizes are multiplied by the
number of data cache colors. After that expansion page tables that cover
kmap regions may become larger than one page. Correctly allocate and
initialize page tables in this case.

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 22def768
Loading
Loading
Loading
Loading
+22 −16
Original line number Original line Diff line number Diff line
@@ -18,32 +18,38 @@
#include <asm/io.h>
#include <asm/io.h>


#if defined(CONFIG_HIGHMEM)
#if defined(CONFIG_HIGHMEM)
static void * __init init_pmd(unsigned long vaddr)
static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
{
{
	pgd_t *pgd = pgd_offset_k(vaddr);
	pgd_t *pgd = pgd_offset_k(vaddr);
	pmd_t *pmd = pmd_offset(pgd, vaddr);
	pmd_t *pmd = pmd_offset(pgd, vaddr);
	pte_t *pte;
	unsigned long i;


	if (pmd_none(*pmd)) {
	n_pages = ALIGN(n_pages, PTRS_PER_PTE);
		unsigned i;
		pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);


		for (i = 0; i < 1024; i++)
	pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n",
		 __func__, vaddr, n_pages);

	pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t));

	for (i = 0; i < n_pages; ++i)
		pte_clear(NULL, 0, pte + i);
		pte_clear(NULL, 0, pte + i);


		set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
	for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) {
		BUG_ON(pte != pte_offset_kernel(pmd, 0));
		pte_t *cur_pte = pte + i;
		pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",

			 __func__, vaddr, pmd, pte);
		BUG_ON(!pmd_none(*pmd));
		return pte;
		set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK));
	} else {
		BUG_ON(cur_pte != pte_offset_kernel(pmd, 0));
		return pte_offset_kernel(pmd, 0);
		pr_debug("%s: pmd: 0x%p, pte: 0x%p\n",
			 __func__, pmd, cur_pte);
	}
	}
	return pte;
}
}


static void __init fixedrange_init(void)
static void __init fixedrange_init(void)
{
{
	BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
	init_pmd(__fix_to_virt(0), __end_of_fixed_addresses);
	init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
}
}
#endif
#endif


@@ -52,7 +58,7 @@ void __init paging_init(void)
	memset(swapper_pg_dir, 0, PAGE_SIZE);
	memset(swapper_pg_dir, 0, PAGE_SIZE);
#ifdef CONFIG_HIGHMEM
#ifdef CONFIG_HIGHMEM
	fixedrange_init();
	fixedrange_init();
	pkmap_page_table = init_pmd(PKMAP_BASE);
	pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP);
	kmap_init();
	kmap_init();
#endif
#endif
}
}