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