Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/pv/emul-inv-op.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * arch/x86/pv/emul-inv-op.c
3
 *
4
 * Emulate invalid op for PV guests
5
 *
6
 * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include <xen/errno.h>
23
#include <xen/event.h>
24
#include <xen/guest_access.h>
25
#include <xen/iocap.h>
26
#include <xen/spinlock.h>
27
#include <xen/trace.h>
28
29
#include <asm/apic.h>
30
#include <asm/debugreg.h>
31
#include <asm/hpet.h>
32
#include <asm/hypercall.h>
33
#include <asm/mc146818rtc.h>
34
#include <asm/p2m.h>
35
#include <asm/pv/traps.h>
36
#include <asm/shared.h>
37
#include <asm/traps.h>
38
#include <asm/x86_emulate.h>
39
40
#include <xsm/xsm.h>
41
42
#include "emulate.h"
43
44
static int emulate_invalid_rdtscp(struct cpu_user_regs *regs)
45
0
{
46
0
    char opcode[3];
47
0
    unsigned long eip, rc;
48
0
    struct vcpu *v = current;
49
0
50
0
    eip = regs->rip;
51
0
    if ( (rc = copy_from_user(opcode, (char *)eip, sizeof(opcode))) != 0 )
52
0
    {
53
0
        pv_inject_page_fault(0, eip + sizeof(opcode) - rc);
54
0
        return EXCRET_fault_fixed;
55
0
    }
56
0
    if ( memcmp(opcode, "\xf\x1\xf9", sizeof(opcode)) )
57
0
        return 0;
58
0
    eip += sizeof(opcode);
59
0
    pv_soft_rdtsc(v, regs, 1);
60
0
    pv_emul_instruction_done(regs, eip);
61
0
    return EXCRET_fault_fixed;
62
0
}
63
64
static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
65
0
{
66
0
    char sig[5], instr[2];
67
0
    unsigned long eip, rc;
68
0
    struct cpuid_leaf res;
69
0
    const struct msr_vcpu_policy *vp = current->arch.msr;
70
0
71
0
    eip = regs->rip;
72
0
73
0
    /* Check for forced emulation signature: ud2 ; .ascii "xen". */
74
0
    if ( (rc = copy_from_user(sig, (char *)eip, sizeof(sig))) != 0 )
75
0
    {
76
0
        pv_inject_page_fault(0, eip + sizeof(sig) - rc);
77
0
        return EXCRET_fault_fixed;
78
0
    }
79
0
    if ( memcmp(sig, "\xf\xbxen", sizeof(sig)) )
80
0
        return 0;
81
0
    eip += sizeof(sig);
82
0
83
0
    /* We only emulate CPUID. */
84
0
    if ( ( rc = copy_from_user(instr, (char *)eip, sizeof(instr))) != 0 )
85
0
    {
86
0
        pv_inject_page_fault(0, eip + sizeof(instr) - rc);
87
0
        return EXCRET_fault_fixed;
88
0
    }
89
0
    if ( memcmp(instr, "\xf\xa2", sizeof(instr)) )
90
0
        return 0;
91
0
92
0
    /* If cpuid faulting is enabled and CPL>0 inject a #GP in place of #UD. */
93
0
    if ( vp->misc_features_enables.cpuid_faulting &&
94
0
         !guest_kernel_mode(current, regs) )
95
0
    {
96
0
        regs->rip = eip;
97
0
        pv_inject_hw_exception(TRAP_gp_fault, regs->error_code);
98
0
        return EXCRET_fault_fixed;
99
0
    }
100
0
101
0
    eip += sizeof(instr);
102
0
103
0
    guest_cpuid(current, regs->eax, regs->ecx, &res);
104
0
105
0
    regs->rax = res.a;
106
0
    regs->rbx = res.b;
107
0
    regs->rcx = res.c;
108
0
    regs->rdx = res.d;
109
0
110
0
    pv_emul_instruction_done(regs, eip);
111
0
112
0
    trace_trap_one_addr(TRC_PV_FORCED_INVALID_OP, regs->rip);
113
0
114
0
    return EXCRET_fault_fixed;
115
0
}
116
117
bool pv_emulate_invalid_op(struct cpu_user_regs *regs)
118
0
{
119
0
    return !emulate_invalid_rdtscp(regs) && !emulate_forced_invalid_op(regs);
120
0
}
121
122
/*
123
 * Local variables:
124
 * mode: C
125
 * c-file-style: "BSD"
126
 * c-basic-offset: 4
127
 * tab-width: 4
128
 * indent-tabs-mode: nil
129
 * End:
130
 */