VirtualBox

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

Last change on this file since 103131 was 101063, checked in by vboxsync, 13 months ago

Main: More stub code for ARM. bugref:10384

  • 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 101063 2023-09-08 12:41:13Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation - x86 platform settings.
4 */
5
6/*
7 * Copyright (C) 2023 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 if (aValue)
406 m->bd->fAPIC = !!aValue;
407 break;
408 }
409
410 case CPUPropertyTypeX86_IBPBOnVMExit:
411 {
412 m->bd.backup();
413 m->bd->fIBPBOnVMExit = !!aValue;
414 break;
415 }
416
417 case CPUPropertyTypeX86_IBPBOnVMEntry:
418 {
419 m->bd.backup();
420 m->bd->fIBPBOnVMEntry = !!aValue;
421 break;
422 }
423
424 case CPUPropertyTypeX86_SpecCtrl:
425 {
426 m->bd.backup();
427 m->bd->fSpecCtrl = !!aValue;
428 break;
429 }
430
431 case CPUPropertyTypeX86_SpecCtrlByHost:
432 {
433 m->bd.backup();
434 m->bd->fSpecCtrlByHost = !!aValue;
435 break;
436 }
437
438 case CPUPropertyTypeX86_HWVirt:
439 {
440 m->bd.backup();
441 m->bd->fNestedHWVirt = !!aValue;
442 break;
443 }
444
445 case CPUPropertyTypeX86_L1DFlushOnEMTScheduling:
446 {
447 m->bd.backup();
448 m->bd->fL1DFlushOnSched = !!aValue;
449 break;
450 }
451
452 case CPUPropertyTypeX86_L1DFlushOnVMEntry:
453 {
454 m->bd.backup();
455 m->bd->fL1DFlushOnVMEntry = !!aValue;
456 break;
457 }
458
459 case CPUPropertyTypeX86_MDSClearOnEMTScheduling:
460 {
461 m->bd.backup();
462 m->bd->fMDSClearOnSched = !!aValue;
463 break;
464 }
465
466 case CPUPropertyTypeX86_MDSClearOnVMEntry:
467 {
468 m->bd.backup();
469 m->bd->fMDSClearOnVMEntry = !!aValue;
470 break;
471 }
472
473 default:
474 return E_INVALIDARG;
475 }
476
477 alock.release();
478
479 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
480 mMachine->i_setModified(Machine::IsModified_Platform);
481
482 return S_OK;
483}
484
485HRESULT PlatformX86::getCPUIDLeafByOrdinal(ULONG aOrdinal, ULONG *aIdx, ULONG *aSubIdx, ULONG *aValEax, ULONG *aValEbx,
486 ULONG *aValEcx, ULONG *aValEdx)
487{
488 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
489 if (aOrdinal < m->bd->llCpuIdLeafs.size())
490 {
491 for (settings::CpuIdLeafsX86List::const_iterator it = m->bd->llCpuIdLeafs.begin();
492 it != m->bd->llCpuIdLeafs.end();
493 ++it)
494 {
495 if (aOrdinal == 0)
496 {
497 const settings::CpuIdLeafX86 &rLeaf= *it;
498 *aIdx = rLeaf.idx;
499 *aSubIdx = rLeaf.idxSub;
500 *aValEax = rLeaf.uEax;
501 *aValEbx = rLeaf.uEbx;
502 *aValEcx = rLeaf.uEcx;
503 *aValEdx = rLeaf.uEdx;
504 return S_OK;
505 }
506 aOrdinal--;
507 }
508 }
509 return E_INVALIDARG;
510}
511
512HRESULT PlatformX86::getCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, ULONG *aValEax, ULONG *aValEbx, ULONG *aValEcx, ULONG *aValEdx)
513{
514 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
515
516 /*
517 * Search the list.
518 */
519 for (settings::CpuIdLeafsX86List::const_iterator it = m->bd->llCpuIdLeafs.begin();
520 it != m->bd->llCpuIdLeafs.end();
521 ++it)
522 {
523 const settings::CpuIdLeafX86 &rLeaf= *it;
524 if ( rLeaf.idx == aIdx
525 && ( aSubIdx == UINT32_MAX
526 || rLeaf.idxSub == aSubIdx) )
527 {
528 *aValEax = rLeaf.uEax;
529 *aValEbx = rLeaf.uEbx;
530 *aValEcx = rLeaf.uEcx;
531 *aValEdx = rLeaf.uEdx;
532 return S_OK;
533 }
534 }
535
536 return E_INVALIDARG;
537}
538
539HRESULT PlatformX86::setCPUIDLeaf(ULONG aIdx, ULONG aSubIdx, ULONG aValEax, ULONG aValEbx, ULONG aValEcx, ULONG aValEdx)
540{
541 /* sanity */
542 AutoCaller autoCaller(this);
543 AssertComRCReturnRC(autoCaller.hrc());
544
545 /*
546 * Validate input before taking locks and checking state.
547 */
548 if (aSubIdx != 0 && aSubIdx != UINT32_MAX)
549 return setError(E_INVALIDARG, tr("Currently only aSubIdx values 0 and 0xffffffff are supported: %#x"), aSubIdx);
550 if ( aIdx >= UINT32_C(0x20)
551 && aIdx - UINT32_C(0x80000000) >= UINT32_C(0x20)
552 && aIdx - UINT32_C(0xc0000000) >= UINT32_C(0x10) )
553 return setError(E_INVALIDARG, tr("CpuId override leaf %#x is out of range"), aIdx);
554
555 /* the machine needs to be mutable */
556 AutoMutableStateDependency adep(mMachine);
557 if (FAILED(adep.hrc())) return adep.hrc();
558
559 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
560
561 /*
562 * Impose a maximum number of leaves.
563 */
564 if (m->bd->llCpuIdLeafs.size() > 256)
565 return setError(E_FAIL, tr("Max of 256 CPUID override leaves reached"));
566
567 /*
568 * Updating the list is a bit more complicated. So, let's do a remove first followed by an insert.
569 */
570 m->bd.backup();
571
572 for (settings::CpuIdLeafsX86List::iterator it = m->bd->llCpuIdLeafs.begin(); it != m->bd->llCpuIdLeafs.end(); )
573 {
574 settings::CpuIdLeafX86 &rLeaf= *it;
575 if ( rLeaf.idx == aIdx
576 && ( aSubIdx == UINT32_MAX
577 || rLeaf.idxSub == aSubIdx) )
578 it = m->bd->llCpuIdLeafs.erase(it);
579 else
580 ++it;
581 }
582
583 settings::CpuIdLeafX86 NewLeaf;
584 NewLeaf.idx = aIdx;
585 NewLeaf.idxSub = aSubIdx == UINT32_MAX ? 0 : aSubIdx;
586 NewLeaf.uEax = aValEax;
587 NewLeaf.uEbx = aValEbx;
588 NewLeaf.uEcx = aValEcx;
589 NewLeaf.uEdx = aValEdx;
590 m->bd->llCpuIdLeafs.push_back(NewLeaf);
591
592 alock.release();
593
594 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
595 mMachine->i_setModified(Machine::IsModified_Platform);
596
597 return S_OK;
598}
599
600HRESULT PlatformX86::removeCPUIDLeaf(ULONG aIdx, ULONG aSubIdx)
601{
602 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
603
604 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
605 HRESULT hrc = mMachine->i_checkStateDependency(Machine::MutableStateDep);
606 if (FAILED(hrc)) return hrc;
607
608 /*
609 * Do the removal.
610 */
611 bool fModified = m->bd.isBackedUp();
612 for (settings::CpuIdLeafsX86List::iterator it = m->bd->llCpuIdLeafs.begin(); it != m->bd->llCpuIdLeafs.end(); )
613 {
614 settings::CpuIdLeafX86 &rLeaf= *it;
615 if ( rLeaf.idx == aIdx
616 && ( aSubIdx == UINT32_MAX
617 || rLeaf.idxSub == aSubIdx) )
618 {
619 if (!fModified)
620 {
621 fModified = true;
622 mMachine->i_setModified(Machine::IsModified_Platform);
623 m->bd.backup();
624 // Start from the beginning, since m->bd.backup() creates
625 // a new list, causing iterator mixup. This makes sure that
626 // the settings are not unnecessarily marked as modified,
627 // at the price of extra list walking.
628 it = m->bd->llCpuIdLeafs.begin();
629 }
630 else
631 it = m->bd->llCpuIdLeafs.erase(it);
632 }
633 else
634 ++it;
635 }
636
637 return S_OK;
638}
639
640HRESULT PlatformX86::removeAllCPUIDLeaves()
641{
642 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
643
644 AutoWriteLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
645 HRESULT hrc = mMachine->i_checkStateDependency(Machine::MutableStateDep);
646 if (FAILED(hrc)) return hrc;
647
648 if (m->bd->llCpuIdLeafs.size() > 0)
649 {
650 mMachine->i_setModified(Machine::IsModified_Platform);
651 m->bd.backup();
652
653 m->bd->llCpuIdLeafs.clear();
654 }
655
656 return S_OK;
657}
658
659HRESULT PlatformX86::getHWVirtExProperty(HWVirtExPropertyType_T aProperty, BOOL *aValue)
660{
661 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
662
663 switch(aProperty)
664 {
665 case HWVirtExPropertyType_Enabled:
666 *aValue = m->bd->fHWVirtEx;
667 break;
668
669 case HWVirtExPropertyType_VPID:
670 *aValue = m->bd->fHWVirtExVPID;
671 break;
672
673 case HWVirtExPropertyType_NestedPaging:
674 *aValue = m->bd->fHWVirtExNestedPaging;
675 break;
676
677 case HWVirtExPropertyType_UnrestrictedExecution:
678 *aValue = m->bd->fHWVirtExUX;
679 break;
680
681 case HWVirtExPropertyType_LargePages:
682 *aValue = m->bd->fHWVirtExLargePages;
683 break;
684
685 case HWVirtExPropertyType_Force:
686 *aValue = m->bd->fHWVirtExForce;
687 break;
688
689 case HWVirtExPropertyType_UseNativeApi:
690 *aValue = m->bd->fHWVirtExUseNativeApi;
691 break;
692
693 case HWVirtExPropertyType_VirtVmsaveVmload:
694 *aValue = m->bd->fHWVirtExVirtVmsaveVmload;
695 break;
696
697 default:
698 return E_INVALIDARG;
699 }
700 return S_OK;
701}
702
703HRESULT PlatformX86::setHWVirtExProperty(HWVirtExPropertyType_T aProperty, BOOL aValue)
704{
705 /* sanity */
706 AutoCaller autoCaller(this);
707 AssertComRCReturnRC(autoCaller.hrc());
708
709 /* the machine needs to be mutable */
710 AutoMutableStateDependency adep(mMachine);
711 if (FAILED(adep.hrc())) return adep.hrc();
712
713 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
714
715 switch (aProperty)
716 {
717 case HWVirtExPropertyType_Enabled:
718 {
719 m->bd.backup();
720 m->bd->fHWVirtEx = !!aValue;
721 break;
722 }
723
724 case HWVirtExPropertyType_VPID:
725 {
726 m->bd.backup();
727 m->bd->fHWVirtExVPID = !!aValue;
728 break;
729 }
730
731 case HWVirtExPropertyType_NestedPaging:
732 {
733 m->bd.backup();
734 m->bd->fHWVirtExNestedPaging = !!aValue;
735 break;
736 }
737
738 case HWVirtExPropertyType_UnrestrictedExecution:
739 {
740 m->bd.backup();
741 m->bd->fHWVirtExUX = !!aValue;
742 break;
743 }
744
745 case HWVirtExPropertyType_LargePages:
746 {
747 m->bd.backup();
748 m->bd->fHWVirtExLargePages = !!aValue;
749 break;
750 }
751
752 case HWVirtExPropertyType_Force:
753 {
754 m->bd.backup();
755 m->bd->fHWVirtExForce = !!aValue;
756 break;
757 }
758
759 case HWVirtExPropertyType_UseNativeApi:
760 {
761 m->bd.backup();
762 m->bd->fHWVirtExUseNativeApi = !!aValue;
763 break;
764 }
765
766 case HWVirtExPropertyType_VirtVmsaveVmload:
767 {
768 m->bd.backup();
769 m->bd->fHWVirtExVirtVmsaveVmload = !!aValue;
770 break;
771 }
772
773 default:
774 return E_INVALIDARG;
775 }
776
777 alock.release();
778
779 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
780 mMachine->i_setModified(Machine::IsModified_Platform);
781
782 return S_OK;
783}
784
785// public methods only for internal purposes
786////////////////////////////////////////////////////////////////////////////////
787
788#if 0
789void PlatformX86::i_copyFrom(PlatformX86 *aThat)
790{
791 AssertReturnVoid(aThat != NULL);
792
793 /* sanity */
794 AutoCaller autoCaller(this);
795 AssertComRCReturnVoid(autoCaller.hrc());
796
797 /* sanity too */
798 AutoCaller thatCaller(aThat);
799 AssertComRCReturnVoid(thatCaller.hrc());
800
801 /* peer is not modified, lock it for reading (aThat is "master" so locked
802 * first) */
803 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
804 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
805
806 /* this will back up current data */
807 m->bd.assignCopy(aThat->m->bd);
808}
809#endif
810
811/**
812 * Loads settings from the given platform x86 node.
813 * May be called once right after this object creation.
814 *
815 * @returns HRESULT
816 * @param data Configuration settings.
817 *
818 * @note Locks this object for writing.
819 */
820HRESULT PlatformX86::i_loadSettings(const settings::PlatformX86 &data)
821{
822 AutoCaller autoCaller(this);
823 AssertComRCReturnRC(autoCaller.hrc());
824
825 AutoReadLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
826 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
827
828 // cpuid leafs
829 for (settings::CpuIdLeafsX86List::const_iterator
830 it = data.llCpuIdLeafs.begin();
831 it != data.llCpuIdLeafs.end();
832 ++it)
833 {
834 const settings::CpuIdLeafX86 &rLeaf= *it;
835 if ( rLeaf.idx < UINT32_C(0x20)
836 || rLeaf.idx - UINT32_C(0x80000000) < UINT32_C(0x20)
837 || rLeaf.idx - UINT32_C(0xc0000000) < UINT32_C(0x10) )
838 m->bd->llCpuIdLeafs.push_back(rLeaf);
839 /* else: just ignore */
840 }
841
842 // simply copy
843 m->bd.assignCopy(&data);
844 return S_OK;
845}
846
847/**
848 * Saves settings to the given platform x86 node.
849 *
850 * @returns HRESULT
851 * @param data Configuration settings.
852 *
853 * @note Locks this object for reading.
854 */
855HRESULT PlatformX86::i_saveSettings(settings::PlatformX86 &data)
856{
857 AutoCaller autoCaller(this);
858 AssertComRCReturnRC(autoCaller.hrc());
859
860 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
861
862 /* Standard and Extended CPUID leafs. */
863 data.llCpuIdLeafs.clear();
864 data.llCpuIdLeafs = m->bd->llCpuIdLeafs;
865
866 data = *m->bd.data();
867
868 return S_OK;
869}
870
871#if 0
872void PlatformX86::i_rollback()
873{
874 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
875 m->bd.rollback();
876}
877
878void PlatformX86::i_commit()
879{
880 /* sanity */
881 AutoCaller autoCaller(this);
882 AssertComRCReturnVoid(autoCaller.hrc());
883
884 /* sanity too */
885 AutoCaller peerCaller(m->pPeer);
886 AssertComRCReturnVoid(peerCaller.hrc());
887
888 /* lock both for writing since we modify both (mPeer is "master" so locked
889 * first) */
890 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
891
892 if (m->bd.isBackedUp())
893 {
894 m->bd.commit();
895 if (m->pPeer)
896 {
897 /* attach new data to the peer and reshare it */
898 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
899 m->pPeer->m->bd.attach(m->bd);
900 }
901 }
902}
903#endif
904
905HRESULT PlatformX86::i_applyDefaults(GuestOSType *aOsType)
906{
907 /* sanity */
908 AutoCaller autoCaller(this);
909 AssertComRCReturn(autoCaller.hrc(), autoCaller.hrc());
910
911 HRESULT hrc = S_OK;
912
913 BOOL fPAE;
914 BOOL fAPIC = TRUE; /* Always was enabled. */
915 BOOL fX2APIC;
916 settings::PlatformX86::LongModeType enmLongMode;
917 BOOL fHPET;
918 BOOL fTripleFaultReset;
919
920 if (aOsType)
921 {
922 hrc = aOsType->COMGETTER(RecommendedPAE)(&fPAE);
923 AssertComRCReturn(hrc, hrc);
924
925 hrc = aOsType->COMGETTER(RecommendedX2APIC)(&fX2APIC);
926 AssertComRCReturn(hrc, hrc);
927
928 /* Let the OS type select 64-bit ness. */
929 enmLongMode = aOsType->i_is64Bit()
930 ? settings::PlatformX86::LongMode_Enabled : settings::PlatformX86::LongMode_Disabled;
931
932 hrc = aOsType->COMGETTER(RecommendedHPET)(&fHPET);
933 AssertComRCReturn(hrc, hrc);
934
935 hrc = aOsType->COMGETTER(RecommendedTFReset)(&fTripleFaultReset);
936 AssertComRCReturn(hrc, hrc);
937 }
938 else
939 {
940 /* No guest OS type object. Pick some plausible defaults which the
941 * host can handle. There's no way to know or validate anything. */
942 fX2APIC = FALSE;
943 enmLongMode = HC_ARCH_BITS == 64
944 ? settings::PlatformX86::LongMode_Enabled : settings::PlatformX86::LongMode_Disabled;
945
946#if HC_ARCH_BITS == 64 || defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN)
947 fPAE = TRUE;
948#else
949 fPAE = FALSE;
950#endif
951 fHPET = FALSE;
952 fTripleFaultReset = FALSE;
953 }
954
955 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
956
957 m->bd->fPAE = fPAE;
958 m->bd->fAPIC = fAPIC;
959 m->bd->fX2APIC = fX2APIC;
960 m->bd->enmLongMode = enmLongMode;
961 m->bd->fHPETEnabled = fHPET;
962
963 m->bd->fTripleFaultReset = RT_BOOL(fTripleFaultReset);
964 m->bd->fIBPBOnVMExit = false;
965 m->bd->fIBPBOnVMEntry = false;
966 m->bd->fSpecCtrl = false;
967 m->bd->fSpecCtrlByHost = false;
968 m->bd->fL1DFlushOnSched = true;
969 m->bd->fL1DFlushOnVMEntry = false;
970 m->bd->fMDSClearOnSched = true;
971 m->bd->fMDSClearOnVMEntry = false;
972
973 /* Hardware virtualization must be ON by default. */
974 m->bd->fHWVirtEx = true;
975
976 return hrc;
977}
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