summaryrefslogtreecommitdiff
path: root/xen/include/asm-x86/hvm/vcpu.h
blob: 5ccd0758152ed9cb4b4947c921e6fa88815ec511 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
 * vcpu.h: HVM per vcpu definitions
 *
 * Copyright (c) 2005, International Business Machines Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __ASM_X86_HVM_VCPU_H__
#define __ASM_X86_HVM_VCPU_H__

#include <xen/tasklet.h>
#include <asm/hvm/vlapic.h>
#include <asm/hvm/vmx/vmcs.h>
#include <asm/hvm/vmx/vvmx.h>
#include <asm/hvm/svm/vmcb.h>
#include <asm/hvm/svm/nestedsvm.h>
#include <asm/mtrr.h>
#include <public/hvm/ioreq.h>

enum hvm_io_completion {
    HVMIO_no_completion,
    HVMIO_mmio_completion,
    HVMIO_pio_completion,
    HVMIO_realmode_completion
};

struct hvm_vcpu_asid {
    uint64_t generation;
    uint32_t asid;
};

/*
 * We may read or write up to m512 as a number of device-model
 * transactions.
 */
struct hvm_mmio_cache {
    unsigned long gla;
    unsigned int size;
    uint8_t dir;
    uint8_t buffer[64] __aligned(sizeof(long));
};

struct hvm_vcpu_io {
    /* I/O request in flight to device model. */
    enum hvm_io_completion io_completion;
    ioreq_t                io_req;

    /*
     * HVM emulation:
     *  Linear address @mmio_gla maps to MMIO physical frame @mmio_gpfn.
     *  The latter is known to be an MMIO frame (not RAM).
     *  This translation is only valid for accesses as per @mmio_access.
     */
    struct npfec        mmio_access;
    unsigned long       mmio_gla;
    unsigned long       mmio_gpfn;

    /*
     * We may need to handle up to 3 distinct memory accesses per
     * instruction.
     */
    struct hvm_mmio_cache mmio_cache[3];
    unsigned int mmio_cache_count;

    /* For retries we shouldn't re-fetch the instruction. */
    unsigned int mmio_insn_bytes;
    unsigned char mmio_insn[16];
    struct hvmemul_cache *cache;

    /*
     * For string instruction emulation we need to be able to signal a
     * necessary retry through other than function return codes.
     */
    bool_t mmio_retry;

    unsigned long msix_unmask_address;
    unsigned long msix_snoop_address;
    unsigned long msix_snoop_gpa;

    const struct g2m_ioport *g2m_ioport;
};

static inline bool hvm_ioreq_needs_completion(const ioreq_t *ioreq)
{
    return ioreq->state == STATE_IOREQ_READY &&
           !ioreq->data_is_ptr &&
           (ioreq->type != IOREQ_TYPE_PIO || ioreq->dir != IOREQ_WRITE);
}

struct nestedvcpu {
    bool_t nv_guestmode; /* vcpu in guestmode? */
    void *nv_vvmcx; /* l1 guest virtual VMCB/VMCS */
    void *nv_n1vmcx; /* VMCB/VMCS used to run l1 guest */
    void *nv_n2vmcx; /* shadow VMCB/VMCS used to run l2 guest */

    uint64_t nv_vvmcxaddr; /* l1 guest physical address of nv_vvmcx */
    paddr_t nv_n1vmcx_pa; /* host physical address of nv_n1vmcx */
    paddr_t nv_n2vmcx_pa; /* host physical address of nv_n2vmcx */

    /* SVM/VMX arch specific */
    union {
        struct nestedsvm nsvm;
        struct nestedvmx nvmx;
    } u;

    bool_t nv_flushp2m; /* True, when p2m table must be flushed */
    struct p2m_domain *nv_p2m; /* used p2m table for this vcpu */
    bool stale_np2m; /* True when p2m_base in VMCx02 is no longer valid */
    uint64_t np2m_generation;

    struct hvm_vcpu_asid nv_n2asid;

    bool_t nv_vmentry_pending;
    bool_t nv_vmexit_pending;
    bool_t nv_vmswitch_in_progress; /* true during vmentry/vmexit emulation */

    /* Does l1 guest intercept io ports 0x80 and/or 0xED ?
     * Useful to optimize io permission handling.
     */
    bool_t nv_ioport80;
    bool_t nv_ioportED;

    /* L2's control-resgister, just as the L2 sees them. */
    unsigned long       guest_cr[5];
};

#define vcpu_nestedhvm(v) ((v)->arch.hvm.nvcpu)

struct altp2mvcpu {
    /*
     * #VE information page.  This pointer being non-NULL indicates that a
     * VMCS's VIRT_EXCEPTION_INFO field is pointing to the page, and an extra
     * page reference is held.
     */
    struct page_info *veinfo_pg;
    uint16_t    p2midx;         /* alternate p2m index */
};

#define vcpu_altp2m(v) ((v)->arch.hvm.avcpu)

struct hvm_vcpu {
    /* Guest control-register and EFER values, just as the guest sees them. */
    unsigned long       guest_cr[5];
    unsigned long       guest_efer;

    /*
     * Processor-visible control-register values, while guest executes.
     *  CR0, CR4: Used as a cache of VMCS contents by VMX only.
     *  CR1, CR2: Never used (guest_cr[2] is always processor-visible CR2).
     *  CR3:      Always used and kept up to date by paging subsystem.
     */
    unsigned long       hw_cr[5];

    struct vlapic       vlapic;
    s64                 cache_tsc_offset;
    u64                 guest_time;

    /* Lock and list for virtual platform timers. */
    spinlock_t          tm_lock;
    struct list_head    tm_list;

    bool                flag_dr_dirty;
    bool                debug_state_latch;
    bool                single_step;
    struct {
        bool     enabled;
        uint16_t p2midx;
    } fast_single_step;

    /* (MFN) hypervisor page table */
    pagetable_t         monitor_table;

    struct hvm_vcpu_asid n1asid;

    u64                 msr_tsc_adjust;

    union {
        struct vmx_vcpu vmx;
        struct svm_vcpu svm;
    };

    struct tasklet      assert_evtchn_irq_tasklet;

    struct nestedvcpu   nvcpu;

    struct altp2mvcpu   avcpu;

    struct mtrr_state   mtrr;
    u64                 pat_cr;

    /* In mode delay_for_missed_ticks, VCPUs have differing guest times. */
    int64_t             stime_offset;

    u8                  evtchn_upcall_vector;

    /* Which cache mode is this VCPU in (CR0:CD/NW)? */
    u8                  cache_mode;

    struct hvm_vcpu_io  hvm_io;

    /* Pending hw/sw interrupt (.vector = -1 means nothing pending). */
    struct x86_event     inject_event;

    struct viridian_vcpu *viridian;
};

#endif /* __ASM_X86_HVM_VCPU_H__ */

/*
 * Local variables:
 * mode: C
 * c-file-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */