Lines Matching full:ve

129 	 * The kernel can not handle #VE's when accessing normal kernel  in tdx_parse_tdinfo()
130 * memory. Ensure that no #VE will be delivered for accesses to in tdx_parse_tdinfo()
131 * TD-private memory. Only VMM-shared memory (MMIO) will #VE. in tdx_parse_tdinfo()
139 * The TDX module spec states that #VE may be injected for a limited set of
142 * - Emulation of the architectural #VE injection on EPT violation;
156 * information if #VE occurred due to instruction execution, but not for EPT
159 static int ve_instr_len(struct ve_info *ve) in ve_instr_len() argument
161 switch (ve->exit_reason) { in ve_instr_len()
167 /* It is safe to use ve->instr_len for #VE due instructions */ in ve_instr_len()
168 return ve->instr_len; in ve_instr_len()
171 * For EPT violations, ve->insn_len is not defined. For those, in ve_instr_len()
175 WARN_ONCE(1, "ve->instr_len is not defined for EPT violations"); in ve_instr_len()
178 WARN_ONCE(1, "Unexpected #VE-type: %lld\n", ve->exit_reason); in ve_instr_len()
179 return ve->instr_len; in ve_instr_len()
206 static int handle_halt(struct ve_info *ve) in handle_halt() argument
219 return ve_instr_len(ve); in handle_halt()
239 static int read_msr(struct pt_regs *regs, struct ve_info *ve) in read_msr() argument
257 return ve_instr_len(ve); in read_msr()
260 static int write_msr(struct pt_regs *regs, struct ve_info *ve) in write_msr() argument
277 return ve_instr_len(ve); in write_msr()
280 static int handle_cpuid(struct pt_regs *regs, struct ve_info *ve) in handle_cpuid() argument
298 return ve_instr_len(ve); in handle_cpuid()
319 return ve_instr_len(ve); in handle_cpuid()
345 static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) in handle_mmio() argument
391 if (!mmio_write(size, ve->gpa, val)) in handle_mmio()
396 if (!mmio_write(size, ve->gpa, val)) in handle_mmio()
418 if (!mmio_read(size, ve->gpa, &val)) in handle_mmio()
498 static int handle_io(struct pt_regs *regs, struct ve_info *ve) in handle_io() argument
500 u32 exit_qual = ve->exit_qual; in handle_io()
519 return ve_instr_len(ve); in handle_io()
523 * Early #VE exception handler. Only handles a subset of port I/O.
528 struct ve_info ve; in tdx_early_handle_ve() local
531 tdx_get_ve_info(&ve); in tdx_early_handle_ve()
533 if (ve.exit_reason != EXIT_REASON_IO_INSTRUCTION) in tdx_early_handle_ve()
536 insn_len = handle_io(regs, &ve); in tdx_early_handle_ve()
544 void tdx_get_ve_info(struct ve_info *ve) in tdx_get_ve_info() argument
549 * Called during #VE handling to retrieve the #VE info from the in tdx_get_ve_info()
552 * This has to be called early in #VE handling. A "nested" #VE which in tdx_get_ve_info()
555 * The call retrieves the #VE info from the TDX module, which also in tdx_get_ve_info()
556 * clears the "#VE valid" flag. This must be done before anything else in tdx_get_ve_info()
557 * because any #VE that occurs while the valid flag is set will lead to in tdx_get_ve_info()
560 * Note, the TDX module treats virtual NMIs as inhibited if the #VE in tdx_get_ve_info()
561 * valid flag is set. It means that NMI=>#VE will not result in a #DF. in tdx_get_ve_info()
566 ve->exit_reason = out.rcx; in tdx_get_ve_info()
567 ve->exit_qual = out.rdx; in tdx_get_ve_info()
568 ve->gla = out.r8; in tdx_get_ve_info()
569 ve->gpa = out.r9; in tdx_get_ve_info()
570 ve->instr_len = lower_32_bits(out.r10); in tdx_get_ve_info()
571 ve->instr_info = upper_32_bits(out.r10); in tdx_get_ve_info()
575 * Handle the user initiated #VE.
580 static int virt_exception_user(struct pt_regs *regs, struct ve_info *ve) in virt_exception_user() argument
582 switch (ve->exit_reason) { in virt_exception_user()
584 return handle_cpuid(regs, ve); in virt_exception_user()
586 pr_warn("Unexpected #VE: %lld\n", ve->exit_reason); in virt_exception_user()
592 * Handle the kernel #VE.
597 static int virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve) in virt_exception_kernel() argument
599 switch (ve->exit_reason) { in virt_exception_kernel()
601 return handle_halt(ve); in virt_exception_kernel()
603 return read_msr(regs, ve); in virt_exception_kernel()
605 return write_msr(regs, ve); in virt_exception_kernel()
607 return handle_cpuid(regs, ve); in virt_exception_kernel()
609 return handle_mmio(regs, ve); in virt_exception_kernel()
611 return handle_io(regs, ve); in virt_exception_kernel()
613 pr_warn("Unexpected #VE: %lld\n", ve->exit_reason); in virt_exception_kernel()
618 bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve) in tdx_handle_virt_exception() argument
623 insn_len = virt_exception_user(regs, ve); in tdx_handle_virt_exception()
625 insn_len = virt_exception_kernel(regs, ve); in tdx_handle_virt_exception()
629 /* After successful #VE handling, move the IP */ in tdx_handle_virt_exception()