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 
9 
10 #include <linux/efi.h>
11 #include <asm/efi.h>
12 #include <asm/memory.h>
13 #include <asm/sysreg.h>
14 
15 #include "efistub.h"
16 
17 efi_status_t check_platform_features(void)
18 {
19 	u64 tg;
20 
21 	/*
22 	 * If we have 48 bits of VA space for TTBR0 mappings, we can map the
23 	 * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
24 	 * unnecessary.
25 	 */
26 	if (VA_BITS_MIN >= 48)
27 		efi_novamap = true;
28 
29 	/* UEFI mandates support for 4 KB granularity, no need to check */
30 	if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
31 		return EFI_SUCCESS;
32 
33 	tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
34 	if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
35 		if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
36 			efi_err("This 64 KB granular kernel is not supported by your CPU\n");
37 		else
38 			efi_err("This 16 KB granular kernel is not supported by your CPU\n");
39 		return EFI_UNSUPPORTED;
40 	}
41 	return EFI_SUCCESS;
42 }
43 
44 void efi_cache_sync_image(unsigned long image_base,
45 			  unsigned long alloc_size,
46 			  unsigned long code_size)
47 {
48 	u32 ctr = read_cpuid_effective_cachetype();
49 	u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
50 						CTR_EL0_DminLine_SHIFT);
51 
52 	do {
53 		asm("dc civac, %0" :: "r"(image_base));
54 		image_base += lsize;
55 		alloc_size -= lsize;
56 	} while (alloc_size >= lsize);
57 
58 	asm("ic ialluis");
59 	dsb(ish);
60 	isb();
61 }
62