Changeset 42427 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Jul 26, 2012 11:48:01 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 79529
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/SELM.cpp
r42418 r42427 1068 1068 */ 1069 1069 RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu); 1070 if ( (SelLdt & X86_SEL_MASK) == 0)1070 if (!(SelLdt & X86_SEL_MASK_OFF_RPL)) 1071 1071 { 1072 1072 /* ldtr = 0 - update hyper LDTR and deregister any active handler. */ … … 1085 1085 * Get the LDT selector. 1086 1086 */ 1087 /** @todo this is wrong, use CPUMGetGuestLdtrEx */ 1087 1088 PX86DESC pDesc = &pVM->selm.s.paGdtR3[SelLdt >> X86_SEL_SHIFT]; 1088 1089 RTGCPTR GCPtrLdt = X86DESC_BASE(pDesc); … … 1293 1294 for (uint32_t iSReg = 0; iSReg < X86_SREG_COUNT; iSReg++) 1294 1295 { 1295 RTSEL const Sel = paSReg[iSReg].Sel & (X86_SEL_MASK | X86_SEL_LDT);1296 if (Sel & (X86_SEL_MASK | X86_SEL_LDT))1296 RTSEL const Sel = paSReg[iSReg].Sel; 1297 if (Sel & X86_SEL_MASK_OFF_RPL) 1297 1298 { 1298 1299 /* Get the shadow descriptor entry corresponding to this. */ … … 1553 1554 * make sure cbTss is 0. 1554 1555 */ 1556 /** @todo use the hidden bits, not shadow GDT. */ 1555 1557 CPUMSELREGHID trHid; 1556 1558 RTSEL SelTss = CPUMGetGuestTR(pVCpu, &trHid); 1557 1559 RTGCPTR GCPtrTss = trHid.u64Base; 1558 1560 uint32_t cbTss = trHid.u32Limit; 1559 Assert( (SelTss & X86_SEL_MASK)1560 || 1561 || 1562 if (SelTss & X86_SEL_MASK )1561 Assert( (SelTss & X86_SEL_MASK_OFF_RPL) 1562 || (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */) 1563 || (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */)); 1564 if (SelTss & X86_SEL_MASK_OFF_RPL) 1563 1565 { 1564 1566 Assert(!(SelTss & X86_SEL_LDT)); … … 1793 1795 */ 1794 1796 RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu); 1795 if ((SelLdt & X86_SEL_MASK ) == 0)1797 if ((SelLdt & X86_SEL_MASK_OFF_RPL) == 0) 1796 1798 return VINF_SUCCESS; 1799 Assert(!(SelLdt & X86_SEL_LDT)); 1797 1800 if (SelLdt > GDTR.cbGdt) 1798 1801 { … … 1886 1889 RTGCPTR GCPtrTss = trHid.u64Base; 1887 1890 uint32_t cbTss = trHid.u32Limit; 1888 Assert( (SelTss & X86_SEL_MASK)1889 || 1890 || 1891 if (SelTss & X86_SEL_MASK )1891 Assert( (SelTss & X86_SEL_MASK_OFF_RPL) 1892 || (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */) 1893 || (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */)); 1894 if (SelTss & X86_SEL_MASK_OFF_RPL) 1892 1895 { 1893 1896 AssertReturn(!(SelTss & X86_SEL_LDT), false); … … 2007 2010 2008 2011 /** 2009 * Returns flat address and limit of LDT by LDT selector from guest GDTR.2010 *2011 * Fully validate selector.2012 *2013 * @returns VBox status.2014 * @param pVM Pointer to the VM.2015 * @param SelLdt LDT selector.2016 * @param ppvLdt Where to store the flat address of LDT.2017 * @param pcbLimit Where to store LDT limit.2018 */2019 VMMDECL(int) SELMGetLDTFromSel(PVM pVM, RTSEL SelLdt, PRTGCPTR ppvLdt, unsigned *pcbLimit)2020 {2021 PVMCPU pVCpu = VMMGetCpu(pVM);2022 2023 /* Get guest GDTR. */2024 VBOXGDTR GDTR;2025 CPUMGetGuestGDTR(pVCpu, &GDTR);2026 2027 /* Check selector TI and GDT limit. */2028 if ( (SelLdt & X86_SEL_LDT)2029 || SelLdt > GDTR.cbGdt)2030 return VERR_INVALID_SELECTOR;2031 2032 /* Read descriptor from GC. */2033 X86DESC Desc;2034 int rc = PGMPhysSimpleReadGCPtr(pVCpu, (void *)&Desc, (RTGCPTR)(GDTR.pGdt + (SelLdt & X86_SEL_MASK)), sizeof(Desc));2035 if (RT_FAILURE(rc))2036 {2037 /* fatal */2038 Log(("Can't read LDT descriptor for selector=%04X\n", SelLdt));2039 return VERR_SELECTOR_NOT_PRESENT;2040 }2041 2042 /* Check if LDT descriptor is not present. */2043 if (Desc.Gen.u1Present == 0)2044 return VERR_SELECTOR_NOT_PRESENT;2045 2046 /* Check LDT descriptor type. */2047 if ( Desc.Gen.u1DescType == 12048 || Desc.Gen.u4Type != X86_SEL_TYPE_SYS_LDT)2049 return VERR_INVALID_SELECTOR;2050 2051 /* LDT descriptor is ok. */2052 if (ppvLdt)2053 {2054 *ppvLdt = (RTGCPTR)X86DESC_BASE(&Desc);2055 *pcbLimit = X86DESC_LIMIT_G(&Desc);2056 }2057 return VINF_SUCCESS;2058 }2059 2060 2061 /**2062 2012 * Gets information about a 64-bit selector, SELMR3GetSelectorInfo helper. 2063 2013 * … … 2075 2025 * Read it from the guest descriptor table. 2076 2026 */ 2027 /** @todo this is bogus wrt the LDT/GDT limit on long selectors. */ 2077 2028 X86DESC64 Desc; 2078 VBOXGDTR Gdtr;2079 2029 RTGCPTR GCPtrDesc; 2080 CPUMGetGuestGDTR(pVCpu, &Gdtr);2081 2030 if (!(Sel & X86_SEL_LDT)) 2082 2031 { 2083 2032 /* GDT */ 2084 if ((unsigned)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt) 2033 VBOXGDTR Gdtr; 2034 CPUMGetGuestGDTR(pVCpu, &Gdtr); 2035 if ((Sel | X86_SEL_RPL_LDT) > Gdtr.cbGdt) 2085 2036 return VERR_INVALID_SELECTOR; 2086 2037 GCPtrDesc = Gdtr.pGdt + (Sel & X86_SEL_MASK); … … 2088 2039 else 2089 2040 { 2090 /* 2091 * LDT - must locate the LDT first. 2092 */ 2093 RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu); 2094 if ( (unsigned)(SelLdt & X86_SEL_MASK) < sizeof(X86DESC) /* the first selector is invalid, right? */ /** @todo r=bird: No, I don't think so */ 2095 || (unsigned)(SelLdt & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt) 2041 /* LDT */ 2042 uint64_t GCPtrBase; 2043 uint32_t cbLimit; 2044 CPUMGetGuestLdtrEx(pVCpu, &GCPtrBase, &cbLimit); 2045 if ((Sel | X86_SEL_RPL_LDT) > cbLimit) 2096 2046 return VERR_INVALID_SELECTOR; 2097 GCPtrDesc = Gdtr.pGdt + (SelLdt & X86_SEL_MASK);2098 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &Desc, GCPtrDesc, sizeof(Desc));2099 if (RT_FAILURE(rc))2100 return rc;2101 2102 /* validate the LDT descriptor. */2103 if (Desc.Gen.u1Present == 0)2104 return VERR_SELECTOR_NOT_PRESENT;2105 if ( Desc.Gen.u1DescType == 12106 || Desc.Gen.u4Type != AMD64_SEL_TYPE_SYS_LDT)2107 return VERR_INVALID_SELECTOR;2108 2109 uint32_t cbLimit = X86DESC_LIMIT_G(&Desc);2110 if ((uint32_t)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > cbLimit)2111 return VERR_INVALID_SELECTOR;2112 2047 2113 2048 /* calc the descriptor location. */ 2114 GCPtrDesc = X86DESC64_BASE(&Desc); 2115 GCPtrDesc += (Sel & X86_SEL_MASK); 2049 GCPtrDesc = GCPtrBase + (Sel & X86_SEL_MASK); 2116 2050 } 2117 2051 … … 2255 2189 X86DESC Desc; 2256 2190 if ( !(Sel & X86_SEL_LDT) 2257 && ( pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_MASK)2258 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_MASK)2259 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_MASK)2260 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_MASK)2261 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_ MASK))2191 && ( pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_RPL_LDT) 2192 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_RPL_LDT) 2193 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_RPL_LDT) 2194 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_RPL_LDT) 2195 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_RPL_LDT)) 2262 2196 ) 2263 2197 { … … 2280 2214 pSelInfo->fFlags = DBGFSELINFO_FLAGS_PROT_MODE; 2281 2215 2282 VBOXGDTR Gdtr;2283 2216 RTGCPTR GCPtrDesc; 2284 CPUMGetGuestGDTR(pVCpu, &Gdtr);2285 2217 if (!(Sel & X86_SEL_LDT)) 2286 2218 { 2287 2219 /* GDT */ 2288 if ((unsigned)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt) 2220 VBOXGDTR Gdtr; 2221 CPUMGetGuestGDTR(pVCpu, &Gdtr); 2222 if ((Sel | X86_SEL_RPL_LDT) > Gdtr.cbGdt) 2289 2223 return VERR_INVALID_SELECTOR; 2290 2224 GCPtrDesc = Gdtr.pGdt + (Sel & X86_SEL_MASK); … … 2292 2226 else 2293 2227 { 2294 /* 2295 * LDT - must locate the LDT first... 2296 */ 2297 RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu); 2298 if ( (unsigned)(SelLdt & X86_SEL_MASK) < sizeof(X86DESC) /* the first selector is invalid, right? */ /** @todo r=bird: No, I don't think so */ 2299 || (unsigned)(SelLdt & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt) 2228 /* LDT */ 2229 uint64_t GCPtrBase; 2230 uint32_t cbLimit; 2231 CPUMGetGuestLdtrEx(pVCpu, &GCPtrBase, &cbLimit); 2232 if ((Sel | X86_SEL_RPL_LDT) > cbLimit) 2300 2233 return VERR_INVALID_SELECTOR; 2301 GCPtrDesc = Gdtr.pGdt + (SelLdt & X86_SEL_MASK);2302 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &Desc, GCPtrDesc, sizeof(Desc));2303 if (RT_FAILURE(rc))2304 return rc;2305 2306 /* validate the LDT descriptor. */2307 if (Desc.Gen.u1Present == 0)2308 return VERR_SELECTOR_NOT_PRESENT;2309 if ( Desc.Gen.u1DescType == 12310 || Desc.Gen.u4Type != X86_SEL_TYPE_SYS_LDT)2311 return VERR_INVALID_SELECTOR;2312 2313 uint32_t cbLimit = X86DESC_LIMIT_G(&Desc);2314 if ((uint32_t)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > cbLimit)2315 return VERR_INVALID_SELECTOR;2316 2234 2317 2235 /* calc the descriptor location. */ 2318 GCPtrDesc = X86DESC_BASE(&Desc); 2319 GCPtrDesc += (Sel & X86_SEL_MASK); 2236 GCPtrDesc = GCPtrBase + (Sel & X86_SEL_MASK); 2320 2237 } 2321 2238 … … 2416 2333 */ 2417 2334 Desc = pVM->selm.s.paGdtR3[Sel >> X86_SEL_SHIFT]; 2418 pSelInfo->fFlags = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_MASK)2419 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_MASK)2420 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_MASK)2421 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_MASK)2422 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_MASK )2335 pSelInfo->fFlags = pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_MASK_OFF_RPL) 2336 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_MASK_OFF_RPL) 2337 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_MASK_OFF_RPL) 2338 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_MASK_OFF_RPL) 2339 || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_MASK_OFF_RPL) 2423 2340 ? DBGFSELINFO_FLAGS_HYPER 2424 2341 : 0; … … 2666 2583 { 2667 2584 /** @todo SMP support! */ 2668 PVMCPU pVCpu = &pVM->aCpus[0]; 2669 2670 RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu); 2671 if (!(SelLdt & X86_SEL_MASK)) 2585 PVMCPU pVCpu = &pVM->aCpus[0]; 2586 2587 uint64_t GCPtrLdt; 2588 uint32_t cbLdt; 2589 RTSEL SelLdt = CPUMGetGuestLdtrEx(pVCpu, &GCPtrLdt, &cbLdt); 2590 if (!(SelLdt & X86_SEL_MASK_OFF_RPL)) 2672 2591 { 2673 2592 pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x): Null-Selector\n", SelLdt); … … 2675 2594 } 2676 2595 2677 RTGCPTR GCPtrLdt; 2678 unsigned cbLdt; 2679 int rc = SELMGetLDTFromSel(pVM, SelLdt, &GCPtrLdt, &cbLdt); 2680 if (RT_FAILURE(rc)) 2681 { 2682 pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x): rc=%Rrc\n", SelLdt, rc); 2683 return; 2684 } 2685 2686 pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x GCAddr=%RGv limit=%x):\n", SelLdt, GCPtrLdt, cbLdt); 2687 unsigned cLdts = (cbLdt + 1) >> X86_SEL_SHIFT; 2596 pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x GCAddr=%RX64 limit=%x):\n", SelLdt, GCPtrLdt, cbLdt); 2597 unsigned cLdts = (cbLdt + 1) >> X86_SEL_SHIFT; 2688 2598 for (unsigned iLdt = 0; iLdt < cLdts; iLdt++, GCPtrLdt += sizeof(X86DESC)) 2689 2599 { 2690 2600 X86DESC LdtE; 2691 rc = PGMPhysSimpleReadGCPtr(pVCpu, &LdtE, GCPtrLdt, sizeof(LdtE));2601 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &LdtE, GCPtrLdt, sizeof(LdtE)); 2692 2602 if (RT_SUCCESS(rc)) 2693 2603 {
Note:
See TracChangeset
for help on using the changeset viewer.