18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/sched.h>
38c2ecf20Sopenharmony_ci#include <linux/kernel.h>
48c2ecf20Sopenharmony_ci#include <linux/errno.h>
58c2ecf20Sopenharmony_ci#include <linux/mm.h>
68c2ecf20Sopenharmony_ci#include <linux/nmi.h>
78c2ecf20Sopenharmony_ci#include <linux/swap.h>
88c2ecf20Sopenharmony_ci#include <linux/smp.h>
98c2ecf20Sopenharmony_ci#include <linux/highmem.h>
108c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
118c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <asm/cpu_entry_area.h>
148c2ecf20Sopenharmony_ci#include <asm/fixmap.h>
158c2ecf20Sopenharmony_ci#include <asm/e820/api.h>
168c2ecf20Sopenharmony_ci#include <asm/tlb.h>
178c2ecf20Sopenharmony_ci#include <asm/tlbflush.h>
188c2ecf20Sopenharmony_ci#include <asm/io.h>
198c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciunsigned int __VMALLOC_RESERVE = 128 << 20;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/*
248c2ecf20Sopenharmony_ci * Associate a virtual page frame with a given physical page frame
258c2ecf20Sopenharmony_ci * and protection flags for that frame.
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_civoid set_pte_vaddr(unsigned long vaddr, pte_t pteval)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	pgd_t *pgd;
308c2ecf20Sopenharmony_ci	p4d_t *p4d;
318c2ecf20Sopenharmony_ci	pud_t *pud;
328c2ecf20Sopenharmony_ci	pmd_t *pmd;
338c2ecf20Sopenharmony_ci	pte_t *pte;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	pgd = swapper_pg_dir + pgd_index(vaddr);
368c2ecf20Sopenharmony_ci	if (pgd_none(*pgd)) {
378c2ecf20Sopenharmony_ci		BUG();
388c2ecf20Sopenharmony_ci		return;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci	p4d = p4d_offset(pgd, vaddr);
418c2ecf20Sopenharmony_ci	if (p4d_none(*p4d)) {
428c2ecf20Sopenharmony_ci		BUG();
438c2ecf20Sopenharmony_ci		return;
448c2ecf20Sopenharmony_ci	}
458c2ecf20Sopenharmony_ci	pud = pud_offset(p4d, vaddr);
468c2ecf20Sopenharmony_ci	if (pud_none(*pud)) {
478c2ecf20Sopenharmony_ci		BUG();
488c2ecf20Sopenharmony_ci		return;
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci	pmd = pmd_offset(pud, vaddr);
518c2ecf20Sopenharmony_ci	if (pmd_none(*pmd)) {
528c2ecf20Sopenharmony_ci		BUG();
538c2ecf20Sopenharmony_ci		return;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci	pte = pte_offset_kernel(pmd, vaddr);
568c2ecf20Sopenharmony_ci	if (!pte_none(pteval))
578c2ecf20Sopenharmony_ci		set_pte_at(&init_mm, vaddr, pte, pteval);
588c2ecf20Sopenharmony_ci	else
598c2ecf20Sopenharmony_ci		pte_clear(&init_mm, vaddr, pte);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/*
628c2ecf20Sopenharmony_ci	 * It's enough to flush this one mapping.
638c2ecf20Sopenharmony_ci	 * (PGE mappings get flushed as well)
648c2ecf20Sopenharmony_ci	 */
658c2ecf20Sopenharmony_ci	flush_tlb_one_kernel(vaddr);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciunsigned long __FIXADDR_TOP = 0xfffff000;
698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__FIXADDR_TOP);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci/*
728c2ecf20Sopenharmony_ci * vmalloc=size forces the vmalloc area to be exactly 'size'
738c2ecf20Sopenharmony_ci * bytes. This can be used to increase (or decrease) the
748c2ecf20Sopenharmony_ci * vmalloc area - the default is 128m.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_cistatic int __init parse_vmalloc(char *arg)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	if (!arg)
798c2ecf20Sopenharmony_ci		return -EINVAL;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	/* Add VMALLOC_OFFSET to the parsed value due to vm area guard hole*/
828c2ecf20Sopenharmony_ci	__VMALLOC_RESERVE = memparse(arg, &arg) + VMALLOC_OFFSET;
838c2ecf20Sopenharmony_ci	return 0;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ciearly_param("vmalloc", parse_vmalloc);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/*
888c2ecf20Sopenharmony_ci * reservetop=size reserves a hole at the top of the kernel address space which
898c2ecf20Sopenharmony_ci * a hypervisor can load into later.  Needed for dynamically loaded hypervisors,
908c2ecf20Sopenharmony_ci * so relocating the fixmap can be done before paging initialization.
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_cistatic int __init parse_reservetop(char *arg)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	unsigned long address;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if (!arg)
978c2ecf20Sopenharmony_ci		return -EINVAL;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	address = memparse(arg, &arg);
1008c2ecf20Sopenharmony_ci	reserve_top_address(address);
1018c2ecf20Sopenharmony_ci	early_ioremap_init();
1028c2ecf20Sopenharmony_ci	return 0;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ciearly_param("reservetop", parse_reservetop);
105