VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/GIMAll.cpp@ 55048

Last change on this file since 55048 was 55037, checked in by vboxsync, 10 years ago

VMM/GIM: Add hypercall support and KVM spinlock support.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: GIMAll.cpp 55037 2015-03-31 14:09:10Z vboxsync $ */
2/** @file
3 * GIM - Guest Interface Manager - All Contexts.
4 */
5
6/*
7 * Copyright (C) 2014-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_GIM
23#include "GIMInternal.h"
24#include <VBox/err.h>
25#include <VBox/vmm/vm.h>
26
27/* Include all the providers. */
28#include "GIMHvInternal.h"
29#include "GIMMinimalInternal.h"
30
31
32/**
33 * Checks whether GIM is being used by this VM.
34 *
35 * @retval @c true if used.
36 * @retval @c false if no GIM provider ("none") is used.
37 *
38 * @param pVM Pointer to the VM.
39 */
40VMMDECL(bool) GIMIsEnabled(PVM pVM)
41{
42 return pVM->gim.s.enmProviderId != GIMPROVIDERID_NONE;
43}
44
45
46/**
47 * Gets the GIM provider configured for this VM.
48 *
49 * @returns The GIM provider Id.
50 * @param pVM Pointer to the VM.
51 */
52VMMDECL(GIMPROVIDERID) GIMGetProvider(PVM pVM)
53{
54 return pVM->gim.s.enmProviderId;
55}
56
57
58/**
59 * Returns whether the guest has configured and enabled calls to the hypervisor.
60 *
61 * @returns true if hypercalls are enabled and usable, false otherwise.
62 * @param pVCpu Pointer to the VMCPU.
63 */
64VMM_INT_DECL(bool) GIMAreHypercallsEnabled(PVMCPU pVCpu)
65{
66 PVM pVM = pVCpu->CTX_SUFF(pVM);
67 if (!GIMIsEnabled(pVM))
68 return false;
69
70 switch (pVM->gim.s.enmProviderId)
71 {
72 case GIMPROVIDERID_HYPERV:
73 return gimHvAreHypercallsEnabled(pVCpu);
74
75 case GIMPROVIDERID_KVM:
76 return gimKvmAreHypercallsEnabled(pVCpu);
77
78 default:
79 return false;
80 }
81}
82
83
84/**
85 * Implements a GIM hypercall with the provider configured for the VM.
86 *
87 * @returns VBox status code.
88 * @param pVCpu Pointer to the VMCPU.
89 * @param pCtx Pointer to the guest-CPU context.
90 */
91VMM_INT_DECL(int) GIMHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
92{
93 PVM pVM = pVCpu->CTX_SUFF(pVM);
94 VMCPU_ASSERT_EMT(pVCpu);
95
96 if (RT_UNLIKELY(!GIMIsEnabled(pVM)))
97 return VERR_GIM_NOT_ENABLED;
98
99 switch (pVM->gim.s.enmProviderId)
100 {
101 case GIMPROVIDERID_HYPERV:
102 return gimHvHypercall(pVCpu, pCtx);
103
104 case GIMPROVIDERID_KVM:
105 return gimKvmHypercall(pVCpu, pCtx);
106
107 default:
108 AssertMsgFailed(("GIMHypercall: for provider %u not available/implemented\n", pVM->gim.s.enmProviderId));
109 return VERR_GIM_HYPERCALLS_NOT_AVAILABLE;
110 }
111}
112
113
114/**
115 * Returns whether the guest has configured and setup the use of paravirtualized
116 * TSC.
117 *
118 * Paravirtualized TSCs are per-VM and the rest of the execution engine logic
119 * relies on that.
120 *
121 * @returns true if enabled and usable, false otherwise.
122 * @param pVM Pointer to the VM.
123 */
124VMM_INT_DECL(bool) GIMIsParavirtTscEnabled(PVM pVM)
125{
126 switch (pVM->gim.s.enmProviderId)
127 {
128 case GIMPROVIDERID_HYPERV:
129 return gimHvIsParavirtTscEnabled(pVM);
130
131 default:
132 break;
133 }
134 return false;
135}
136
137
138/**
139 * Whether #UD exceptions in the guest needs to be intercepted by the GIM
140 * provider.
141 *
142 * At the moment, the reason why this isn't a more generic interface wrt to
143 * exceptions is because of performance (each VM-exit would have to manually
144 * check whether or not GIM needs to be notified). Left as a todo for later if
145 * really required.
146 *
147 * @returns true if needed, false otherwise.
148 * @param pVM Pointer to the VM.
149 */
150VMM_INT_DECL(bool) GIMShouldTrapXcptUD(PVM pVM)
151{
152 if (!GIMIsEnabled(pVM))
153 return 0;
154
155 switch (pVM->gim.s.enmProviderId)
156 {
157 case GIMPROVIDERID_KVM:
158 return gimKvmShouldTrapXcptUD(pVM);
159
160 default:
161 return 0;
162 }
163}
164
165
166/**
167 * Exception handler for #UD when requested by the GIM provider.
168 *
169 * @param pVCpu Pointer to the VMCPU.
170 * @param pCtx Pointer to the guest-CPU context.
171 */
172VMM_INT_DECL(int) GIMXcptUD(PVMCPU pVCpu, PCPUMCTX pCtx)
173{
174 PVM pVM = pVCpu->CTX_SUFF(pVM);
175 Assert(GIMIsEnabled(pVM));
176
177 switch (pVM->gim.s.enmProviderId)
178 {
179 case GIMPROVIDERID_KVM:
180 return gimKvmXcptUD(pVCpu, pCtx);
181
182 default:
183 return VERR_GIM_OPERATION_FAILED;
184 }
185}
186
187
188/**
189 * Invokes the read-MSR handler for the GIM provider configured for the VM.
190 *
191 * @returns Strict VBox status code like CPUMQueryGuestMsr.
192 * @retval VINF_CPUM_R3_MSR_READ
193 * @retval VERR_CPUM_RAISE_GP_0
194 *
195 * @param pVCpu Pointer to the VMCPU.
196 * @param idMsr The MSR to read.
197 * @param pRange The range this MSR belongs to.
198 * @param puValue Where to store the MSR value read.
199 */
200VMM_INT_DECL(VBOXSTRICTRC) GIMReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
201{
202 Assert(pVCpu);
203 PVM pVM = pVCpu->CTX_SUFF(pVM);
204 Assert(GIMIsEnabled(pVM));
205 VMCPU_ASSERT_EMT(pVCpu);
206
207 switch (pVM->gim.s.enmProviderId)
208 {
209 case GIMPROVIDERID_HYPERV:
210 return gimHvReadMsr(pVCpu, idMsr, pRange, puValue);
211
212 case GIMPROVIDERID_KVM:
213 return gimKvmReadMsr(pVCpu, idMsr, pRange, puValue);
214
215 default:
216 AssertMsgFailed(("GIMReadMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
217 return VERR_CPUM_RAISE_GP_0;
218 }
219}
220
221
222/**
223 * Invokes the write-MSR handler for the GIM provider configured for the VM.
224 *
225 * @returns Strict VBox status code like CPUMSetGuestMsr.
226 * @retval VINF_CPUM_R3_MSR_WRITE
227 * @retval VERR_CPUM_RAISE_GP_0
228 *
229 * @param pVCpu Pointer to the VMCPU.
230 * @param idMsr The MSR to write.
231 * @param pRange The range this MSR belongs to.
232 * @param uValue The value to set, ignored bits masked.
233 * @param uRawValue The raw value with the ignored bits not masked.
234 */
235VMM_INT_DECL(VBOXSTRICTRC) GIMWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue)
236{
237 AssertPtr(pVCpu);
238 NOREF(uValue);
239
240 PVM pVM = pVCpu->CTX_SUFF(pVM);
241 Assert(GIMIsEnabled(pVM));
242 VMCPU_ASSERT_EMT(pVCpu);
243
244 switch (pVM->gim.s.enmProviderId)
245 {
246 case GIMPROVIDERID_HYPERV:
247 return gimHvWriteMsr(pVCpu, idMsr, pRange, uRawValue);
248
249 case GIMPROVIDERID_KVM:
250 return gimKvmWriteMsr(pVCpu, idMsr, pRange, uRawValue);
251
252 default:
253 AssertMsgFailed(("GIMWriteMsr: for unknown provider %u idMsr=%#RX32 -> #GP(0)", pVM->gim.s.enmProviderId, idMsr));
254 return VERR_CPUM_RAISE_GP_0;
255 }
256}
257
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette