1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /******************************************************************************
3 * arch/x86/pv/emul-inv-op.c
4 *
5 * Emulate invalid op for PV guests
6 *
7 * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser
8 */
9
10 #include <asm/pv/trace.h>
11
12 #include "emulate.h"
13
emulate_forced_invalid_op(struct cpu_user_regs * regs)14 static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
15 {
16 char sig[5], instr[2];
17 unsigned long eip, rc;
18 struct cpuid_leaf res;
19 const struct vcpu_msrs *msrs = current->arch.msrs;
20
21 eip = regs->rip;
22
23 /* Check for forced emulation signature: ud2 ; .ascii "xen". */
24 if ( (rc = copy_from_guest_pv(sig, (char __user *)eip, sizeof(sig))) != 0 )
25 {
26 pv_inject_page_fault(0, eip + sizeof(sig) - rc);
27 return EXCRET_fault_fixed;
28 }
29 if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
30 return 0;
31 eip += sizeof(sig);
32
33 /* We only emulate CPUID. */
34 if ( (rc = copy_from_guest_pv(instr, (char __user *)eip,
35 sizeof(instr))) != 0 )
36 {
37 pv_inject_page_fault(0, eip + sizeof(instr) - rc);
38 return EXCRET_fault_fixed;
39 }
40 if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
41 return 0;
42
43 /* If cpuid faulting is enabled and CPL>0 inject a #GP in place of #UD. */
44 if ( msrs->misc_features_enables.cpuid_faulting &&
45 !guest_kernel_mode(current, regs) )
46 {
47 regs->rip = eip;
48 pv_inject_hw_exception(X86_EXC_GP, regs->error_code);
49 return EXCRET_fault_fixed;
50 }
51
52 eip += sizeof(instr);
53
54 guest_cpuid(current, regs->eax, regs->ecx, &res);
55
56 regs->rax = res.a;
57 regs->rbx = res.b;
58 regs->rcx = res.c;
59 regs->rdx = res.d;
60
61 pv_emul_instruction_done(regs, eip);
62
63 trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->rip);
64
65 return EXCRET_fault_fixed;
66 }
67
pv_emulate_invalid_op(struct cpu_user_regs * regs)68 bool pv_emulate_invalid_op(struct cpu_user_regs *regs)
69 {
70 return !emulate_forced_invalid_op(regs);
71 }
72
73 /*
74 * Local variables:
75 * mode: C
76 * c-file-style: "BSD"
77 * c-basic-offset: 4
78 * tab-width: 4
79 * indent-tabs-mode: nil
80 * End:
81 */
82