Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 106361)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 106384)
@@ -1221,4 +1221,23 @@
         setting may slow down workloads causing many VM exits, so it is only
         recommended for situation where there is a real need to be paranoid.
+      </desc>
+    </const>
+  </enum>
+
+  <enum
+    name="CPUPropertyTypeARM"
+    uuid="c84685f6-6bd3-4071-97c6-86f34595648f"
+    >
+    <desc>
+      Virtual CPU property type for ARM-based CPUs. This enumeration represents possible values of the
+      IPlatformARM get- and setCPUProperty methods.
+    </desc>
+    <const name="Null"                  value="0">
+      <desc>Null value (never used by the API).</desc>
+    </const>
+    <const name="HWVirt"                value="1">
+      <desc>
+        Enables the hardware virtualization feature on the guest CPU.
+        This requires the nested virtualization feature on the host CPU.
       </desc>
     </const>
@@ -7392,5 +7411,5 @@
   <interface
     name="IPlatformARM" extends="$unknown"
-    uuid="75dff9be-6cb3-4857-bde6-2faf82ed9a8d"
+    uuid="002c75fe-3316-4920-aece-7d21ce6f624b"
     wsmap="managed"
     rest="managed"
@@ -7403,6 +7422,47 @@
     </desc>
 
-    <!-- Currently empty, but that should change before long... -->
-    <attribute name="midlDoesNotLikeEmptyInterfaces" readonly="yes" type="boolean"/>
+    <method name="getCPUProperty" const="yes">
+      <rest request="get" path="/vms/{vmid}/configuration/"/>
+      <desc>
+        Returns the virtual CPU boolean value of the specified property.
+
+        <result name="E_INVALIDARG">
+          Invalid property.
+        </result>
+
+      </desc>
+      <param name="property" type="CPUPropertyTypeARM" dir="in">
+        <desc>
+          Property type to query.
+        </desc>
+      </param>
+      <param name="value" type="boolean" dir="return">
+        <desc>
+          Property value.
+        </desc>
+      </param>
+    </method>
+
+    <method name="setCPUProperty">
+      <rest request="post" path="/vms/{vmid}/configuration/"/>
+      <desc>
+        Sets the virtual CPU boolean value of the specified property.
+
+        <result name="E_INVALIDARG">
+          Invalid property.
+        </result>
+
+      </desc>
+      <param name="property" type="CPUPropertyTypeARM" dir="in">
+        <desc>
+          Property type to query.
+        </desc>
+      </param>
+      <param name="value" type="boolean" dir="in">
+        <desc>
+          Property value.
+        </desc>
+      </param>
+    </method>
 
   </interface>
Index: trunk/src/VBox/Main/include/PlatformARMImpl.h
===================================================================
--- trunk/src/VBox/Main/include/PlatformARMImpl.h	(revision 106361)
+++ trunk/src/VBox/Main/include/PlatformARMImpl.h	(revision 106384)
@@ -68,4 +68,10 @@
     HRESULT i_saveSettings(settings::PlatformARM &data);
     HRESULT i_applyDefaults(GuestOSType *aOsType);
+
+private:
+
+    // wrapped IPlatformARM methods
+    HRESULT getCPUProperty(CPUPropertyTypeARM_T aProperty, BOOL *aValue);
+    HRESULT setCPUProperty(CPUPropertyTypeARM_T aProperty, BOOL aValue);
 };
 #endif /* !MAIN_INCLUDED_PlatformARMImpl_h */
Index: trunk/src/VBox/Main/src-all/PlatformPropertiesImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-all/PlatformPropertiesImpl.cpp	(revision 106361)
+++ trunk/src/VBox/Main/src-all/PlatformPropertiesImpl.cpp	(revision 106384)
@@ -1277,5 +1277,6 @@
             static const TpmType_T aTpmTypes[] =
             {
-                TpmType_None
+                TpmType_None,
+                TpmType_v2_0
             };
             aSupportedTpmTypes.assign(aTpmTypes,
Index: trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp	(revision 106361)
+++ trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp	(revision 106384)
@@ -153,4 +153,8 @@
 #endif
 
+    /* Get the ARM platform object. */
+    ComPtr<IPlatformARM> platformARM;
+    hrc = platform->COMGETTER(ARM)(platformARM.asOutParam());                               H();
+
     ComPtr<IPlatformProperties> pPlatformProperties;
     hrc = platform->COMGETTER(Properties)(pPlatformProperties.asOutParam());                H();
@@ -364,4 +368,9 @@
         PCFGMNODE pCpum;
         InsertConfigNode(pRoot, "CPUM", &pCpum);
+
+        /* Nested Virtualization. */
+        BOOL fNestedHWVirt = FALSE;
+        hrc = platformARM->GetCPUProperty(CPUPropertyTypeARM_HWVirt, &fNestedHWVirt); H();
+        InsertConfigInteger(pCpum, "NestedHWVirt", fNestedHWVirt ? true : false);
 
 
Index: trunk/src/VBox/Main/src-server/PlatformARMImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/PlatformARMImpl.cpp	(revision 106361)
+++ trunk/src/VBox/Main/src-server/PlatformARMImpl.cpp	(revision 106384)
@@ -31,4 +31,6 @@
 #include "PlatformImpl.h"
 #include "LoggingNew.h"
+
+#include "AutoStateDep.h"
 
 #include <VBox/settings.h>
@@ -239,7 +241,12 @@
 HRESULT PlatformARM::i_loadSettings(const settings::PlatformARM &data)
 {
-    RT_NOREF(data);
-
-    /* Nothing here yet. */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.hrc());
+
+    AutoReadLock mlock(mMachine COMMA_LOCKVAL_SRC_POS);
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    // simply copy
+    m->bd.assignCopy(&data);
     return S_OK;
 }
@@ -255,5 +262,17 @@
 HRESULT PlatformARM::i_saveSettings(settings::PlatformARM &data)
 {
-    RT_NOREF(data);
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.hrc());
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    data = *m->bd.data();
+
+    return S_OK;
+}
+
+HRESULT PlatformARM::i_applyDefaults(GuestOSType *aOsType)
+{
+    RT_NOREF(aOsType);
 
     /* Nothing here yet. */
@@ -261,9 +280,50 @@
 }
 
-HRESULT PlatformARM::i_applyDefaults(GuestOSType *aOsType)
-{
-    RT_NOREF(aOsType);
-
-    /* Nothing here yet. */
-    return S_OK;
-}
+HRESULT PlatformARM::getCPUProperty(CPUPropertyTypeARM_T aProperty, BOOL *aValue)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    switch (aProperty)
+    {
+        case CPUPropertyTypeARM_HWVirt:
+            *aValue = m->bd->fNestedHWVirt;
+            break;
+
+        default:
+            return E_INVALIDARG;
+    }
+    return S_OK;
+}
+
+HRESULT PlatformARM::setCPUProperty(CPUPropertyTypeARM_T aProperty, BOOL aValue)
+{
+    /* sanity */
+    AutoCaller autoCaller(this);
+    AssertComRCReturnRC(autoCaller.hrc());
+
+    /* the machine needs to be mutable */
+    AutoMutableStateDependency adep(mMachine);
+    if (FAILED(adep.hrc())) return adep.hrc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    switch (aProperty)
+    {
+        case CPUPropertyTypeARM_HWVirt:
+        {
+            m->bd.backup();
+            m->bd->fNestedHWVirt = !!aValue;
+            break;
+        }
+
+        default:
+            return E_INVALIDARG;
+    }
+
+    alock.release();
+
+    AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS);
+    mMachine->i_setModified(Machine::IsModified_Platform);
+
+    return S_OK;
+}
Index: trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- trunk/src/VBox/Main/xml/Settings.cpp	(revision 106361)
+++ trunk/src/VBox/Main/xml/Settings.cpp	(revision 106384)
@@ -3969,5 +3969,6 @@
 
 #ifdef VBOX_WITH_VIRT_ARMV8
-PlatformARM::PlatformARM()
+PlatformARM::PlatformARM() :
+    fNestedHWVirt(false)
 {
 }
@@ -3975,6 +3976,6 @@
 bool PlatformARM::operator==(const PlatformARM& h) const
 {
-    RT_NOREF(h);
-    return true;
+    return (this == &h)
+        || (fNestedHWVirt == h.fNestedHWVirt);
 }
 #endif /* VBOX_WITH_VIRT_ARMV8 */
@@ -5306,4 +5307,31 @@
 }
 
+#ifdef VBOX_WITH_VIRT_ARMV8
+/**
+ * Reads the ARM platform settings.
+ *
+ * For settings >= v1.20 these were stored under the "Platform/arm" node.
+ *
+ * @param elmPlatformARM  Platform/arm node to read from.
+ * @param platARM         Where to store the ARM platform settings.
+ */
+void MachineConfigFile::readPlatformARM(const xml::ElementNode &elmPlatformARM,
+                                        PlatformARM &platARM)
+{
+    xml::NodesLoop nl1(elmPlatformARM);
+
+    const xml::ElementNode *pelChild;
+    while ((pelChild = nl1.forAllNodes()))
+    {
+        if (pelChild->nameEquals("CPU"))
+        {
+            const xml::ElementNode *pelmCPUChild;
+            if ((pelmCPUChild = pelChild->findChildElement("NestedHWVirt")))
+                pelmCPUChild->getAttributeValue("enabled", platARM.fNestedHWVirt);
+        }
+    }
+}
+#endif
+
 /**
  * Reads the platform settings.
@@ -5443,5 +5471,9 @@
         case PlatformArchitecture_ARM:
         {
-            /* Nothing here yet -- add ARM-specific stuff as soon as we have it. */
+            const xml::ElementNode *pelmPlatformARM;
+
+            pelmPlatformARM = elmPlatformOrHardware.findChildElement("arm");
+            if (pelmPlatformARM)
+                readPlatformARM(*pelmPlatformARM, plat.arm);
             break;
         }
@@ -7350,4 +7382,28 @@
 }
 
+#ifdef VBOX_WITH_VIRT_ARMV8
+/**
+ * Writes ARM-specific platform settings out to the XML.
+ *
+ * For settings >= v1.20 this creates a \<arm\> node under elmParent.
+ * keys under that. Called for both the \<Machine\> node and for snapshots.
+ *
+ * @param elmParent                         Parent element.
+ *                                          For settings >= v1.20 this is the \<Platform\> element.
+ * @param elmCPU                            CPU element platform-generic settings.
+ *                                          For settings >= v1.20 this is the \<Platform/CPU\> element.
+ * @param platARM                           ARM-specific platform settings to use for building the XML.
+ */
+void MachineConfigFile::buildPlatformARMXML(xml::ElementNode &elmParent, const PlatformARM &platARM)
+{
+    xml::ElementNode *pelmARMRoot = elmParent.createChild("arm");
+    xml::ElementNode *pelmARMCPU  = pelmARMRoot->createChild("CPU");
+
+    if (platARM.fNestedHWVirt)
+        pelmARMCPU->createChild("NestedHWVirt")->setAttribute("enabled", platARM.fNestedHWVirt);
+}
+#endif /* VBOX_WITH_VIRT_ARMV8 */
+
+
 /**
  * Stores platform-generic and platform-specific data and then writes out the XML.
@@ -7465,5 +7521,11 @@
     if (plat.architectureType == PlatformArchitecture_x86)
         buildPlatformX86XML(*pelmPlatformOrHardware, *pelmCPU, plat.x86);
-    /** @todo Put ARM stuff here as soon as we have it. */
+#ifdef VBOX_WITH_VIRT_ARMV8
+    else if (plat.architectureType == PlatformArchitecture_ARM)
+    {
+        Assert(m->sv >= SettingsVersion_v1_20);
+        buildPlatformARMXML(*pelmPlatformOrHardware, plat.arm);
+    }
+#endif
 }
 
