mmu.c 18.5 KB
Newer Older
C
Catalin Marinas 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Based on arch/arm/mm/mmu.c
 *
 * Copyright (C) 1995-2005 Russell King
 * Copyright (C) 2012 ARM Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
24
#include <linux/libfdt.h>
C
Catalin Marinas 已提交
25 26 27 28
#include <linux/mman.h>
#include <linux/nodemask.h>
#include <linux/memblock.h>
#include <linux/fs.h>
29
#include <linux/io.h>
30
#include <linux/slab.h>
31
#include <linux/stop_machine.h>
C
Catalin Marinas 已提交
32

33
#include <asm/barrier.h>
C
Catalin Marinas 已提交
34
#include <asm/cputype.h>
35
#include <asm/fixmap.h>
36
#include <asm/kasan.h>
37
#include <asm/kernel-pgtable.h>
C
Catalin Marinas 已提交
38 39 40 41
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/sizes.h>
#include <asm/tlb.h>
42
#include <asm/memblock.h>
C
Catalin Marinas 已提交
43 44 45 46
#include <asm/mmu_context.h>

#include "mm.h"

47 48
u64 idmap_t0sz = TCR_T0SZ(VA_BITS);

C
Catalin Marinas 已提交
49 50 51 52
/*
 * Empty_zero_page is a special page that is used for zero-initialized data
 * and COW.
 */
53
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
C
Catalin Marinas 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66
EXPORT_SYMBOL(empty_zero_page);

pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
			      unsigned long size, pgprot_t vma_prot)
{
	if (!pfn_valid(pfn))
		return pgprot_noncached(vma_prot);
	else if (file->f_flags & O_SYNC)
		return pgprot_writecombine(vma_prot);
	return vma_prot;
}
EXPORT_SYMBOL(phys_mem_access_prot);

67
static phys_addr_t __init early_pgtable_alloc(void)
C
Catalin Marinas 已提交
68
{
69 70 71
	phys_addr_t phys;
	void *ptr;

72
	phys = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
73
	BUG_ON(!phys);
74 75 76 77 78 79 80 81

	/*
	 * The FIX_{PGD,PUD,PMD} slots may be in active use, but the FIX_PTE
	 * slot will be free, so we can (ab)use the FIX_PTE slot to initialise
	 * any level of table.
	 */
	ptr = pte_set_fixmap(phys);

82 83
	memset(ptr, 0, PAGE_SIZE);

84 85 86 87 88 89 90
	/*
	 * Implicit barriers also ensure the zeroed page is visible to the page
	 * table walker
	 */
	pte_clear_fixmap();

	return phys;
C
Catalin Marinas 已提交
91 92
}

93 94 95 96 97 98 99 100 101 102 103
/*
 * remap a PMD into pages
 */
static void split_pmd(pmd_t *pmd, pte_t *pte)
{
	unsigned long pfn = pmd_pfn(*pmd);
	int i = 0;

	do {
		/*
		 * Need to have the least restrictive permissions available
104
		 * permissions will be fixed up later
105
		 */
106
		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
107 108 109 110 111
		pfn++;
	} while (pte++, i++, i < PTRS_PER_PTE);
}

static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
112
				  unsigned long end, unsigned long pfn,
113
				  pgprot_t prot,
114
				  phys_addr_t (*pgtable_alloc)(void))
C
Catalin Marinas 已提交
115 116 117
{
	pte_t *pte;

118
	if (pmd_none(*pmd) || pmd_sect(*pmd)) {
119 120 121
		phys_addr_t pte_phys;
		BUG_ON(!pgtable_alloc);
		pte_phys = pgtable_alloc();
122
		pte = pte_set_fixmap(pte_phys);
123 124
		if (pmd_sect(*pmd))
			split_pmd(pmd, pte);
125
		__pmd_populate(pmd, pte_phys, PMD_TYPE_TABLE);
126
		flush_tlb_all();
127
		pte_clear_fixmap();
C
Catalin Marinas 已提交
128
	}
129
	BUG_ON(pmd_bad(*pmd));
C
Catalin Marinas 已提交
130

131
	pte = pte_set_fixmap_offset(pmd, addr);
C
Catalin Marinas 已提交
132
	do {
133 134 135
		set_pte(pte, pfn_pte(pfn, prot));
		pfn++;
	} while (pte++, addr += PAGE_SIZE, addr != end);
136 137

	pte_clear_fixmap();
C
Catalin Marinas 已提交
138 139
}

140
static void split_pud(pud_t *old_pud, pmd_t *pmd)
141 142 143 144 145 146
{
	unsigned long addr = pud_pfn(*old_pud) << PAGE_SHIFT;
	pgprot_t prot = __pgprot(pud_val(*old_pud) ^ addr);
	int i = 0;

	do {
147
		set_pmd(pmd, __pmd(addr | pgprot_val(prot)));
148 149 150 151
		addr += PMD_SIZE;
	} while (pmd++, i++, i < PTRS_PER_PMD);
}

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#ifdef CONFIG_DEBUG_PAGEALLOC
static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
{

	/*
	 * If debug_page_alloc is enabled we must map the linear map
	 * using pages. However, other mappings created by
	 * create_mapping_noalloc must use sections in some cases. Allow
	 * sections to be used in those cases, where no pgtable_alloc
	 * function is provided.
	 */
	return !pgtable_alloc || !debug_pagealloc_enabled();
}
#else
static bool block_mappings_allowed(phys_addr_t (*pgtable_alloc)(void))
{
	return true;
}
#endif

172
static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
173
				  phys_addr_t phys, pgprot_t prot,
174
				  phys_addr_t (*pgtable_alloc)(void))
C
Catalin Marinas 已提交
175 176 177 178 179 180 181
{
	pmd_t *pmd;
	unsigned long next;

	/*
	 * Check for initial section mappings in the pgd/pud and remove them.
	 */
182
	if (pud_none(*pud) || pud_sect(*pud)) {
183 184 185
		phys_addr_t pmd_phys;
		BUG_ON(!pgtable_alloc);
		pmd_phys = pgtable_alloc();
186
		pmd = pmd_set_fixmap(pmd_phys);
187 188 189 190 191 192 193
		if (pud_sect(*pud)) {
			/*
			 * need to have the 1G of mappings continue to be
			 * present
			 */
			split_pud(pud, pmd);
		}
194
		__pud_populate(pud, pmd_phys, PUD_TYPE_TABLE);
195
		flush_tlb_all();
196
		pmd_clear_fixmap();
C
Catalin Marinas 已提交
197
	}
198
	BUG_ON(pud_bad(*pud));
C
Catalin Marinas 已提交
199

200
	pmd = pmd_set_fixmap_offset(pud, addr);
C
Catalin Marinas 已提交
201 202 203
	do {
		next = pmd_addr_end(addr, end);
		/* try section mapping first */
204 205
		if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
		      block_mappings_allowed(pgtable_alloc)) {
206
			pmd_t old_pmd =*pmd;
207 208
			set_pmd(pmd, __pmd(phys |
					   pgprot_val(mk_sect_prot(prot))));
209 210 211 212
			/*
			 * Check for previous table entries created during
			 * boot (__create_page_tables) and flush them.
			 */
213
			if (!pmd_none(old_pmd)) {
214
				flush_tlb_all();
215
				if (pmd_table(old_pmd)) {
216
					phys_addr_t table = pmd_page_paddr(old_pmd);
217 218
					if (!WARN_ON_ONCE(slab_is_available()))
						memblock_free(table, PAGE_SIZE);
219 220
				}
			}
221
		} else {
222
			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
223
				       prot, pgtable_alloc);
224
		}
C
Catalin Marinas 已提交
225 226
		phys += next - addr;
	} while (pmd++, addr = next, addr != end);
227 228

	pmd_clear_fixmap();
C
Catalin Marinas 已提交
229 230
}

231 232 233 234 235 236 237 238 239 240 241 242
static inline bool use_1G_block(unsigned long addr, unsigned long next,
			unsigned long phys)
{
	if (PAGE_SHIFT != 12)
		return false;

	if (((addr | next | phys) & ~PUD_MASK) != 0)
		return false;

	return true;
}

243
static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
244
				  phys_addr_t phys, pgprot_t prot,
245
				  phys_addr_t (*pgtable_alloc)(void))
C
Catalin Marinas 已提交
246
{
247
	pud_t *pud;
C
Catalin Marinas 已提交
248 249
	unsigned long next;

250
	if (pgd_none(*pgd)) {
251 252 253
		phys_addr_t pud_phys;
		BUG_ON(!pgtable_alloc);
		pud_phys = pgtable_alloc();
254
		__pgd_populate(pgd, pud_phys, PUD_TYPE_TABLE);
255 256 257
	}
	BUG_ON(pgd_bad(*pgd));

258
	pud = pud_set_fixmap_offset(pgd, addr);
C
Catalin Marinas 已提交
259 260
	do {
		next = pud_addr_end(addr, end);
261 262 263 264

		/*
		 * For 4K granule only, attempt to put down a 1GB block
		 */
265 266
		if (use_1G_block(addr, next, phys) &&
		    block_mappings_allowed(pgtable_alloc)) {
267
			pud_t old_pud = *pud;
268 269
			set_pud(pud, __pud(phys |
					   pgprot_val(mk_sect_prot(prot))));
270 271 272 273 274 275 276 277 278 279

			/*
			 * If we have an old value for a pud, it will
			 * be pointing to a pmd table that we no longer
			 * need (from swapper_pg_dir).
			 *
			 * Look up the old pmd table and free it.
			 */
			if (!pud_none(old_pud)) {
				flush_tlb_all();
280
				if (pud_table(old_pud)) {
281
					phys_addr_t table = pud_page_paddr(old_pud);
282 283
					if (!WARN_ON_ONCE(slab_is_available()))
						memblock_free(table, PAGE_SIZE);
284
				}
285 286
			}
		} else {
287
			alloc_init_pmd(pud, addr, next, phys, prot,
288
				       pgtable_alloc);
289
		}
C
Catalin Marinas 已提交
290 291
		phys += next - addr;
	} while (pud++, addr = next, addr != end);
292 293

	pud_clear_fixmap();
C
Catalin Marinas 已提交
294 295 296 297 298 299
}

/*
 * Create the page directory entries and any necessary page tables for the
 * mapping specified by 'md'.
 */
300
static void init_pgd(pgd_t *pgd, phys_addr_t phys, unsigned long virt,
301
				    phys_addr_t size, pgprot_t prot,
302
				    phys_addr_t (*pgtable_alloc)(void))
C
Catalin Marinas 已提交
303 304 305
{
	unsigned long addr, length, end, next;

306 307 308 309 310 311 312
	/*
	 * If the virtual and physical address don't have the same offset
	 * within a page, we cannot map the region as the caller expects.
	 */
	if (WARN_ON((phys ^ virt) & ~PAGE_MASK))
		return;

313
	phys &= PAGE_MASK;
C
Catalin Marinas 已提交
314 315 316 317 318 319
	addr = virt & PAGE_MASK;
	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));

	end = addr + length;
	do {
		next = pgd_addr_end(addr, end);
320
		alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc);
C
Catalin Marinas 已提交
321 322 323 324
		phys += next - addr;
	} while (pgd++, addr = next, addr != end);
}

325
static phys_addr_t late_pgtable_alloc(void)
326
{
327
	void *ptr = (void *)__get_free_page(PGALLOC_GFP);
328
	BUG_ON(!ptr);
329 330 331

	/* Ensure the zeroed page is visible to the page table walker */
	dsb(ishst);
332
	return __pa(ptr);
333 334
}

335 336 337 338 339 340 341 342
static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
				 unsigned long virt, phys_addr_t size,
				 pgprot_t prot,
				 phys_addr_t (*alloc)(void))
{
	init_pgd(pgd_offset_raw(pgdir, virt), phys, virt, size, prot, alloc);
}

343 344 345 346 347 348
/*
 * This function can only be used to modify existing table entries,
 * without allocating new levels of table. Note that this permits the
 * creation of new section or page entries.
 */
static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
349
				  phys_addr_t size, pgprot_t prot)
350 351 352 353 354 355
{
	if (virt < VMALLOC_START) {
		pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
			&phys, virt);
		return;
	}
356
	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
357
			     NULL);
358 359
}

360 361 362 363
void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
			       unsigned long virt, phys_addr_t size,
			       pgprot_t prot)
{
364 365
	__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
			     late_pgtable_alloc);
366 367
}

368 369 370 371 372 373 374 375 376
static void create_mapping_late(phys_addr_t phys, unsigned long virt,
				  phys_addr_t size, pgprot_t prot)
{
	if (virt < VMALLOC_START) {
		pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
			&phys, virt);
		return;
	}

377 378
	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
			     late_pgtable_alloc);
379 380
}

381
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
382
{
383 384 385 386

	unsigned long kernel_start = __pa(_stext);
	unsigned long kernel_end = __pa(_end);

387
	/*
388 389
	 * The kernel itself is mapped at page granularity. Map all other
	 * memory, making sure we don't overwrite the existing kernel mappings.
390
	 */
391 392 393 394 395 396 397

	/* No overlap with the kernel. */
	if (end < kernel_start || start >= kernel_end) {
		__create_pgd_mapping(pgd, start, __phys_to_virt(start),
				     end - start, PAGE_KERNEL,
				     early_pgtable_alloc);
		return;
398 399
	}

400 401 402 403 404 405 406 407 408 409 410 411 412 413
	/*
	 * This block overlaps the kernel mapping. Map the portion(s) which
	 * don't overlap.
	 */
	if (start < kernel_start)
		__create_pgd_mapping(pgd, start,
				     __phys_to_virt(start),
				     kernel_start - start, PAGE_KERNEL,
				     early_pgtable_alloc);
	if (kernel_end < end)
		__create_pgd_mapping(pgd, kernel_end,
				     __phys_to_virt(kernel_end),
				     end - kernel_end, PAGE_KERNEL,
				     early_pgtable_alloc);
414 415
}

416
static void __init map_mem(pgd_t *pgd)
C
Catalin Marinas 已提交
417 418
{
	struct memblock_region *reg;
419

C
Catalin Marinas 已提交
420 421 422 423 424 425 426
	/* map all the memory banks */
	for_each_memblock(memory, reg) {
		phys_addr_t start = reg->base;
		phys_addr_t end = start + reg->size;

		if (start >= end)
			break;
427 428
		if (memblock_is_nomap(reg))
			continue;
C
Catalin Marinas 已提交
429

430
		__map_memblock(pgd, start, end);
C
Catalin Marinas 已提交
431 432 433
	}
}

434 435 436 437 438
#ifdef CONFIG_DEBUG_RODATA
void mark_rodata_ro(void)
{
	create_mapping_late(__pa(_stext), (unsigned long)_stext,
				(unsigned long)_etext - (unsigned long)_stext,
439
				PAGE_KERNEL_ROX);
440 441 442 443 444 445 446 447 448 449 450

}
#endif

void fixup_init(void)
{
	create_mapping_late(__pa(__init_begin), (unsigned long)__init_begin,
			(unsigned long)__init_end - (unsigned long)__init_begin,
			PAGE_KERNEL);
}

451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
				    pgprot_t prot)
{
	phys_addr_t pa_start = __pa(va_start);
	unsigned long size = va_end - va_start;

	BUG_ON(!PAGE_ALIGNED(pa_start));
	BUG_ON(!PAGE_ALIGNED(size));

	__create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot,
			     early_pgtable_alloc);
}

/*
 * Create fine-grained mappings for the kernel.
 */
static void __init map_kernel(pgd_t *pgd)
{

	map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC);
	map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC);
	map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL);

	/*
	 * The fixmap falls in a separate pgd to the kernel, and doesn't live
	 * in the carveout for the swapper_pg_dir. We can simply re-use the
	 * existing dir for the fixmap.
	 */
	set_pgd(pgd_offset_raw(pgd, FIXADDR_START), *pgd_offset_k(FIXADDR_START));

	kasan_copy_shadow(pgd);
}

C
Catalin Marinas 已提交
484 485 486 487 488 489
/*
 * paging_init() sets up the page tables, initialises the zone memory
 * maps and sets up the zero page.
 */
void __init paging_init(void)
{
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
	phys_addr_t pgd_phys = early_pgtable_alloc();
	pgd_t *pgd = pgd_set_fixmap(pgd_phys);

	map_kernel(pgd);
	map_mem(pgd);

	/*
	 * We want to reuse the original swapper_pg_dir so we don't have to
	 * communicate the new address to non-coherent secondaries in
	 * secondary_entry, and so cpu_switch_mm can generate the address with
	 * adrp+add rather than a load from some global variable.
	 *
	 * To do this we need to go via a temporary pgd.
	 */
	cpu_replace_ttbr1(__va(pgd_phys));
	memcpy(swapper_pg_dir, pgd, PAGE_SIZE);
	cpu_replace_ttbr1(swapper_pg_dir);

	pgd_clear_fixmap();
	memblock_free(pgd_phys, PAGE_SIZE);

	/*
	 * We only reuse the PGD from the swapper_pg_dir, not the pud + pmd
	 * allocated with it.
	 */
	memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
		      SWAPPER_DIR_SIZE - PAGE_SIZE);
C
Catalin Marinas 已提交
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541

	bootmem_init();
}

/*
 * Check whether a kernel address is valid (derived from arch/x86/).
 */
int kern_addr_valid(unsigned long addr)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;

	if ((((long)addr) >> VA_BITS) != -1UL)
		return 0;

	pgd = pgd_offset_k(addr);
	if (pgd_none(*pgd))
		return 0;

	pud = pud_offset(pgd, addr);
	if (pud_none(*pud))
		return 0;

542 543 544
	if (pud_sect(*pud))
		return pfn_valid(pud_pfn(*pud));

C
Catalin Marinas 已提交
545 546 547 548
	pmd = pmd_offset(pud, addr);
	if (pmd_none(*pmd))
		return 0;

549 550 551
	if (pmd_sect(*pmd))
		return pfn_valid(pmd_pfn(*pmd));

C
Catalin Marinas 已提交
552 553 554 555 556 557 558
	pte = pte_offset_kernel(pmd, addr);
	if (pte_none(*pte))
		return 0;

	return pfn_valid(pte_pfn(*pte));
}
#ifdef CONFIG_SPARSEMEM_VMEMMAP
559
#if !ARM64_SWAPPER_USES_SECTION_MAPS
560
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
C
Catalin Marinas 已提交
561
{
562
	return vmemmap_populate_basepages(start, end, node);
C
Catalin Marinas 已提交
563
}
564
#else	/* !ARM64_SWAPPER_USES_SECTION_MAPS */
565
int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node)
C
Catalin Marinas 已提交
566
{
567
	unsigned long addr = start;
C
Catalin Marinas 已提交
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
	unsigned long next;
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;

	do {
		next = pmd_addr_end(addr, end);

		pgd = vmemmap_pgd_populate(addr, node);
		if (!pgd)
			return -ENOMEM;

		pud = vmemmap_pud_populate(pgd, addr, node);
		if (!pud)
			return -ENOMEM;

		pmd = pmd_offset(pud, addr);
		if (pmd_none(*pmd)) {
			void *p = NULL;

			p = vmemmap_alloc_block_buf(PMD_SIZE, node);
			if (!p)
				return -ENOMEM;

592
			set_pmd(pmd, __pmd(__pa(p) | PROT_SECT_NORMAL));
C
Catalin Marinas 已提交
593 594 595 596 597 598 599
		} else
			vmemmap_verify((pte_t *)pmd, node, addr, next);
	} while (addr = next, addr != end);

	return 0;
}
#endif	/* CONFIG_ARM64_64K_PAGES */
600
void vmemmap_free(unsigned long start, unsigned long end)
601 602
{
}
C
Catalin Marinas 已提交
603
#endif	/* CONFIG_SPARSEMEM_VMEMMAP */
604 605

static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
606
#if CONFIG_PGTABLE_LEVELS > 2
607 608
static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
#endif
609
#if CONFIG_PGTABLE_LEVELS > 3
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
#endif

static inline pud_t * fixmap_pud(unsigned long addr)
{
	pgd_t *pgd = pgd_offset_k(addr);

	BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));

	return pud_offset(pgd, addr);
}

static inline pmd_t * fixmap_pmd(unsigned long addr)
{
	pud_t *pud = fixmap_pud(addr);

	BUG_ON(pud_none(*pud) || pud_bad(*pud));

	return pmd_offset(pud, addr);
}

static inline pte_t * fixmap_pte(unsigned long addr)
{
	pmd_t *pmd = fixmap_pmd(addr);

	BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));

	return pte_offset_kernel(pmd, addr);
}

void __init early_fixmap_init(void)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	unsigned long addr = FIXADDR_START;

	pgd = pgd_offset_k(addr);
	pgd_populate(&init_mm, pgd, bm_pud);
	pud = pud_offset(pgd, addr);
	pud_populate(&init_mm, pud, bm_pmd);
	pmd = pmd_offset(pud, addr);
	pmd_populate_kernel(&init_mm, pmd, bm_pte);

	/*
	 * The boot-ioremap range spans multiple pmds, for which
	 * we are not preparted:
	 */
	BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));

	if ((pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)))
	     || pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_END))) {
		WARN_ON(1);
		pr_warn("pmd %p != %p, %p\n",
			pmd, fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)),
			fixmap_pmd(fix_to_virt(FIX_BTMAP_END)));
		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
			fix_to_virt(FIX_BTMAP_BEGIN));
		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
			fix_to_virt(FIX_BTMAP_END));

		pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
		pr_warn("FIX_BTMAP_BEGIN:     %d\n", FIX_BTMAP_BEGIN);
	}
}

void __set_fixmap(enum fixed_addresses idx,
			       phys_addr_t phys, pgprot_t flags)
{
	unsigned long addr = __fix_to_virt(idx);
	pte_t *pte;

683
	BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses);
684 685 686 687 688 689 690 691 692 693

	pte = fixmap_pte(addr);

	if (pgprot_val(flags)) {
		set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
	} else {
		pte_clear(&init_mm, addr, pte);
		flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
	}
}
694 695 696 697

void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
{
	const u64 dt_virt_base = __fix_to_virt(FIX_FDT);
698
	pgprot_t prot = PAGE_KERNEL_RO;
699
	int size, offset;
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
	void *dt_virt;

	/*
	 * Check whether the physical FDT address is set and meets the minimum
	 * alignment requirement. Since we are relying on MIN_FDT_ALIGN to be
	 * at least 8 bytes so that we can always access the size field of the
	 * FDT header after mapping the first chunk, double check here if that
	 * is indeed the case.
	 */
	BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
	if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
		return NULL;

	/*
	 * Make sure that the FDT region can be mapped without the need to
	 * allocate additional translation table pages, so that it is safe
716
	 * to call create_mapping_noalloc() this early.
717 718 719 720 721 722 723 724
	 *
	 * On 64k pages, the FDT will be mapped using PTEs, so we need to
	 * be in the same PMD as the rest of the fixmap.
	 * On 4k pages, we'll use section mappings for the FDT so we only
	 * have to be in the same PUD.
	 */
	BUILD_BUG_ON(dt_virt_base % SZ_2M);

725 726
	BUILD_BUG_ON(__fix_to_virt(FIX_FDT_END) >> SWAPPER_TABLE_SHIFT !=
		     __fix_to_virt(FIX_BTMAP_BEGIN) >> SWAPPER_TABLE_SHIFT);
727

728
	offset = dt_phys % SWAPPER_BLOCK_SIZE;
729 730 731
	dt_virt = (void *)dt_virt_base + offset;

	/* map the first chunk so we can read the size from the header */
732 733
	create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
			dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
734 735 736 737 738 739 740 741

	if (fdt_check_header(dt_virt) != 0)
		return NULL;

	size = fdt_totalsize(dt_virt);
	if (size > MAX_FDT_SIZE)
		return NULL;

742
	if (offset + size > SWAPPER_BLOCK_SIZE)
743
		create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
744
			       round_up(offset + size, SWAPPER_BLOCK_SIZE), prot);
745 746 747 748 749

	memblock_reserve(dt_phys, size);

	return dt_virt;
}