Changeset 40357 in vbox
- Timestamp:
- Mar 5, 2012 1:55:06 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r40356 r40357 105 105 106 106 /** 107 * Sets the PC for which interrupts should be inhibited. 108 * 109 * @param pVCpu The VMCPU handle. 110 * @param PC The PC. 111 */ 112 VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC) 113 { 114 pVCpu->em.s.GCPtrInhibitInterrupts = PC; 115 VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); 116 } 117 118 119 /** 120 * Gets the PC for which interrupts should be inhibited. 121 * 122 * There are a few instructions which inhibits or delays interrupts 123 * for the instruction following them. These instructions are: 124 * - STI 125 * - MOV SS, r/m16 126 * - POP SS 127 * 128 * @returns The PC for which interrupts should be inhibited. 129 * @param pVCpu The VMCPU handle. 130 * 131 */ 132 VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu) 133 { 134 return pVCpu->em.s.GCPtrInhibitInterrupts; 135 } 136 137 138 /** 139 * Prepare an MWAIT - essentials of the MONITOR instruction. 140 * 141 * @returns VINF_SUCCESS 142 * @param pVCpu The current CPU. 143 * @param rax The content of RAX. 144 * @param rcx The content of RCX. 145 * @param rdx The content of RDX. 146 */ 147 VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx) 148 { 149 pVCpu->em.s.MWait.uMonitorRAX = rax; 150 pVCpu->em.s.MWait.uMonitorRCX = rcx; 151 pVCpu->em.s.MWait.uMonitorRDX = rdx; 152 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE; 153 /** @todo Complete MONITOR implementation. */ 154 return VINF_SUCCESS; 155 } 156 157 158 /** 159 * Performs an MWAIT. 160 * 161 * @returns VINF_SUCCESS 162 * @param pVCpu The current CPU. 163 * @param rax The content of RAX. 164 * @param rcx The content of RCX. 165 */ 166 VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx) 167 { 168 pVCpu->em.s.MWait.uMWaitRAX = rax; 169 pVCpu->em.s.MWait.uMWaitRCX = rcx; 170 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_ACTIVE; 171 if (rcx) 172 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_BREAKIRQIF0; 173 else 174 pVCpu->em.s.MWait.fWait &= ~EMMWAIT_FLAG_BREAKIRQIF0; 175 /** @todo not completely correct?? */ 176 return VINF_EM_HALT; 177 } 178 179 180 181 /** 182 * Determine if we should continue after encountering a hlt or mwait 183 * instruction. 184 * 185 * Clears MWAIT flags if returning @c true. 186 * 187 * @returns boolean 188 * @param pVCpu The VMCPU to operate on. 189 * @param pCtx Current CPU context. 190 */ 191 VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx) 192 { 193 if ( pCtx->eflags.Bits.u1IF 194 || ( (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) 195 == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) ) 196 { 197 pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0); 198 return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)); 199 } 200 201 return false; 202 } 203 204 205 /** 206 * Locks REM execution to a single VCpu 207 * 208 * @param pVM VM handle. 209 */ 210 VMMDECL(void) EMRemLock(PVM pVM) 211 { 212 #ifdef VBOX_WITH_REM 213 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 214 return; /* early init */ 215 216 Assert(!PGMIsLockOwner(pVM)); 217 Assert(!IOMIsLockOwner(pVM)); 218 int rc = PDMCritSectEnter(&pVM->em.s.CritSectREM, VERR_SEM_BUSY); 219 AssertRCSuccess(rc); 220 #endif 221 } 222 223 224 /** 225 * Unlocks REM execution 226 * 227 * @param pVM VM handle. 228 */ 229 VMMDECL(void) EMRemUnlock(PVM pVM) 230 { 231 #ifdef VBOX_WITH_REM 232 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 233 return; /* early init */ 234 235 PDMCritSectLeave(&pVM->em.s.CritSectREM); 236 #endif 237 } 238 239 240 /** 241 * Check if this VCPU currently owns the REM lock. 242 * 243 * @returns bool owner/not owner 244 * @param pVM The VM to operate on. 245 */ 246 VMMDECL(bool) EMRemIsLockOwner(PVM pVM) 247 { 248 #ifdef VBOX_WITH_REM 249 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 250 return true; /* early init */ 251 252 return PDMCritSectIsOwner(&pVM->em.s.CritSectREM); 253 #else 254 return true; 255 #endif 256 } 257 258 259 /** 260 * Try to acquire the REM lock. 261 * 262 * @returns VBox status code 263 * @param pVM The VM to operate on. 264 */ 265 VMMDECL(int) EMRemTryLock(PVM pVM) 266 { 267 #ifdef VBOX_WITH_REM 268 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 269 return VINF_SUCCESS; /* early init */ 270 271 return PDMCritSectTryEnter(&pVM->em.s.CritSectREM); 272 #else 273 return VINF_SUCCESS; 274 #endif 275 } 276 277 278 /** 107 279 * Read callback for disassembly function; supports reading bytes that cross a page boundary 108 280 * … … 114 286 * 115 287 */ 116 DECLCALLBACK(int) EMReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata)288 static DECLCALLBACK(int) EMReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata) 117 289 { 118 290 PDISCPUSTATE pDis = (PDISCPUSTATE)pvUserdata; … … 411 583 } 412 584 585 586 #ifndef VBOX_WITH_IEM 413 587 414 588 DECLINLINE(int) emRamRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb) … … 2576 2750 NOREF(pDis); NOREF(pvFault); NOREF(pcbSize); 2577 2751 return EMInterpretRdpmc(pVM, pVCpu, pRegFrame); 2578 }2579 2580 2581 /**2582 * Prepare an MWAIT - essentials of the MONITOR instruction.2583 *2584 * @returns VINF_SUCCESS2585 * @param pVCpu The current CPU.2586 * @param rax The content of RAX.2587 * @param rcx The content of RCX.2588 * @param rdx The content of RDX.2589 */2590 VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx)2591 {2592 pVCpu->em.s.MWait.uMonitorRAX = rax;2593 pVCpu->em.s.MWait.uMonitorRCX = rcx;2594 pVCpu->em.s.MWait.uMonitorRDX = rdx;2595 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;2596 /** @todo Complete MONITOR implementation. */2597 return VINF_SUCCESS;2598 }2599 2600 2601 /**2602 * Performs an MWAIT.2603 *2604 * @returns VINF_SUCCESS2605 * @param pVCpu The current CPU.2606 * @param rax The content of RAX.2607 * @param rcx The content of RCX.2608 */2609 VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx)2610 {2611 pVCpu->em.s.MWait.uMWaitRAX = rax;2612 pVCpu->em.s.MWait.uMWaitRCX = rcx;2613 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_ACTIVE;2614 if (rcx)2615 pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_BREAKIRQIF0;2616 else2617 pVCpu->em.s.MWait.fWait &= ~EMMWAIT_FLAG_BREAKIRQIF0;2618 /** @todo not completely correct?? */2619 return VINF_EM_HALT;2620 2752 } 2621 2753 … … 3146 3278 } 3147 3279 3148 3149 /** 3150 * Sets the PC for which interrupts should be inhibited. 3151 * 3152 * @param pVCpu The VMCPU handle. 3153 * @param PC The PC. 3154 */ 3155 VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC) 3156 { 3157 pVCpu->em.s.GCPtrInhibitInterrupts = PC; 3158 VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); 3159 } 3160 3161 3162 /** 3163 * Gets the PC for which interrupts should be inhibited. 3164 * 3165 * There are a few instructions which inhibits or delays interrupts 3166 * for the instruction following them. These instructions are: 3167 * - STI 3168 * - MOV SS, r/m16 3169 * - POP SS 3170 * 3171 * @returns The PC for which interrupts should be inhibited. 3172 * @param pVCpu The VMCPU handle. 3173 * 3174 */ 3175 VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu) 3176 { 3177 return pVCpu->em.s.GCPtrInhibitInterrupts; 3178 } 3179 3180 /** 3181 * Locks REM execution to a single VCpu 3182 * 3183 * @param pVM VM handle. 3184 */ 3185 VMMDECL(void) EMRemLock(PVM pVM) 3186 { 3187 #ifdef VBOX_WITH_REM 3188 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 3189 return; /* early init */ 3190 3191 Assert(!PGMIsLockOwner(pVM)); 3192 Assert(!IOMIsLockOwner(pVM)); 3193 int rc = PDMCritSectEnter(&pVM->em.s.CritSectREM, VERR_SEM_BUSY); 3194 AssertRCSuccess(rc); 3195 #endif 3196 } 3197 3198 /** 3199 * Unlocks REM execution 3200 * 3201 * @param pVM VM handle. 3202 */ 3203 VMMDECL(void) EMRemUnlock(PVM pVM) 3204 { 3205 #ifdef VBOX_WITH_REM 3206 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 3207 return; /* early init */ 3208 3209 PDMCritSectLeave(&pVM->em.s.CritSectREM); 3210 #endif 3211 } 3212 3213 /** 3214 * Check if this VCPU currently owns the REM lock. 3215 * 3216 * @returns bool owner/not owner 3217 * @param pVM The VM to operate on. 3218 */ 3219 VMMDECL(bool) EMRemIsLockOwner(PVM pVM) 3220 { 3221 #ifdef VBOX_WITH_REM 3222 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 3223 return true; /* early init */ 3224 3225 return PDMCritSectIsOwner(&pVM->em.s.CritSectREM); 3226 #else 3227 return true; 3228 #endif 3229 } 3230 3231 /** 3232 * Try to acquire the REM lock. 3233 * 3234 * @returns VBox status code 3235 * @param pVM The VM to operate on. 3236 */ 3237 VMMDECL(int) EMRemTryLock(PVM pVM) 3238 { 3239 #ifdef VBOX_WITH_REM 3240 if (!PDMCritSectIsInitialized(&pVM->em.s.CritSectREM)) 3241 return VINF_SUCCESS; /* early init */ 3242 3243 return PDMCritSectTryEnter(&pVM->em.s.CritSectREM); 3244 #else 3245 return VINF_SUCCESS; 3246 #endif 3247 } 3248 3249 /** 3250 * Determine if we should continue after encountering a hlt or mwait 3251 * instruction. 3252 * 3253 * Clears MWAIT flags if returning @c true. 3254 * 3255 * @returns boolean 3256 * @param pVCpu The VMCPU to operate on. 3257 * @param pCtx Current CPU context. 3258 */ 3259 VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx) 3260 { 3261 if ( pCtx->eflags.Bits.u1IF 3262 || ( (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) 3263 == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) ) 3264 { 3265 pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0); 3266 return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)); 3267 } 3268 3269 return false; 3270 } 3271 3280 #endif /* !VBOX_WITH_IEM */
Note:
See TracChangeset
for help on using the changeset viewer.