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 */
|