x86_fake_mem.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright(c) 2019 Intel Corporation. All rights reserved. */
  3. #include <linux/efi.h>
  4. #include <asm/e820/api.h>
  5. #include "fake_mem.h"
  6. void __init efi_fake_memmap_early(void)
  7. {
  8. int i;
  9. /*
  10. * The late efi_fake_mem() call can handle all requests if
  11. * EFI_MEMORY_SP support is disabled.
  12. */
  13. if (!efi_soft_reserve_enabled())
  14. return;
  15. if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
  16. return;
  17. /*
  18. * Given that efi_fake_memmap() needs to perform memblock
  19. * allocations it needs to run after e820__memblock_setup().
  20. * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given
  21. * address range that potentially needs to mark the memory as
  22. * reserved prior to e820__memblock_setup(). Update e820
  23. * directly if EFI_MEMORY_SP is specified for an
  24. * EFI_CONVENTIONAL_MEMORY descriptor.
  25. */
  26. for (i = 0; i < nr_fake_mem; i++) {
  27. struct efi_mem_range *mem = &efi_fake_mems[i];
  28. efi_memory_desc_t *md;
  29. u64 m_start, m_end;
  30. if ((mem->attribute & EFI_MEMORY_SP) == 0)
  31. continue;
  32. m_start = mem->range.start;
  33. m_end = mem->range.end;
  34. for_each_efi_memory_desc(md) {
  35. u64 start, end, size;
  36. if (md->type != EFI_CONVENTIONAL_MEMORY)
  37. continue;
  38. start = md->phys_addr;
  39. end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
  40. if (m_start <= end && m_end >= start)
  41. /* fake range overlaps descriptor */;
  42. else
  43. continue;
  44. /*
  45. * Trim the boundary of the e820 update to the
  46. * descriptor in case the fake range overlaps
  47. * !EFI_CONVENTIONAL_MEMORY
  48. */
  49. start = max(start, m_start);
  50. end = min(end, m_end);
  51. size = end - start + 1;
  52. if (end <= start)
  53. continue;
  54. /*
  55. * Ensure each efi_fake_mem instance results in
  56. * a unique e820 resource
  57. */
  58. e820__range_remove(start, size, E820_TYPE_RAM, 1);
  59. e820__range_add(start, size, E820_TYPE_SOFT_RESERVED);
  60. e820__update_table(e820_table);
  61. }
  62. }
  63. }