160863c0dSMatt Fleming /* 260863c0dSMatt Fleming * Common EFI memory map functions. 360863c0dSMatt Fleming */ 460863c0dSMatt Fleming 560863c0dSMatt Fleming #define pr_fmt(fmt) "efi: " fmt 660863c0dSMatt Fleming 760863c0dSMatt Fleming #include <linux/init.h> 860863c0dSMatt Fleming #include <linux/kernel.h> 960863c0dSMatt Fleming #include <linux/efi.h> 1060863c0dSMatt Fleming #include <linux/io.h> 1160863c0dSMatt Fleming #include <asm/early_ioremap.h> 12*20b1e22dSNicolai Stange #include <linux/memblock.h> 13*20b1e22dSNicolai Stange #include <linux/slab.h> 14*20b1e22dSNicolai Stange 15*20b1e22dSNicolai Stange static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size) 16*20b1e22dSNicolai Stange { 17*20b1e22dSNicolai Stange return memblock_alloc(size, 0); 18*20b1e22dSNicolai Stange } 19*20b1e22dSNicolai Stange 20*20b1e22dSNicolai Stange static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size) 21*20b1e22dSNicolai Stange { 22*20b1e22dSNicolai Stange unsigned int order = get_order(size); 23*20b1e22dSNicolai Stange struct page *p = alloc_pages(GFP_KERNEL, order); 24*20b1e22dSNicolai Stange 25*20b1e22dSNicolai Stange if (!p) 26*20b1e22dSNicolai Stange return 0; 27*20b1e22dSNicolai Stange 28*20b1e22dSNicolai Stange return PFN_PHYS(page_to_pfn(p)); 29*20b1e22dSNicolai Stange } 30*20b1e22dSNicolai Stange 31*20b1e22dSNicolai Stange /** 32*20b1e22dSNicolai Stange * efi_memmap_alloc - Allocate memory for the EFI memory map 33*20b1e22dSNicolai Stange * @num_entries: Number of entries in the allocated map. 34*20b1e22dSNicolai Stange * 35*20b1e22dSNicolai Stange * Depending on whether mm_init() has already been invoked or not, 36*20b1e22dSNicolai Stange * either memblock or "normal" page allocation is used. 37*20b1e22dSNicolai Stange * 38*20b1e22dSNicolai Stange * Returns the physical address of the allocated memory map on 39*20b1e22dSNicolai Stange * success, zero on failure. 40*20b1e22dSNicolai Stange */ 41*20b1e22dSNicolai Stange phys_addr_t __init efi_memmap_alloc(unsigned int num_entries) 42*20b1e22dSNicolai Stange { 43*20b1e22dSNicolai Stange unsigned long size = num_entries * efi.memmap.desc_size; 44*20b1e22dSNicolai Stange 45*20b1e22dSNicolai Stange if (slab_is_available()) 46*20b1e22dSNicolai Stange return __efi_memmap_alloc_late(size); 47*20b1e22dSNicolai Stange 48*20b1e22dSNicolai Stange return __efi_memmap_alloc_early(size); 49*20b1e22dSNicolai Stange } 5060863c0dSMatt Fleming 5160863c0dSMatt Fleming /** 5260863c0dSMatt Fleming * __efi_memmap_init - Common code for mapping the EFI memory map 5360863c0dSMatt Fleming * @data: EFI memory map data 5460863c0dSMatt Fleming * @late: Use early or late mapping function? 5560863c0dSMatt Fleming * 5660863c0dSMatt Fleming * This function takes care of figuring out which function to use to 5760863c0dSMatt Fleming * map the EFI memory map in efi.memmap based on how far into the boot 5860863c0dSMatt Fleming * we are. 5960863c0dSMatt Fleming * 6060863c0dSMatt Fleming * During bootup @late should be %false since we only have access to 6160863c0dSMatt Fleming * the early_memremap*() functions as the vmalloc space isn't setup. 6260863c0dSMatt Fleming * Once the kernel is fully booted we can fallback to the more robust 6360863c0dSMatt Fleming * memremap*() API. 6460863c0dSMatt Fleming * 6560863c0dSMatt Fleming * Returns zero on success, a negative error code on failure. 6660863c0dSMatt Fleming */ 6760863c0dSMatt Fleming static int __init 6860863c0dSMatt Fleming __efi_memmap_init(struct efi_memory_map_data *data, bool late) 6960863c0dSMatt Fleming { 7060863c0dSMatt Fleming struct efi_memory_map map; 7160863c0dSMatt Fleming phys_addr_t phys_map; 7260863c0dSMatt Fleming 7360863c0dSMatt Fleming if (efi_enabled(EFI_PARAVIRT)) 7460863c0dSMatt Fleming return 0; 7560863c0dSMatt Fleming 7660863c0dSMatt Fleming phys_map = data->phys_map; 7760863c0dSMatt Fleming 7860863c0dSMatt Fleming if (late) 7960863c0dSMatt Fleming map.map = memremap(phys_map, data->size, MEMREMAP_WB); 8060863c0dSMatt Fleming else 8160863c0dSMatt Fleming map.map = early_memremap(phys_map, data->size); 8260863c0dSMatt Fleming 8360863c0dSMatt Fleming if (!map.map) { 8460863c0dSMatt Fleming pr_err("Could not map the memory map!\n"); 8560863c0dSMatt Fleming return -ENOMEM; 8660863c0dSMatt Fleming } 8760863c0dSMatt Fleming 8860863c0dSMatt Fleming map.phys_map = data->phys_map; 8960863c0dSMatt Fleming map.nr_map = data->size / data->desc_size; 9060863c0dSMatt Fleming map.map_end = map.map + data->size; 9160863c0dSMatt Fleming 9260863c0dSMatt Fleming map.desc_version = data->desc_version; 9360863c0dSMatt Fleming map.desc_size = data->desc_size; 9460863c0dSMatt Fleming map.late = late; 9560863c0dSMatt Fleming 9660863c0dSMatt Fleming set_bit(EFI_MEMMAP, &efi.flags); 9760863c0dSMatt Fleming 9860863c0dSMatt Fleming efi.memmap = map; 9960863c0dSMatt Fleming 10060863c0dSMatt Fleming return 0; 10160863c0dSMatt Fleming } 10260863c0dSMatt Fleming 10360863c0dSMatt Fleming /** 10460863c0dSMatt Fleming * efi_memmap_init_early - Map the EFI memory map data structure 10560863c0dSMatt Fleming * @data: EFI memory map data 10660863c0dSMatt Fleming * 10760863c0dSMatt Fleming * Use early_memremap() to map the passed in EFI memory map and assign 10860863c0dSMatt Fleming * it to efi.memmap. 10960863c0dSMatt Fleming */ 11060863c0dSMatt Fleming int __init efi_memmap_init_early(struct efi_memory_map_data *data) 11160863c0dSMatt Fleming { 11260863c0dSMatt Fleming /* Cannot go backwards */ 11360863c0dSMatt Fleming WARN_ON(efi.memmap.late); 11460863c0dSMatt Fleming 11560863c0dSMatt Fleming return __efi_memmap_init(data, false); 11660863c0dSMatt Fleming } 11760863c0dSMatt Fleming 11860863c0dSMatt Fleming void __init efi_memmap_unmap(void) 11960863c0dSMatt Fleming { 12060863c0dSMatt Fleming if (!efi.memmap.late) { 12160863c0dSMatt Fleming unsigned long size; 12260863c0dSMatt Fleming 12360863c0dSMatt Fleming size = efi.memmap.desc_size * efi.memmap.nr_map; 12460863c0dSMatt Fleming early_memunmap(efi.memmap.map, size); 12560863c0dSMatt Fleming } else { 12660863c0dSMatt Fleming memunmap(efi.memmap.map); 12760863c0dSMatt Fleming } 12860863c0dSMatt Fleming 12960863c0dSMatt Fleming efi.memmap.map = NULL; 13060863c0dSMatt Fleming clear_bit(EFI_MEMMAP, &efi.flags); 13160863c0dSMatt Fleming } 13260863c0dSMatt Fleming 13360863c0dSMatt Fleming /** 13460863c0dSMatt Fleming * efi_memmap_init_late - Map efi.memmap with memremap() 13560863c0dSMatt Fleming * @phys_addr: Physical address of the new EFI memory map 13660863c0dSMatt Fleming * @size: Size in bytes of the new EFI memory map 13760863c0dSMatt Fleming * 13860863c0dSMatt Fleming * Setup a mapping of the EFI memory map using ioremap_cache(). This 13960863c0dSMatt Fleming * function should only be called once the vmalloc space has been 14060863c0dSMatt Fleming * setup and is therefore not suitable for calling during early EFI 14160863c0dSMatt Fleming * initialise, e.g. in efi_init(). Additionally, it expects 14260863c0dSMatt Fleming * efi_memmap_init_early() to have already been called. 14360863c0dSMatt Fleming * 14460863c0dSMatt Fleming * The reason there are two EFI memmap initialisation 14560863c0dSMatt Fleming * (efi_memmap_init_early() and this late version) is because the 14660863c0dSMatt Fleming * early EFI memmap should be explicitly unmapped once EFI 14760863c0dSMatt Fleming * initialisation is complete as the fixmap space used to map the EFI 14860863c0dSMatt Fleming * memmap (via early_memremap()) is a scarce resource. 14960863c0dSMatt Fleming * 15060863c0dSMatt Fleming * This late mapping is intended to persist for the duration of 15160863c0dSMatt Fleming * runtime so that things like efi_mem_desc_lookup() and 15260863c0dSMatt Fleming * efi_mem_attributes() always work. 15360863c0dSMatt Fleming * 15460863c0dSMatt Fleming * Returns zero on success, a negative error code on failure. 15560863c0dSMatt Fleming */ 15660863c0dSMatt Fleming int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size) 15760863c0dSMatt Fleming { 15860863c0dSMatt Fleming struct efi_memory_map_data data = { 15960863c0dSMatt Fleming .phys_map = addr, 16060863c0dSMatt Fleming .size = size, 16160863c0dSMatt Fleming }; 16260863c0dSMatt Fleming 16360863c0dSMatt Fleming /* Did we forget to unmap the early EFI memmap? */ 16460863c0dSMatt Fleming WARN_ON(efi.memmap.map); 16560863c0dSMatt Fleming 16660863c0dSMatt Fleming /* Were we already called? */ 16760863c0dSMatt Fleming WARN_ON(efi.memmap.late); 16860863c0dSMatt Fleming 16960863c0dSMatt Fleming /* 17060863c0dSMatt Fleming * It makes no sense to allow callers to register different 17160863c0dSMatt Fleming * values for the following fields. Copy them out of the 17260863c0dSMatt Fleming * existing early EFI memmap. 17360863c0dSMatt Fleming */ 17460863c0dSMatt Fleming data.desc_version = efi.memmap.desc_version; 17560863c0dSMatt Fleming data.desc_size = efi.memmap.desc_size; 17660863c0dSMatt Fleming 17760863c0dSMatt Fleming return __efi_memmap_init(&data, true); 17860863c0dSMatt Fleming } 17960863c0dSMatt Fleming 18060863c0dSMatt Fleming /** 181c45f4da3SMatt Fleming * efi_memmap_install - Install a new EFI memory map in efi.memmap 182c45f4da3SMatt Fleming * @addr: Physical address of the memory map 183c45f4da3SMatt Fleming * @nr_map: Number of entries in the memory map 184c45f4da3SMatt Fleming * 185c45f4da3SMatt Fleming * Unlike efi_memmap_init_*(), this function does not allow the caller 186c45f4da3SMatt Fleming * to switch from early to late mappings. It simply uses the existing 187c45f4da3SMatt Fleming * mapping function and installs the new memmap. 188c45f4da3SMatt Fleming * 189c45f4da3SMatt Fleming * Returns zero on success, a negative error code on failure. 190c45f4da3SMatt Fleming */ 191c45f4da3SMatt Fleming int __init efi_memmap_install(phys_addr_t addr, unsigned int nr_map) 192c45f4da3SMatt Fleming { 193c45f4da3SMatt Fleming struct efi_memory_map_data data; 194c45f4da3SMatt Fleming 195c45f4da3SMatt Fleming efi_memmap_unmap(); 196c45f4da3SMatt Fleming 197c45f4da3SMatt Fleming data.phys_map = addr; 198c45f4da3SMatt Fleming data.size = efi.memmap.desc_size * nr_map; 199c45f4da3SMatt Fleming data.desc_version = efi.memmap.desc_version; 200c45f4da3SMatt Fleming data.desc_size = efi.memmap.desc_size; 201c45f4da3SMatt Fleming 202c45f4da3SMatt Fleming return __efi_memmap_init(&data, efi.memmap.late); 203c45f4da3SMatt Fleming } 204c45f4da3SMatt Fleming 205c45f4da3SMatt Fleming /** 20660863c0dSMatt Fleming * efi_memmap_split_count - Count number of additional EFI memmap entries 20760863c0dSMatt Fleming * @md: EFI memory descriptor to split 20860863c0dSMatt Fleming * @range: Address range (start, end) to split around 20960863c0dSMatt Fleming * 21060863c0dSMatt Fleming * Returns the number of additional EFI memmap entries required to 21160863c0dSMatt Fleming * accomodate @range. 21260863c0dSMatt Fleming */ 21360863c0dSMatt Fleming int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range) 21460863c0dSMatt Fleming { 21560863c0dSMatt Fleming u64 m_start, m_end; 21660863c0dSMatt Fleming u64 start, end; 21760863c0dSMatt Fleming int count = 0; 21860863c0dSMatt Fleming 21960863c0dSMatt Fleming start = md->phys_addr; 22060863c0dSMatt Fleming end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1; 22160863c0dSMatt Fleming 22260863c0dSMatt Fleming /* modifying range */ 22360863c0dSMatt Fleming m_start = range->start; 22460863c0dSMatt Fleming m_end = range->end; 22560863c0dSMatt Fleming 22660863c0dSMatt Fleming if (m_start <= start) { 22760863c0dSMatt Fleming /* split into 2 parts */ 22860863c0dSMatt Fleming if (start < m_end && m_end < end) 22960863c0dSMatt Fleming count++; 23060863c0dSMatt Fleming } 23160863c0dSMatt Fleming 23260863c0dSMatt Fleming if (start < m_start && m_start < end) { 23360863c0dSMatt Fleming /* split into 3 parts */ 23460863c0dSMatt Fleming if (m_end < end) 23560863c0dSMatt Fleming count += 2; 23660863c0dSMatt Fleming /* split into 2 parts */ 23760863c0dSMatt Fleming if (end <= m_end) 23860863c0dSMatt Fleming count++; 23960863c0dSMatt Fleming } 24060863c0dSMatt Fleming 24160863c0dSMatt Fleming return count; 24260863c0dSMatt Fleming } 24360863c0dSMatt Fleming 24460863c0dSMatt Fleming /** 24560863c0dSMatt Fleming * efi_memmap_insert - Insert a memory region in an EFI memmap 24660863c0dSMatt Fleming * @old_memmap: The existing EFI memory map structure 24760863c0dSMatt Fleming * @buf: Address of buffer to store new map 24860863c0dSMatt Fleming * @mem: Memory map entry to insert 24960863c0dSMatt Fleming * 25060863c0dSMatt Fleming * It is suggested that you call efi_memmap_split_count() first 25160863c0dSMatt Fleming * to see how large @buf needs to be. 25260863c0dSMatt Fleming */ 25360863c0dSMatt Fleming void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf, 25460863c0dSMatt Fleming struct efi_mem_range *mem) 25560863c0dSMatt Fleming { 25660863c0dSMatt Fleming u64 m_start, m_end, m_attr; 25760863c0dSMatt Fleming efi_memory_desc_t *md; 25860863c0dSMatt Fleming u64 start, end; 25960863c0dSMatt Fleming void *old, *new; 26060863c0dSMatt Fleming 26160863c0dSMatt Fleming /* modifying range */ 26260863c0dSMatt Fleming m_start = mem->range.start; 26360863c0dSMatt Fleming m_end = mem->range.end; 26460863c0dSMatt Fleming m_attr = mem->attribute; 26560863c0dSMatt Fleming 26692dc3350SMatt Fleming /* 26792dc3350SMatt Fleming * The EFI memory map deals with regions in EFI_PAGE_SIZE 26892dc3350SMatt Fleming * units. Ensure that the region described by 'mem' is aligned 26992dc3350SMatt Fleming * correctly. 27092dc3350SMatt Fleming */ 27192dc3350SMatt Fleming if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) || 27292dc3350SMatt Fleming !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) { 27392dc3350SMatt Fleming WARN_ON(1); 27492dc3350SMatt Fleming return; 27592dc3350SMatt Fleming } 27692dc3350SMatt Fleming 27760863c0dSMatt Fleming for (old = old_memmap->map, new = buf; 27860863c0dSMatt Fleming old < old_memmap->map_end; 27960863c0dSMatt Fleming old += old_memmap->desc_size, new += old_memmap->desc_size) { 28060863c0dSMatt Fleming 28160863c0dSMatt Fleming /* copy original EFI memory descriptor */ 28260863c0dSMatt Fleming memcpy(new, old, old_memmap->desc_size); 28360863c0dSMatt Fleming md = new; 28460863c0dSMatt Fleming start = md->phys_addr; 28560863c0dSMatt Fleming end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; 28660863c0dSMatt Fleming 28760863c0dSMatt Fleming if (m_start <= start && end <= m_end) 28860863c0dSMatt Fleming md->attribute |= m_attr; 28960863c0dSMatt Fleming 29060863c0dSMatt Fleming if (m_start <= start && 29160863c0dSMatt Fleming (start < m_end && m_end < end)) { 29260863c0dSMatt Fleming /* first part */ 29360863c0dSMatt Fleming md->attribute |= m_attr; 29460863c0dSMatt Fleming md->num_pages = (m_end - md->phys_addr + 1) >> 29560863c0dSMatt Fleming EFI_PAGE_SHIFT; 29660863c0dSMatt Fleming /* latter part */ 29760863c0dSMatt Fleming new += old_memmap->desc_size; 29860863c0dSMatt Fleming memcpy(new, old, old_memmap->desc_size); 29960863c0dSMatt Fleming md = new; 30060863c0dSMatt Fleming md->phys_addr = m_end + 1; 30160863c0dSMatt Fleming md->num_pages = (end - md->phys_addr + 1) >> 30260863c0dSMatt Fleming EFI_PAGE_SHIFT; 30360863c0dSMatt Fleming } 30460863c0dSMatt Fleming 30560863c0dSMatt Fleming if ((start < m_start && m_start < end) && m_end < end) { 30660863c0dSMatt Fleming /* first part */ 30760863c0dSMatt Fleming md->num_pages = (m_start - md->phys_addr) >> 30860863c0dSMatt Fleming EFI_PAGE_SHIFT; 30960863c0dSMatt Fleming /* middle part */ 31060863c0dSMatt Fleming new += old_memmap->desc_size; 31160863c0dSMatt Fleming memcpy(new, old, old_memmap->desc_size); 31260863c0dSMatt Fleming md = new; 31360863c0dSMatt Fleming md->attribute |= m_attr; 31460863c0dSMatt Fleming md->phys_addr = m_start; 31560863c0dSMatt Fleming md->num_pages = (m_end - m_start + 1) >> 31660863c0dSMatt Fleming EFI_PAGE_SHIFT; 31760863c0dSMatt Fleming /* last part */ 31860863c0dSMatt Fleming new += old_memmap->desc_size; 31960863c0dSMatt Fleming memcpy(new, old, old_memmap->desc_size); 32060863c0dSMatt Fleming md = new; 32160863c0dSMatt Fleming md->phys_addr = m_end + 1; 32260863c0dSMatt Fleming md->num_pages = (end - m_end) >> 32360863c0dSMatt Fleming EFI_PAGE_SHIFT; 32460863c0dSMatt Fleming } 32560863c0dSMatt Fleming 32660863c0dSMatt Fleming if ((start < m_start && m_start < end) && 32760863c0dSMatt Fleming (end <= m_end)) { 32860863c0dSMatt Fleming /* first part */ 32960863c0dSMatt Fleming md->num_pages = (m_start - md->phys_addr) >> 33060863c0dSMatt Fleming EFI_PAGE_SHIFT; 33160863c0dSMatt Fleming /* latter part */ 33260863c0dSMatt Fleming new += old_memmap->desc_size; 33360863c0dSMatt Fleming memcpy(new, old, old_memmap->desc_size); 33460863c0dSMatt Fleming md = new; 33560863c0dSMatt Fleming md->phys_addr = m_start; 33660863c0dSMatt Fleming md->num_pages = (end - md->phys_addr + 1) >> 33760863c0dSMatt Fleming EFI_PAGE_SHIFT; 33860863c0dSMatt Fleming md->attribute |= m_attr; 33960863c0dSMatt Fleming } 34060863c0dSMatt Fleming } 34160863c0dSMatt Fleming } 342