18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Re-map IO memory to kernel address space so that we can access it. 48c2ecf20Sopenharmony_ci * This is needed for high PCI addresses that aren't mapped in the 58c2ecf20Sopenharmony_ci * 640k-1MB IO memory area on PC's 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * (C) Copyright 1995 1996 Linus Torvalds 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/memblock.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/ioport.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 168c2ecf20Sopenharmony_ci#include <linux/mmiotrace.h> 178c2ecf20Sopenharmony_ci#include <linux/mem_encrypt.h> 188c2ecf20Sopenharmony_ci#include <linux/efi.h> 198c2ecf20Sopenharmony_ci#include <linux/pgtable.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <asm/set_memory.h> 228c2ecf20Sopenharmony_ci#include <asm/e820/api.h> 238c2ecf20Sopenharmony_ci#include <asm/efi.h> 248c2ecf20Sopenharmony_ci#include <asm/fixmap.h> 258c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 268c2ecf20Sopenharmony_ci#include <asm/pgalloc.h> 278c2ecf20Sopenharmony_ci#include <asm/memtype.h> 288c2ecf20Sopenharmony_ci#include <asm/setup.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include "physaddr.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Descriptor controlling ioremap() behavior. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistruct ioremap_desc { 368c2ecf20Sopenharmony_ci unsigned int flags; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* 408c2ecf20Sopenharmony_ci * Fix up the linear direct mapping of the kernel to avoid cache attribute 418c2ecf20Sopenharmony_ci * conflicts. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ciint ioremap_change_attr(unsigned long vaddr, unsigned long size, 448c2ecf20Sopenharmony_ci enum page_cache_mode pcm) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci unsigned long nrpages = size >> PAGE_SHIFT; 478c2ecf20Sopenharmony_ci int err; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci switch (pcm) { 508c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_UC: 518c2ecf20Sopenharmony_ci default: 528c2ecf20Sopenharmony_ci err = _set_memory_uc(vaddr, nrpages); 538c2ecf20Sopenharmony_ci break; 548c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WC: 558c2ecf20Sopenharmony_ci err = _set_memory_wc(vaddr, nrpages); 568c2ecf20Sopenharmony_ci break; 578c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WT: 588c2ecf20Sopenharmony_ci err = _set_memory_wt(vaddr, nrpages); 598c2ecf20Sopenharmony_ci break; 608c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WB: 618c2ecf20Sopenharmony_ci err = _set_memory_wb(vaddr, nrpages); 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return err; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Does the range (or a subset of) contain normal RAM? */ 698c2ecf20Sopenharmony_cistatic unsigned int __ioremap_check_ram(struct resource *res) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci unsigned long start_pfn, stop_pfn; 728c2ecf20Sopenharmony_ci unsigned long i; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if ((res->flags & IORESOURCE_SYSTEM_RAM) != IORESOURCE_SYSTEM_RAM) 758c2ecf20Sopenharmony_ci return 0; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci start_pfn = (res->start + PAGE_SIZE - 1) >> PAGE_SHIFT; 788c2ecf20Sopenharmony_ci stop_pfn = (res->end + 1) >> PAGE_SHIFT; 798c2ecf20Sopenharmony_ci if (stop_pfn > start_pfn) { 808c2ecf20Sopenharmony_ci for (i = 0; i < (stop_pfn - start_pfn); ++i) 818c2ecf20Sopenharmony_ci if (pfn_valid(start_pfn + i) && 828c2ecf20Sopenharmony_ci !PageReserved(pfn_to_page(start_pfn + i))) 838c2ecf20Sopenharmony_ci return IORES_MAP_SYSTEM_RAM; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* 908c2ecf20Sopenharmony_ci * In a SEV guest, NONE and RESERVED should not be mapped encrypted because 918c2ecf20Sopenharmony_ci * there the whole memory is already encrypted. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_cistatic unsigned int __ioremap_check_encrypted(struct resource *res) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if (!sev_active()) 968c2ecf20Sopenharmony_ci return 0; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci switch (res->desc) { 998c2ecf20Sopenharmony_ci case IORES_DESC_NONE: 1008c2ecf20Sopenharmony_ci case IORES_DESC_RESERVED: 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci default: 1038c2ecf20Sopenharmony_ci return IORES_MAP_ENCRYPTED; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* 1108c2ecf20Sopenharmony_ci * The EFI runtime services data area is not covered by walk_mem_res(), but must 1118c2ecf20Sopenharmony_ci * be mapped encrypted when SEV is active. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_cistatic void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *desc) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci if (!sev_active()) 1168c2ecf20Sopenharmony_ci return; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (!IS_ENABLED(CONFIG_EFI)) 1198c2ecf20Sopenharmony_ci return; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA || 1228c2ecf20Sopenharmony_ci (efi_mem_type(addr) == EFI_BOOT_SERVICES_DATA && 1238c2ecf20Sopenharmony_ci efi_mem_attributes(addr) & EFI_MEMORY_RUNTIME)) 1248c2ecf20Sopenharmony_ci desc->flags |= IORES_MAP_ENCRYPTED; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int __ioremap_collect_map_flags(struct resource *res, void *arg) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci struct ioremap_desc *desc = arg; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (!(desc->flags & IORES_MAP_SYSTEM_RAM)) 1328c2ecf20Sopenharmony_ci desc->flags |= __ioremap_check_ram(res); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (!(desc->flags & IORES_MAP_ENCRYPTED)) 1358c2ecf20Sopenharmony_ci desc->flags |= __ioremap_check_encrypted(res); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return ((desc->flags & (IORES_MAP_SYSTEM_RAM | IORES_MAP_ENCRYPTED)) == 1388c2ecf20Sopenharmony_ci (IORES_MAP_SYSTEM_RAM | IORES_MAP_ENCRYPTED)); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* 1428c2ecf20Sopenharmony_ci * To avoid multiple resource walks, this function walks resources marked as 1438c2ecf20Sopenharmony_ci * IORESOURCE_MEM and IORESOURCE_BUSY and looking for system RAM and/or a 1448c2ecf20Sopenharmony_ci * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES). 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci * After that, deal with misc other ranges in __ioremap_check_other() which do 1478c2ecf20Sopenharmony_ci * not fall into the above category. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistatic void __ioremap_check_mem(resource_size_t addr, unsigned long size, 1508c2ecf20Sopenharmony_ci struct ioremap_desc *desc) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci u64 start, end; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci start = (u64)addr; 1558c2ecf20Sopenharmony_ci end = start + size - 1; 1568c2ecf20Sopenharmony_ci memset(desc, 0, sizeof(struct ioremap_desc)); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci walk_mem_res(start, end, desc, __ioremap_collect_map_flags); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci __ioremap_check_other(addr, desc); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* 1648c2ecf20Sopenharmony_ci * Remap an arbitrary physical address space into the kernel virtual 1658c2ecf20Sopenharmony_ci * address space. It transparently creates kernel huge I/O mapping when 1668c2ecf20Sopenharmony_ci * the physical address is aligned by a huge page size (1GB or 2MB) and 1678c2ecf20Sopenharmony_ci * the requested size is at least the huge page size. 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * NOTE: MTRRs can override PAT memory types with a 4KB granularity. 1708c2ecf20Sopenharmony_ci * Therefore, the mapping code falls back to use a smaller page toward 4KB 1718c2ecf20Sopenharmony_ci * when a mapping range is covered by non-WB type of MTRRs. 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * NOTE! We need to allow non-page-aligned mappings too: we will obviously 1748c2ecf20Sopenharmony_ci * have to convert them into an offset in a page-aligned mapping, but the 1758c2ecf20Sopenharmony_ci * caller shouldn't need to know that small detail. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_cistatic void __iomem * 1788c2ecf20Sopenharmony_ci__ioremap_caller(resource_size_t phys_addr, unsigned long size, 1798c2ecf20Sopenharmony_ci enum page_cache_mode pcm, void *caller, bool encrypted) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci unsigned long offset, vaddr; 1828c2ecf20Sopenharmony_ci resource_size_t last_addr; 1838c2ecf20Sopenharmony_ci const resource_size_t unaligned_phys_addr = phys_addr; 1848c2ecf20Sopenharmony_ci const unsigned long unaligned_size = size; 1858c2ecf20Sopenharmony_ci struct ioremap_desc io_desc; 1868c2ecf20Sopenharmony_ci struct vm_struct *area; 1878c2ecf20Sopenharmony_ci enum page_cache_mode new_pcm; 1888c2ecf20Sopenharmony_ci pgprot_t prot; 1898c2ecf20Sopenharmony_ci int retval; 1908c2ecf20Sopenharmony_ci void __iomem *ret_addr; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* Don't allow wraparound or zero size */ 1938c2ecf20Sopenharmony_ci last_addr = phys_addr + size - 1; 1948c2ecf20Sopenharmony_ci if (!size || last_addr < phys_addr) 1958c2ecf20Sopenharmony_ci return NULL; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (!phys_addr_valid(phys_addr)) { 1988c2ecf20Sopenharmony_ci printk(KERN_WARNING "ioremap: invalid physical address %llx\n", 1998c2ecf20Sopenharmony_ci (unsigned long long)phys_addr); 2008c2ecf20Sopenharmony_ci WARN_ON_ONCE(1); 2018c2ecf20Sopenharmony_ci return NULL; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci __ioremap_check_mem(phys_addr, size, &io_desc); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* 2078c2ecf20Sopenharmony_ci * Don't allow anybody to remap normal RAM that we're using.. 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci if (io_desc.flags & IORES_MAP_SYSTEM_RAM) { 2108c2ecf20Sopenharmony_ci WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n", 2118c2ecf20Sopenharmony_ci &phys_addr, &last_addr); 2128c2ecf20Sopenharmony_ci return NULL; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* 2168c2ecf20Sopenharmony_ci * Mappings have to be page-aligned 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci offset = phys_addr & ~PAGE_MASK; 2198c2ecf20Sopenharmony_ci phys_addr &= PAGE_MASK; 2208c2ecf20Sopenharmony_ci size = PAGE_ALIGN(last_addr+1) - phys_addr; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* 2238c2ecf20Sopenharmony_ci * Mask out any bits not part of the actual physical 2248c2ecf20Sopenharmony_ci * address, like memory encryption bits. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci phys_addr &= PHYSICAL_PAGE_MASK; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci retval = memtype_reserve(phys_addr, (u64)phys_addr + size, 2298c2ecf20Sopenharmony_ci pcm, &new_pcm); 2308c2ecf20Sopenharmony_ci if (retval) { 2318c2ecf20Sopenharmony_ci printk(KERN_ERR "ioremap memtype_reserve failed %d\n", retval); 2328c2ecf20Sopenharmony_ci return NULL; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (pcm != new_pcm) { 2368c2ecf20Sopenharmony_ci if (!is_new_memtype_allowed(phys_addr, size, pcm, new_pcm)) { 2378c2ecf20Sopenharmony_ci printk(KERN_ERR 2388c2ecf20Sopenharmony_ci "ioremap error for 0x%llx-0x%llx, requested 0x%x, got 0x%x\n", 2398c2ecf20Sopenharmony_ci (unsigned long long)phys_addr, 2408c2ecf20Sopenharmony_ci (unsigned long long)(phys_addr + size), 2418c2ecf20Sopenharmony_ci pcm, new_pcm); 2428c2ecf20Sopenharmony_ci goto err_free_memtype; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci pcm = new_pcm; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* 2488c2ecf20Sopenharmony_ci * If the page being mapped is in memory and SEV is active then 2498c2ecf20Sopenharmony_ci * make sure the memory encryption attribute is enabled in the 2508c2ecf20Sopenharmony_ci * resulting mapping. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci prot = PAGE_KERNEL_IO; 2538c2ecf20Sopenharmony_ci if ((io_desc.flags & IORES_MAP_ENCRYPTED) || encrypted) 2548c2ecf20Sopenharmony_ci prot = pgprot_encrypted(prot); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci switch (pcm) { 2578c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_UC: 2588c2ecf20Sopenharmony_ci default: 2598c2ecf20Sopenharmony_ci prot = __pgprot(pgprot_val(prot) | 2608c2ecf20Sopenharmony_ci cachemode2protval(_PAGE_CACHE_MODE_UC)); 2618c2ecf20Sopenharmony_ci break; 2628c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_UC_MINUS: 2638c2ecf20Sopenharmony_ci prot = __pgprot(pgprot_val(prot) | 2648c2ecf20Sopenharmony_ci cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS)); 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WC: 2678c2ecf20Sopenharmony_ci prot = __pgprot(pgprot_val(prot) | 2688c2ecf20Sopenharmony_ci cachemode2protval(_PAGE_CACHE_MODE_WC)); 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WT: 2718c2ecf20Sopenharmony_ci prot = __pgprot(pgprot_val(prot) | 2728c2ecf20Sopenharmony_ci cachemode2protval(_PAGE_CACHE_MODE_WT)); 2738c2ecf20Sopenharmony_ci break; 2748c2ecf20Sopenharmony_ci case _PAGE_CACHE_MODE_WB: 2758c2ecf20Sopenharmony_ci break; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* 2798c2ecf20Sopenharmony_ci * Ok, go for it.. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ci area = get_vm_area_caller(size, VM_IOREMAP, caller); 2828c2ecf20Sopenharmony_ci if (!area) 2838c2ecf20Sopenharmony_ci goto err_free_memtype; 2848c2ecf20Sopenharmony_ci area->phys_addr = phys_addr; 2858c2ecf20Sopenharmony_ci vaddr = (unsigned long) area->addr; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (memtype_kernel_map_sync(phys_addr, size, pcm)) 2888c2ecf20Sopenharmony_ci goto err_free_area; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) 2918c2ecf20Sopenharmony_ci goto err_free_area; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ret_addr = (void __iomem *) (vaddr + offset); 2948c2ecf20Sopenharmony_ci mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci /* 2978c2ecf20Sopenharmony_ci * Check if the request spans more than any BAR in the iomem resource 2988c2ecf20Sopenharmony_ci * tree. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci if (iomem_map_sanity_check(unaligned_phys_addr, unaligned_size)) 3018c2ecf20Sopenharmony_ci pr_warn("caller %pS mapping multiple BARs\n", caller); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return ret_addr; 3048c2ecf20Sopenharmony_cierr_free_area: 3058c2ecf20Sopenharmony_ci free_vm_area(area); 3068c2ecf20Sopenharmony_cierr_free_memtype: 3078c2ecf20Sopenharmony_ci memtype_free(phys_addr, phys_addr + size); 3088c2ecf20Sopenharmony_ci return NULL; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/** 3128c2ecf20Sopenharmony_ci * ioremap - map bus memory into CPU space 3138c2ecf20Sopenharmony_ci * @phys_addr: bus address of the memory 3148c2ecf20Sopenharmony_ci * @size: size of the resource to map 3158c2ecf20Sopenharmony_ci * 3168c2ecf20Sopenharmony_ci * ioremap performs a platform specific sequence of operations to 3178c2ecf20Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/ 3188c2ecf20Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned 3198c2ecf20Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual 3208c2ecf20Sopenharmony_ci * address. 3218c2ecf20Sopenharmony_ci * 3228c2ecf20Sopenharmony_ci * This version of ioremap ensures that the memory is marked uncachable 3238c2ecf20Sopenharmony_ci * on the CPU as well as honouring existing caching rules from things like 3248c2ecf20Sopenharmony_ci * the PCI bus. Note that there are other caches and buffers on many 3258c2ecf20Sopenharmony_ci * busses. In particular driver authors should read up on PCI writes 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * It's useful if some control registers are in such an area and 3288c2ecf20Sopenharmony_ci * write combining or read caching is not desirable: 3298c2ecf20Sopenharmony_ci * 3308c2ecf20Sopenharmony_ci * Must be freed with iounmap. 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_civoid __iomem *ioremap(resource_size_t phys_addr, unsigned long size) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci /* 3358c2ecf20Sopenharmony_ci * Ideally, this should be: 3368c2ecf20Sopenharmony_ci * pat_enabled() ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS; 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * Till we fix all X drivers to use ioremap_wc(), we will use 3398c2ecf20Sopenharmony_ci * UC MINUS. Drivers that are certain they need or can already 3408c2ecf20Sopenharmony_ci * be converted over to strong UC can use ioremap_uc(). 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC_MINUS; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, pcm, 3458c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/** 3508c2ecf20Sopenharmony_ci * ioremap_uc - map bus memory into CPU space as strongly uncachable 3518c2ecf20Sopenharmony_ci * @phys_addr: bus address of the memory 3528c2ecf20Sopenharmony_ci * @size: size of the resource to map 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * ioremap_uc performs a platform specific sequence of operations to 3558c2ecf20Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/ 3568c2ecf20Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned 3578c2ecf20Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual 3588c2ecf20Sopenharmony_ci * address. 3598c2ecf20Sopenharmony_ci * 3608c2ecf20Sopenharmony_ci * This version of ioremap ensures that the memory is marked with a strong 3618c2ecf20Sopenharmony_ci * preference as completely uncachable on the CPU when possible. For non-PAT 3628c2ecf20Sopenharmony_ci * systems this ends up setting page-attribute flags PCD=1, PWT=1. For PAT 3638c2ecf20Sopenharmony_ci * systems this will set the PAT entry for the pages as strong UC. This call 3648c2ecf20Sopenharmony_ci * will honor existing caching rules from things like the PCI bus. Note that 3658c2ecf20Sopenharmony_ci * there are other caches and buffers on many busses. In particular driver 3668c2ecf20Sopenharmony_ci * authors should read up on PCI writes. 3678c2ecf20Sopenharmony_ci * 3688c2ecf20Sopenharmony_ci * It's useful if some control registers are in such an area and 3698c2ecf20Sopenharmony_ci * write combining or read caching is not desirable: 3708c2ecf20Sopenharmony_ci * 3718c2ecf20Sopenharmony_ci * Must be freed with iounmap. 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_civoid __iomem *ioremap_uc(resource_size_t phys_addr, unsigned long size) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, pcm, 3788c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ioremap_uc); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/** 3838c2ecf20Sopenharmony_ci * ioremap_wc - map memory into CPU space write combined 3848c2ecf20Sopenharmony_ci * @phys_addr: bus address of the memory 3858c2ecf20Sopenharmony_ci * @size: size of the resource to map 3868c2ecf20Sopenharmony_ci * 3878c2ecf20Sopenharmony_ci * This version of ioremap ensures that the memory is marked write combining. 3888c2ecf20Sopenharmony_ci * Write combining allows faster writes to some hardware devices. 3898c2ecf20Sopenharmony_ci * 3908c2ecf20Sopenharmony_ci * Must be freed with iounmap. 3918c2ecf20Sopenharmony_ci */ 3928c2ecf20Sopenharmony_civoid __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WC, 3958c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap_wc); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci/** 4008c2ecf20Sopenharmony_ci * ioremap_wt - map memory into CPU space write through 4018c2ecf20Sopenharmony_ci * @phys_addr: bus address of the memory 4028c2ecf20Sopenharmony_ci * @size: size of the resource to map 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * This version of ioremap ensures that the memory is marked write through. 4058c2ecf20Sopenharmony_ci * Write through stores data into memory while keeping the cache up-to-date. 4068c2ecf20Sopenharmony_ci * 4078c2ecf20Sopenharmony_ci * Must be freed with iounmap. 4088c2ecf20Sopenharmony_ci */ 4098c2ecf20Sopenharmony_civoid __iomem *ioremap_wt(resource_size_t phys_addr, unsigned long size) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WT, 4128c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap_wt); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_civoid __iomem *ioremap_encrypted(resource_size_t phys_addr, unsigned long size) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WB, 4198c2ecf20Sopenharmony_ci __builtin_return_address(0), true); 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap_encrypted); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_civoid __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WB, 4268c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap_cache); 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_civoid __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size, 4318c2ecf20Sopenharmony_ci unsigned long prot_val) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci return __ioremap_caller(phys_addr, size, 4348c2ecf20Sopenharmony_ci pgprot2cachemode(__pgprot(prot_val)), 4358c2ecf20Sopenharmony_ci __builtin_return_address(0), false); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioremap_prot); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/** 4408c2ecf20Sopenharmony_ci * iounmap - Free a IO remapping 4418c2ecf20Sopenharmony_ci * @addr: virtual address from ioremap_* 4428c2ecf20Sopenharmony_ci * 4438c2ecf20Sopenharmony_ci * Caller must ensure there is only one unmapping for the same pointer. 4448c2ecf20Sopenharmony_ci */ 4458c2ecf20Sopenharmony_civoid iounmap(volatile void __iomem *addr) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci struct vm_struct *p, *o; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if ((void __force *)addr <= high_memory) 4508c2ecf20Sopenharmony_ci return; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci /* 4538c2ecf20Sopenharmony_ci * The PCI/ISA range special-casing was removed from __ioremap() 4548c2ecf20Sopenharmony_ci * so this check, in theory, can be removed. However, there are 4558c2ecf20Sopenharmony_ci * cases where iounmap() is called for addresses not obtained via 4568c2ecf20Sopenharmony_ci * ioremap() (vga16fb for example). Add a warning so that these 4578c2ecf20Sopenharmony_ci * cases can be caught and fixed. 4588c2ecf20Sopenharmony_ci */ 4598c2ecf20Sopenharmony_ci if ((void __force *)addr >= phys_to_virt(ISA_START_ADDRESS) && 4608c2ecf20Sopenharmony_ci (void __force *)addr < phys_to_virt(ISA_END_ADDRESS)) { 4618c2ecf20Sopenharmony_ci WARN(1, "iounmap() called for ISA range not obtained using ioremap()\n"); 4628c2ecf20Sopenharmony_ci return; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci mmiotrace_iounmap(addr); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci addr = (volatile void __iomem *) 4688c2ecf20Sopenharmony_ci (PAGE_MASK & (unsigned long __force)addr); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* Use the vm area unlocked, assuming the caller 4718c2ecf20Sopenharmony_ci ensures there isn't another iounmap for the same address 4728c2ecf20Sopenharmony_ci in parallel. Reuse of the virtual address is prevented by 4738c2ecf20Sopenharmony_ci leaving it in the global lists until we're done with it. 4748c2ecf20Sopenharmony_ci cpa takes care of the direct mappings. */ 4758c2ecf20Sopenharmony_ci p = find_vm_area((void __force *)addr); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!p) { 4788c2ecf20Sopenharmony_ci printk(KERN_ERR "iounmap: bad address %p\n", addr); 4798c2ecf20Sopenharmony_ci dump_stack(); 4808c2ecf20Sopenharmony_ci return; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci memtype_free(p->phys_addr, p->phys_addr + get_vm_area_size(p)); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* Finally remove it */ 4868c2ecf20Sopenharmony_ci o = remove_vm_area((void __force *)addr); 4878c2ecf20Sopenharmony_ci BUG_ON(p != o || o == NULL); 4888c2ecf20Sopenharmony_ci kfree(p); 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(iounmap); 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ciint __init arch_ioremap_p4d_supported(void) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci return 0; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ciint __init arch_ioremap_pud_supported(void) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 5008c2ecf20Sopenharmony_ci return boot_cpu_has(X86_FEATURE_GBPAGES); 5018c2ecf20Sopenharmony_ci#else 5028c2ecf20Sopenharmony_ci return 0; 5038c2ecf20Sopenharmony_ci#endif 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ciint __init arch_ioremap_pmd_supported(void) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci return boot_cpu_has(X86_FEATURE_PSE); 5098c2ecf20Sopenharmony_ci} 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci/* 5128c2ecf20Sopenharmony_ci * Convert a physical pointer to a virtual kernel pointer for /dev/mem 5138c2ecf20Sopenharmony_ci * access 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_civoid *xlate_dev_mem_ptr(phys_addr_t phys) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci unsigned long start = phys & PAGE_MASK; 5188c2ecf20Sopenharmony_ci unsigned long offset = phys & ~PAGE_MASK; 5198c2ecf20Sopenharmony_ci void *vaddr; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* memremap() maps if RAM, otherwise falls back to ioremap() */ 5228c2ecf20Sopenharmony_ci vaddr = memremap(start, PAGE_SIZE, MEMREMAP_WB); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci /* Only add the offset on success and return NULL if memremap() failed */ 5258c2ecf20Sopenharmony_ci if (vaddr) 5268c2ecf20Sopenharmony_ci vaddr += offset; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci return vaddr; 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_civoid unxlate_dev_mem_ptr(phys_addr_t phys, void *addr) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci memunmap((void *)((unsigned long)addr & PAGE_MASK)); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci/* 5378c2ecf20Sopenharmony_ci * Examine the physical address to determine if it is an area of memory 5388c2ecf20Sopenharmony_ci * that should be mapped decrypted. If the memory is not part of the 5398c2ecf20Sopenharmony_ci * kernel usable area it was accessed and created decrypted, so these 5408c2ecf20Sopenharmony_ci * areas should be mapped decrypted. And since the encryption key can 5418c2ecf20Sopenharmony_ci * change across reboots, persistent memory should also be mapped 5428c2ecf20Sopenharmony_ci * decrypted. 5438c2ecf20Sopenharmony_ci * 5448c2ecf20Sopenharmony_ci * If SEV is active, that implies that BIOS/UEFI also ran encrypted so 5458c2ecf20Sopenharmony_ci * only persistent memory should be mapped decrypted. 5468c2ecf20Sopenharmony_ci */ 5478c2ecf20Sopenharmony_cistatic bool memremap_should_map_decrypted(resource_size_t phys_addr, 5488c2ecf20Sopenharmony_ci unsigned long size) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci int is_pmem; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* 5538c2ecf20Sopenharmony_ci * Check if the address is part of a persistent memory region. 5548c2ecf20Sopenharmony_ci * This check covers areas added by E820, EFI and ACPI. 5558c2ecf20Sopenharmony_ci */ 5568c2ecf20Sopenharmony_ci is_pmem = region_intersects(phys_addr, size, IORESOURCE_MEM, 5578c2ecf20Sopenharmony_ci IORES_DESC_PERSISTENT_MEMORY); 5588c2ecf20Sopenharmony_ci if (is_pmem != REGION_DISJOINT) 5598c2ecf20Sopenharmony_ci return true; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* 5628c2ecf20Sopenharmony_ci * Check if the non-volatile attribute is set for an EFI 5638c2ecf20Sopenharmony_ci * reserved area. 5648c2ecf20Sopenharmony_ci */ 5658c2ecf20Sopenharmony_ci if (efi_enabled(EFI_BOOT)) { 5668c2ecf20Sopenharmony_ci switch (efi_mem_type(phys_addr)) { 5678c2ecf20Sopenharmony_ci case EFI_RESERVED_TYPE: 5688c2ecf20Sopenharmony_ci if (efi_mem_attributes(phys_addr) & EFI_MEMORY_NV) 5698c2ecf20Sopenharmony_ci return true; 5708c2ecf20Sopenharmony_ci break; 5718c2ecf20Sopenharmony_ci default: 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci /* Check if the address is outside kernel usable area */ 5778c2ecf20Sopenharmony_ci switch (e820__get_entry_type(phys_addr, phys_addr + size - 1)) { 5788c2ecf20Sopenharmony_ci case E820_TYPE_RESERVED: 5798c2ecf20Sopenharmony_ci case E820_TYPE_ACPI: 5808c2ecf20Sopenharmony_ci case E820_TYPE_NVS: 5818c2ecf20Sopenharmony_ci case E820_TYPE_UNUSABLE: 5828c2ecf20Sopenharmony_ci /* For SEV, these areas are encrypted */ 5838c2ecf20Sopenharmony_ci if (sev_active()) 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci fallthrough; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci case E820_TYPE_PRAM: 5888c2ecf20Sopenharmony_ci return true; 5898c2ecf20Sopenharmony_ci default: 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci return false; 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci/* 5978c2ecf20Sopenharmony_ci * Examine the physical address to determine if it is EFI data. Check 5988c2ecf20Sopenharmony_ci * it against the boot params structure and EFI tables and memory types. 5998c2ecf20Sopenharmony_ci */ 6008c2ecf20Sopenharmony_cistatic bool memremap_is_efi_data(resource_size_t phys_addr, 6018c2ecf20Sopenharmony_ci unsigned long size) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci u64 paddr; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci /* Check if the address is part of EFI boot/runtime data */ 6068c2ecf20Sopenharmony_ci if (!efi_enabled(EFI_BOOT)) 6078c2ecf20Sopenharmony_ci return false; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci paddr = boot_params.efi_info.efi_memmap_hi; 6108c2ecf20Sopenharmony_ci paddr <<= 32; 6118c2ecf20Sopenharmony_ci paddr |= boot_params.efi_info.efi_memmap; 6128c2ecf20Sopenharmony_ci if (phys_addr == paddr) 6138c2ecf20Sopenharmony_ci return true; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci paddr = boot_params.efi_info.efi_systab_hi; 6168c2ecf20Sopenharmony_ci paddr <<= 32; 6178c2ecf20Sopenharmony_ci paddr |= boot_params.efi_info.efi_systab; 6188c2ecf20Sopenharmony_ci if (phys_addr == paddr) 6198c2ecf20Sopenharmony_ci return true; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (efi_is_table_address(phys_addr)) 6228c2ecf20Sopenharmony_ci return true; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci switch (efi_mem_type(phys_addr)) { 6258c2ecf20Sopenharmony_ci case EFI_BOOT_SERVICES_DATA: 6268c2ecf20Sopenharmony_ci case EFI_RUNTIME_SERVICES_DATA: 6278c2ecf20Sopenharmony_ci return true; 6288c2ecf20Sopenharmony_ci default: 6298c2ecf20Sopenharmony_ci break; 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci return false; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci/* 6368c2ecf20Sopenharmony_ci * Examine the physical address to determine if it is boot data by checking 6378c2ecf20Sopenharmony_ci * it against the boot params setup_data chain. 6388c2ecf20Sopenharmony_ci */ 6398c2ecf20Sopenharmony_cistatic bool memremap_is_setup_data(resource_size_t phys_addr, 6408c2ecf20Sopenharmony_ci unsigned long size) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct setup_indirect *indirect; 6438c2ecf20Sopenharmony_ci struct setup_data *data; 6448c2ecf20Sopenharmony_ci u64 paddr, paddr_next; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci paddr = boot_params.hdr.setup_data; 6478c2ecf20Sopenharmony_ci while (paddr) { 6488c2ecf20Sopenharmony_ci unsigned int len; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (phys_addr == paddr) 6518c2ecf20Sopenharmony_ci return true; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci data = memremap(paddr, sizeof(*data), 6548c2ecf20Sopenharmony_ci MEMREMAP_WB | MEMREMAP_DEC); 6558c2ecf20Sopenharmony_ci if (!data) { 6568c2ecf20Sopenharmony_ci pr_warn("failed to memremap setup_data entry\n"); 6578c2ecf20Sopenharmony_ci return false; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci paddr_next = data->next; 6618c2ecf20Sopenharmony_ci len = data->len; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci if ((phys_addr > paddr) && (phys_addr < (paddr + len))) { 6648c2ecf20Sopenharmony_ci memunmap(data); 6658c2ecf20Sopenharmony_ci return true; 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (data->type == SETUP_INDIRECT) { 6698c2ecf20Sopenharmony_ci memunmap(data); 6708c2ecf20Sopenharmony_ci data = memremap(paddr, sizeof(*data) + len, 6718c2ecf20Sopenharmony_ci MEMREMAP_WB | MEMREMAP_DEC); 6728c2ecf20Sopenharmony_ci if (!data) { 6738c2ecf20Sopenharmony_ci pr_warn("failed to memremap indirect setup_data\n"); 6748c2ecf20Sopenharmony_ci return false; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci indirect = (struct setup_indirect *)data->data; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (indirect->type != SETUP_INDIRECT) { 6808c2ecf20Sopenharmony_ci paddr = indirect->addr; 6818c2ecf20Sopenharmony_ci len = indirect->len; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci memunmap(data); 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if ((phys_addr > paddr) && (phys_addr < (paddr + len))) 6888c2ecf20Sopenharmony_ci return true; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci paddr = paddr_next; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci return false; 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci/* 6978c2ecf20Sopenharmony_ci * Examine the physical address to determine if it is boot data by checking 6988c2ecf20Sopenharmony_ci * it against the boot params setup_data chain (early boot version). 6998c2ecf20Sopenharmony_ci */ 7008c2ecf20Sopenharmony_cistatic bool __init early_memremap_is_setup_data(resource_size_t phys_addr, 7018c2ecf20Sopenharmony_ci unsigned long size) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci struct setup_indirect *indirect; 7048c2ecf20Sopenharmony_ci struct setup_data *data; 7058c2ecf20Sopenharmony_ci u64 paddr, paddr_next; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci paddr = boot_params.hdr.setup_data; 7088c2ecf20Sopenharmony_ci while (paddr) { 7098c2ecf20Sopenharmony_ci unsigned int len, size; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci if (phys_addr == paddr) 7128c2ecf20Sopenharmony_ci return true; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci data = early_memremap_decrypted(paddr, sizeof(*data)); 7158c2ecf20Sopenharmony_ci if (!data) { 7168c2ecf20Sopenharmony_ci pr_warn("failed to early memremap setup_data entry\n"); 7178c2ecf20Sopenharmony_ci return false; 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci size = sizeof(*data); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci paddr_next = data->next; 7238c2ecf20Sopenharmony_ci len = data->len; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci if ((phys_addr > paddr) && (phys_addr < (paddr + len))) { 7268c2ecf20Sopenharmony_ci early_memunmap(data, sizeof(*data)); 7278c2ecf20Sopenharmony_ci return true; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (data->type == SETUP_INDIRECT) { 7318c2ecf20Sopenharmony_ci size += len; 7328c2ecf20Sopenharmony_ci early_memunmap(data, sizeof(*data)); 7338c2ecf20Sopenharmony_ci data = early_memremap_decrypted(paddr, size); 7348c2ecf20Sopenharmony_ci if (!data) { 7358c2ecf20Sopenharmony_ci pr_warn("failed to early memremap indirect setup_data\n"); 7368c2ecf20Sopenharmony_ci return false; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci indirect = (struct setup_indirect *)data->data; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci if (indirect->type != SETUP_INDIRECT) { 7428c2ecf20Sopenharmony_ci paddr = indirect->addr; 7438c2ecf20Sopenharmony_ci len = indirect->len; 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci early_memunmap(data, size); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci if ((phys_addr > paddr) && (phys_addr < (paddr + len))) 7508c2ecf20Sopenharmony_ci return true; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci paddr = paddr_next; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci return false; 7568c2ecf20Sopenharmony_ci} 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci/* 7598c2ecf20Sopenharmony_ci * Architecture function to determine if RAM remap is allowed. By default, a 7608c2ecf20Sopenharmony_ci * RAM remap will map the data as encrypted. Determine if a RAM remap should 7618c2ecf20Sopenharmony_ci * not be done so that the data will be mapped decrypted. 7628c2ecf20Sopenharmony_ci */ 7638c2ecf20Sopenharmony_cibool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size, 7648c2ecf20Sopenharmony_ci unsigned long flags) 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci if (!mem_encrypt_active()) 7678c2ecf20Sopenharmony_ci return true; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci if (flags & MEMREMAP_ENC) 7708c2ecf20Sopenharmony_ci return true; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (flags & MEMREMAP_DEC) 7738c2ecf20Sopenharmony_ci return false; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci if (sme_active()) { 7768c2ecf20Sopenharmony_ci if (memremap_is_setup_data(phys_addr, size) || 7778c2ecf20Sopenharmony_ci memremap_is_efi_data(phys_addr, size)) 7788c2ecf20Sopenharmony_ci return false; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci return !memremap_should_map_decrypted(phys_addr, size); 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci/* 7858c2ecf20Sopenharmony_ci * Architecture override of __weak function to adjust the protection attributes 7868c2ecf20Sopenharmony_ci * used when remapping memory. By default, early_memremap() will map the data 7878c2ecf20Sopenharmony_ci * as encrypted. Determine if an encrypted mapping should not be done and set 7888c2ecf20Sopenharmony_ci * the appropriate protection attributes. 7898c2ecf20Sopenharmony_ci */ 7908c2ecf20Sopenharmony_cipgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr, 7918c2ecf20Sopenharmony_ci unsigned long size, 7928c2ecf20Sopenharmony_ci pgprot_t prot) 7938c2ecf20Sopenharmony_ci{ 7948c2ecf20Sopenharmony_ci bool encrypted_prot; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (!mem_encrypt_active()) 7978c2ecf20Sopenharmony_ci return prot; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci encrypted_prot = true; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (sme_active()) { 8028c2ecf20Sopenharmony_ci if (early_memremap_is_setup_data(phys_addr, size) || 8038c2ecf20Sopenharmony_ci memremap_is_efi_data(phys_addr, size)) 8048c2ecf20Sopenharmony_ci encrypted_prot = false; 8058c2ecf20Sopenharmony_ci } 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (encrypted_prot && memremap_should_map_decrypted(phys_addr, size)) 8088c2ecf20Sopenharmony_ci encrypted_prot = false; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci return encrypted_prot ? pgprot_encrypted(prot) 8118c2ecf20Sopenharmony_ci : pgprot_decrypted(prot); 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cibool phys_mem_access_encrypted(unsigned long phys_addr, unsigned long size) 8158c2ecf20Sopenharmony_ci{ 8168c2ecf20Sopenharmony_ci return arch_memremap_can_ram_remap(phys_addr, size, 0); 8178c2ecf20Sopenharmony_ci} 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci#ifdef CONFIG_AMD_MEM_ENCRYPT 8208c2ecf20Sopenharmony_ci/* Remap memory with encryption */ 8218c2ecf20Sopenharmony_civoid __init *early_memremap_encrypted(resource_size_t phys_addr, 8228c2ecf20Sopenharmony_ci unsigned long size) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC); 8258c2ecf20Sopenharmony_ci} 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci/* 8288c2ecf20Sopenharmony_ci * Remap memory with encryption and write-protected - cannot be called 8298c2ecf20Sopenharmony_ci * before pat_init() is called 8308c2ecf20Sopenharmony_ci */ 8318c2ecf20Sopenharmony_civoid __init *early_memremap_encrypted_wp(resource_size_t phys_addr, 8328c2ecf20Sopenharmony_ci unsigned long size) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci if (!x86_has_pat_wp()) 8358c2ecf20Sopenharmony_ci return NULL; 8368c2ecf20Sopenharmony_ci return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_ENC_WP); 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci/* Remap memory without encryption */ 8408c2ecf20Sopenharmony_civoid __init *early_memremap_decrypted(resource_size_t phys_addr, 8418c2ecf20Sopenharmony_ci unsigned long size) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_NOENC); 8448c2ecf20Sopenharmony_ci} 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci/* 8478c2ecf20Sopenharmony_ci * Remap memory without encryption and write-protected - cannot be called 8488c2ecf20Sopenharmony_ci * before pat_init() is called 8498c2ecf20Sopenharmony_ci */ 8508c2ecf20Sopenharmony_civoid __init *early_memremap_decrypted_wp(resource_size_t phys_addr, 8518c2ecf20Sopenharmony_ci unsigned long size) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci if (!x86_has_pat_wp()) 8548c2ecf20Sopenharmony_ci return NULL; 8558c2ecf20Sopenharmony_ci return early_memremap_prot(phys_addr, size, __PAGE_KERNEL_NOENC_WP); 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci#endif /* CONFIG_AMD_MEM_ENCRYPT */ 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cistatic pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_cistatic inline pmd_t * __init early_ioremap_pmd(unsigned long addr) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci /* Don't assume we're using swapper_pg_dir at this point */ 8648c2ecf20Sopenharmony_ci pgd_t *base = __va(read_cr3_pa()); 8658c2ecf20Sopenharmony_ci pgd_t *pgd = &base[pgd_index(addr)]; 8668c2ecf20Sopenharmony_ci p4d_t *p4d = p4d_offset(pgd, addr); 8678c2ecf20Sopenharmony_ci pud_t *pud = pud_offset(p4d, addr); 8688c2ecf20Sopenharmony_ci pmd_t *pmd = pmd_offset(pud, addr); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci return pmd; 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic inline pte_t * __init early_ioremap_pte(unsigned long addr) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci return &bm_pte[pte_index(addr)]; 8768c2ecf20Sopenharmony_ci} 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cibool __init is_early_ioremap_ptep(pte_t *ptep) 8798c2ecf20Sopenharmony_ci{ 8808c2ecf20Sopenharmony_ci return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)]; 8818c2ecf20Sopenharmony_ci} 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_civoid __init early_ioremap_init(void) 8848c2ecf20Sopenharmony_ci{ 8858c2ecf20Sopenharmony_ci pmd_t *pmd; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 8888c2ecf20Sopenharmony_ci BUILD_BUG_ON((fix_to_virt(0) + PAGE_SIZE) & ((1 << PMD_SHIFT) - 1)); 8898c2ecf20Sopenharmony_ci#else 8908c2ecf20Sopenharmony_ci WARN_ON((fix_to_virt(0) + PAGE_SIZE) & ((1 << PMD_SHIFT) - 1)); 8918c2ecf20Sopenharmony_ci#endif 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci early_ioremap_setup(); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); 8968c2ecf20Sopenharmony_ci memset(bm_pte, 0, sizeof(bm_pte)); 8978c2ecf20Sopenharmony_ci pmd_populate_kernel(&init_mm, pmd, bm_pte); 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci /* 9008c2ecf20Sopenharmony_ci * The boot-ioremap range spans multiple pmds, for which 9018c2ecf20Sopenharmony_ci * we are not prepared: 9028c2ecf20Sopenharmony_ci */ 9038c2ecf20Sopenharmony_ci#define __FIXADDR_TOP (-PAGE_SIZE) 9048c2ecf20Sopenharmony_ci BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT) 9058c2ecf20Sopenharmony_ci != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT)); 9068c2ecf20Sopenharmony_ci#undef __FIXADDR_TOP 9078c2ecf20Sopenharmony_ci if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) { 9088c2ecf20Sopenharmony_ci WARN_ON(1); 9098c2ecf20Sopenharmony_ci printk(KERN_WARNING "pmd %p != %p\n", 9108c2ecf20Sopenharmony_ci pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))); 9118c2ecf20Sopenharmony_ci printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n", 9128c2ecf20Sopenharmony_ci fix_to_virt(FIX_BTMAP_BEGIN)); 9138c2ecf20Sopenharmony_ci printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END): %08lx\n", 9148c2ecf20Sopenharmony_ci fix_to_virt(FIX_BTMAP_END)); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci printk(KERN_WARNING "FIX_BTMAP_END: %d\n", FIX_BTMAP_END); 9178c2ecf20Sopenharmony_ci printk(KERN_WARNING "FIX_BTMAP_BEGIN: %d\n", 9188c2ecf20Sopenharmony_ci FIX_BTMAP_BEGIN); 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci} 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_civoid __init __early_set_fixmap(enum fixed_addresses idx, 9238c2ecf20Sopenharmony_ci phys_addr_t phys, pgprot_t flags) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci unsigned long addr = __fix_to_virt(idx); 9268c2ecf20Sopenharmony_ci pte_t *pte; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci if (idx >= __end_of_fixed_addresses) { 9298c2ecf20Sopenharmony_ci BUG(); 9308c2ecf20Sopenharmony_ci return; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci pte = early_ioremap_pte(addr); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci /* Sanitize 'prot' against any unsupported bits: */ 9358c2ecf20Sopenharmony_ci pgprot_val(flags) &= __supported_pte_mask; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci if (pgprot_val(flags)) 9388c2ecf20Sopenharmony_ci set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags)); 9398c2ecf20Sopenharmony_ci else 9408c2ecf20Sopenharmony_ci pte_clear(&init_mm, addr, pte); 9418c2ecf20Sopenharmony_ci flush_tlb_one_kernel(addr); 9428c2ecf20Sopenharmony_ci} 943