1*d9ffe524SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0 2*d9ffe524SArd Biesheuvel /* 3*d9ffe524SArd Biesheuvel * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org> 4*d9ffe524SArd Biesheuvel * 5*d9ffe524SArd Biesheuvel * This file implements the EFI boot stub for the arm64 kernel. 6*d9ffe524SArd Biesheuvel * Adapted from ARM version by Mark Salter <msalter@redhat.com> 7*d9ffe524SArd Biesheuvel */ 8*d9ffe524SArd Biesheuvel 9*d9ffe524SArd Biesheuvel 10*d9ffe524SArd Biesheuvel #include <linux/efi.h> 11*d9ffe524SArd Biesheuvel #include <asm/efi.h> 12*d9ffe524SArd Biesheuvel #include <asm/memory.h> 13*d9ffe524SArd Biesheuvel #include <asm/sysreg.h> 14*d9ffe524SArd Biesheuvel 15*d9ffe524SArd Biesheuvel #include "efistub.h" 16*d9ffe524SArd Biesheuvel 1797712289SArd Biesheuvel static bool system_needs_vamap(void) 1897712289SArd Biesheuvel { 1997712289SArd Biesheuvel const u8 *type1_family = efi_get_smbios_string(1, family); 2097712289SArd Biesheuvel 2197712289SArd Biesheuvel /* 2297712289SArd Biesheuvel * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap() 2397712289SArd Biesheuvel * has not been called prior. 2497712289SArd Biesheuvel */ 2597712289SArd Biesheuvel if (!type1_family || strcmp(type1_family, "Altra")) 2697712289SArd Biesheuvel return false; 2797712289SArd Biesheuvel 2897712289SArd Biesheuvel efi_warn("Working around broken SetVirtualAddressMap()\n"); 2997712289SArd Biesheuvel return true; 3097712289SArd Biesheuvel } 3197712289SArd Biesheuvel 32*d9ffe524SArd Biesheuvel efi_status_t check_platform_features(void) 33*d9ffe524SArd Biesheuvel { 34*d9ffe524SArd Biesheuvel u64 tg; 35*d9ffe524SArd Biesheuvel 36*d9ffe524SArd Biesheuvel /* 37*d9ffe524SArd Biesheuvel * If we have 48 bits of VA space for TTBR0 mappings, we can map the 38*d9ffe524SArd Biesheuvel * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is 39*d9ffe524SArd Biesheuvel * unnecessary. 40*d9ffe524SArd Biesheuvel */ 4197712289SArd Biesheuvel if (VA_BITS_MIN >= 48 && !system_needs_vamap()) 42*d9ffe524SArd Biesheuvel efi_novamap = true; 43*d9ffe524SArd Biesheuvel 44*d9ffe524SArd Biesheuvel /* UEFI mandates support for 4 KB granularity, no need to check */ 45*d9ffe524SArd Biesheuvel if (IS_ENABLED(CONFIG_ARM64_4K_PAGES)) 46*d9ffe524SArd Biesheuvel return EFI_SUCCESS; 47*d9ffe524SArd Biesheuvel 48*d9ffe524SArd Biesheuvel tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf; 49*d9ffe524SArd Biesheuvel if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) { 50*d9ffe524SArd Biesheuvel if (IS_ENABLED(CONFIG_ARM64_64K_PAGES)) 51*d9ffe524SArd Biesheuvel efi_err("This 64 KB granular kernel is not supported by your CPU\n"); 52*d9ffe524SArd Biesheuvel else 53*d9ffe524SArd Biesheuvel efi_err("This 16 KB granular kernel is not supported by your CPU\n"); 54*d9ffe524SArd Biesheuvel return EFI_UNSUPPORTED; 55*d9ffe524SArd Biesheuvel } 56*d9ffe524SArd Biesheuvel return EFI_SUCCESS; 57*d9ffe524SArd Biesheuvel } 58*d9ffe524SArd Biesheuvel 59*d9ffe524SArd Biesheuvel void efi_cache_sync_image(unsigned long image_base, 60*d9ffe524SArd Biesheuvel unsigned long alloc_size, 61*d9ffe524SArd Biesheuvel unsigned long code_size) 62*d9ffe524SArd Biesheuvel { 63*d9ffe524SArd Biesheuvel u32 ctr = read_cpuid_effective_cachetype(); 64*d9ffe524SArd Biesheuvel u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr, 65*d9ffe524SArd Biesheuvel CTR_EL0_DminLine_SHIFT); 66*d9ffe524SArd Biesheuvel 67*d9ffe524SArd Biesheuvel do { 68*d9ffe524SArd Biesheuvel asm("dc civac, %0" :: "r"(image_base)); 69*d9ffe524SArd Biesheuvel image_base += lsize; 70*d9ffe524SArd Biesheuvel alloc_size -= lsize; 71*d9ffe524SArd Biesheuvel } while (alloc_size >= lsize); 72*d9ffe524SArd Biesheuvel 73*d9ffe524SArd Biesheuvel asm("ic ialluis"); 74*d9ffe524SArd Biesheuvel dsb(ish); 75*d9ffe524SArd Biesheuvel isb(); 76*d9ffe524SArd Biesheuvel } 77