summaryrefslogtreecommitdiffstats
path: root/src/VBox/VMM/include/GIMKvmInternal.h
blob: 4d68b1d281f582684b2c875bf90c897b07a105b3 (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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/* $Id: GIMKvmInternal.h $ */
/** @file
 * GIM - KVM, Internal header file.
 */

/*
 * Copyright (C) 2015-2020 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef VMM_INCLUDED_SRC_include_GIMKvmInternal_h
#define VMM_INCLUDED_SRC_include_GIMKvmInternal_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <VBox/vmm/gim.h>
#include <VBox/vmm/cpum.h>


/** @name KVM base features.
 * @{
 */
/** Old, deprecated clock source available. */
#define GIM_KVM_BASE_FEAT_CLOCK_OLD                RT_BIT(0)
/** No need for artifical delays on IO operations. */
#define GIM_KVM_BASE_FEAT_NOP_IO_DELAY             RT_BIT(1)
/** MMU op supported (deprecated, unused). */
#define GIM_KVM_BASE_FEAT_MMU_OP                   RT_BIT(2)
/** Clock source available. */
#define GIM_KVM_BASE_FEAT_CLOCK                    RT_BIT(3)
/** Asynchronous page faults supported. */
#define GIM_KVM_BASE_FEAT_ASYNC_PF                 RT_BIT(4)
/** Steal time (VCPU not executing guest code time in ns) available. */
#define GIM_KVM_BASE_FEAT_STEAL_TIME               RT_BIT(5)
/** Paravirtualized EOI (end-of-interrupt) supported. */
#define GIM_KVM_BASE_FEAT_PV_EOI                   RT_BIT(6)
/** Paravirtualized spinlock (unhalting VCPU) supported. */
#define GIM_KVM_BASE_FEAT_PV_UNHALT                RT_BIT(7)
/** The TSC is stable (fixed rate, monotonic). */
#define GIM_KVM_BASE_FEAT_TSC_STABLE               RT_BIT(24)
/** @}  */


/** @name KVM MSRs.
 * @{
 */
/** Start of range 0. */
#define MSR_GIM_KVM_RANGE0_FIRST                   UINT32_C(0x11)
/** Old, deprecated wall clock. */
#define MSR_GIM_KVM_WALL_CLOCK_OLD                 UINT32_C(0x11)
/** Old, deprecated System time. */
#define MSR_GIM_KVM_SYSTEM_TIME_OLD                UINT32_C(0x12)
/** End of range 0. */
#define MSR_GIM_KVM_RANGE0_LAST                    MSR_GIM_KVM_SYSTEM_TIME_OLD

/** Start of range 1. */
#define MSR_GIM_KVM_RANGE1_FIRST                   UINT32_C(0x4b564d00)
/** Wall clock. */
#define MSR_GIM_KVM_WALL_CLOCK                     UINT32_C(0x4b564d00)
/** System time. */
#define MSR_GIM_KVM_SYSTEM_TIME                    UINT32_C(0x4b564d01)
/** Asynchronous page fault. */
#define MSR_GIM_KVM_ASYNC_PF                       UINT32_C(0x4b564d02)
/** Steal time. */
#define MSR_GIM_KVM_STEAL_TIME                     UINT32_C(0x4b564d03)
/** Paravirtualized EOI (end-of-interrupt). */
#define MSR_GIM_KVM_EOI                            UINT32_C(0x4b564d04)
/** End of range 1. */
#define MSR_GIM_KVM_RANGE1_LAST                    MSR_GIM_KVM_EOI

AssertCompile(MSR_GIM_KVM_RANGE0_FIRST <= MSR_GIM_KVM_RANGE0_LAST);
AssertCompile(MSR_GIM_KVM_RANGE1_FIRST <= MSR_GIM_KVM_RANGE1_LAST);
/** @} */

/** KVM page size.  */
#define GIM_KVM_PAGE_SIZE                          0x1000

/**
 * MMIO2 region indices.
 */
/** The system time page(s) region. */
#define GIM_KVM_SYSTEM_TIME_PAGE_REGION_IDX        UINT8_C(0)
/** The steal time page(s) region. */
#define GIM_KVM_STEAL_TIME_PAGE_REGION_IDX         UINT8_C(1)
/** The maximum region index (must be <= UINT8_MAX). */
#define GIM_KVM_REGION_IDX_MAX                     GIM_KVM_STEAL_TIME_PAGE_REGION_IDX

/**
 * KVM system-time structure (GIM_KVM_SYSTEM_TIME_FLAGS_XXX) flags.
 * See "Documentation/virtual/kvm/api.txt".
 */
/** The TSC is stable (monotonic). */
#define GIM_KVM_SYSTEM_TIME_FLAGS_TSC_STABLE       RT_BIT(0)
/** The guest VCPU has been paused by the hypervisor. */
#define GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED     RT_BIT(1)
/** */

/** @name KVM MSR - System time (MSR_GIM_KVM_SYSTEM_TIME and
 * MSR_GIM_KVM_SYSTEM_TIME_OLD).
 * @{
 */
/** The system-time enable bit. */
#define MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT        RT_BIT_64(0)
/** Whether the system-time struct. is enabled or not. */
#define MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(a)     RT_BOOL((a) & MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT)
/** Guest-physical address of the system-time struct. */
#define MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(a)      ((a) & ~MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT)
/** @} */

/** @name KVM MSR - Wall clock (MSR_GIM_KVM_WALL_CLOCK and
 * MSR_GIM_KVM_WALL_CLOCK_OLD).
 * @{
 */
/** Guest-physical address of the wall-clock struct. */
#define MSR_GIM_KVM_WALL_CLOCK_GUEST_GPA(a)        (a)
/** @} */


/** @name KVM Hypercall operations.
 *  @{ */
#define KVM_HYPERCALL_OP_VAPIC_POLL_IRQ            1
#define KVM_HYPERCALL_OP_MMU                       2
#define KVM_HYPERCALL_OP_FEATURES                  3
#define KVM_HYPERCALL_OP_KICK_CPU                  5
/** @} */

/** @name KVM Hypercall return values.
 *  @{ */
/* Return values for hypercalls */
#define KVM_HYPERCALL_RET_SUCCESS                  0
#define KVM_HYPERCALL_RET_ENOSYS                   (uint64_t)(-1000)
#define KVM_HYPERCALL_RET_EFAULT                   (uint64_t)(-14)
#define KVM_HYPERCALL_RET_E2BIG                    (uint64_t)(-7)
#define KVM_HYPERCALL_RET_EPERM                    (uint64_t)(-1)
/** @} */

/**
 * KVM per-VCPU system-time structure.
 */
typedef struct GIMKVMSYSTEMTIME
{
    /** Version (sequence number). */
    uint32_t        u32Version;
    /** Alignment padding. */
    uint32_t        u32Padding0;
    /** TSC time stamp.  */
    uint64_t        u64Tsc;
    /** System time in nanoseconds. */
    uint64_t        u64NanoTS;
    /** TSC to system time scale factor. */
    uint32_t        u32TscScale;
    /** TSC frequency shift.  */
    int8_t          i8TscShift;
    /** Clock source (GIM_KVM_SYSTEM_TIME_FLAGS_XXX) flags. */
    uint8_t         fFlags;
    /** Alignment padding. */
    uint8_t         abPadding0[2];
} GIMKVMSYSTEMTIME;
/** Pointer to KVM system-time struct. */
typedef GIMKVMSYSTEMTIME *PGIMKVMSYSTEMTIME;
/** Pointer to a const KVM system-time struct. */
typedef GIMKVMSYSTEMTIME const *PCGIMKVMSYSTEMTIME;
AssertCompileSize(GIMKVMSYSTEMTIME, 32);


/**
 * KVM per-VM wall-clock structure.
 */
typedef struct GIMKVMWALLCLOCK
{
    /** Version (sequence number). */
    uint32_t        u32Version;
    /** Number of seconds since boot. */
    uint32_t        u32Sec;
    /** Number of nanoseconds since boot. */
    uint32_t        u32Nano;
} GIMKVMWALLCLOCK;
/** Pointer to KVM wall-clock struct. */
typedef GIMKVMWALLCLOCK *PGIMKVMWALLCLOCK;
/** Pointer to a const KVM wall-clock struct. */
typedef GIMKVMWALLCLOCK const *PCGIMKVMWALLCLOCK;
AssertCompileSize(GIMKVMWALLCLOCK, 12);


/**
 * GIM KVM VM instance data.
 * Changes to this must checked against the padding of the gim union in VM!
 */
typedef struct GIMKVM
{
    /** Wall-clock MSR. */
    uint64_t                    u64WallClockMsr;
    /**  CPUID features: Basic. */
    uint32_t                    uBaseFeat;
    /** Whether GIM needs to trap \#UD exceptions. */
    bool                        fTrapXcptUD;
    /** Disassembler opcode of hypercall instruction native for this host CPU. */
    uint16_t                    uOpcodeNative;
    /** Native hypercall opcode bytes.  Use for replacing. */
    uint8_t                     abOpcodeNative[3];
    /** Alignment padding. */
    uint8_t                     abPadding[5];
    /** The TSC frequency (in HZ) reported to the guest. */
    uint64_t                    cTscTicksPerSecond;
} GIMKVM;
/** Pointer to per-VM GIM KVM instance data. */
typedef GIMKVM *PGIMKVM;
/** Pointer to const per-VM GIM KVM instance data. */
typedef GIMKVM const *PCGIMKVM;

/**
 * GIM KVMV VCPU instance data.
 * Changes to this must checked against the padding of the gim union in VMCPU!
 */
typedef struct GIMKVMCPU
{
    /** System-time MSR. */
    uint64_t                    u64SystemTimeMsr;
    /** The guest-physical address of the system-time struct. */
    RTGCPHYS                    GCPhysSystemTime;
    /** The version (sequence number) of the system-time struct. */
    uint32_t                    u32SystemTimeVersion;
    /** The guest TSC value while enabling the system-time MSR. */
    uint64_t                    uTsc;
    /** The guest virtual time while enabling the system-time MSR. */
    uint64_t                    uVirtNanoTS;
    /** The flags of the system-time struct. */
    uint8_t                     fSystemTimeFlags;
} GIMKVMCPU;
/** Pointer to per-VCPU GIM KVM instance data. */
typedef GIMKVMCPU *PGIMKVMCPU;
/** Pointer to const per-VCPU GIM KVM instance data. */
typedef GIMKVMCPU const *PCGIMKVMCPU;


RT_C_DECLS_BEGIN

#ifdef IN_RING3
VMMR3_INT_DECL(int)             gimR3KvmInit(PVM pVM);
VMMR3_INT_DECL(int)             gimR3KvmInitCompleted(PVM pVM);
VMMR3_INT_DECL(int)             gimR3KvmTerm(PVM pVM);
VMMR3_INT_DECL(void)            gimR3KvmRelocate(PVM pVM, RTGCINTPTR offDelta);
VMMR3_INT_DECL(void)            gimR3KvmReset(PVM pVM);
VMMR3_INT_DECL(int)             gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM);
VMMR3_INT_DECL(int)             gimR3KvmLoad(PVM pVM, PSSMHANDLE pSSM);

VMMR3_INT_DECL(int)             gimR3KvmDisableSystemTime(PVM pVM);
VMMR3_INT_DECL(int)             gimR3KvmEnableSystemTime(PVM pVM, PVMCPU pVCpu, uint64_t uMsrSystemTime);
VMMR3_INT_DECL(int)             gimR3KvmEnableWallClock(PVM pVM, RTGCPHYS GCPhysSysTime);
#endif /* IN_RING3 */

VMM_INT_DECL(bool)              gimKvmIsParavirtTscEnabled(PVMCC pVM);
VMM_INT_DECL(bool)              gimKvmAreHypercallsEnabled(PVMCPU pVCpu);
VMM_INT_DECL(VBOXSTRICTRC)      gimKvmHypercall(PVMCPUCC pVCpu, PCPUMCTX pCtx);
VMM_INT_DECL(VBOXSTRICTRC)      gimKvmReadMsr(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
VMM_INT_DECL(VBOXSTRICTRC)      gimKvmWriteMsr(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue);
VMM_INT_DECL(bool)              gimKvmShouldTrapXcptUD(PVM pVM);
VMM_INT_DECL(VBOXSTRICTRC)      gimKvmXcptUD(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis, uint8_t *pcbInstr);
VMM_INT_DECL(VBOXSTRICTRC)      gimKvmHypercallEx(PVMCPUCC pVCpu, PCPUMCTX pCtx, unsigned uDisOpcode, uint8_t cbInstr);

RT_C_DECLS_END

#endif /* !VMM_INCLUDED_SRC_include_GIMKvmInternal_h */