Lines Matching +full:secure +full:- +full:reg +full:- +full:access

1 // SPDX-License-Identifier: GPL-2.0-only
19 #include <linux/psp-sev.h>
21 #include <uapi/linux/sev-guest.h>
26 #include <asm/sev-internal.h>
27 #include <asm/insn-eval.h>
51 ctxt->fi.vector = X86_TRAP_PF; in vc_slow_virt_to_phys()
52 ctxt->fi.cr2 = vaddr; in vc_slow_virt_to_phys()
53 ctxt->fi.error_code = 0; in vc_slow_virt_to_phys()
55 if (user_mode(ctxt->regs)) in vc_slow_virt_to_phys()
56 ctxt->fi.error_code |= X86_PF_USER; in vc_slow_virt_to_phys()
77 if (user_mode(ctxt->regs)) { in vc_ioio_check()
78 struct thread_struct *t = &current->thread; in vc_ioio_check()
79 struct io_bitmap *iobm = t->io_bitmap; in vc_ioio_check()
86 if (test_bit(idx, iobm->bitmap)) in vc_ioio_check()
94 ctxt->fi.vector = X86_TRAP_GP; in vc_ioio_check()
95 ctxt->fi.error_code = 0; in vc_ioio_check()
102 long error_code = ctxt->fi.error_code; in vc_forward_exception()
103 int trapnr = ctxt->fi.vector; in vc_forward_exception()
105 ctxt->regs->orig_ax = ctxt->fi.error_code; in vc_forward_exception()
109 exc_general_protection(ctxt->regs, error_code); in vc_forward_exception()
112 exc_invalid_op(ctxt->regs); in vc_forward_exception()
115 write_cr2(ctxt->fi.cr2); in vc_forward_exception()
116 exc_page_fault(ctxt->regs, error_code); in vc_forward_exception()
119 exc_alignment_check(ctxt->regs, error_code); in vc_forward_exception()
122 pr_emerg("Unsupported exception in #VC instruction emulation - can't continue\n"); in vc_forward_exception()
130 return copy_from_kernel_nofault(buffer, (unsigned char *)ctxt->regs->ip, MAX_INSN_SIZE); in vc_fetch_insn_kernel()
138 insn_bytes = insn_fetch_from_user_inatomic(ctxt->regs, buffer); in __vc_decode_user_insn()
141 ctxt->fi.vector = X86_TRAP_PF; in __vc_decode_user_insn()
142 ctxt->fi.error_code = X86_PF_INSTR | X86_PF_USER; in __vc_decode_user_insn()
143 ctxt->fi.cr2 = ctxt->regs->ip; in __vc_decode_user_insn()
145 } else if (insn_bytes == -EINVAL) { in __vc_decode_user_insn()
147 ctxt->fi.vector = X86_TRAP_GP; in __vc_decode_user_insn()
148 ctxt->fi.error_code = 0; in __vc_decode_user_insn()
149 ctxt->fi.cr2 = 0; in __vc_decode_user_insn()
153 if (!insn_decode_from_regs(&ctxt->insn, ctxt->regs, buffer, insn_bytes)) in __vc_decode_user_insn()
156 if (ctxt->insn.immediate.got) in __vc_decode_user_insn()
169 ctxt->fi.vector = X86_TRAP_PF; in __vc_decode_kern_insn()
170 ctxt->fi.error_code = X86_PF_INSTR; in __vc_decode_kern_insn()
171 ctxt->fi.cr2 = ctxt->regs->ip; in __vc_decode_kern_insn()
175 ret = insn_decode(&ctxt->insn, buffer, MAX_INSN_SIZE, INSN_MODE_64); in __vc_decode_kern_insn()
190 if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm)) in vc_decode_insn()
205 * to report when the access failed. in vc_write_mem()
208 * allowed to sleep. The page-fault handler detects that it is running in vc_write_mem()
213 * The access can't be done via copy_to_user() here because in vc_write_mem()
214 * vc_write_mem() must not use string instructions to access unsafe in vc_write_mem()
217 * exception on whatever of them is the MMIO access. Using string in vc_write_mem()
265 if (user_mode(ctxt->regs)) in vc_write_mem()
268 ctxt->fi.vector = X86_TRAP_PF; in vc_write_mem()
269 ctxt->fi.error_code = error_code; in vc_write_mem()
270 ctxt->fi.cr2 = (unsigned long)dst; in vc_write_mem()
284 * to report when the access failed. in vc_read_mem()
287 * allowed to sleep. The page-fault handler detects that it is running in vc_read_mem()
292 * The access can't be done via copy_from_user() here because in vc_read_mem()
293 * vc_read_mem() must not use string instructions to access unsafe in vc_read_mem()
296 * exception on whatever of them is the MMIO access. Using string in vc_read_mem()
343 if (user_mode(ctxt->regs)) in vc_read_mem()
346 ctxt->fi.vector = X86_TRAP_PF; in vc_read_mem()
347 ctxt->fi.error_code = error_code; in vc_read_mem()
348 ctxt->fi.cr2 = (unsigned long)src; in vc_read_mem()
357 #include "vc-shared.c"
365 regs->ax = lower_32_bits(this_cpu_read(svsm_caa_pa)); in __vc_handle_msr_caa()
366 regs->dx = upper_32_bits(this_cpu_read(svsm_caa_pa)); in __vc_handle_msr_caa()
373 * executing with Secure TSC enabled, so special handling is required for
378 struct pt_regs *regs = ctxt->regs; in __vc_handle_secure_tsc_msrs()
383 * return undefined values, and GUEST_TSC_FREQ is read-only. Generate in __vc_handle_secure_tsc_msrs()
387 ctxt->fi.vector = X86_TRAP_GP; in __vc_handle_secure_tsc_msrs()
388 ctxt->fi.error_code = 0; in __vc_handle_secure_tsc_msrs()
393 * GUEST_TSC_FREQ read should not be intercepted when Secure TSC is in __vc_handle_secure_tsc_msrs()
396 if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) in __vc_handle_secure_tsc_msrs()
401 regs->ax = lower_32_bits(tsc); in __vc_handle_secure_tsc_msrs()
402 regs->dx = upper_32_bits(tsc); in __vc_handle_secure_tsc_msrs()
409 struct pt_regs *regs = ctxt->regs; in sev_es_ghcb_handle_msr()
412 switch (regs->cx) { in sev_es_ghcb_handle_msr()
423 * Secure AVIC is enabled. Terminate the Secure AVIC guest in sev_es_ghcb_handle_msr()
433 ghcb_set_rcx(ghcb, regs->cx); in sev_es_ghcb_handle_msr()
435 ghcb_set_rax(ghcb, regs->ax); in sev_es_ghcb_handle_msr()
436 ghcb_set_rdx(ghcb, regs->dx); in sev_es_ghcb_handle_msr()
442 regs->ax = ghcb->save.rax; in sev_es_ghcb_handle_msr()
443 regs->dx = ghcb->save.rdx; in sev_es_ghcb_handle_msr()
451 return sev_es_ghcb_handle_msr(ghcb, ctxt, ctxt->insn.opcode.bytes[1] == 0x30); in vc_handle_msr()
456 int trapnr = ctxt->fi.vector; in vc_early_forward_exception()
459 native_write_cr2(ctxt->fi.cr2); in vc_early_forward_exception()
461 ctxt->regs->orig_ax = ctxt->fi.error_code; in vc_early_forward_exception()
462 do_early_exception(ctxt->regs, trapnr); in vc_early_forward_exception()
470 reg_array = (long *)ctxt->regs; in vc_insn_get_rm()
471 offset = insn_get_modrm_rm_off(&ctxt->insn, ctxt->regs); in vc_insn_get_rm()
489 ref = insn_get_addr_ref(&ctxt->insn, ctxt->regs); in vc_do_mmio()
490 if (ref == (void __user *)-1L) in vc_do_mmio()
498 ctxt->fi.error_code |= X86_PF_WRITE; in vc_do_mmio()
514 * problem that it is not known whether the access to the source or the
518 * Instead of playing games with walking page-tables and trying to guess
527 * It will slow MOVS on MMIO down a lot, but in SEV-ES guests it is a
541 ds_base = insn_get_seg_base(ctxt->regs, INAT_SEG_REG_DS); in vc_handle_mmio_movs()
542 es_base = insn_get_seg_base(ctxt->regs, INAT_SEG_REG_ES); in vc_handle_mmio_movs()
544 if (ds_base == -1L || es_base == -1L) { in vc_handle_mmio_movs()
545 ctxt->fi.vector = X86_TRAP_GP; in vc_handle_mmio_movs()
546 ctxt->fi.error_code = 0; in vc_handle_mmio_movs()
550 src = ds_base + (unsigned char *)ctxt->regs->si; in vc_handle_mmio_movs()
551 dst = es_base + (unsigned char *)ctxt->regs->di; in vc_handle_mmio_movs()
561 if (ctxt->regs->flags & X86_EFLAGS_DF) in vc_handle_mmio_movs()
562 off = -bytes; in vc_handle_mmio_movs()
566 ctxt->regs->si += off; in vc_handle_mmio_movs()
567 ctxt->regs->di += off; in vc_handle_mmio_movs()
569 rep = insn_has_rep_prefix(&ctxt->insn); in vc_handle_mmio_movs()
571 ctxt->regs->cx -= 1; in vc_handle_mmio_movs()
573 if (!rep || ctxt->regs->cx == 0) in vc_handle_mmio_movs()
581 struct insn *insn = &ctxt->insn; in vc_handle_mmio()
593 reg_data = insn_get_modrm_reg_ptr(insn, ctxt->regs); in vc_handle_mmio()
598 if (user_mode(ctxt->regs)) in vc_handle_mmio()
603 memcpy(ghcb->shared_buffer, reg_data, bytes); in vc_handle_mmio()
607 memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes); in vc_handle_mmio()
615 /* Zero-extend for 32-bit operation */ in vc_handle_mmio()
619 memcpy(reg_data, ghcb->shared_buffer, bytes); in vc_handle_mmio()
627 memset(reg_data, 0, insn->opnd_bytes); in vc_handle_mmio()
628 memcpy(reg_data, ghcb->shared_buffer, bytes); in vc_handle_mmio()
636 u8 *val = (u8 *)ghcb->shared_buffer; in vc_handle_mmio()
640 u16 *val = (u16 *)ghcb->shared_buffer; in vc_handle_mmio()
646 memset(reg_data, sign_byte, insn->opnd_bytes); in vc_handle_mmio()
647 memcpy(reg_data, ghcb->shared_buffer, bytes); in vc_handle_mmio()
664 long val, *reg = vc_insn_get_rm(ctxt); in vc_handle_dr7_write() local
670 if (!reg) in vc_handle_dr7_write()
673 val = *reg; in vc_handle_dr7_write()
677 ctxt->fi.vector = X86_TRAP_GP; in vc_handle_dr7_write()
678 ctxt->fi.error_code = 0; in vc_handle_dr7_write()
685 /* Early non-zero writes to DR7 are not supported */ in vc_handle_dr7_write()
696 data->dr7 = val; in vc_handle_dr7_write()
705 long *reg = vc_insn_get_rm(ctxt); in vc_handle_dr7_read() local
710 if (!reg) in vc_handle_dr7_read()
714 *reg = data->dr7; in vc_handle_dr7_read()
716 *reg = DR7_RESET_VALUE; in vc_handle_dr7_read()
731 ghcb_set_rcx(ghcb, ctxt->regs->cx); in vc_handle_rdpmc()
740 ctxt->regs->ax = ghcb->save.rax; in vc_handle_rdpmc()
741 ctxt->regs->dx = ghcb->save.rdx; in vc_handle_rdpmc()
768 ghcb_set_rax(ghcb, ctxt->regs->ax); in vc_handle_vmmcall()
769 ghcb_set_cpl(ghcb, user_mode(ctxt->regs) ? 3 : 0); in vc_handle_vmmcall()
772 x86_platform.hyper.sev_es_hcall_prepare(ghcb, ctxt->regs); in vc_handle_vmmcall()
781 ctxt->regs->ax = ghcb->save.rax; in vc_handle_vmmcall()
784 * Call sev_es_hcall_finish() after regs->ax is already set. in vc_handle_vmmcall()
789 !x86_platform.hyper.sev_es_hcall_finish(ghcb, ctxt->regs)) in vc_handle_vmmcall()
803 ctxt->fi.vector = X86_TRAP_AC; in vc_handle_trap_ac()
804 ctxt->fi.error_code = 0; in vc_handle_trap_ac()
882 prev_sp = regs->sp; in vc_from_invalid_context()
910 /* Done - now check the result */ in vc_raw_handle_exception()
916 pr_err_ratelimited("Unsupported exit-code 0x%02lx in #VC exception (IP: 0x%lx)\n", in vc_raw_handle_exception()
917 error_code, regs->ip); in vc_raw_handle_exception()
921 pr_err_ratelimited("Failure in communication with VMM (exit-code 0x%02lx IP: 0x%lx)\n", in vc_raw_handle_exception()
922 error_code, regs->ip); in vc_raw_handle_exception()
926 pr_err_ratelimited("Failed to decode instruction (exit-code 0x%02lx IP: 0x%lx)\n", in vc_raw_handle_exception()
927 error_code, regs->ip); in vc_raw_handle_exception()
940 * failed - can't continue so print debug information in vc_raw_handle_exception()
997 /* If that fails and we get here - just panic */ in DEFINE_IDTENTRY_VC_KERNEL()
998 panic("Returned from Terminate-Request to Hypervisor\n"); in DEFINE_IDTENTRY_VC_KERNEL()
1024 * Do not kill the machine if user-space triggered the in DEFINE_IDTENTRY_VC_USER()
1025 * exception. Send SIGBUS instead and let user-space deal with in DEFINE_IDTENTRY_VC_USER()
1037 unsigned long exit_code = regs->orig_ax; in handle_vc_boot_ghcb()
1047 /* Done - now check the result */ in handle_vc_boot_ghcb()
1053 early_printk("PANIC: Unsupported exit-code 0x%02lx in early #VC exception (IP: 0x%lx)\n", in handle_vc_boot_ghcb()
1054 exit_code, regs->ip); in handle_vc_boot_ghcb()
1057 early_printk("PANIC: Failure in communication with VMM (exit-code 0x%02lx IP: 0x%lx)\n", in handle_vc_boot_ghcb()
1058 exit_code, regs->ip); in handle_vc_boot_ghcb()
1061 early_printk("PANIC: Failed to decode instruction (exit-code 0x%02lx IP: 0x%lx)\n", in handle_vc_boot_ghcb()
1062 exit_code, regs->ip); in handle_vc_boot_ghcb()