18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/highmem.h>
38c2ecf20Sopenharmony_ci#include <linux/export.h>
48c2ecf20Sopenharmony_ci#include <linux/swap.h> /* for totalram_pages */
58c2ecf20Sopenharmony_ci#include <linux/memblock.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_civoid *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
88c2ecf20Sopenharmony_ci{
98c2ecf20Sopenharmony_ci	unsigned long vaddr;
108c2ecf20Sopenharmony_ci	int idx, type;
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci	type = kmap_atomic_idx_push();
138c2ecf20Sopenharmony_ci	idx = type + KM_TYPE_NR*smp_processor_id();
148c2ecf20Sopenharmony_ci	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
158c2ecf20Sopenharmony_ci	BUG_ON(!pte_none(*(kmap_pte-idx)));
168c2ecf20Sopenharmony_ci	set_pte(kmap_pte-idx, mk_pte(page, prot));
178c2ecf20Sopenharmony_ci	arch_flush_lazy_mmu_mode();
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	return (void *)vaddr;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kmap_atomic_high_prot);
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/*
248c2ecf20Sopenharmony_ci * This is the same as kmap_atomic() but can map memory that doesn't
258c2ecf20Sopenharmony_ci * have a struct page associated with it.
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_civoid *kmap_atomic_pfn(unsigned long pfn)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	return kmap_atomic_prot_pfn(pfn, kmap_prot);
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(kmap_atomic_pfn);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_civoid kunmap_atomic_high(void *kvaddr)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
388c2ecf20Sopenharmony_ci	    vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
398c2ecf20Sopenharmony_ci		int idx, type;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci		type = kmap_atomic_idx();
428c2ecf20Sopenharmony_ci		idx = type + KM_TYPE_NR * smp_processor_id();
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_HIGHMEM
458c2ecf20Sopenharmony_ci		WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
468c2ecf20Sopenharmony_ci#endif
478c2ecf20Sopenharmony_ci		/*
488c2ecf20Sopenharmony_ci		 * Force other mappings to Oops if they'll try to access this
498c2ecf20Sopenharmony_ci		 * pte without first remap it.  Keeping stale mappings around
508c2ecf20Sopenharmony_ci		 * is a bad idea also, in case the page changes cacheability
518c2ecf20Sopenharmony_ci		 * attributes or becomes a protected page in a hypervisor.
528c2ecf20Sopenharmony_ci		 */
538c2ecf20Sopenharmony_ci		kpte_clear_flush(kmap_pte-idx, vaddr);
548c2ecf20Sopenharmony_ci		kmap_atomic_idx_pop();
558c2ecf20Sopenharmony_ci		arch_flush_lazy_mmu_mode();
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_HIGHMEM
588c2ecf20Sopenharmony_ci	else {
598c2ecf20Sopenharmony_ci		BUG_ON(vaddr < PAGE_OFFSET);
608c2ecf20Sopenharmony_ci		BUG_ON(vaddr >= (unsigned long)high_memory);
618c2ecf20Sopenharmony_ci	}
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kunmap_atomic_high);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_civoid __init set_highmem_pages_init(void)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	struct zone *zone;
698c2ecf20Sopenharmony_ci	int nid;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/*
728c2ecf20Sopenharmony_ci	 * Explicitly reset zone->managed_pages because set_highmem_pages_init()
738c2ecf20Sopenharmony_ci	 * is invoked before memblock_free_all()
748c2ecf20Sopenharmony_ci	 */
758c2ecf20Sopenharmony_ci	reset_all_zones_managed_pages();
768c2ecf20Sopenharmony_ci	for_each_zone(zone) {
778c2ecf20Sopenharmony_ci		unsigned long zone_start_pfn, zone_end_pfn;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci		if (!is_highmem(zone))
808c2ecf20Sopenharmony_ci			continue;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci		zone_start_pfn = zone->zone_start_pfn;
838c2ecf20Sopenharmony_ci		zone_end_pfn = zone_start_pfn + zone->spanned_pages;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		nid = zone_to_nid(zone);
868c2ecf20Sopenharmony_ci		printk(KERN_INFO "Initializing %s for node %d (%08lx:%08lx)\n",
878c2ecf20Sopenharmony_ci				zone->name, nid, zone_start_pfn, zone_end_pfn);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci		add_highpages_with_active_regions(nid, zone_start_pfn,
908c2ecf20Sopenharmony_ci				 zone_end_pfn);
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci}
93