1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | |
3 | #include "error.h" |
4 | #include "misc.h" |
5 | #include "tdx.h" |
6 | #include "sev.h" |
7 | #include <asm/shared/tdx.h> |
8 | |
9 | /* |
10 | * accept_memory() and process_unaccepted_memory() called from EFI stub which |
11 | * runs before decompresser and its early_tdx_detect(). |
12 | * |
13 | * Enumerate TDX directly from the early users. |
14 | */ |
15 | static bool early_is_tdx_guest(void) |
16 | { |
17 | static bool once; |
18 | static bool is_tdx; |
19 | |
20 | if (!IS_ENABLED(CONFIG_INTEL_TDX_GUEST)) |
21 | return false; |
22 | |
23 | if (!once) { |
24 | u32 eax, sig[3]; |
25 | |
26 | cpuid_count(TDX_CPUID_LEAF_ID, count: 0, eax: &eax, |
27 | ebx: &sig[0], ecx: &sig[2], edx: &sig[1]); |
28 | is_tdx = !memcmp(TDX_IDENT, sig, sizeof(sig)); |
29 | once = true; |
30 | } |
31 | |
32 | return is_tdx; |
33 | } |
34 | |
35 | void arch_accept_memory(phys_addr_t start, phys_addr_t end) |
36 | { |
37 | /* Platform-specific memory-acceptance call goes here */ |
38 | if (early_is_tdx_guest()) { |
39 | if (!tdx_accept_memory(start, end)) |
40 | panic(fmt: "TDX: Failed to accept memory\n" ); |
41 | } else if (sev_snp_enabled()) { |
42 | snp_accept_memory(start, end); |
43 | } else { |
44 | error(m: "Cannot accept memory: unknown platform\n" ); |
45 | } |
46 | } |
47 | |
48 | bool init_unaccepted_memory(void) |
49 | { |
50 | guid_t guid = LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID; |
51 | struct efi_unaccepted_memory *table; |
52 | unsigned long cfg_table_pa; |
53 | unsigned int cfg_table_len; |
54 | enum efi_type et; |
55 | int ret; |
56 | |
57 | et = efi_get_type(bp: boot_params_ptr); |
58 | if (et == EFI_TYPE_NONE) |
59 | return false; |
60 | |
61 | ret = efi_get_conf_table(bp: boot_params_ptr, cfg_tbl_pa: &cfg_table_pa, cfg_tbl_len: &cfg_table_len); |
62 | if (ret) { |
63 | warn(m: "EFI config table not found." ); |
64 | return false; |
65 | } |
66 | |
67 | table = (void *)efi_find_vendor_table(bp: boot_params_ptr, cfg_tbl_pa: cfg_table_pa, |
68 | cfg_tbl_len: cfg_table_len, guid); |
69 | if (!table) |
70 | return false; |
71 | |
72 | if (table->version != 1) |
73 | error(m: "Unknown version of unaccepted memory table\n" ); |
74 | |
75 | /* |
76 | * In many cases unaccepted_table is already set by EFI stub, but it |
77 | * has to be initialized again to cover cases when the table is not |
78 | * allocated by EFI stub or EFI stub copied the kernel image with |
79 | * efi_relocate_kernel() before the variable is set. |
80 | * |
81 | * It must be initialized before the first usage of accept_memory(). |
82 | */ |
83 | unaccepted_table = table; |
84 | |
85 | return true; |
86 | } |
87 | |