1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2021-2022 Intel Corporation */
5 #define pr_fmt(fmt) "tdx: " fmt
7 #include <linux/cpufeature.h>
8 #include <linux/export.h>
14 #include <asm/insn-eval.h>
15 #include <asm/pgtable.h>
21 /* Port I/O direction */
25 /* See Exit Qualification for I/O Instructions in VMX documentation */
26 #define VE_IS_IO_IN(e) ((e) & BIT(3))
27 #define VE_GET_IO_SIZE(e) (((e) & GENMASK(2, 0)) + 1)
28 #define VE_GET_PORT_NUM(e) ((e) >> 16)
29 #define VE_IS_IO_STRING(e) ((e) & BIT(4))
31 #define ATTR_DEBUG BIT(0)
32 #define ATTR_SEPT_VE_DISABLE BIT(28)
34 /* TDX Module call error codes */
35 #define TDCALL_RETURN_CODE(a) ((a) >> 32)
36 #define TDCALL_INVALID_OPERAND 0xc0000100
38 #define TDREPORT_SUBTYPE_0 0
40 /* Called from __tdx_hypercall() for unrecoverable failure */
41 noinstr
void __noreturn
__tdx_hypercall_failed(void)
43 instrumentation_begin();
44 panic("TDVMCALL failed. TDX module bug?");
47 #ifdef CONFIG_KVM_GUEST
48 long tdx_kvm_hypercall(unsigned int nr
, unsigned long p1
, unsigned long p2
,
49 unsigned long p3
, unsigned long p4
)
51 struct tdx_module_args args
= {
59 return __tdx_hypercall(&args
);
61 EXPORT_SYMBOL_GPL(tdx_kvm_hypercall
);
65 * Used for TDX guests to make calls directly to the TD module. This
66 * should only be used for calls that have no legitimate reason to fail
67 * or where the kernel can not survive the call failing.
69 static inline void tdcall(u64 fn
, struct tdx_module_args
*args
)
71 if (__tdcall_ret(fn
, args
))
72 panic("TDCALL %lld failed (Buggy TDX module!)\n", fn
);
76 * tdx_mcall_get_report0() - Wrapper to get TDREPORT0 (a.k.a. TDREPORT
77 * subtype 0) using TDG.MR.REPORT TDCALL.
78 * @reportdata: Address of the input buffer which contains user-defined
79 * REPORTDATA to be included into TDREPORT.
80 * @tdreport: Address of the output buffer to store TDREPORT.
82 * Refer to section titled "TDG.MR.REPORT leaf" in the TDX Module
83 * v1.0 specification for more information on TDG.MR.REPORT TDCALL.
84 * It is used in the TDX guest driver module to get the TDREPORT0.
86 * Return 0 on success, -EINVAL for invalid operands, or -EIO on
87 * other TDCALL failures.
89 int tdx_mcall_get_report0(u8
*reportdata
, u8
*tdreport
)
91 struct tdx_module_args args
= {
92 .rcx
= virt_to_phys(tdreport
),
93 .rdx
= virt_to_phys(reportdata
),
94 .r8
= TDREPORT_SUBTYPE_0
,
98 ret
= __tdcall(TDG_MR_REPORT
, &args
);
100 if (TDCALL_RETURN_CODE(ret
) == TDCALL_INVALID_OPERAND
)
107 EXPORT_SYMBOL_GPL(tdx_mcall_get_report0
);
110 * tdx_hcall_get_quote() - Wrapper to request TD Quote using GetQuote
112 * @buf: Address of the directly mapped shared kernel buffer which
113 * contains TDREPORT. The same buffer will be used by VMM to
114 * store the generated TD Quote output.
115 * @size: size of the tdquote buffer (4KB-aligned).
117 * Refer to section titled "TDG.VP.VMCALL<GetQuote>" in the TDX GHCI
118 * v1.0 specification for more information on GetQuote hypercall.
119 * It is used in the TDX guest driver module to get the TD Quote.
121 * Return 0 on success or error code on failure.
123 u64
tdx_hcall_get_quote(u8
*buf
, size_t size
)
125 /* Since buf is a shared memory, set the shared (decrypted) bits */
126 return _tdx_hypercall(TDVMCALL_GET_QUOTE
, cc_mkdec(virt_to_phys(buf
)), size
, 0, 0);
128 EXPORT_SYMBOL_GPL(tdx_hcall_get_quote
);
130 static void __noreturn
tdx_panic(const char *msg
)
132 struct tdx_module_args args
= {
133 .r10
= TDX_HYPERCALL_STANDARD
,
134 .r11
= TDVMCALL_REPORT_FATAL_ERROR
,
135 .r12
= 0, /* Error code: 0 is Panic */
138 /* Define register order according to the GHCI */
139 struct { u64 r14
, r15
, rbx
, rdi
, rsi
, r8
, r9
, rdx
; };
144 /* VMM assumes '\0' in byte 65, if the message took all 64 bytes */
145 strtomem_pad(message
.str
, msg
, '\0');
147 args
.r8
= message
.r8
;
148 args
.r9
= message
.r9
;
149 args
.r14
= message
.r14
;
150 args
.r15
= message
.r15
;
151 args
.rdi
= message
.rdi
;
152 args
.rsi
= message
.rsi
;
153 args
.rbx
= message
.rbx
;
154 args
.rdx
= message
.rdx
;
157 * This hypercall should never return and it is not safe
158 * to keep the guest running. Call it forever if it
162 __tdx_hypercall(&args
);
165 static void tdx_parse_tdinfo(u64
*cc_mask
)
167 struct tdx_module_args args
= {};
168 unsigned int gpa_width
;
172 * TDINFO TDX module call is used to get the TD execution environment
173 * information like GPA width, number of available vcpus, debug mode
174 * information, etc. More details about the ABI can be found in TDX
175 * Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
178 tdcall(TDG_VP_INFO
, &args
);
181 * The highest bit of a guest physical address is the "sharing" bit.
182 * Set it for shared pages and clear it for private pages.
184 * The GPA width that comes out of this call is critical. TDX guests
185 * can not meaningfully run without it.
187 gpa_width
= args
.rcx
& GENMASK(5, 0);
188 *cc_mask
= BIT_ULL(gpa_width
- 1);
191 * The kernel can not handle #VE's when accessing normal kernel
192 * memory. Ensure that no #VE will be delivered for accesses to
193 * TD-private memory. Only VMM-shared memory (MMIO) will #VE.
196 if (!(td_attr
& ATTR_SEPT_VE_DISABLE
)) {
197 const char *msg
= "TD misconfiguration: SEPT_VE_DISABLE attribute must be set.";
199 /* Relax SEPT_VE_DISABLE check for debug TD. */
200 if (td_attr
& ATTR_DEBUG
)
201 pr_warn("%s\n", msg
);
208 * The TDX module spec states that #VE may be injected for a limited set of
211 * - Emulation of the architectural #VE injection on EPT violation;
213 * - As a result of guest TD execution of a disallowed instruction,
214 * a disallowed MSR access, or CPUID virtualization;
216 * - A notification to the guest TD about anomalous behavior;
218 * The last one is opt-in and is not used by the kernel.
220 * The Intel Software Developer's Manual describes cases when instruction
221 * length field can be used in section "Information for VM Exits Due to
222 * Instruction Execution".
224 * For TDX, it ultimately means GET_VEINFO provides reliable instruction length
225 * information if #VE occurred due to instruction execution, but not for EPT
228 static int ve_instr_len(struct ve_info
*ve
)
230 switch (ve
->exit_reason
) {
231 case EXIT_REASON_HLT
:
232 case EXIT_REASON_MSR_READ
:
233 case EXIT_REASON_MSR_WRITE
:
234 case EXIT_REASON_CPUID
:
235 case EXIT_REASON_IO_INSTRUCTION
:
236 /* It is safe to use ve->instr_len for #VE due instructions */
237 return ve
->instr_len
;
238 case EXIT_REASON_EPT_VIOLATION
:
240 * For EPT violations, ve->insn_len is not defined. For those,
241 * the kernel must decode instructions manually and should not
242 * be using this function.
244 WARN_ONCE(1, "ve->instr_len is not defined for EPT violations");
247 WARN_ONCE(1, "Unexpected #VE-type: %lld\n", ve
->exit_reason
);
248 return ve
->instr_len
;
252 static u64 __cpuidle
__halt(const bool irq_disabled
)
254 struct tdx_module_args args
= {
255 .r10
= TDX_HYPERCALL_STANDARD
,
256 .r11
= hcall_func(EXIT_REASON_HLT
),
261 * Emulate HLT operation via hypercall. More info about ABI
262 * can be found in TDX Guest-Host-Communication Interface
263 * (GHCI), section 3.8 TDG.VP.VMCALL<Instruction.HLT>.
265 * The VMM uses the "IRQ disabled" param to understand IRQ
266 * enabled status (RFLAGS.IF) of the TD guest and to determine
267 * whether or not it should schedule the halted vCPU if an
268 * IRQ becomes pending. E.g. if IRQs are disabled, the VMM
269 * can keep the vCPU in virtual HLT, even if an IRQ is
270 * pending, without hanging/breaking the guest.
272 return __tdx_hypercall(&args
);
275 static int handle_halt(struct ve_info
*ve
)
277 const bool irq_disabled
= irqs_disabled();
279 if (__halt(irq_disabled
))
282 return ve_instr_len(ve
);
285 void __cpuidle
tdx_safe_halt(void)
287 const bool irq_disabled
= false;
290 * Use WARN_ONCE() to report the failure.
292 if (__halt(irq_disabled
))
293 WARN_ONCE(1, "HLT instruction emulation failed\n");
296 static int read_msr(struct pt_regs
*regs
, struct ve_info
*ve
)
298 struct tdx_module_args args
= {
299 .r10
= TDX_HYPERCALL_STANDARD
,
300 .r11
= hcall_func(EXIT_REASON_MSR_READ
),
305 * Emulate the MSR read via hypercall. More info about ABI
306 * can be found in TDX Guest-Host-Communication Interface
307 * (GHCI), section titled "TDG.VP.VMCALL<Instruction.RDMSR>".
309 if (__tdx_hypercall(&args
))
312 regs
->ax
= lower_32_bits(args
.r11
);
313 regs
->dx
= upper_32_bits(args
.r11
);
314 return ve_instr_len(ve
);
317 static int write_msr(struct pt_regs
*regs
, struct ve_info
*ve
)
319 struct tdx_module_args args
= {
320 .r10
= TDX_HYPERCALL_STANDARD
,
321 .r11
= hcall_func(EXIT_REASON_MSR_WRITE
),
323 .r13
= (u64
)regs
->dx
<< 32 | regs
->ax
,
327 * Emulate the MSR write via hypercall. More info about ABI
328 * can be found in TDX Guest-Host-Communication Interface
329 * (GHCI) section titled "TDG.VP.VMCALL<Instruction.WRMSR>".
331 if (__tdx_hypercall(&args
))
334 return ve_instr_len(ve
);
337 static int handle_cpuid(struct pt_regs
*regs
, struct ve_info
*ve
)
339 struct tdx_module_args args
= {
340 .r10
= TDX_HYPERCALL_STANDARD
,
341 .r11
= hcall_func(EXIT_REASON_CPUID
),
347 * Only allow VMM to control range reserved for hypervisor
350 * Return all-zeros for any CPUID outside the range. It matches CPU
351 * behaviour for non-supported leaf.
353 if (regs
->ax
< 0x40000000 || regs
->ax
> 0x4FFFFFFF) {
354 regs
->ax
= regs
->bx
= regs
->cx
= regs
->dx
= 0;
355 return ve_instr_len(ve
);
359 * Emulate the CPUID instruction via a hypercall. More info about
360 * ABI can be found in TDX Guest-Host-Communication Interface
361 * (GHCI), section titled "VP.VMCALL<Instruction.CPUID>".
363 if (__tdx_hypercall(&args
))
367 * As per TDX GHCI CPUID ABI, r12-r15 registers contain contents of
368 * EAX, EBX, ECX, EDX registers after the CPUID instruction execution.
369 * So copy the register contents back to pt_regs.
376 return ve_instr_len(ve
);
379 static bool mmio_read(int size
, unsigned long addr
, unsigned long *val
)
381 struct tdx_module_args args
= {
382 .r10
= TDX_HYPERCALL_STANDARD
,
383 .r11
= hcall_func(EXIT_REASON_EPT_VIOLATION
),
390 if (__tdx_hypercall(&args
))
397 static bool mmio_write(int size
, unsigned long addr
, unsigned long val
)
399 return !_tdx_hypercall(hcall_func(EXIT_REASON_EPT_VIOLATION
), size
,
400 EPT_WRITE
, addr
, val
);
403 static int handle_mmio(struct pt_regs
*regs
, struct ve_info
*ve
)
405 unsigned long *reg
, val
, vaddr
;
406 char buffer
[MAX_INSN_SIZE
];
407 enum insn_mmio_type mmio
;
408 struct insn insn
= {};
409 int size
, extend_size
;
412 /* Only in-kernel MMIO is supported */
413 if (WARN_ON_ONCE(user_mode(regs
)))
416 if (copy_from_kernel_nofault(buffer
, (void *)regs
->ip
, MAX_INSN_SIZE
))
419 if (insn_decode(&insn
, buffer
, MAX_INSN_SIZE
, INSN_MODE_64
))
422 mmio
= insn_decode_mmio(&insn
, &size
);
423 if (WARN_ON_ONCE(mmio
== INSN_MMIO_DECODE_FAILED
))
426 if (mmio
!= INSN_MMIO_WRITE_IMM
&& mmio
!= INSN_MMIO_MOVS
) {
427 reg
= insn_get_modrm_reg_ptr(&insn
, regs
);
433 * Reject EPT violation #VEs that split pages.
435 * MMIO accesses are supposed to be naturally aligned and therefore
436 * never cross page boundaries. Seeing split page accesses indicates
437 * a bug or a load_unaligned_zeropad() that stepped into an MMIO page.
439 * load_unaligned_zeropad() will recover using exception fixups.
441 vaddr
= (unsigned long)insn_get_addr_ref(&insn
, regs
);
442 if (vaddr
/ PAGE_SIZE
!= (vaddr
+ size
- 1) / PAGE_SIZE
)
445 /* Handle writes first */
447 case INSN_MMIO_WRITE
:
448 memcpy(&val
, reg
, size
);
449 if (!mmio_write(size
, ve
->gpa
, val
))
452 case INSN_MMIO_WRITE_IMM
:
453 val
= insn
.immediate
.value
;
454 if (!mmio_write(size
, ve
->gpa
, val
))
458 case INSN_MMIO_READ_ZERO_EXTEND
:
459 case INSN_MMIO_READ_SIGN_EXTEND
:
460 /* Reads are handled below */
463 case INSN_MMIO_DECODE_FAILED
:
465 * MMIO was accessed with an instruction that could not be
466 * decoded or handled properly. It was likely not using io.h
467 * helpers or accessed MMIO accidentally.
471 WARN_ONCE(1, "Unknown insn_decode_mmio() decode value?");
476 if (!mmio_read(size
, ve
->gpa
, &val
))
481 /* Zero-extend for 32-bit operation */
482 extend_size
= size
== 4 ? sizeof(*reg
) : 0;
484 case INSN_MMIO_READ_ZERO_EXTEND
:
485 /* Zero extend based on operand size */
486 extend_size
= insn
.opnd_bytes
;
488 case INSN_MMIO_READ_SIGN_EXTEND
:
489 /* Sign extend based on operand size */
490 extend_size
= insn
.opnd_bytes
;
491 if (size
== 1 && val
& BIT(7))
493 else if (size
> 1 && val
& BIT(15))
497 /* All other cases has to be covered with the first switch() */
503 memset(reg
, extend_val
, extend_size
);
504 memcpy(reg
, &val
, size
);
508 static bool handle_in(struct pt_regs
*regs
, int size
, int port
)
510 struct tdx_module_args args
= {
511 .r10
= TDX_HYPERCALL_STANDARD
,
512 .r11
= hcall_func(EXIT_REASON_IO_INSTRUCTION
),
517 u64 mask
= GENMASK(BITS_PER_BYTE
* size
, 0);
521 * Emulate the I/O read via hypercall. More info about ABI can be found
522 * in TDX Guest-Host-Communication Interface (GHCI) section titled
523 * "TDG.VP.VMCALL<Instruction.IO>".
525 success
= !__tdx_hypercall(&args
);
527 /* Update part of the register affected by the emulated instruction */
530 regs
->ax
|= args
.r11
& mask
;
535 static bool handle_out(struct pt_regs
*regs
, int size
, int port
)
537 u64 mask
= GENMASK(BITS_PER_BYTE
* size
, 0);
540 * Emulate the I/O write via hypercall. More info about ABI can be found
541 * in TDX Guest-Host-Communication Interface (GHCI) section titled
542 * "TDG.VP.VMCALL<Instruction.IO>".
544 return !_tdx_hypercall(hcall_func(EXIT_REASON_IO_INSTRUCTION
), size
,
545 PORT_WRITE
, port
, regs
->ax
& mask
);
549 * Emulate I/O using hypercall.
551 * Assumes the IO instruction was using ax, which is enforced
552 * by the standard io.h macros.
554 * Return True on success or False on failure.
556 static int handle_io(struct pt_regs
*regs
, struct ve_info
*ve
)
558 u32 exit_qual
= ve
->exit_qual
;
562 if (VE_IS_IO_STRING(exit_qual
))
565 in
= VE_IS_IO_IN(exit_qual
);
566 size
= VE_GET_IO_SIZE(exit_qual
);
567 port
= VE_GET_PORT_NUM(exit_qual
);
571 ret
= handle_in(regs
, size
, port
);
573 ret
= handle_out(regs
, size
, port
);
577 return ve_instr_len(ve
);
581 * Early #VE exception handler. Only handles a subset of port I/O.
582 * Intended only for earlyprintk. If failed, return false.
584 __init
bool tdx_early_handle_ve(struct pt_regs
*regs
)
589 tdx_get_ve_info(&ve
);
591 if (ve
.exit_reason
!= EXIT_REASON_IO_INSTRUCTION
)
594 insn_len
= handle_io(regs
, &ve
);
598 regs
->ip
+= insn_len
;
602 void tdx_get_ve_info(struct ve_info
*ve
)
604 struct tdx_module_args args
= {};
607 * Called during #VE handling to retrieve the #VE info from the
610 * This has to be called early in #VE handling. A "nested" #VE which
611 * occurs before this will raise a #DF and is not recoverable.
613 * The call retrieves the #VE info from the TDX module, which also
614 * clears the "#VE valid" flag. This must be done before anything else
615 * because any #VE that occurs while the valid flag is set will lead to
618 * Note, the TDX module treats virtual NMIs as inhibited if the #VE
619 * valid flag is set. It means that NMI=>#VE will not result in a #DF.
621 tdcall(TDG_VP_VEINFO_GET
, &args
);
623 /* Transfer the output parameters */
624 ve
->exit_reason
= args
.rcx
;
625 ve
->exit_qual
= args
.rdx
;
628 ve
->instr_len
= lower_32_bits(args
.r10
);
629 ve
->instr_info
= upper_32_bits(args
.r10
);
633 * Handle the user initiated #VE.
635 * On success, returns the number of bytes RIP should be incremented (>=0)
636 * or -errno on error.
638 static int virt_exception_user(struct pt_regs
*regs
, struct ve_info
*ve
)
640 switch (ve
->exit_reason
) {
641 case EXIT_REASON_CPUID
:
642 return handle_cpuid(regs
, ve
);
644 pr_warn("Unexpected #VE: %lld\n", ve
->exit_reason
);
649 static inline bool is_private_gpa(u64 gpa
)
651 return gpa
== cc_mkenc(gpa
);
655 * Handle the kernel #VE.
657 * On success, returns the number of bytes RIP should be incremented (>=0)
658 * or -errno on error.
660 static int virt_exception_kernel(struct pt_regs
*regs
, struct ve_info
*ve
)
662 switch (ve
->exit_reason
) {
663 case EXIT_REASON_HLT
:
664 return handle_halt(ve
);
665 case EXIT_REASON_MSR_READ
:
666 return read_msr(regs
, ve
);
667 case EXIT_REASON_MSR_WRITE
:
668 return write_msr(regs
, ve
);
669 case EXIT_REASON_CPUID
:
670 return handle_cpuid(regs
, ve
);
671 case EXIT_REASON_EPT_VIOLATION
:
672 if (is_private_gpa(ve
->gpa
))
673 panic("Unexpected EPT-violation on private memory.");
674 return handle_mmio(regs
, ve
);
675 case EXIT_REASON_IO_INSTRUCTION
:
676 return handle_io(regs
, ve
);
678 pr_warn("Unexpected #VE: %lld\n", ve
->exit_reason
);
683 bool tdx_handle_virt_exception(struct pt_regs
*regs
, struct ve_info
*ve
)
688 insn_len
= virt_exception_user(regs
, ve
);
690 insn_len
= virt_exception_kernel(regs
, ve
);
694 /* After successful #VE handling, move the IP */
695 regs
->ip
+= insn_len
;
700 static bool tdx_tlb_flush_required(bool private)
703 * TDX guest is responsible for flushing TLB on private->shared
704 * transition. VMM is responsible for flushing on shared->private.
706 * The VMM _can't_ flush private addresses as it can't generate PAs
707 * with the guest's HKID. Shared memory isn't subject to integrity
708 * checking, i.e. the VMM doesn't need to flush for its own protection.
710 * There's no need to flush when converting from shared to private,
711 * as flushing is the VMM's responsibility in this case, e.g. it must
712 * flush to avoid integrity failures in the face of a buggy or
718 static bool tdx_cache_flush_required(void)
721 * AMD SME/SEV can avoid cache flushing if HW enforces cache coherence.
722 * TDX doesn't have such capability.
724 * Flush cache unconditionally.
730 * Notify the VMM about page mapping conversion. More info about ABI
731 * can be found in TDX Guest-Host-Communication Interface (GHCI),
732 * section "TDG.VP.VMCALL<MapGPA>".
734 static bool tdx_map_gpa(phys_addr_t start
, phys_addr_t end
, bool enc
)
736 /* Retrying the hypercall a second time should succeed; use 3 just in case */
737 const int max_retries_per_page
= 3;
741 /* Set the shared (decrypted) bits: */
742 start
|= cc_mkdec(0);
746 while (retry_count
< max_retries_per_page
) {
747 struct tdx_module_args args
= {
748 .r10
= TDX_HYPERCALL_STANDARD
,
749 .r11
= TDVMCALL_MAP_GPA
,
751 .r13
= end
- start
};
754 u64 ret
= __tdx_hypercall(&args
);
756 if (ret
!= TDVMCALL_STATUS_RETRY
)
759 * The guest must retry the operation for the pages in the
760 * region starting at the GPA specified in R11. R11 comes
761 * from the untrusted VMM. Sanity check it.
763 map_fail_paddr
= args
.r11
;
764 if (map_fail_paddr
< start
|| map_fail_paddr
>= end
)
767 /* "Consume" a retry without forward progress */
768 if (map_fail_paddr
== start
) {
773 start
= map_fail_paddr
;
781 * Inform the VMM of the guest's intent for this physical page: shared with
782 * the VMM or private to the guest. The VMM is expected to change its mapping
783 * of the page in response.
785 static bool tdx_enc_status_changed(unsigned long vaddr
, int numpages
, bool enc
)
787 phys_addr_t start
= __pa(vaddr
);
788 phys_addr_t end
= __pa(vaddr
+ numpages
* PAGE_SIZE
);
790 if (!tdx_map_gpa(start
, end
, enc
))
793 /* shared->private conversion requires memory to be accepted before use */
795 return tdx_accept_memory(start
, end
);
800 static bool tdx_enc_status_change_prepare(unsigned long vaddr
, int numpages
,
804 * Only handle shared->private conversion here.
805 * See the comment in tdx_early_init().
808 return tdx_enc_status_changed(vaddr
, numpages
, enc
);
812 static bool tdx_enc_status_change_finish(unsigned long vaddr
, int numpages
,
816 * Only handle private->shared conversion here.
817 * See the comment in tdx_early_init().
820 return tdx_enc_status_changed(vaddr
, numpages
, enc
);
824 void __init
tdx_early_init(void)
826 struct tdx_module_args args
= {
827 .rdx
= TDCS_NOTIFY_ENABLES
,
833 cpuid_count(TDX_CPUID_LEAF_ID
, 0, &eax
, &sig
[0], &sig
[2], &sig
[1]);
835 if (memcmp(TDX_IDENT
, sig
, sizeof(sig
)))
838 setup_force_cpu_cap(X86_FEATURE_TDX_GUEST
);
840 /* TSC is the only reliable clock in TDX guest */
841 setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE
);
843 cc_vendor
= CC_VENDOR_INTEL
;
844 tdx_parse_tdinfo(&cc_mask
);
845 cc_set_mask(cc_mask
);
847 /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
848 tdcall(TDG_VM_WR
, &args
);
851 * All bits above GPA width are reserved and kernel treats shared bit
852 * as flag, not as part of physical address.
854 * Adjust physical mask to only cover valid GPA bits.
856 physical_mask
&= cc_mask
- 1;
859 * The kernel mapping should match the TDX metadata for the page.
860 * load_unaligned_zeropad() can touch memory *adjacent* to that which is
861 * owned by the caller and can catch even _momentary_ mismatches. Bad
862 * things happen on mismatch:
864 * - Private mapping => Shared Page == Guest shutdown
865 * - Shared mapping => Private Page == Recoverable #VE
867 * guest.enc_status_change_prepare() converts the page from
868 * shared=>private before the mapping becomes private.
870 * guest.enc_status_change_finish() converts the page from
871 * private=>shared after the mapping becomes private.
873 * In both cases there is a temporary shared mapping to a private page,
874 * which can result in a #VE. But, there is never a private mapping to
877 x86_platform
.guest
.enc_status_change_prepare
= tdx_enc_status_change_prepare
;
878 x86_platform
.guest
.enc_status_change_finish
= tdx_enc_status_change_finish
;
880 x86_platform
.guest
.enc_cache_flush_required
= tdx_cache_flush_required
;
881 x86_platform
.guest
.enc_tlb_flush_required
= tdx_tlb_flush_required
;
884 * TDX intercepts the RDMSR to read the X2APIC ID in the parallel
885 * bringup low level code. That raises #VE which cannot be handled
888 * Intel-TDX has a secure RDMSR hypercall, but that needs to be
889 * implemented seperately in the low level startup ASM code.
890 * Until that is in place, disable parallel bringup for TDX.
892 x86_cpuinit
.parallel_bringup
= false;
894 pr_info("Guest detected\n");