arm64.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
  4. *
  5. * This file implements the EFI boot stub for the arm64 kernel.
  6. * Adapted from ARM version by Mark Salter <msalter@redhat.com>
  7. */
  8. #include <linux/efi.h>
  9. #include <asm/efi.h>
  10. #include <asm/image.h>
  11. #include <asm/memory.h>
  12. #include <asm/sysreg.h>
  13. #include "efistub.h"
  14. static bool system_needs_vamap(void)
  15. {
  16. const struct efi_smbios_type4_record *record;
  17. const u32 __aligned(1) *socid;
  18. const u8 *version;
  19. /*
  20. * Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
  21. * SetVirtualAddressMap() has not been called prior. Most Altra systems
  22. * can be identified by the SMCCC soc ID, which is conveniently exposed
  23. * via the type 4 SMBIOS records. Otherwise, test the processor version
  24. * field. eMAG systems all appear to have the processor version field
  25. * set to "eMAG".
  26. */
  27. record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
  28. if (!record)
  29. return false;
  30. socid = (u32 *)record->processor_id;
  31. switch (*socid & 0xffff000f) {
  32. static char const altra[] = "Ampere(TM) Altra(TM) Processor";
  33. static char const emag[] = "eMAG";
  34. default:
  35. version = efi_get_smbios_string(record, processor_version);
  36. if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
  37. strncmp(version, emag, sizeof(emag) - 1)))
  38. break;
  39. fallthrough;
  40. case 0x0a160001: // Altra
  41. case 0x0a160002: // Altra Max
  42. efi_warn("Working around broken SetVirtualAddressMap()\n");
  43. return true;
  44. }
  45. return false;
  46. }
  47. efi_status_t check_platform_features(void)
  48. {
  49. u64 tg;
  50. /*
  51. * If we have 48 bits of VA space for TTBR0 mappings, we can map the
  52. * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
  53. * unnecessary.
  54. */
  55. if (VA_BITS_MIN >= 48 && !system_needs_vamap())
  56. efi_novamap = true;
  57. /* UEFI mandates support for 4 KB granularity, no need to check */
  58. if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
  59. return EFI_SUCCESS;
  60. tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
  61. if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
  62. if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
  63. efi_err("This 64 KB granular kernel is not supported by your CPU\n");
  64. else
  65. efi_err("This 16 KB granular kernel is not supported by your CPU\n");
  66. return EFI_UNSUPPORTED;
  67. }
  68. return EFI_SUCCESS;
  69. }
  70. #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
  71. #define DCTYPE "civac"
  72. #else
  73. #define DCTYPE "cvau"
  74. #endif
  75. u32 __weak code_size;
  76. void efi_cache_sync_image(unsigned long image_base,
  77. unsigned long alloc_size)
  78. {
  79. u32 ctr = read_cpuid_effective_cachetype();
  80. u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
  81. CTR_EL0_DminLine_SHIFT);
  82. /* only perform the cache maintenance if needed for I/D coherency */
  83. if (!(ctr & BIT(CTR_EL0_IDC_SHIFT))) {
  84. unsigned long base = image_base;
  85. unsigned long size = code_size;
  86. do {
  87. asm("dc " DCTYPE ", %0" :: "r"(base));
  88. base += lsize;
  89. size -= lsize;
  90. } while (size >= lsize);
  91. }
  92. asm("ic ialluis");
  93. dsb(ish);
  94. isb();
  95. efi_remap_image(image_base, alloc_size, code_size);
  96. }
  97. unsigned long __weak primary_entry_offset(void)
  98. {
  99. /*
  100. * By default, we can invoke the kernel via the branch instruction in
  101. * the image header, so offset #0. This will be overridden by the EFI
  102. * stub build that is linked into the core kernel, as in that case, the
  103. * image header may not have been loaded into memory, or may be mapped
  104. * with non-executable permissions.
  105. */
  106. return 0;
  107. }
  108. void __noreturn efi_enter_kernel(unsigned long entrypoint,
  109. unsigned long fdt_addr,
  110. unsigned long fdt_size)
  111. {
  112. void (* __noreturn enter_kernel)(u64, u64, u64, u64);
  113. enter_kernel = (void *)entrypoint + primary_entry_offset();
  114. enter_kernel(fdt_addr, 0, 0, 0);
  115. }