VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/PlatformX86Impl.cpp@ 106297

Last change on this file since 106297 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.7 KB
Line 
1/* $Id: PlatformX86Impl.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation - x86 platform settings.
4 */
5
6/*
7 * Copyright (C) 2023-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_MAIN_PLATFORMX86
29#include "MachineImpl.h"
30#include "PlatformX86Impl.h"
31#include "PlatformImpl.h"
32#include "LoggingNew.h"
33
34#include "AutoStateDep.h"
35
36#include <iprt/cpp/utils.h>
37
38#include <VBox/settings.h>
39
40
41/**
42 * x86-specific platform data.
43 *
44 * This data is unique for a machine and for every machine snapshot.
45 * Stored using the util::Backupable template in the |mPlatformX86Data| variable.
46 *
47 * SessionMachine instances can alter this data and discard changes.
48 */
49struct Data
50{
51 Data() { }
52
53 ComObjPtr<PlatformX86> pPeer;
54
55 // use the XML settings structure in the members for simplicity
56 Backupable<settings::PlatformX86> bd;
57};
58
59
60/*
61 * PlatformX86 implementation.
62 */
63PlatformX86::PlatformX86()
64{
65}
66
67PlatformX86::~PlatformX86()
68{
69 uninit();
70}
71
72HRESULT PlatformX86::FinalConstruct()
73{
74 return BaseFinalConstruct();
75}
76
77void PlatformX86::FinalRelease()
78{
79 uninit();
80
81 BaseFinalRelease();
82}
83
84HRESULT PlatformX86::init(Platform *aParent, Machine *aMachine)
85{
86 /* Enclose the state transition NotReady->InInit->Ready */
87 AutoInitSpan autoInitSpan(this);
88 AssertReturn(autoInitSpan.isOk(), E_FAIL);
89
90 /* share the parent + machine weakly */
91 unconst(mParent) = aParent;
92 unconst(mMachine) = aMachine;
93
94 m = new Data;
95 m->bd.allocate();
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Initializes the platform object given another platform object
105 * (a kind of copy constructor). This object shares data with
106 * the object passed as an argument.
107 *
108 * @note This object must be destroyed before the original object
109 * it shares data with is destroyed.
110 */
111HRESULT PlatformX86::init(Platform *aParent, Machine *aMachine, PlatformX86 *aThat)
112{
113 /* Enclose the state transition NotReady->InInit->Ready */
114 AutoInitSpan autoInitSpan(this);
115 AssertReturn(autoInitSpan.isOk(), E_FAIL);
116
117 ComAssertRet(aParent && aParent, E_INVALIDARG);
118
119 unconst(mParent) = aParent;
120 unconst(mMachine) = aMachine;
121
122 m = new Data();
123 m->pPeer = aThat;
124
125 AutoWriteLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
126 m->bd.share(aThat->m->bd);
127
128 autoInitSpan.setSucceeded();
129
130 return S_OK;
131}
132
133/**
134 * Initializes the guest object given another guest object
135 * (a kind of copy constructor). This object makes a private copy of data
136 * of the original object passed as an argument.
137 */
138HRESULT PlatformX86::initCopy(Platform *aParent, Machine *aMachine, PlatformX86 *aThat)
139{
140 ComAssertRet(aParent && aParent, E_INVALIDARG);
141
142 /* Enclose the state transition NotReady->InInit->Ready */
143 AutoInitSpan autoInitSpan(this);
144 AssertReturn(autoInitSpan.isOk(), E_FAIL);
145
146 unconst(mParent) = aParent;
147 unconst(mMachine) = aMachine;
148
149 m = new Data();
150 // m->pPeer is left null
151
152 AutoWriteLock thatlock(aThat COMMA_LOCKVAL_SRC_POS); /** @todo r=andy Shouldn't a read lock be sufficient here? */
153 m->bd.attachCopy(aThat->m->bd);
154
155 autoInitSpan.setSucceeded();
156
157 return S_OK;
158}
159
160void PlatformX86::uninit()
161{
162 /* Enclose the state transition Ready->InUninit->NotReady */
163 AutoUninitSpan autoUninitSpan(this);
164 if (autoUninitSpan.uninitDone())
165 return;
166
167 unconst(mMachine) = NULL;
168
169 if (m)
170 {
171 m->bd.free();
172 unconst(m->pPeer) = NULL;
173
174 delete m;
175 m = NULL;
176 }
177}
178
179void PlatformX86::i_rollback()
180{
181 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
182 if (m)
183 m->bd.rollback();
184}
185
186void PlatformX86::i_commit()
187{
188 /* sanity */
189 AutoCaller autoCaller(this);
190 AssertComRCReturnVoid(autoCaller.hrc());
191
192 /* sanity too */
193 AutoCaller peerCaller(m->pPeer);
194 AssertComRCReturnVoid(peerCaller.hrc());
195
196 /* lock both for writing since we modify both (mPeer is "master" so locked
197 * first) */
198 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
199
200 if (m->bd.isBackedUp())
201 {
202 m->bd.commit();
203 if (m->pPeer)
204 {
205 /* attach new data to the peer and reshare it */
206 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
207 m->pPeer->m->bd.attach(m->bd);
208 }
209 }
210}
211
212void PlatformX86::i_copyFrom(PlatformX86 *aThat)
213{
214 AssertReturnVoid(aThat != NULL);
215
216 /* sanity */
217 AutoCaller autoCaller(this);
218 AssertComRCReturnVoid(autoCaller.hrc());
219
220 /* sanity too */
221 AutoCaller thatCaller(aThat);
222 AssertComRCReturnVoid(thatCaller.hrc());
223
224 /* peer is not modified, lock it for reading (aThat is "master" so locked
225 * first) */
226 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
227 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
228
229 /* this will back up current data */
230 m->bd.assignCopy(aThat->m->bd);
231}
232
233HRESULT PlatformX86::getHPETEnabled(BOOL *aHPETEnabled)
234{
235 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
236
237 *aHPETEnabled = m->bd->fHPETEnabled;
238
239 return S_OK;
240}
241
242HRESULT PlatformX86::setHPETEnabled(BOOL aHPETEnabled)
243{
244 /* the machine needs to be mutable */
245 AutoMutableStateDependency adep(mMachine);
246 if (FAILED(adep.hrc())) return adep.hrc();
247
248 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
249
250 m->bd.backup();
251 m->bd->fHPETEnabled = aHPETEnabled;
252
253 alock.release();
254
255 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
256 mMachine->i_setModified(Machine::IsModified_Platform);
257
258 return S_OK;
259}
260
261HRESULT PlatformX86::getCPUProperty(CPUPropertyTypeX86_T aProperty, BOOL *aValue)
262{
263 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
264
265 switch (aProperty)
266 {
267 case CPUPropertyTypeX86_PAE:
268 *aValue = m->bd->fPAE;
269 break;
270
271 case CPUPropertyTypeX86_LongMode:
272 if (m->bd->enmLongMode == settings::PlatformX86::LongMode_Enabled)
273 *aValue = TRUE;
274 else if (m->bd->enmLongMode == settings::PlatformX86::LongMode_Disabled)
275 *aValue = FALSE;
276#if HC_ARCH_BITS == 64
277 else
278 *aValue = TRUE;
279#else
280 else
281 {
282 *aValue = FALSE;
283
284 ComObjPtr<GuestOSType> pGuestOSType;
285 HRESULT hrc2 = mParent->i_findGuestOSType(mUserData->s.strOsType,
286 pGuestOSType);
287 if (SUCCEEDED(hrc2) && !pGuestOSType.isNull())
288 {
289 if (pGuestOSType->i_is64Bit())
290 {
291 ComObjPtr<Host> pHost = mParent->i_host();
292 alock.release();
293
294 hrc2 = pHost->GetProcessorFeature(ProcessorFeature_LongMode, aValue); AssertComRC(hrc2);
295 if (FAILED(hrc2))
296 *aValue = FALSE;
297 }
298 }
299 }
300#endif
301 break;
302
303 case CPUPropertyTypeX86_TripleFaultReset:
304 *aValue = m->bd->fTripleFaultReset;
305 break;
306
307 case CPUPropertyTypeX86_APIC:
308 *aValue = m->bd->fAPIC;
309 break;
310
311 case CPUPropertyTypeX86_X2APIC:
312 *aValue = m->bd->fX2APIC;
313 break;
314
315 case CPUPropertyTypeX86_IBPBOnVMExit:
316 *aValue = m->bd->fIBPBOnVMExit;
317 break;
318
319 case CPUPropertyTypeX86_IBPBOnVMEntry:
320 *aValue = m->bd->fIBPBOnVMEntry;
321 break;
322
323 case CPUPropertyTypeX86_SpecCtrl:
324 *aValue = m->bd->fSpecCtrl;
325 break;
326
327 case CPUPropertyTypeX86_SpecCtrlByHost:
328 *aValue = m->bd->fSpecCtrlByHost;
329 break;
330
331 case CPUPropertyTypeX86_HWVirt:
332 *aValue = m->bd->fNestedHWVirt;
333 break;
334
335 case CPUPropertyTypeX86_L1DFlushOnEMTScheduling:
336 *aValue = m->bd->fL1DFlushOnSched;
337 break;
338
339 case CPUPropertyTypeX86_L1DFlushOnVMEntry:
340 *aValue = m->bd->fL1DFlushOnVMEntry;
341 break;
342
343 case CPUPropertyTypeX86_MDSClearOnEMTScheduling:
344 *aValue = m->bd->fMDSClearOnSched;
345 break;
346
347 case CPUPropertyTypeX86_MDSClearOnVMEntry:
348 *aValue = m->bd->fMDSClearOnVMEntry;
349 break;
350
351 default:
352 return E_INVALIDARG;
353 }
354 return S_OK;
355}
356
357HRESULT PlatformX86::setCPUProperty(CPUPropertyTypeX86_T aProperty, BOOL aValue)
358{
359 /* sanity */
360 AutoCaller autoCaller(this);
361 AssertComRCReturnRC(autoCaller.hrc());
362
363 /* the machine needs to be mutable */
364 AutoMutableStateDependency adep(mMachine);
365 if (FAILED(adep.hrc())) return adep.hrc();
366
367 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
368
369 switch (aProperty)
370 {
371 case CPUPropertyTypeX86_PAE:
372 {
373 m->bd.backup();
374 m->bd->fPAE = !!aValue;
375 break;
376 }
377
378 case CPUPropertyTypeX86_LongMode:
379 {
380 m->bd.backup();
381 m->bd->enmLongMode = !aValue ? settings::PlatformX86::LongMode_Disabled : settings::PlatformX86::LongMode_Enabled;
382 break;
383 }
384
385 case CPUPropertyTypeX86_TripleFaultReset:
386 {
387 m->bd.backup();
388 m->bd->fTripleFaultReset = !!aValue;
389 break;
390 }
391
392 case CPUPropertyTypeX86_APIC:
393 {
394 if (m->bd->fX2APIC)
395 aValue = TRUE;
396 m->bd.backup();
397 m->bd->fAPIC = !!aValue;
398 break;
399 }
400
401 case CPUPropertyTypeX86_X2APIC:
402 {
403 m->bd.backup();
404 m->bd->fX2APIC = !!aValue;
405 m->bd->fAPIC = !!aValue;
406 break;
407 }
408
409 case CPUPropertyTypeX86_IBPBOnVMExit:
410 {
411 m->bd.backup();
412 m->bd->fIBPBOnVMExit = !!aValue;
413 break;
414 }
415
416 case CPUPropertyTypeX86_IBPBOnVMEntry:
417 {
418 m->bd.backup();
419 m->bd->fIBPBOnVMEntry = !!aValue;
420 break;
421 }
422
423 case CPUPropertyTypeX86_SpecCtrl:
424 {
425 m->bd.backup();
426 m->bd->fSpecCtrl = !!aValue;
427 break;
428 }
429
430 case CPUPropertyTypeX86_SpecCtrlByHost:
431 {
432 m->bd.backup();
433 m->bd->fSpecCtrlByHost = !!aValue;
434 break;
435 }
436
437 case CPUPropertyTypeX86_HWVirt:
438 {
439 m->bd.backup();
440 m->bd->fNestedHWVirt = !!aValue;
441 break;
442 }
443
444 case CPUPropertyTypeX86_L1DFlushOnEMTScheduling:
445 {
446 m->bd.backup();
447 m->bd->fL1DFlushOnSched = !!aValue;
448 break;
449 }
450
451 case CPUPropertyTypeX86_L1DFlushOnVMEntry:
452 {
453 m->bd.backup();
454 m->bd->fL1DFlushOnVMEntry = !!aValue;
455 break;
456 }
457
458 case CPUPropertyTypeX86_MDSClearOnEMTScheduling:
459 {
460 m->bd.backup();
461 m->bd->fMDSClearOnSched = !!aValue;
462 break;
463 }
464
465 case CPUPropertyTypeX86_MDSClearOnVMEntry:
466 {
467 m->bd.backup();
468 m->bd->fMDSClearOnVMEntry = !!aValue;
469 break;
470 }
471
472 default:
473 return E_INVALIDARG;
474 }
475
476 alock.release();
477
478 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
479 mMachine->i_setModified(Machine::IsModified_Platform);
480
481 return S_OK;
482}
483
484HRESULT PlatformX86::getCPUIDLeafByOrdinal(ULONG aOrdinal, ULONG *aIdx, ULONG *aSubIdx, ULONG *aValEax, ULONG *aValEbx,
485 ULONG *aValEcx, ULONG *aValEdx)
486{
487 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
488 if (aOrdinal < m->bd->llCpuIdLeafs.size())
489 {
490 for (settings::CpuIdLeafsX86List::const_iterator it = m->bd->llCpuIdLeafs.begin();
491 it != m->bd->llCpuIdLeafs.end();
492 ++it)
493 {
494 if (aOrdinal == 0)
495 {
496 const settings::CpuIdLeafX86 &rLeaf= *it;
497 *aIdx = rLeaf.idx;
498 *aSubIdx = rLeaf.idxSub;
499 *aValEax = rLeaf.uEax;
500 *aValEbx = rLeaf.uEbx;
501 *aValEcx = rLeaf.uEcx;
502 *aValEdx = rLeaf.uEdx;
503 return S_OK;
504 }
505 aOrdinal--;
506 }
507 }
508 return E_INVALIDARG;
509}
510
511HRESULT PlatformX86::getCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, ULONG *aValEax, ULONG *aValEbx, ULONG *aValEcx, ULONG *aValEdx)
512{
513 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
514
515 /*
516 * Search the list.
517 */
518 for (settings::CpuIdLeafsX86List::const_iterator it = m->bd->llCpuIdLeafs.begin();
519 it != m->bd->llCpuIdLeafs.end();
520 ++it)
521 {
522 const settings::CpuIdLeafX86 &rLeaf= *it;
523 if ( rLeaf.idx == aIdx
524 && ( aSubIdx == UINT32_MAX
525 || rLeaf.idxSub == aSubIdx) )
526 {
527 *aValEax = rLeaf.uEax;
528 *aValEbx = rLeaf.uEbx;
529 *aValEcx = rLeaf.uEcx;
530 *aValEdx = rLeaf.uEdx;
531 return S_OK;
532 }
533 }
534
535 return E_INVALIDARG;
536}
537
538HRESULT PlatformX86::setCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, ULONG aValEax, ULONG aValEbx, ULONG aValEcx, ULONG aValEdx)
539{
540 /* sanity */
541 AutoCaller autoCaller(this);
542 AssertComRCReturnRC(autoCaller.hrc());
543
544 /*
545 * Validate input before taking locks and checking state.
546 */
547 if (aSubIdx != 0 && aSubIdx != UINT32_MAX)
548 return setError(E_INVALIDARG, tr("Currently only aSubIdx values 0 and 0xffffffff are supported: %#x"), aSubIdx);
549 if ( aIdx >= UINT32_C(0x20)
550 && aIdx - UINT32_C(0x80000000) >= UINT32_C(0x20)
551 && aIdx - UINT32_C(0xc0000000) >= UINT32_C(0x10) )
552 return setError(E_INVALIDARG, tr("CpuId override leaf %#x is out of range"), aIdx);
553
554 /* the machine needs to be mutable */
555 AutoMutableStateDependency adep(mMachine);
556 if (FAILED(adep.hrc())) return adep.hrc();
557
558 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
559
560 /*
561 * Impose a maximum number of leaves.
562 */
563 if (m->bd->llCpuIdLeafs.size() > 256)
564 return setError(E_FAIL, tr("Max of 256 CPUID override leaves reached"));
565
566 /*
567 * Updating the list is a bit more complicated. So, let's do a remove first followed by an insert.
568 */
569 m->bd.backup();
570
571 for (settings::CpuIdLeafsX86List::iterator it = m->bd->llCpuIdLeafs.begin(); it != m->bd->llCpuIdLeafs.end(); )
572 {
573 settings::CpuIdLeafX86 &rLeaf= *it;
574 if ( rLeaf.idx == aIdx
575 && ( aSubIdx == UINT32_MAX
576 || rLeaf.idxSub == aSubIdx) )
577 it = m->bd->llCpuIdLeafs.erase(it);
578 else
579 ++it;
580 }
581
582 settings::CpuIdLeafX86 NewLeaf;
583 NewLeaf.idx = aIdx;
584 NewLeaf.idxSub = aSubIdx == UINT32_MAX ? 0 : aSubIdx;
585 NewLeaf.uEax = aValEax;
586 NewLeaf.uEbx = aValEbx;
587 NewLeaf.uEcx = aValEcx;
588 NewLeaf.uEdx = aValEdx;
589 m->bd->llCpuIdLeafs.push_back(NewLeaf);
590
591 alock.release();
592
593 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
594 mMachine->i_setModified(Machine::IsModified_Platform);
595
596 return S_OK;
597}
598
599HRESULT PlatformX86::removeCPUIDLeaf(ULONG aIdx, ULONG aSubIdx)
600{
601 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
602
603 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
604 HRESULT hrc = mMachine->i_checkStateDependency(Machine::MutableStateDep);
605 if (FAILED(hrc)) return hrc;
606
607 /*
608 * Do the removal.
609 */
610 bool fModified = m->bd.isBackedUp();
611 for (settings::CpuIdLeafsX86List::iterator it = m->bd->llCpuIdLeafs.begin(); it != m->bd->llCpuIdLeafs.end(); )
612 {
613 settings::CpuIdLeafX86 &rLeaf= *it;
614 if ( rLeaf.idx == aIdx
615 && ( aSubIdx == UINT32_MAX
616 || rLeaf.idxSub == aSubIdx) )
617 {
618 if (!fModified)
619 {
620 fModified = true;
621 mMachine->i_setModified(Machine::IsModified_Platform);
622 m->bd.backup();
623 // Start from the beginning, since m->bd.backup() creates
624 // a new list, causing iterator mixup. This makes sure that
625 // the settings are not unnecessarily marked as modified,
626 // at the price of extra list walking.
627 it = m->bd->llCpuIdLeafs.begin();
628 }
629 else
630 it = m->bd->llCpuIdLeafs.erase(it);
631 }
632 else
633 ++it;
634 }
635
636 return S_OK;
637}
638
639HRESULT PlatformX86::removeAllCPUIDLeaves()
640{
641 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
642
643 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
644 HRESULT hrc = mMachine->i_checkStateDependency(Machine::MutableStateDep);
645 if (FAILED(hrc)) return hrc;
646
647 if (m->bd->llCpuIdLeafs.size() > 0)
648 {
649 mMachine->i_setModified(Machine::IsModified_Platform);
650 m->bd.backup();
651
652 m->bd->llCpuIdLeafs.clear();
653 }
654
655 return S_OK;
656}
657
658HRESULT PlatformX86::getHWVirtExProperty(HWVirtExPropertyType_T aProperty, BOOL *aValue)
659{
660 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
661
662 switch(aProperty)
663 {
664 case HWVirtExPropertyType_Enabled:
665 *aValue = m->bd->fHWVirtEx;
666 break;
667
668 case HWVirtExPropertyType_VPID:
669 *aValue = m->bd->fHWVirtExVPID;
670 break;
671
672 case HWVirtExPropertyType_NestedPaging:
673 *aValue = m->bd->fHWVirtExNestedPaging;
674 break;
675
676 case HWVirtExPropertyType_UnrestrictedExecution:
677 *aValue = m->bd->fHWVirtExUX;
678 break;
679
680 case HWVirtExPropertyType_LargePages:
681 *aValue = m->bd->fHWVirtExLargePages;
682 break;
683
684 case HWVirtExPropertyType_Force:
685 *aValue = m->bd->fHWVirtExForce;
686 break;
687
688 case HWVirtExPropertyType_UseNativeApi:
689 *aValue = m->bd->fHWVirtExUseNativeApi;
690 break;
691
692 case HWVirtExPropertyType_VirtVmsaveVmload:
693 *aValue = m->bd->fHWVirtExVirtVmsaveVmload;
694 break;
695
696 default:
697 return E_INVALIDARG;
698 }
699 return S_OK;
700}
701
702HRESULT PlatformX86::setHWVirtExProperty(HWVirtExPropertyType_T aProperty, BOOL aValue)
703{
704 /* sanity */
705 AutoCaller autoCaller(this);
706 AssertComRCReturnRC(autoCaller.hrc());
707
708 /* the machine needs to be mutable */
709 AutoMutableStateDependency adep(mMachine);
710 if (FAILED(adep.hrc())) return adep.hrc();
711
712 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
713
714 switch (aProperty)
715 {
716 case HWVirtExPropertyType_Enabled:
717 {
718 m->bd.backup();
719 m->bd->fHWVirtEx = !!aValue;
720 break;
721 }
722
723 case HWVirtExPropertyType_VPID:
724 {
725 m->bd.backup();
726 m->bd->fHWVirtExVPID = !!aValue;
727 break;
728 }
729
730 case HWVirtExPropertyType_NestedPaging:
731 {
732 m->bd.backup();
733 m->bd->fHWVirtExNestedPaging = !!aValue;
734 break;
735 }
736
737 case HWVirtExPropertyType_UnrestrictedExecution:
738 {
739 m->bd.backup();
740 m->bd->fHWVirtExUX = !!aValue;
741 break;
742 }
743
744 case HWVirtExPropertyType_LargePages:
745 {
746 m->bd.backup();
747 m->bd->fHWVirtExLargePages = !!aValue;
748 break;
749 }
750
751 case HWVirtExPropertyType_Force:
752 {
753 m->bd.backup();
754 m->bd->fHWVirtExForce = !!aValue;
755 break;
756 }
757
758 case HWVirtExPropertyType_UseNativeApi:
759 {
760 m->bd.backup();
761 m->bd->fHWVirtExUseNativeApi = !!aValue;
762 break;
763 }
764
765 case HWVirtExPropertyType_VirtVmsaveVmload:
766 {
767 m->bd.backup();
768 m->bd->fHWVirtExVirtVmsaveVmload = !!aValue;
769 break;
770 }
771
772 default:
773 return E_INVALIDARG;
774 }
775
776 alock.release();
777
778 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
779 mMachine->i_setModified(Machine::IsModified_Platform);
780
781 return S_OK;
782}
783
784// public methods only for internal purposes
785////////////////////////////////////////////////////////////////////////////////
786
787#if 0
788void PlatformX86::i_copyFrom(PlatformX86 *aThat)
789{
790 AssertReturnVoid(aThat != NULL);
791
792 /* sanity */
793 AutoCaller autoCaller(this);
794 AssertComRCReturnVoid(autoCaller.hrc());
795
796 /* sanity too */
797 AutoCaller thatCaller(aThat);
798 AssertComRCReturnVoid(thatCaller.hrc());
799
800 /* peer is not modified, lock it for reading (aThat is "master" so locked
801 * first) */
802 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
803 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
804
805 /* this will back up current data */
806 m->bd.assignCopy(aThat->m->bd);
807}
808#endif
809
810/**
811 * Loads settings from the given platform x86 node.
812 * May be called once right after this object creation.
813 *
814 * @returns HRESULT
815 * @param data Configuration settings.
816 *
817 * @note Locks this object for writing.
818 */
819HRESULT PlatformX86::i_loadSettings(const settings::PlatformX86 &data)
820{
821 AutoCaller autoCaller(this);
822 AssertComRCReturnRC(autoCaller.hrc());
823
824 AutoReadLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
825 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
826
827 // cpuid leafs
828 for (settings::CpuIdLeafsX86List::const_iterator
829 it = data.llCpuIdLeafs.begin();
830 it != data.llCpuIdLeafs.end();
831 ++it)
832 {
833 const settings::CpuIdLeafX86 &rLeaf= *it;
834 if ( rLeaf.idx < UINT32_C(0x20)
835 || rLeaf.idx - UINT32_C(0x80000000) < UINT32_C(0x20)
836 || rLeaf.idx - UINT32_C(0xc0000000) < UINT32_C(0x10) )
837 m->bd->llCpuIdLeafs.push_back(rLeaf);
838 /* else: just ignore */
839 }
840
841 // simply copy
842 m->bd.assignCopy(&data);
843 return S_OK;
844}
845
846/**
847 * Saves settings to the given platform x86 node.
848 *
849 * @returns HRESULT
850 * @param data Configuration settings.
851 *
852 * @note Locks this object for reading.
853 */
854HRESULT PlatformX86::i_saveSettings(settings::PlatformX86 &data)
855{
856 AutoCaller autoCaller(this);
857 AssertComRCReturnRC(autoCaller.hrc());
858
859 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
860
861 /* Standard and Extended CPUID leafs. */
862 data.llCpuIdLeafs.clear();
863 data.llCpuIdLeafs = m->bd->llCpuIdLeafs;
864
865 data = *m->bd.data();
866
867 return S_OK;
868}
869
870#if 0
871void PlatformX86::i_rollback()
872{
873 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
874 m->bd.rollback();
875}
876
877void PlatformX86::i_commit()
878{
879 /* sanity */
880 AutoCaller autoCaller(this);
881 AssertComRCReturnVoid(autoCaller.hrc());
882
883 /* sanity too */
884 AutoCaller peerCaller(m->pPeer);
885 AssertComRCReturnVoid(peerCaller.hrc());
886
887 /* lock both for writing since we modify both (mPeer is "master" so locked
888 * first) */
889 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
890
891 if (m->bd.isBackedUp())
892 {
893 m->bd.commit();
894 if (m->pPeer)
895 {
896 /* attach new data to the peer and reshare it */
897 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
898 m->pPeer->m->bd.attach(m->bd);
899 }
900 }
901}
902#endif
903
904HRESULT PlatformX86::i_applyDefaults(GuestOSType *aOsType)
905{
906 /* sanity */
907 AutoCaller autoCaller(this);
908 AssertComRCReturn(autoCaller.hrc(), autoCaller.hrc());
909
910 HRESULT hrc = S_OK;
911
912 BOOL fPAE;
913 BOOL fAPIC = TRUE; /* Always was enabled. */
914 BOOL fX2APIC;
915 settings::PlatformX86::LongModeType enmLongMode;
916 BOOL fHPET;
917 BOOL fTripleFaultReset;
918
919 if (aOsType)
920 {
921 hrc = aOsType->COMGETTER(RecommendedPAE)(&fPAE);
922 AssertComRCReturn(hrc, hrc);
923
924 hrc = aOsType->COMGETTER(RecommendedX2APIC)(&fX2APIC);
925 AssertComRCReturn(hrc, hrc);
926
927 /* Let the OS type select 64-bit ness. */
928 enmLongMode = aOsType->i_is64Bit()
929 ? settings::PlatformX86::LongMode_Enabled : settings::PlatformX86::LongMode_Disabled;
930
931 hrc = aOsType->COMGETTER(RecommendedHPET)(&fHPET);
932 AssertComRCReturn(hrc, hrc);
933
934 hrc = aOsType->COMGETTER(RecommendedTFReset)(&fTripleFaultReset);
935 AssertComRCReturn(hrc, hrc);
936 }
937 else
938 {
939 /* No guest OS type object. Pick some plausible defaults which the
940 * host can handle. There's no way to know or validate anything. */
941 fX2APIC = FALSE;
942 enmLongMode = HC_ARCH_BITS == 64
943 ? settings::PlatformX86::LongMode_Enabled : settings::PlatformX86::LongMode_Disabled;
944
945#if HC_ARCH_BITS == 64 || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN)
946 fPAE = TRUE;
947#else
948 fPAE = FALSE;
949#endif
950 fHPET = FALSE;
951 fTripleFaultReset = FALSE;
952 }
953
954 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
955
956 m->bd->fPAE = fPAE;
957 m->bd->fAPIC = fAPIC;
958 m->bd->fX2APIC = fX2APIC;
959 m->bd->enmLongMode = enmLongMode;
960 m->bd->fHPETEnabled = fHPET;
961
962 m->bd->fTripleFaultReset = RT_BOOL(fTripleFaultReset);
963 m->bd->fIBPBOnVMExit = false;
964 m->bd->fIBPBOnVMEntry = false;
965 m->bd->fSpecCtrl = false;
966 m->bd->fSpecCtrlByHost = false;
967 m->bd->fL1DFlushOnSched = true;
968 m->bd->fL1DFlushOnVMEntry = false;
969 m->bd->fMDSClearOnSched = true;
970 m->bd->fMDSClearOnVMEntry = false;
971
972 /* Hardware virtualization must be ON by default. */
973 m->bd->fHWVirtEx = true;
974
975 return hrc;
976}
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