Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/hvm/svm/svmdebug.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * svmdebug.c: debug functions
3
 * Copyright (c) 2011, Advanced Micro Devices, Inc.
4
 *
5
 * This program is free software; you can redistribute it and/or modify it
6
 * under the terms and conditions of the GNU General Public License,
7
 * version 2, as published by the Free Software Foundation.
8
 *
9
 * This program is distributed in the hope it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12
 * more details.
13
 *
14
 * You should have received a copy of the GNU General Public License along with
15
 * this program; If not, see <http://www.gnu.org/licenses/>.
16
 *
17
 */
18
19
#include <xen/sched.h>
20
#include <asm/processor.h>
21
#include <asm/msr-index.h>
22
#include <asm/hvm/svm/svmdebug.h>
23
24
static void svm_dump_sel(const char *name, const struct segment_register *s)
25
0
{
26
0
    printk("%s: %04x %04x %08x %016"PRIx64"\n",
27
0
           name, s->sel, s->attr, s->limit, s->base);
28
0
}
29
30
void svm_vmcb_dump(const char *from, const struct vmcb_struct *vmcb)
31
0
{
32
0
    printk("Dumping guest's current state at %s...\n", from);
33
0
    printk("Size of VMCB = %zu, paddr = %"PRIpaddr", vaddr = %p\n",
34
0
           sizeof(struct vmcb_struct), virt_to_maddr(vmcb), vmcb);
35
0
36
0
    printk("cr_intercepts = %#x dr_intercepts = %#x "
37
0
           "exception_intercepts = %#x\n",
38
0
           vmcb_get_cr_intercepts(vmcb), vmcb_get_dr_intercepts(vmcb),
39
0
           vmcb_get_exception_intercepts(vmcb));
40
0
    printk("general1_intercepts = %#x general2_intercepts = %#x\n",
41
0
           vmcb_get_general1_intercepts(vmcb), vmcb_get_general2_intercepts(vmcb));
42
0
    printk("iopm_base_pa = %#"PRIx64" msrpm_base_pa = %#"PRIx64" tsc_offset = %#"PRIx64"\n",
43
0
           vmcb_get_iopm_base_pa(vmcb), vmcb_get_msrpm_base_pa(vmcb),
44
0
           vmcb_get_tsc_offset(vmcb));
45
0
    printk("tlb_control = %#x vintr = %#"PRIx64" interrupt_shadow = %#"PRIx64"\n",
46
0
           vmcb->tlb_control, vmcb_get_vintr(vmcb).bytes,
47
0
           vmcb->interrupt_shadow);
48
0
    printk("eventinj %016"PRIx64", valid? %d, ec? %d, type %u, vector %#x\n",
49
0
           vmcb->eventinj.bytes, vmcb->eventinj.fields.v,
50
0
           vmcb->eventinj.fields.ev, vmcb->eventinj.fields.type,
51
0
           vmcb->eventinj.fields.vector);
52
0
    printk("exitcode = %#"PRIx64" exitintinfo = %#"PRIx64"\n",
53
0
           vmcb->exitcode, vmcb->exitintinfo.bytes);
54
0
    printk("exitinfo1 = %#"PRIx64" exitinfo2 = %#"PRIx64"\n",
55
0
           vmcb->exitinfo1, vmcb->exitinfo2);
56
0
    printk("np_enable = %#"PRIx64" guest_asid = %#x\n",
57
0
           vmcb_get_np_enable(vmcb), vmcb_get_guest_asid(vmcb));
58
0
    printk("cpl = %d efer = %#"PRIx64" star = %#"PRIx64" lstar = %#"PRIx64"\n",
59
0
           vmcb_get_cpl(vmcb), vmcb_get_efer(vmcb), vmcb->star, vmcb->lstar);
60
0
    printk("CR0 = 0x%016"PRIx64" CR2 = 0x%016"PRIx64"\n",
61
0
           vmcb_get_cr0(vmcb), vmcb_get_cr2(vmcb));
62
0
    printk("CR3 = 0x%016"PRIx64" CR4 = 0x%016"PRIx64"\n",
63
0
           vmcb_get_cr3(vmcb), vmcb_get_cr4(vmcb));
64
0
    printk("RSP = 0x%016"PRIx64"  RIP = 0x%016"PRIx64"\n",
65
0
           vmcb->rsp, vmcb->rip);
66
0
    printk("RAX = 0x%016"PRIx64"  RFLAGS=0x%016"PRIx64"\n",
67
0
           vmcb->rax, vmcb->rflags);
68
0
    printk("DR6 = 0x%016"PRIx64", DR7 = 0x%016"PRIx64"\n",
69
0
           vmcb_get_dr6(vmcb), vmcb_get_dr7(vmcb));
70
0
    printk("CSTAR = 0x%016"PRIx64" SFMask = 0x%016"PRIx64"\n",
71
0
           vmcb->cstar, vmcb->sfmask);
72
0
    printk("KernGSBase = 0x%016"PRIx64" PAT = 0x%016"PRIx64"\n",
73
0
           vmcb->kerngsbase, vmcb_get_g_pat(vmcb));
74
0
    printk("H_CR3 = 0x%016"PRIx64" CleanBits = %#x\n",
75
0
           vmcb_get_h_cr3(vmcb), vmcb->cleanbits.bytes);
76
0
77
0
    /* print out all the selectors */
78
0
    printk("       sel attr  limit   base\n");
79
0
    svm_dump_sel("  CS", &vmcb->cs);
80
0
    svm_dump_sel("  DS", &vmcb->ds);
81
0
    svm_dump_sel("  SS", &vmcb->ss);
82
0
    svm_dump_sel("  ES", &vmcb->es);
83
0
    svm_dump_sel("  FS", &vmcb->fs);
84
0
    svm_dump_sel("  GS", &vmcb->gs);
85
0
    svm_dump_sel("GDTR", &vmcb->gdtr);
86
0
    svm_dump_sel("LDTR", &vmcb->ldtr);
87
0
    svm_dump_sel("IDTR", &vmcb->idtr);
88
0
    svm_dump_sel("  TR", &vmcb->tr);
89
0
}
90
91
bool svm_vmcb_isvalid(const char *from, const struct vmcb_struct *vmcb,
92
                      const struct vcpu *v, bool verbose)
93
0
{
94
0
    bool ret = false; /* ok */
95
0
    unsigned long cr0 = vmcb_get_cr0(vmcb);
96
0
    unsigned long cr3 = vmcb_get_cr3(vmcb);
97
0
    unsigned long cr4 = vmcb_get_cr4(vmcb);
98
0
    uint64_t efer = vmcb_get_efer(vmcb);
99
0
100
0
#define PRINTF(fmt, args...) do { \
101
0
    if ( !verbose ) return true; \
102
0
    ret = true; \
103
0
    printk(XENLOG_GUEST "%pv[%s]: " fmt, v, from, ## args); \
104
0
} while (0)
105
0
106
0
    if ( !(efer & EFER_SVME) )
107
0
        PRINTF("EFER: SVME bit not set (%#"PRIx64")\n", efer);
108
0
109
0
    if ( !(cr0 & X86_CR0_CD) && (cr0 & X86_CR0_NW) )
110
0
        PRINTF("CR0: CD bit is zero and NW bit set (%#"PRIx64")\n", cr0);
111
0
112
0
    if ( cr0 >> 32 )
113
0
        PRINTF("CR0: bits [63:32] are not zero (%#"PRIx64")\n", cr0);
114
0
115
0
    if ( (cr0 & X86_CR0_PG) &&
116
0
         ((cr3 & 7) ||
117
0
          ((!(cr4 & X86_CR4_PAE) || (efer & EFER_LMA)) && (cr3 & 0xfe0)) ||
118
0
          ((efer & EFER_LMA) &&
119
0
           (cr3 >> v->domain->arch.cpuid->extd.maxphysaddr))) )
120
0
        PRINTF("CR3: MBZ bits are set (%#"PRIx64")\n", cr3);
121
0
122
0
    if ( cr4 & ~hvm_cr4_guest_valid_bits(v, false) )
123
0
        PRINTF("CR4: invalid bits are set (%#"PRIx64", valid: %#"PRIx64")\n",
124
0
               cr4, hvm_cr4_guest_valid_bits(v, false));
125
0
126
0
    if ( vmcb_get_dr6(vmcb) >> 32 )
127
0
        PRINTF("DR6: bits [63:32] are not zero (%#"PRIx64")\n",
128
0
               vmcb_get_dr6(vmcb));
129
0
130
0
    if ( vmcb_get_dr7(vmcb) >> 32 )
131
0
        PRINTF("DR7: bits [63:32] are not zero (%#"PRIx64")\n",
132
0
               vmcb_get_dr7(vmcb));
133
0
134
0
    if ( efer & ~(EFER_SCE | EFER_LME | EFER_LMA | EFER_NX | EFER_SVME |
135
0
                  EFER_LMSLE | EFER_FFXSE) )
136
0
        PRINTF("EFER: undefined bits are not zero (%#"PRIx64")\n", efer);
137
0
138
0
    if ( hvm_efer_valid(v, efer, -1) )
139
0
        PRINTF("EFER: %s (%"PRIx64")\n", hvm_efer_valid(v, efer, -1), efer);
140
0
141
0
    if ( (efer & EFER_LME) && (cr0 & X86_CR0_PG) )
142
0
    {
143
0
        if ( !(cr4 & X86_CR4_PAE) )
144
0
            PRINTF("EFER_LME and CR0.PG are both set and CR4.PAE is zero\n");
145
0
        if ( !(cr0 & X86_CR0_PE) )
146
0
            PRINTF("EFER_LME and CR0.PG are both set and CR0.PE is zero\n");
147
0
    }
148
0
149
0
    if ( (efer & EFER_LME) && (cr0 & X86_CR0_PG) && (cr4 & X86_CR4_PAE) &&
150
0
         vmcb->cs.l && vmcb->cs.db )
151
0
        PRINTF("EFER_LME, CR0.PG, CR4.PAE, CS.L and CS.D are all non-zero\n");
152
0
153
0
    if ( !(vmcb_get_general2_intercepts(vmcb) & GENERAL2_INTERCEPT_VMRUN) )
154
0
        PRINTF("GENERAL2_INTERCEPT: VMRUN intercept bit is clear (%#"PRIx32")\n",
155
0
               vmcb_get_general2_intercepts(vmcb));
156
0
157
0
    if ( vmcb->eventinj.fields.resvd1 )
158
0
        PRINTF("eventinj: MBZ bits are set (%#"PRIx64")\n",
159
0
               vmcb->eventinj.bytes);
160
0
161
0
#undef PRINTF
162
0
    return ret;
163
0
}
164
165
/*
166
 * Local variables:
167
 * mode: C
168
 * c-file-style: "BSD"
169
 * c-basic-offset: 4
170
 * tab-width: 4
171
 * indent-tabs-mode: nil
172
 * End:
173
 */