VirtualBox

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

Last change on this file since 101041 was 101035, checked in by vboxsync, 19 months ago

Initial commit (based draft v2 / on patch v5) for implementing platform architecture support for x86 and ARM. bugref:10384

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