Index: /trunk/include/VBox/vmm/cpumctx-armv8.h
===================================================================
--- /trunk/include/VBox/vmm/cpumctx-armv8.h	(revision 105685)
+++ /trunk/include/VBox/vmm/cpumctx-armv8.h	(revision 105686)
@@ -236,4 +236,58 @@
     CPUMCTXSYSREG       MDccInt;
 
+    /** @name Hypervisor (EL2) support.
+     * @{ */
+    /** The CNTHCTL_EL2 register. */
+    CPUMCTXSYSREG       CntHCtlEl2;
+    /** The CNTP_CTL_EL2 register. */
+    CPUMCTXSYSREG       CntHpCtlEl2;
+    /** The CNTP_CVAL_EL2 register. */
+    CPUMCTXSYSREG       CntHpCValEl2;
+    /** The CNTP_TVAL_EL2 register. */
+    CPUMCTXSYSREG       CntHpTValEl2;
+    /** The CNTVOFF_EL2 register. */
+    CPUMCTXSYSREG       CntVOffEl2;
+    /** The CPTR_EL2 register. */
+    CPUMCTXSYSREG       CptrEl2;
+    /** The ELR_EL2 register. */
+    CPUMCTXSYSREG       ElrEl2;
+    /** The ESR_EL2 register. */
+    CPUMCTXSYSREG       EsrEl2;
+    /** The FAR_EL2 register. */
+    CPUMCTXSYSREG       FarEl2;
+    /** The HCR_EL2 register. */
+    CPUMCTXSYSREG       HcrEl2;
+    /** The HPFAR_EL2 register. */
+    CPUMCTXSYSREG       HpFarEl2;
+    /** The MAIR_EL2 register. */
+    CPUMCTXSYSREG       MairEl2;
+    /** The MDCR_EL2 register. */
+    CPUMCTXSYSREG       MdcrEl2;
+    /** The SCTLR_EL2 register. */
+    CPUMCTXSYSREG       SctlrEl2;
+    /** The SPSR_EL2 register. */
+    CPUMCTXSYSREG       SpsrEl2;
+    /** The SP_EL2 register. */
+    CPUMCTXSYSREG       SpEl2;
+    /** The TCR_EL2 register. */
+    CPUMCTXSYSREG       TcrEl2;
+    /** The TPIDR_EL2 register. */
+    CPUMCTXSYSREG       TpidrEl2;
+    /** The TTBR0_EL2 register. */
+    CPUMCTXSYSREG       Ttbr0El2;
+    /** The TTBR1_EL2 register. */
+    CPUMCTXSYSREG       Ttbr1El2;
+    /** The VBAR_EL2 register. */
+    CPUMCTXSYSREG       VBarEl2;
+    /** The VMPIDR_EL2 register. */
+    CPUMCTXSYSREG       VMpidrEl2;
+    /** The VPIDR_EL2 register. */
+    CPUMCTXSYSREG       VPidrEl2;
+    /** The VTCR_EL2 register. */
+    CPUMCTXSYSREG       VTcrEl2;
+    /** The VTTBR_EL2 register. */
+    CPUMCTXSYSREG       VTtbrEl2;
+    /** @} */
+
     /** Floating point control register. */
     uint64_t            fpcr;
@@ -258,5 +312,5 @@
     uint64_t            CntvCValEl0;
 
-    uint64_t            au64Padding2[4];
+    uint64_t            au64Padding2[3];
 } CPUMCTX;
 
@@ -323,6 +377,8 @@
 /** PAuth key system registers are kept externally. */
 #define CPUMCTX_EXTRN_SYSREG_PAUTH_KEYS         UINT64_C(0x0000000000020000)
+/** EL2 system registers are kept externally. */
+#define CPUMCTX_EXTRN_SYSREG_EL2                UINT64_C(0x0000000000040000)
 /** Various system registers (rarely accessed) are kept externally. */
-#define CPUMCTX_EXTRN_SYSREG_MISC               UINT64_C(0x0000000000040000)
+#define CPUMCTX_EXTRN_SYSREG_MISC               UINT64_C(0x0000000000080000)
 
 /** Mask of bits the keepers can use for state tracking. */
Index: /trunk/include/VBox/vmm/dbgf.h
===================================================================
--- /trunk/include/VBox/vmm/dbgf.h	(revision 105685)
+++ /trunk/include/VBox/vmm/dbgf.h	(revision 105686)
@@ -2156,6 +2156,5 @@
     DBGFREG_ARMV8_SP_EL1,
     DBGFREG_ARMV8_SPSR_EL1,
-    DBGFREG_ARMV8_SPSR_EL2,
-    DBGFREG_ARMV8_PSTATE = DBGFREG_ARMV8_SPSR_EL2,
+    DBGFREG_ARMV8_PSTATE,
     DBGFREG_ARMV8_SCTLR_EL1,
     DBGFREG_ARMV8_TCR_EL1,
@@ -2165,5 +2164,31 @@
     DBGFREG_ARMV8_VBAR_EL1,
 
-    DBGFREG_ARMV8_LAST = DBGFREG_ARMV8_VBAR_EL1,
+    /** EL2 system registers: */
+    DBGFREG_ARMV8_CNTHCTL_EL2,
+    DBGFREG_ARMV8_CNTHP_CTL_EL2,
+    DBGFREG_ARMV8_CNTHP_CVAL_EL2,
+    DBGFREG_ARMV8_CNTHP_TVAL_EL2,
+    DBGFREG_ARMV8_CNTVOFF_EL2,
+    DBGFREG_ARMV8_CPTR_EL2,
+    DBGFREG_ARMV8_ELR_EL2,
+    DBGFREG_ARMV8_ESR_EL2,
+    DBGFREG_ARMV8_FAR_EL2,
+    DBGFREG_ARMV8_HCR_EL2,
+    DBGFREG_ARMV8_HPFAR_EL2,
+    DBGFREG_ARMV8_MAIR_EL2,
+    DBGFREG_ARMV8_MDCR_EL2,
+    DBGFREG_ARMV8_SCTLR_EL2,
+    DBGFREG_ARMV8_SPSR_EL2,
+    DBGFREG_ARMV8_SP_EL2,
+    DBGFREG_ARMV8_TCR_EL2,
+    DBGFREG_ARMV8_TPIDR_EL2,
+    DBGFREG_ARMV8_TTBR0_EL2,
+    DBGFREG_ARMV8_TTBR1_EL2,
+    DBGFREG_ARMV8_VBAR_EL2,
+    DBGFREG_ARMV8_VMPIDR_EL2,
+    DBGFREG_ARMV8_VPIDR_EL2,
+    DBGFREG_ARMV8_VTCR_EL2,
+    DBGFREG_ARMV8_VTTBR_EL2,
+    DBGFREG_ARMV8_LAST = DBGFREG_ARMV8_VTTBR_EL2,
     /** @} */
 
Index: /trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp	(revision 105685)
+++ /trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp	(revision 105686)
@@ -316,4 +316,33 @@
     SSMFIELD_ENTRY(         CPUMCTX, CntvCtlEl0),
     SSMFIELD_ENTRY(         CPUMCTX, CntvCValEl0),
+    /** @name EL2 support:
+     * @{ */
+    SSMFIELD_ENTRY(         CPUMCTX, CntHCtlEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, CntHpCtlEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, CntHpCValEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, CntHpTValEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, CntVOffEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, CptrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, ElrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, EsrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, FarEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, HcrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, HpFarEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, MairEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, MdcrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, SctlrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, SpsrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, SpEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, TcrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, TpidrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, Ttbr0El2),
+    SSMFIELD_ENTRY(         CPUMCTX, Ttbr1El2),
+    SSMFIELD_ENTRY(         CPUMCTX, VBarEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, VMpidrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, VPidrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, VTcrEl2),
+    SSMFIELD_ENTRY(         CPUMCTX, VTtbrEl2),
+    /** @} */
+
     SSMFIELD_ENTRY_TERM()
 };
@@ -362,11 +391,23 @@
 
     pVM->cpum.s.GuestInfo.paSysRegRangesR3 = &pVM->cpum.s.GuestInfo.aSysRegRanges[0];
+    pVM->cpum.s.bResetEl                   = ARMV8_AARCH64_EL_1;
 
     PCFGMNODE   pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM");
 
     /** @cfgm{/CPUM/ResetPcValue, string}
-     * Program counter value after a reset, sets the address of the first isntruction to execute. */
+     * Program counter value after a reset, sets the address of the first instruction to execute. */
     int rc = CFGMR3QueryU64Def(pCpumCfg, "ResetPcValue", &pVM->cpum.s.u64ResetPc, 0);
     AssertLogRelRCReturn(rc, rc);
+
+    /** @cfgm{/CPUM/NestedHWVirt, bool, false}
+     * Whether to expose the hardware virtualization (EL2) feature to the guest.
+     * The default is false, and when enabled requires a 64-bit CPU and a NEM backend
+     * supporting it.
+     */
+    bool fNestedHWVirt = false;
+    rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedHWVirt", &fNestedHWVirt, false);
+    AssertLogRelRCReturn(rc, rc);
+    if (fNestedHWVirt)
+        pVM->cpum.s.bResetEl = ARMV8_AARCH64_EL_2;
 
     /*
@@ -468,5 +509,5 @@
     /* Start in Supervisor mode. */
     /** @todo Differentiate between Aarch64 and Aarch32 configuation. */
-    pCtx->fPState =   ARMV8_SPSR_EL2_AARCH64_SET_EL(ARMV8_AARCH64_EL_1)
+    pCtx->fPState =   ARMV8_SPSR_EL2_AARCH64_SET_EL(pVM->cpum.s.bResetEl)
                     | ARMV8_SPSR_EL2_AARCH64_SP
                     | ARMV8_SPSR_EL2_AARCH64_D
Index: /trunk/src/VBox/VMM/VMMR3/CPUMDbg-armv8.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUMDbg-armv8.cpp	(revision 105685)
+++ /trunk/src/VBox/VMM/VMMR3/CPUMDbg-armv8.cpp	(revision 105686)
@@ -157,10 +157,4 @@
 #undef CPUMREGALIAS_STD
 
-static DBGFREGALIAS const g_aCpumRegAliases_pstate[] =
-{
-    { "spsr_el2", DBGFREGVALTYPE_U64     },
-    { NULL,       DBGFREGVALTYPE_INVALID }
-};
-
 
 /*
@@ -270,5 +264,5 @@
     CPU_GREG_REG(29),
     CPU_GREG_REG(30),
-    CPU_REG_RW_AS("pstate",         PSTATE,         U64, fPState,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         g_aCpumRegAliases_pstate,   g_aCpumRegFields_pstate ),
+    CPU_REG_RW_AS("pstate",         PSTATE,         U64, fPState,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       g_aCpumRegFields_pstate ),
     CPU_REG_RW_AS("pc",             PC,             U64, Pc,              cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
     CPU_REG_RW_AS("sp_el0",         SP_EL0,         U64, aSpReg[0],       cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
@@ -315,4 +309,30 @@
     CPU_VREG_REG(30),
     CPU_VREG_REG(31),
+    CPU_REG_RW_AS("cnthctl_el2",    CNTHCTL_EL2,    U64, CntHCtlEl2,      cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("cnthp_ctl_el2",  CNTHP_CTL_EL2,  U64, CntHpCtlEl2,     cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("cnthp_cval_el2", CNTHP_CVAL_EL2, U64, CntHpCValEl2,    cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("cnthp_tval_el2", CNTHP_TVAL_EL2, U64, CntHpTValEl2,    cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("cntvoff_el2",    CNTVOFF_EL2,    U64, CntVOffEl2,      cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("cptr_el2",       CPTR_EL2,       U64, CptrEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("elr_el2",        ELR_EL2,        U64, ElrEl2,          cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("esr_el2",        ESR_EL2,        U64, EsrEl2,          cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("far_el2",        FAR_EL2,        U64, FarEl2,          cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("hcr_el2",        HCR_EL2,        U64, HcrEl2,          cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("hpfar_el2",      HPFAR_EL2,      U64, HpFarEl2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("mair_el2",       MAIR_EL2,       U64, MairEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("mdcr_el2",       MDCR_EL2,       U64, MdcrEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("sctlr_el2",      SCTLR_EL2,      U64, SctlrEl2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("spsr_el2",       SPSR_EL2,       U64, SpsrEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("sp_el2",         SP_EL2,         U64, SpEl2,           cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("tcr_el2",        TCR_EL2,        U64, TcrEl2,          cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("tpidr_el2",      TPIDR_EL2,      U64, TpidrEl2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("ttbr0_el2",      TTBR0_EL2,      U64, Ttbr0El2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("ttbr1_el2",      TTBR1_EL2,      U64, Ttbr1El2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("vbar_el2",       VBAR_EL2,       U64, VBarEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("vmpidr_el2",     VMPIDR_EL2,     U64, VMpidrEl2,       cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("vpidr_el2",      VPIDR_EL2,      U64, VPidrEl2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("vtcr_el2",       VTCR_EL2,       U64, VTcrEl2,         cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+    CPU_REG_RW_AS("vttbr_el2",      VTTBR_EL2,      U64, VTtbrEl2,        cpumR3RegGet_Generic,         cpumR3RegSet_Generic,         NULL,                       NULL                    ),
+
     DBGFREGDESC_TERMINATOR()
 
Index: /trunk/src/VBox/VMM/include/CPUMInternal-armv8.h
===================================================================
--- /trunk/src/VBox/VMM/include/CPUMInternal-armv8.h	(revision 105685)
+++ /trunk/src/VBox/VMM/include/CPUMInternal-armv8.h	(revision 105686)
@@ -105,5 +105,9 @@
      * This is used to verify load order dependencies (PGM). */
     bool                    fPendingRestore;
-    uint8_t                 abPadding0[6];
+    /** The initial exception level (EL) to start the CPU after a reset,
+     * should be either ARMV8_AARCH64_EL_1 or ARMV8_AARCH64_EL_2 for nested virtualization. */
+    uint8_t                 bResetEl;
+
+    uint8_t                 abPadding0[5];
 
     /** The reset value of the program counter. */
