cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mem.c (3650B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include <linux/efi.h>
      4#include <asm/efi.h>
      5
      6#include "efistub.h"
      7
      8static inline bool mmap_has_headroom(unsigned long buff_size,
      9				     unsigned long map_size,
     10				     unsigned long desc_size)
     11{
     12	unsigned long slack = buff_size - map_size;
     13
     14	return slack / desc_size >= EFI_MMAP_NR_SLACK_SLOTS;
     15}
     16
     17/**
     18 * efi_get_memory_map() - get memory map
     19 * @map:	on return pointer to memory map
     20 *
     21 * Retrieve the UEFI memory map. The allocated memory leaves room for
     22 * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries.
     23 *
     24 * Return:	status code
     25 */
     26efi_status_t efi_get_memory_map(struct efi_boot_memmap *map)
     27{
     28	efi_memory_desc_t *m = NULL;
     29	efi_status_t status;
     30	unsigned long key;
     31	u32 desc_version;
     32
     33	*map->desc_size =	sizeof(*m);
     34	*map->map_size =	*map->desc_size * 32;
     35	*map->buff_size =	*map->map_size;
     36again:
     37	status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
     38			     *map->map_size, (void **)&m);
     39	if (status != EFI_SUCCESS)
     40		goto fail;
     41
     42	*map->desc_size = 0;
     43	key = 0;
     44	status = efi_bs_call(get_memory_map, map->map_size, m,
     45			     &key, map->desc_size, &desc_version);
     46	if (status == EFI_BUFFER_TOO_SMALL ||
     47	    !mmap_has_headroom(*map->buff_size, *map->map_size,
     48			       *map->desc_size)) {
     49		efi_bs_call(free_pool, m);
     50		/*
     51		 * Make sure there is some entries of headroom so that the
     52		 * buffer can be reused for a new map after allocations are
     53		 * no longer permitted.  Its unlikely that the map will grow to
     54		 * exceed this headroom once we are ready to trigger
     55		 * ExitBootServices()
     56		 */
     57		*map->map_size += *map->desc_size * EFI_MMAP_NR_SLACK_SLOTS;
     58		*map->buff_size = *map->map_size;
     59		goto again;
     60	}
     61
     62	if (status == EFI_SUCCESS) {
     63		if (map->key_ptr)
     64			*map->key_ptr = key;
     65		if (map->desc_ver)
     66			*map->desc_ver = desc_version;
     67	} else {
     68		efi_bs_call(free_pool, m);
     69	}
     70
     71fail:
     72	*map->map = m;
     73	return status;
     74}
     75
     76/**
     77 * efi_allocate_pages() - Allocate memory pages
     78 * @size:	minimum number of bytes to allocate
     79 * @addr:	On return the address of the first allocated page. The first
     80 *		allocated page has alignment EFI_ALLOC_ALIGN which is an
     81 *		architecture dependent multiple of the page size.
     82 * @max:	the address that the last allocated memory page shall not
     83 *		exceed
     84 *
     85 * Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according
     86 * to EFI_ALLOC_ALIGN. The last allocated page will not exceed the address
     87 * given by @max.
     88 *
     89 * Return:	status code
     90 */
     91efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
     92				unsigned long max)
     93{
     94	efi_physical_addr_t alloc_addr;
     95	efi_status_t status;
     96
     97	if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
     98		return efi_allocate_pages_aligned(size, addr, max,
     99						  EFI_ALLOC_ALIGN);
    100
    101	alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
    102	status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
    103			     EFI_LOADER_DATA, DIV_ROUND_UP(size, EFI_PAGE_SIZE),
    104			     &alloc_addr);
    105	if (status != EFI_SUCCESS)
    106		return status;
    107
    108	*addr = alloc_addr;
    109	return EFI_SUCCESS;
    110}
    111
    112/**
    113 * efi_free() - free memory pages
    114 * @size:	size of the memory area to free in bytes
    115 * @addr:	start of the memory area to free (must be EFI_PAGE_SIZE
    116 *		aligned)
    117 *
    118 * @size is rounded up to a multiple of EFI_ALLOC_ALIGN which is an
    119 * architecture specific multiple of EFI_PAGE_SIZE. So this function should
    120 * only be used to return pages allocated with efi_allocate_pages() or
    121 * efi_low_alloc_above().
    122 */
    123void efi_free(unsigned long size, unsigned long addr)
    124{
    125	unsigned long nr_pages;
    126
    127	if (!size)
    128		return;
    129
    130	nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
    131	efi_bs_call(free_pages, addr, nr_pages);
    132}