x86/traps: Refactor exc_general_protection()
[linux-block.git] / arch / x86 / coco / tdx / tdx.c
CommitLineData
59bd54a8
KS
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (C) 2021-2022 Intel Corporation */
3
4#undef pr_fmt
5#define pr_fmt(fmt) "tdx: " fmt
6
7#include <linux/cpufeature.h>
41394e33 8#include <asm/coco.h>
59bd54a8
KS
9#include <asm/tdx.h>
10
41394e33
KS
11/* TDX module Call Leaf IDs */
12#define TDX_GET_INFO 1
13
eb94f1b6
KS
14/*
15 * Wrapper for standard use of __tdx_hypercall with no output aside from
16 * return code.
17 */
18static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
19{
20 struct tdx_hypercall_args args = {
21 .r10 = TDX_HYPERCALL_STANDARD,
22 .r11 = fn,
23 .r12 = r12,
24 .r13 = r13,
25 .r14 = r14,
26 .r15 = r15,
27 };
28
29 return __tdx_hypercall(&args, 0);
30}
31
32/* Called from __tdx_hypercall() for unrecoverable failure */
33void __tdx_hypercall_failed(void)
34{
35 panic("TDVMCALL failed. TDX module bug?");
36}
37
41394e33
KS
38/*
39 * Used for TDX guests to make calls directly to the TD module. This
40 * should only be used for calls that have no legitimate reason to fail
41 * or where the kernel can not survive the call failing.
42 */
43static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
44 struct tdx_module_output *out)
45{
46 if (__tdx_module_call(fn, rcx, rdx, r8, r9, out))
47 panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
48}
49
50static u64 get_cc_mask(void)
51{
52 struct tdx_module_output out;
53 unsigned int gpa_width;
54
55 /*
56 * TDINFO TDX module call is used to get the TD execution environment
57 * information like GPA width, number of available vcpus, debug mode
58 * information, etc. More details about the ABI can be found in TDX
59 * Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
60 * [TDG.VP.INFO].
61 *
62 * The GPA width that comes out of this call is critical. TDX guests
63 * can not meaningfully run without it.
64 */
65 tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
66
67 gpa_width = out.rcx & GENMASK(5, 0);
68
69 /*
70 * The highest bit of a guest physical address is the "sharing" bit.
71 * Set it for shared pages and clear it for private pages.
72 */
73 return BIT_ULL(gpa_width - 1);
74}
75
59bd54a8
KS
76void __init tdx_early_init(void)
77{
41394e33 78 u64 cc_mask;
59bd54a8
KS
79 u32 eax, sig[3];
80
81 cpuid_count(TDX_CPUID_LEAF_ID, 0, &eax, &sig[0], &sig[2], &sig[1]);
82
83 if (memcmp(TDX_IDENT, sig, sizeof(sig)))
84 return;
85
86 setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);
87
41394e33
KS
88 cc_set_vendor(CC_VENDOR_INTEL);
89 cc_mask = get_cc_mask();
90 cc_set_mask(cc_mask);
91
65fab5bc
KS
92 /*
93 * All bits above GPA width are reserved and kernel treats shared bit
94 * as flag, not as part of physical address.
95 *
96 * Adjust physical mask to only cover valid GPA bits.
97 */
98 physical_mask &= cc_mask - 1;
99
59bd54a8
KS
100 pr_info("Guest detected\n");
101}