VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/GIMAllKvm.cpp@ 54985

Last change on this file since 54985 was 54839, checked in by vboxsync, 10 years ago

VMM/GIM: KVM provider fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: GIMAllKvm.cpp 54839 2015-03-18 17:58:28Z vboxsync $ */
2/** @file
3 * GIM - Guest Interface Manager, KVM, All Contexts.
4 */
5
6/*
7 * Copyright (C) 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_GIM
22#include "GIMKvmInternal.h"
23#include "GIMInternal.h"
24
25#include <VBox/err.h>
26#include <VBox/vmm/hm.h>
27#include <VBox/vmm/tm.h>
28#include <VBox/vmm/vm.h>
29#include <VBox/vmm/pgm.h>
30#include <VBox/vmm/pdmdev.h>
31#include <VBox/vmm/pdmapi.h>
32
33#include <iprt/asm-amd64-x86.h>
34
35
36/**
37 * Handles the KVM hypercall.
38 *
39 * @returns VBox status code.
40 * @param pVCpu Pointer to the VMCPU.
41 * @param pCtx Pointer to the guest-CPU context.
42 */
43VMM_INT_DECL(int) gimKvmHypercall(PVMCPU pVCpu, PCPUMCTX pCtx)
44{
45 PVM pVM = pVCpu->CTX_SUFF(pVM);
46 /** @todo Handle hypercalls. Fail for now */
47 return VERR_GIM_IPE_3;
48}
49
50
51/**
52 * Returns whether the guest has configured and enabled the use of KVM's
53 * hypercall interface.
54 *
55 * @returns true if hypercalls are enabled, false otherwise.
56 * @param pVCpu Pointer to the VMCPU.
57 */
58VMM_INT_DECL(bool) gimKvmAreHypercallsEnabled(PVMCPU pVCpu)
59{
60 /* KVM paravirt interface doesn't have hypercall control bits like Hyper-V does
61 that guests can control. It's always enabled. */
62 return true;
63}
64
65
66/**
67 * Returns whether the guest has configured and enabled the use of KVM's
68 * paravirtualized TSC.
69 *
70 * @returns true if paravirt. TSC is enabled, false otherwise.
71 * @param pVM Pointer to the VM.
72 */
73VMM_INT_DECL(bool) gimKvmIsParavirtTscEnabled(PVM pVM)
74{
75 return false; /** @todo implement this! */
76}
77
78
79/**
80 * MSR read handler for KVM.
81 *
82 * @returns Strict VBox status code like CPUMQueryGuestMsr().
83 * @retval VINF_CPUM_R3_MSR_READ
84 * @retval VERR_CPUM_RAISE_GP_0
85 *
86 * @param pVCpu Pointer to the VMCPU.
87 * @param idMsr The MSR being read.
88 * @param pRange The range this MSR belongs to.
89 * @param puValue Where to store the MSR value read.
90 */
91VMM_INT_DECL(VBOXSTRICTRC) gimKvmReadMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
92{
93 NOREF(pRange);
94 PVM pVM = pVCpu->CTX_SUFF(pVM);
95 PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
96 PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
97
98 switch (idMsr)
99 {
100 case MSR_GIM_KVM_SYSTEM_TIME:
101 case MSR_GIM_KVM_SYSTEM_TIME_OLD:
102 *puValue = pKvmCpu->u64SystemTimeMsr;
103 return VINF_SUCCESS;
104
105 case MSR_GIM_KVM_WALL_CLOCK:
106 case MSR_GIM_KVM_WALL_CLOCK_OLD:
107 *puValue = pKvm->u64WallClockMsr;
108 return VINF_SUCCESS;
109
110 default:
111 {
112#ifdef IN_RING3
113 static uint32_t s_cTimes = 0;
114 if (s_cTimes++ < 20)
115 LogRel(("GIM: KVM: Unknown/invalid RdMsr (%#x) -> #GP(0)\n", idMsr));
116#endif
117 LogFunc(("Unknown/invalid RdMsr (%#RX32) -> #GP(0)\n", idMsr));
118 break;
119 }
120 }
121
122 return VERR_CPUM_RAISE_GP_0;
123}
124
125
126/**
127 * MSR write handler for KVM.
128 *
129 * @returns Strict VBox status code like CPUMSetGuestMsr().
130 * @retval VINF_CPUM_R3_MSR_WRITE
131 * @retval VERR_CPUM_RAISE_GP_0
132 *
133 * @param pVCpu Pointer to the VMCPU.
134 * @param idMsr The MSR being written.
135 * @param pRange The range this MSR belongs to.
136 * @param uRawValue The raw value with the ignored bits not masked.
137 */
138VMM_INT_DECL(VBOXSTRICTRC) gimKvmWriteMsr(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uRawValue)
139{
140 NOREF(pRange);
141 PVM pVM = pVCpu->CTX_SUFF(pVM);
142 PGIMKVM pKvm = &pVM->gim.s.u.Kvm;
143 PGIMKVMCPU pKvmCpu = &pVCpu->gim.s.u.KvmCpu;
144
145 switch (idMsr)
146 {
147 case MSR_GIM_KVM_SYSTEM_TIME:
148 case MSR_GIM_KVM_SYSTEM_TIME_OLD:
149 {
150 bool fEnable = RT_BOOL(uRawValue & MSR_GIM_KVM_SYSTEM_TIME_ENABLE_BIT);
151#ifndef IN_RING3
152 if (fEnable)
153 {
154 RTCCUINTREG fEFlags = ASMIntDisableFlags();
155 pKvmCpu->uTsc = TMCpuTickGetNoCheck(pVCpu);
156 pKvmCpu->uVirtNanoTS = TMVirtualGetNoCheck(pVM);
157 ASMSetFlags(fEFlags);
158 }
159 return VINF_CPUM_R3_MSR_WRITE;
160#else
161 if (!fEnable)
162 {
163 gimR3KvmDisableSystemTime(pVM);
164 pKvmCpu->u64SystemTimeMsr = uRawValue;
165 return VINF_SUCCESS;
166 }
167
168 /* Is the system-time struct. already enabled? If so, get flags that need preserving. */
169 uint8_t fFlags = 0;
170 GIMKVMSYSTEMTIME SystemTime;
171 RT_ZERO(SystemTime);
172 if ( MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pKvmCpu->u64SystemTimeMsr)
173 && MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(uRawValue) == pKvmCpu->GCPhysSystemTime)
174 {
175 int rc2 = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
176 if (RT_SUCCESS(rc2))
177 fFlags = (SystemTime.fFlags & GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED);
178 }
179
180 /* Enable and populate the system-time struct. */
181 pKvmCpu->u64SystemTimeMsr = uRawValue;
182 pKvmCpu->GCPhysSystemTime = MSR_GIM_KVM_SYSTEM_TIME_GUEST_GPA(uRawValue);
183 pKvmCpu->u32SystemTimeVersion = pKvmCpu->u32SystemTimeVersion + 2;
184 int rc = gimR3KvmEnableSystemTime(pVM, pVCpu, pKvmCpu, fFlags);
185 if (RT_FAILURE(rc))
186 {
187 pKvmCpu->u64SystemTimeMsr = 0;
188 return VERR_CPUM_RAISE_GP_0;
189 }
190 return VINF_SUCCESS;
191#endif /* IN_RING3 */
192 }
193
194 case MSR_GIM_KVM_WALL_CLOCK:
195 case MSR_GIM_KVM_WALL_CLOCK_OLD:
196 {
197#ifndef IN_RING3
198
199 return VINF_CPUM_R3_MSR_WRITE;
200#else
201 /* Enable the wall-clock struct. */
202 RTGCPHYS GCPhysWallClock = MSR_GIM_KVM_WALL_CLOCK_GUEST_GPA(uRawValue);
203 if (RT_LIKELY(RT_ALIGN_64(GCPhysWallClock, 4) == GCPhysWallClock))
204 {
205 uint32_t uVersion = 2;
206 int rc = gimR3KvmEnableWallClock(pVM, GCPhysWallClock, uVersion);
207 if (RT_SUCCESS(rc))
208 {
209 pKvm->u64WallClockMsr = uRawValue;
210 return VINF_SUCCESS;
211 }
212 }
213 return VERR_CPUM_RAISE_GP_0;
214#endif /* IN_RING3 */
215 }
216
217 default:
218 {
219#ifdef IN_RING3
220 static uint32_t s_cTimes = 0;
221 if (s_cTimes++ < 20)
222 LogRel(("GIM: KVM: Unknown/invalid WrMsr (%#x,%#x`%08x) -> #GP(0)\n", idMsr,
223 uRawValue & UINT64_C(0xffffffff00000000), uRawValue & UINT64_C(0xffffffff)));
224#endif
225 LogFunc(("Unknown/invalid WrMsr (%#RX32,%#RX64) -> #GP(0)\n", idMsr, uRawValue));
226 break;
227 }
228 }
229
230 return VERR_CPUM_RAISE_GP_0;
231}
232
Note: See TracBrowser for help on using the repository browser.

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