Changeset 104399 in vbox for trunk/src/VBox/VMM/VMMR3/NEMR3Native-linux-armv8.cpp
- Timestamp:
- Apr 22, 2024 8:30:25 PM (9 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/NEMR3Native-linux-armv8.cpp
r104387 r104399 46 46 #include <iprt/armv8.h> 47 47 48 #include <iprt/formats/arm-psci.h> 49 48 50 #include <errno.h> 49 51 #include <unistd.h> … … 56 58 * We'll see whether it would make sense to merge things later on when things have settled. 57 59 */ 60 61 62 /********************************************************************************************************************************* 63 * Defined Constants And Macros * 64 *********************************************************************************************************************************/ 58 65 59 66 /** Core register group. */ … … 82 89 #define KVM_ARM64_REG_SYS_CREATE(a_idSysReg) (KVM_ARM64_REG_SYS_GROUP | ((uint64_t)(a_idSysReg) & 0xffff)) 83 90 84 #define KVM_ARM64_REG_SIMD_CREATE(a_iVecReg) (KVM_ARM64_REG_SIMD_GROUP | (((uint64_t)(a_i dReg) << 2) & 0xffff))91 #define KVM_ARM64_REG_SIMD_CREATE(a_iVecReg) (KVM_ARM64_REG_SIMD_GROUP | (((uint64_t)(a_iVecReg) << 2) & 0xffff)) 85 92 86 93 #define KVM_ARM64_REG_FP_CREATE(a_idReg) (KVM_ARM64_REG_FP_GROUP | ((uint64_t)(a_idReg) & 0xffff)) … … 89 96 90 97 98 /********************************************************************************************************************************* 99 * Structures and Typedefs * 100 *********************************************************************************************************************************/ 101 102 103 /********************************************************************************************************************************* 104 * Global Variables * 105 *********************************************************************************************************************************/ 106 /** The general registers. */ 107 static const struct 108 { 109 uint64_t idKvmReg; 110 uint32_t fCpumExtrn; 111 uint32_t offCpumCtx; 112 } s_aCpumRegs[] = 113 { 114 #define CPUM_GREG_EMIT_X0_X3(a_Idx) { KVM_ARM64_REG_GPR(a_Idx), CPUMCTX_EXTRN_X ## a_Idx, RT_UOFFSETOF(CPUMCTX, aGRegs[a_Idx].x) } 115 #define CPUM_GREG_EMIT_X4_X28(a_Idx) { KVM_ARM64_REG_GPR(a_Idx), CPUMCTX_EXTRN_X4_X28, RT_UOFFSETOF(CPUMCTX, aGRegs[a_Idx].x) } 116 CPUM_GREG_EMIT_X0_X3(0), 117 CPUM_GREG_EMIT_X0_X3(1), 118 CPUM_GREG_EMIT_X0_X3(2), 119 CPUM_GREG_EMIT_X0_X3(3), 120 CPUM_GREG_EMIT_X4_X28(4), 121 CPUM_GREG_EMIT_X4_X28(5), 122 CPUM_GREG_EMIT_X4_X28(6), 123 CPUM_GREG_EMIT_X4_X28(7), 124 CPUM_GREG_EMIT_X4_X28(8), 125 CPUM_GREG_EMIT_X4_X28(9), 126 CPUM_GREG_EMIT_X4_X28(10), 127 CPUM_GREG_EMIT_X4_X28(11), 128 CPUM_GREG_EMIT_X4_X28(12), 129 CPUM_GREG_EMIT_X4_X28(13), 130 CPUM_GREG_EMIT_X4_X28(14), 131 CPUM_GREG_EMIT_X4_X28(15), 132 CPUM_GREG_EMIT_X4_X28(16), 133 CPUM_GREG_EMIT_X4_X28(17), 134 CPUM_GREG_EMIT_X4_X28(18), 135 CPUM_GREG_EMIT_X4_X28(19), 136 CPUM_GREG_EMIT_X4_X28(20), 137 CPUM_GREG_EMIT_X4_X28(21), 138 CPUM_GREG_EMIT_X4_X28(22), 139 CPUM_GREG_EMIT_X4_X28(23), 140 CPUM_GREG_EMIT_X4_X28(24), 141 CPUM_GREG_EMIT_X4_X28(25), 142 CPUM_GREG_EMIT_X4_X28(26), 143 CPUM_GREG_EMIT_X4_X28(27), 144 CPUM_GREG_EMIT_X4_X28(28), 145 { KVM_ARM64_REG_GPR(29), CPUMCTX_EXTRN_FP, RT_UOFFSETOF(CPUMCTX, aGRegs[29].x) }, 146 { KVM_ARM64_REG_GPR(30), CPUMCTX_EXTRN_LR, RT_UOFFSETOF(CPUMCTX, aGRegs[30].x) }, 147 { KVM_ARM64_REG_PC, CPUMCTX_EXTRN_PC, RT_UOFFSETOF(CPUMCTX, Pc.u64) }, 148 #undef CPUM_GREG_EMIT_X0_X3 149 #undef CPUM_GREG_EMIT_X4_X28 150 }; 151 /** SIMD/FP registers. */ 152 static const struct 153 { 154 uint64_t idKvmReg; 155 uint32_t offCpumCtx; 156 } s_aCpumFpRegs[] = 157 { 158 #define CPUM_VREG_EMIT(a_Idx) { KVM_ARM64_REG_SIMD_CREATE(a_Idx), RT_UOFFSETOF(CPUMCTX, aVRegs[a_Idx].v) } 159 CPUM_VREG_EMIT(0), 160 CPUM_VREG_EMIT(1), 161 CPUM_VREG_EMIT(2), 162 CPUM_VREG_EMIT(3), 163 CPUM_VREG_EMIT(4), 164 CPUM_VREG_EMIT(5), 165 CPUM_VREG_EMIT(6), 166 CPUM_VREG_EMIT(7), 167 CPUM_VREG_EMIT(8), 168 CPUM_VREG_EMIT(9), 169 CPUM_VREG_EMIT(10), 170 CPUM_VREG_EMIT(11), 171 CPUM_VREG_EMIT(12), 172 CPUM_VREG_EMIT(13), 173 CPUM_VREG_EMIT(14), 174 CPUM_VREG_EMIT(15), 175 CPUM_VREG_EMIT(16), 176 CPUM_VREG_EMIT(17), 177 CPUM_VREG_EMIT(18), 178 CPUM_VREG_EMIT(19), 179 CPUM_VREG_EMIT(20), 180 CPUM_VREG_EMIT(21), 181 CPUM_VREG_EMIT(22), 182 CPUM_VREG_EMIT(23), 183 CPUM_VREG_EMIT(24), 184 CPUM_VREG_EMIT(25), 185 CPUM_VREG_EMIT(26), 186 CPUM_VREG_EMIT(27), 187 CPUM_VREG_EMIT(28), 188 CPUM_VREG_EMIT(29), 189 CPUM_VREG_EMIT(30), 190 CPUM_VREG_EMIT(31) 191 #undef CPUM_VREG_EMIT 192 }; 193 /** System registers. */ 194 static const struct 195 { 196 uint64_t idKvmReg; 197 uint32_t fCpumExtrn; 198 uint32_t offCpumCtx; 199 } s_aCpumSysRegs[] = 200 { 201 { KVM_ARM64_REG_SP_EL0, CPUMCTX_EXTRN_SP, RT_UOFFSETOF(CPUMCTX, aSpReg[0].u64) }, 202 { KVM_ARM64_REG_SP_EL1, CPUMCTX_EXTRN_SP, RT_UOFFSETOF(CPUMCTX, aSpReg[1].u64) }, 203 { KVM_ARM64_REG_SPSR_EL1, CPUMCTX_EXTRN_SPSR, RT_UOFFSETOF(CPUMCTX, Spsr.u64) }, 204 { KVM_ARM64_REG_ELR_EL1, CPUMCTX_EXTRN_ELR, RT_UOFFSETOF(CPUMCTX, Elr.u64) }, 205 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_SCTRL_EL1), CPUMCTX_EXTRN_SCTLR_TCR_TTBR, RT_UOFFSETOF(CPUMCTX, Sctlr.u64) }, 206 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TCR_EL1), CPUMCTX_EXTRN_SCTLR_TCR_TTBR, RT_UOFFSETOF(CPUMCTX, Tcr.u64) }, 207 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TTBR0_EL1), CPUMCTX_EXTRN_SCTLR_TCR_TTBR, RT_UOFFSETOF(CPUMCTX, Ttbr0.u64) }, 208 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TTBR1_EL1), CPUMCTX_EXTRN_SCTLR_TCR_TTBR, RT_UOFFSETOF(CPUMCTX, Ttbr1.u64) }, 209 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_VBAR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, VBar.u64) }, 210 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AFSR0_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Afsr0.u64) }, 211 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AFSR1_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Afsr1.u64) }, 212 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AMAIR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Amair.u64) }, 213 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CNTKCTL_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, CntKCtl.u64) }, 214 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CONTEXTIDR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, ContextIdr.u64) }, 215 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CPACR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Cpacr.u64) }, 216 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CSSELR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Csselr.u64) }, 217 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_ESR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Esr.u64) }, 218 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_FAR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Far.u64) }, 219 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_MAIR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Mair.u64) }, 220 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_PAR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, Par.u64) }, 221 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDRRO_EL0), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, TpIdrRoEl0.u64) }, 222 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDR_EL0), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, aTpIdr[0].u64) }, 223 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDR_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, aTpIdr[1].u64) }, 224 { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_MDCCINT_EL1), CPUMCTX_EXTRN_SYSREG_MISC, RT_UOFFSETOF(CPUMCTX, MDccInt.u64) } 225 }; 91 226 /** ID registers. */ 92 227 static const struct … … 480 615 481 616 482 DECL_FORCE_INLINE(int) nemR3LnxKvmSetQueryReg(PVMCPUCC pVCpu, bool fQuery, uint64_t idKvmReg, const uint64_t *pu64) 617 /** 618 * Sets the given attribute in KVM to the given value. 619 * 620 * @returns VBox status code. 621 * @param pVM The VM instance. 622 * @param u32Grp The device attribute group being set. 623 * @param u32Attr The actual attribute inside the group being set. 624 * @param pvAttrVal Where the attribute value to set. 625 * @param pszAttribute Attribute description for logging. 626 * @param pErrInfo Optional error information. 627 */ 628 static int nemR3LnxSetAttribute(PVM pVM, uint32_t u32Grp, uint32_t u32Attr, const void *pvAttrVal, const char *pszAttribute, 629 PRTERRINFO pErrInfo) 630 { 631 struct kvm_device_attr DevAttr; 632 633 DevAttr.flags = 0; 634 DevAttr.group = u32Grp; 635 DevAttr.attr = u32Attr; 636 DevAttr.addr = (uintptr_t)pvAttrVal; 637 int rcLnx = ioctl(pVM->nem.s.fdVm, KVM_HAS_DEVICE_ATTR, &DevAttr); 638 if (rcLnx < 0) 639 return RTErrInfoSetF(pErrInfo, RTErrConvertFromErrno(errno), 640 N_("KVM error: KVM doesn't support setting the attribute \"%s\" (%d)"), 641 pszAttribute, errno); 642 643 rcLnx = ioctl(pVM->nem.s.fdVm, KVM_SET_DEVICE_ATTR, &DevAttr); 644 if (rcLnx < 0) 645 return RTErrInfoSetF(pErrInfo, RTErrConvertFromErrno(errno), 646 N_("KVM error: Setting the attribute \"%s\" for KVM failed (%d)"), 647 pszAttribute, errno); 648 649 return VINF_SUCCESS; 650 } 651 652 653 DECL_FORCE_INLINE(int) nemR3LnxKvmSetQueryReg(PVMCPUCC pVCpu, bool fQuery, uint64_t idKvmReg, const void *pv) 483 654 { 484 655 struct kvm_one_reg Reg; 485 656 Reg.id = idKvmReg; 486 Reg.addr = (uintptr_t)p u64;657 Reg.addr = (uintptr_t)pv; 487 658 488 659 /* … … 497 668 } 498 669 499 DECLINLINE(int) nemR3LnxKvmQueryReg (PVMCPUCC pVCpu, uint64_t idKvmReg, uint64_t *pu64)670 DECLINLINE(int) nemR3LnxKvmQueryRegU64(PVMCPUCC pVCpu, uint64_t idKvmReg, uint64_t *pu64) 500 671 { 501 672 return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pu64); … … 503 674 504 675 505 DECLINLINE(int) nemR3LnxKvmSetReg(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint64_t *pu64) 676 DECLINLINE(int) nemR3LnxKvmQueryRegU32(PVMCPUCC pVCpu, uint64_t idKvmReg, uint32_t *pu32) 677 { 678 return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pu32); 679 } 680 681 682 DECLINLINE(int) nemR3LnxKvmQueryRegPV(PVMCPUCC pVCpu, uint64_t idKvmReg, void *pv) 683 { 684 return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pv); 685 } 686 687 688 DECLINLINE(int) nemR3LnxKvmSetRegU64(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint64_t *pu64) 506 689 { 507 690 return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pu64); 691 } 692 693 694 DECLINLINE(int) nemR3LnxKvmSetRegU32(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint32_t *pu32) 695 { 696 return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pu32); 697 } 698 699 700 DECLINLINE(int) nemR3LnxKvmSetRegPV(PVMCPUCC pVCpu, uint64_t idKvmReg, const void *pv) 701 { 702 return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pv); 508 703 } 509 704 … … 563 758 { 564 759 uint64_t *pu64 = (uint64_t *)((uint8_t *)&IdRegs + s_aIdRegs[i].offIdStruct); 565 rc = nemR3LnxKvmQueryReg (pVCpu, s_aIdRegs[i].idKvmReg, pu64);760 rc = nemR3LnxKvmQueryRegU64(pVCpu, s_aIdRegs[i].idKvmReg, pu64); 566 761 if (RT_FAILURE(rc)) 567 762 return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS, … … 574 769 } 575 770 } 771 772 /* 773 * Setup the SMCCC filter to get exits for PSCI related 774 * guest calls (to support SMP, power off and reset). 775 */ 776 struct kvm_smccc_filter SmcccPsciFilter; RT_ZERO(SmcccPsciFilter); 777 SmcccPsciFilter.base = ARM_PSCI_FUNC_ID_CREATE_FAST_64(ARM_PSCI_FUNC_ID_PSCI_VERSION); 778 SmcccPsciFilter.nr_functions = ARM_PSCI_FUNC_ID_CREATE_FAST_64(ARM_PSCI_FUNC_ID_SYSTEM_RESET) - SmcccPsciFilter.base + 1; 779 SmcccPsciFilter.action = KVM_SMCCC_FILTER_FWD_TO_USER; 780 int rc = nemR3LnxSetAttribute(pVM, KVM_ARM_VM_SMCCC_CTRL, KVM_ARM_VM_SMCCC_FILTER, &SmcccPsciFilter, 781 "KVM_ARM_VM_SMCCC_FILTER", pErrInfo); 782 if (RT_FAILURE(rc)) 783 return rc; 784 785 SmcccPsciFilter.base = ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_PSCI_VERSION); 786 SmcccPsciFilter.nr_functions = ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_SYSTEM_RESET) - SmcccPsciFilter.base + 1; 787 SmcccPsciFilter.action = KVM_SMCCC_FILTER_FWD_TO_USER; 788 rc = nemR3LnxSetAttribute(pVM, KVM_ARM_VM_SMCCC_CTRL, KVM_ARM_VM_SMCCC_FILTER, &SmcccPsciFilter, 789 "KVM_ARM_VM_SMCCC_FILTER", pErrInfo); 790 if (RT_FAILURE(rc)) 791 return rc; 792 576 793 return VINF_SUCCESS; 577 794 } … … 1176 1393 1177 1394 /** 1395 * Sets the given general purpose register to the given value. 1396 * 1397 * @param pVCpu The cross context virtual CPU structure of the 1398 * calling EMT. 1399 * @param uReg The register index. 1400 * @param f64BitReg Flag whether to operate on a 64-bit or 32-bit register. 1401 * @param fSignExtend Flag whether to sign extend the value. 1402 * @param u64Val The value. 1403 */ 1404 DECLINLINE(void) nemR3LnxSetGReg(PVMCPU pVCpu, uint8_t uReg, bool f64BitReg, bool fSignExtend, uint64_t u64Val) 1405 { 1406 AssertReturnVoid(uReg < 31); 1407 1408 if (f64BitReg) 1409 pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val; 1410 else 1411 pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */ 1412 1413 /* Mark the register as not extern anymore. */ 1414 switch (uReg) 1415 { 1416 case 0: 1417 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X0; 1418 break; 1419 case 1: 1420 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X1; 1421 break; 1422 case 2: 1423 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X2; 1424 break; 1425 case 3: 1426 pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X3; 1427 break; 1428 default: 1429 AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_X4_X28)); 1430 /** @todo We need to import all missing registers in order to clear this flag (or just set it in HV from here). */ 1431 } 1432 } 1433 1434 1435 /** 1436 * Gets the given general purpose register and returns the value. 1437 * 1438 * @returns Value from the given register. 1439 * @param pVCpu The cross context virtual CPU structure of the 1440 * calling EMT. 1441 * @param uReg The register index. 1442 */ 1443 DECLINLINE(uint64_t) nemR3LnxGetGReg(PVMCPU pVCpu, uint8_t uReg) 1444 { 1445 AssertReturn(uReg <= ARMV8_AARCH64_REG_ZR, 0); 1446 1447 if (uReg == ARMV8_AARCH64_REG_ZR) 1448 return 0; 1449 1450 /** @todo Import the register if extern. */ 1451 //AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_GPRS_MASK)); 1452 1453 return pVCpu->cpum.GstCtx.aGRegs[uReg].x; 1454 } 1455 1456 /** 1178 1457 * Worker that imports selected state from KVM. 1179 1458 */ 1180 static int nemHCLnxImportState(PVMCPUCC pVCpu, uint64_t fWhat, PCPUMCTX pCtx , struct kvm_run *pRun)1459 static int nemHCLnxImportState(PVMCPUCC pVCpu, uint64_t fWhat, PCPUMCTX pCtx) 1181 1460 { 1182 1461 fWhat &= pVCpu->cpum.GstCtx.fExtrn; … … 1184 1463 return VINF_SUCCESS; 1185 1464 1186 RT_NOREF(pRun); 1187 1188 /** @todo */ 1465 #if 0 1466 hv_return_t hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CTL_EL0, &pVCpu->cpum.GstCtx.CntvCtlEl0); 1467 if (hrc == HV_SUCCESS) 1468 hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CVAL_EL0, &pVCpu->cpum.GstCtx.CntvCValEl0); 1469 #endif 1470 1471 int rc = VINF_SUCCESS; 1472 if (fWhat & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC)) 1473 { 1474 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumRegs); i++) 1475 { 1476 if (s_aCpumRegs[i].fCpumExtrn & fWhat) 1477 { 1478 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumRegs[i].offCpumCtx); 1479 rc |= nemR3LnxKvmQueryRegU64(pVCpu, s_aCpumRegs[i].idKvmReg, pu64); 1480 } 1481 } 1482 } 1483 1484 if ( rc == VINF_SUCCESS 1485 && (fWhat & CPUMCTX_EXTRN_FPCR)) 1486 { 1487 uint32_t u32Tmp; 1488 rc |= nemR3LnxKvmQueryRegU32(pVCpu, KVM_ARM64_REG_FP_FPCR, &u32Tmp); 1489 if (rc == VINF_SUCCESS) 1490 pVCpu->cpum.GstCtx.fpcr = u32Tmp; 1491 } 1492 1493 if ( rc == VINF_SUCCESS 1494 && (fWhat & CPUMCTX_EXTRN_FPSR)) 1495 { 1496 uint32_t u32Tmp; 1497 rc |= nemR3LnxKvmQueryRegU32(pVCpu, KVM_ARM64_REG_FP_FPSR, &u32Tmp); 1498 if (rc == VINF_SUCCESS) 1499 pVCpu->cpum.GstCtx.fpsr = u32Tmp; 1500 } 1501 1502 if ( rc == VINF_SUCCESS 1503 && (fWhat & CPUMCTX_EXTRN_V0_V31)) 1504 { 1505 /* SIMD/FP registers. */ 1506 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumFpRegs); i++) 1507 { 1508 void *pu128 = (void *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumFpRegs[i].offCpumCtx); 1509 rc |= nemR3LnxKvmQueryRegPV(pVCpu, s_aCpumFpRegs[i].idKvmReg, pu128); 1510 } 1511 } 1512 1513 if ( rc == VINF_SUCCESS 1514 && (fWhat & CPUMCTX_EXTRN_SYSREG_DEBUG)) 1515 { 1516 #if 0 1517 /* Debug registers. */ 1518 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumDbgRegs); i++) 1519 { 1520 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumDbgRegs[i].offCpumCtx); 1521 rc |= nemR3LnxKvmQueryReg(pVCpu, s_aCpumDbgRegs[i].idKvmReg, pu64); 1522 } 1523 #endif 1524 } 1525 1526 if ( rc == VINF_SUCCESS 1527 && (fWhat & CPUMCTX_EXTRN_SYSREG_PAUTH_KEYS)) 1528 { 1529 #if 0 1530 /* PAuth registers. */ 1531 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumPAuthKeyRegs); i++) 1532 { 1533 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumPAuthKeyRegs[i].offCpumCtx); 1534 hrc |= nemR3LnxKvmQueryReg(pVCpu, s_aCpumPAuthKeyRegs[i].idKvmReg, pu64); 1535 } 1536 #endif 1537 } 1538 1539 if ( rc == VINF_SUCCESS 1540 && (fWhat & (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC))) 1541 { 1542 /* System registers. */ 1543 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumSysRegs); i++) 1544 { 1545 if (s_aCpumSysRegs[i].fCpumExtrn & fWhat) 1546 { 1547 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumSysRegs[i].offCpumCtx); 1548 rc |= nemR3LnxKvmQueryRegU64(pVCpu, s_aCpumSysRegs[i].idKvmReg, pu64); 1549 } 1550 } 1551 } 1552 1553 if ( rc == VINF_SUCCESS 1554 && (fWhat & CPUMCTX_EXTRN_PSTATE)) 1555 { 1556 uint64_t u64Tmp; 1557 rc |= nemR3LnxKvmQueryRegU64(pVCpu, KVM_ARM64_REG_PSTATE, &u64Tmp); 1558 if (rc == VINF_SUCCESS) 1559 pVCpu->cpum.GstCtx.fPState = (uint32_t)u64Tmp; 1560 1561 } 1189 1562 1190 1563 /* … … 1210 1583 { 1211 1584 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatImportOnDemand); 1212 return nemHCLnxImportState(pVCpu, fWhat, &pVCpu->cpum.GstCtx , pVCpu->nem.s.pRun);1585 return nemHCLnxImportState(pVCpu, fWhat, &pVCpu->cpum.GstCtx); 1213 1586 } 1214 1587 … … 1217 1590 * Exports state to KVM. 1218 1591 */ 1219 static int nemHCLnxExportState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx , struct kvm_run *pRun)1592 static int nemHCLnxExportState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1220 1593 { 1221 1594 uint64_t const fExtrn = ~pCtx->fExtrn & CPUMCTX_EXTRN_ALL; 1222 Assert((~fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL); 1223 1224 RT_NOREF(pVM, pVCpu, pCtx, pRun, fExtrn); 1225 /** @todo */ 1595 Assert((~fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL); RT_NOREF(fExtrn); 1596 1597 RT_NOREF(pVM); 1598 int rc = VINF_SUCCESS; 1599 if ( (pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC)) 1600 != (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC)) 1601 { 1602 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumRegs); i++) 1603 { 1604 if (!(s_aCpumRegs[i].fCpumExtrn & pVCpu->cpum.GstCtx.fExtrn)) 1605 { 1606 const uint64_t *pu64 = (const uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumRegs[i].offCpumCtx); 1607 rc |= nemR3LnxKvmSetRegU64(pVCpu, s_aCpumRegs[i].idKvmReg, pu64); 1608 } 1609 } 1610 } 1611 1612 if ( rc == VINF_SUCCESS 1613 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_FPCR)) 1614 { 1615 uint32_t u32Tmp = pVCpu->cpum.GstCtx.fpcr; 1616 rc |= nemR3LnxKvmSetRegU32(pVCpu, KVM_ARM64_REG_FP_FPCR, &u32Tmp); 1617 } 1618 1619 if ( rc == VINF_SUCCESS 1620 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_FPSR)) 1621 { 1622 uint32_t u32Tmp = pVCpu->cpum.GstCtx.fpsr; 1623 rc |= nemR3LnxKvmSetRegU32(pVCpu, KVM_ARM64_REG_FP_FPSR, &u32Tmp); 1624 } 1625 1626 if ( rc == VINF_SUCCESS 1627 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_V0_V31)) 1628 { 1629 /* SIMD/FP registers. */ 1630 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumFpRegs); i++) 1631 { 1632 void *pu128 = (void *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumFpRegs[i].offCpumCtx); 1633 rc |= nemR3LnxKvmSetRegPV(pVCpu, s_aCpumFpRegs[i].idKvmReg, pu128); 1634 } 1635 } 1636 1637 if ( rc == VINF_SUCCESS 1638 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_SYSREG_DEBUG)) 1639 { 1640 #if 0 1641 /* Debug registers. */ 1642 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumDbgRegs); i++) 1643 { 1644 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumDbgRegs[i].offCpumCtx); 1645 hrc |= hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, s_aCpumDbgRegs[i].enmHvReg, *pu64); 1646 } 1647 #endif 1648 } 1649 1650 if ( rc == VINF_SUCCESS 1651 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_SYSREG_PAUTH_KEYS)) 1652 { 1653 #if 0 1654 /* Debug registers. */ 1655 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumPAuthKeyRegs); i++) 1656 { 1657 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumPAuthKeyRegs[i].offCpumCtx); 1658 hrc |= hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, s_aCpumPAuthKeyRegs[i].enmHvReg, *pu64); 1659 } 1660 #endif 1661 } 1662 1663 if ( rc == VINF_SUCCESS 1664 && (pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC)) 1665 != (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC)) 1666 { 1667 /* System registers. */ 1668 for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumSysRegs); i++) 1669 { 1670 if (!(s_aCpumSysRegs[i].fCpumExtrn & pVCpu->cpum.GstCtx.fExtrn)) 1671 { 1672 uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumSysRegs[i].offCpumCtx); 1673 rc |= nemR3LnxKvmSetRegU64(pVCpu, s_aCpumSysRegs[i].idKvmReg, pu64); 1674 } 1675 } 1676 } 1677 1678 if ( rc == VINF_SUCCESS 1679 && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_PSTATE)) 1680 { 1681 uint64_t u64Tmp = pVCpu->cpum.GstCtx.fPState; 1682 rc = nemR3LnxKvmSetRegU64(pVCpu, KVM_ARM64_REG_PSTATE, &u64Tmp); 1683 } 1226 1684 1227 1685 /* … … 1479 1937 1480 1938 1939 /** 1940 * Handles KVM_EXIT_HYPERCALL. 1941 */ 1942 static VBOXSTRICTRC nemHCLnxHandleExitHypercall(PVMCC pVM, PVMCPUCC pVCpu, struct kvm_run *pRun) 1943 { 1944 #if 0 1945 /* 1946 * We cannot easily act on the exit history here, because the MMIO port 1947 * exit is stateful and the instruction will be completed in the next 1948 * KVM_RUN call. There seems no way to circumvent this. 1949 */ 1950 EMHistoryAddExit(pVCpu, 1951 pRun->mmio.is_write 1952 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE) 1953 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ), 1954 pRun->s.regs.regs.pc, ASMReadTSC()); 1955 #else 1956 RT_NOREF(pVCpu); 1957 #endif 1958 1959 /* 1960 * Do the requested job. 1961 */ 1962 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 1963 1964 /** @todo Raise exception to EL1 if PSCI not configured. */ 1965 /** @todo Need a generic mechanism here to pass this to, GIM maybe?. */ 1966 uint32_t uFunId = pRun->hypercall.nr; 1967 bool fHvc64 = RT_BOOL(uFunId & ARM_SMCCC_FUNC_ID_64BIT); RT_NOREF(fHvc64); 1968 uint32_t uEntity = ARM_SMCCC_FUNC_ID_ENTITY_GET(uFunId); 1969 uint32_t uFunNum = ARM_SMCCC_FUNC_ID_NUM_GET(uFunId); 1970 if (uEntity == ARM_SMCCC_FUNC_ID_ENTITY_STD_SEC_SERVICE) 1971 { 1972 rcStrict = nemHCLnxImportState(pVCpu, CPUMCTX_EXTRN_X0 | CPUMCTX_EXTRN_X1 | CPUMCTX_EXTRN_X2 | CPUMCTX_EXTRN_X3, 1973 &pVCpu->cpum.GstCtx); 1974 if (rcStrict != VINF_SUCCESS) 1975 return rcStrict; 1976 1977 switch (uFunNum) 1978 { 1979 case ARM_PSCI_FUNC_ID_PSCI_VERSION: 1980 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_FUNC_ID_PSCI_VERSION_SET(1, 2)); 1981 break; 1982 case ARM_PSCI_FUNC_ID_SYSTEM_OFF: 1983 rcStrict = VMR3PowerOff(pVM->pUVM); 1984 break; 1985 case ARM_PSCI_FUNC_ID_SYSTEM_RESET: 1986 case ARM_PSCI_FUNC_ID_SYSTEM_RESET2: 1987 { 1988 bool fHaltOnReset; 1989 int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset); 1990 if (RT_SUCCESS(rc) && fHaltOnReset) 1991 { 1992 Log(("nemHCLnxHandleExitHypercall: Halt On Reset!\n")); 1993 rcStrict = VINF_EM_HALT; 1994 } 1995 else 1996 { 1997 /** @todo pVM->pdm.s.fResetFlags = fFlags; */ 1998 VM_FF_SET(pVM, VM_FF_RESET); 1999 rcStrict = VINF_EM_RESET; 2000 } 2001 break; 2002 } 2003 case ARM_PSCI_FUNC_ID_CPU_ON: 2004 { 2005 uint64_t u64TgtCpu = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X1); 2006 RTGCPHYS GCPhysExecAddr = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X2); 2007 uint64_t u64CtxId = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X3); 2008 VMMR3CpuOn(pVM, u64TgtCpu & 0xff, GCPhysExecAddr, u64CtxId); 2009 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, true /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_STS_SUCCESS); 2010 break; 2011 } 2012 case ARM_PSCI_FUNC_ID_PSCI_FEATURES: 2013 { 2014 uint32_t u32FunNum = (uint32_t)nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X1); 2015 switch (u32FunNum) 2016 { 2017 case ARM_PSCI_FUNC_ID_PSCI_VERSION: 2018 case ARM_PSCI_FUNC_ID_SYSTEM_OFF: 2019 case ARM_PSCI_FUNC_ID_SYSTEM_RESET: 2020 case ARM_PSCI_FUNC_ID_SYSTEM_RESET2: 2021 case ARM_PSCI_FUNC_ID_CPU_ON: 2022 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, 2023 false /*f64BitReg*/, false /*fSignExtend*/, 2024 (uint64_t)ARM_PSCI_STS_SUCCESS); 2025 break; 2026 default: 2027 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, 2028 false /*f64BitReg*/, false /*fSignExtend*/, 2029 (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED); 2030 } 2031 break; 2032 } 2033 default: 2034 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED); 2035 } 2036 } 2037 else 2038 nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED); 2039 2040 2041 return rcStrict; 2042 } 2043 2044 1481 2045 static VBOXSTRICTRC nemHCLnxHandleExit(PVMCC pVM, PVMCPUCC pVCpu, struct kvm_run *pRun, bool *pfStatefulExit) 1482 2046 { … … 1520 2084 return VINF_SUCCESS; 1521 2085 1522 #if 01523 2086 case KVM_EXIT_HYPERCALL: 1524 2087 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHypercall); 1525 AssertFailed();1526 break; 1527 2088 return nemHCLnxHandleExitHypercall(pVM, pVCpu, pRun); 2089 2090 #if 0 1528 2091 case KVM_EXIT_DEBUG: 1529 2092 STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitDebug); … … 1643 2206 if ((pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL) 1644 2207 { 1645 int rc2 = nemHCLnxExportState(pVM, pVCpu, &pVCpu->cpum.GstCtx , pRun);2208 int rc2 = nemHCLnxExportState(pVM, pVCpu, &pVCpu->cpum.GstCtx); 1646 2209 AssertRCReturn(rc2, rc2); 1647 2210 } … … 1811 2374 if (pVCpu->cpum.GstCtx.fExtrn & fImport) 1812 2375 { 1813 int rc2 = nemHCLnxImportState(pVCpu, fImport, &pVCpu->cpum.GstCtx , pRun);2376 int rc2 = nemHCLnxImportState(pVCpu, fImport, &pVCpu->cpum.GstCtx); 1814 2377 if (RT_SUCCESS(rc2)) 1815 2378 pVCpu->cpum.GstCtx.fExtrn &= ~fImport;
Note:
See TracChangeset
for help on using the changeset viewer.