18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * highmem.c: virtual kernel memory mappings for high memory 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * PowerPC version, stolen from the i386 version. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Used in CONFIG_HIGHMEM systems for memory pages which 88c2ecf20Sopenharmony_ci * are not addressable by direct kernel virtual addresses. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 1999 Gerhard Wichert, Siemens AG 118c2ecf20Sopenharmony_ci * Gerhard.Wichert@pdb.siemens.de 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Redesigned the x86 32-bit VM architecture to deal with 158c2ecf20Sopenharmony_ci * up to 16 Terrabyte physical memory. With current x86 CPUs 168c2ecf20Sopenharmony_ci * we now support up to 64 Gigabytes physical RAM. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Reworked for PowerPC by various contributors. Moved from 218c2ecf20Sopenharmony_ci * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/export.h> 258c2ecf20Sopenharmony_ci#include <linux/highmem.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* 288c2ecf20Sopenharmony_ci * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap 298c2ecf20Sopenharmony_ci * gives a more generic (and caching) interface. But kmap_atomic can 308c2ecf20Sopenharmony_ci * be used in IRQ contexts, so in some (very limited) cases we need 318c2ecf20Sopenharmony_ci * it. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_civoid *kmap_atomic_high_prot(struct page *page, pgprot_t prot) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci unsigned long vaddr; 398c2ecf20Sopenharmony_ci int idx, type; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci type = kmap_atomic_idx_push(); 428c2ecf20Sopenharmony_ci idx = type + KM_TYPE_NR*smp_processor_id(); 438c2ecf20Sopenharmony_ci vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); 448c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_HIGHMEM 458c2ecf20Sopenharmony_ci BUG_ON(!pte_none(*(kmap_pte-idx))); 468c2ecf20Sopenharmony_ci#endif 478c2ecf20Sopenharmony_ci set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot)); 488c2ecf20Sopenharmony_ci local_flush_tlb_page(NULL, vaddr); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return (void *) vaddr; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kmap_atomic_high_prot); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_civoid kunmap_atomic_high(void *kvaddr) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; 578c2ecf20Sopenharmony_ci int type; 588c2ecf20Sopenharmony_ci unsigned int idx; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (vaddr < __fix_to_virt(FIX_KMAP_END)) 618c2ecf20Sopenharmony_ci return; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci type = kmap_atomic_idx(); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci idx = type + KM_TYPE_NR * smp_processor_id(); 668c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_HIGHMEM 678c2ecf20Sopenharmony_ci BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); 688c2ecf20Sopenharmony_ci#endif 698c2ecf20Sopenharmony_ci /* 708c2ecf20Sopenharmony_ci * force other mappings to Oops if they'll try to access 718c2ecf20Sopenharmony_ci * this pte without first remap it 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci pte_clear(&init_mm, vaddr, kmap_pte-idx); 748c2ecf20Sopenharmony_ci local_flush_tlb_page(NULL, vaddr); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci kmap_atomic_idx_pop(); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(kunmap_atomic_high); 79