Changeset 25901 in vbox for trunk/src/VBox
- Timestamp:
- Jan 18, 2010 4:52:21 PM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
r25840 r25901 403 403 404 404 STDMETHOD(OnMediumChange)(IMediumAttachment * /* aMediumAttachment */) 405 { 406 return S_OK; 407 } 408 409 STDMETHOD(OnCPUChange)(ULONG /*aCPU*/, BOOL /* aRemove */) 405 410 { 406 411 return S_OK; -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r25693 r25901 116 116 CHECK_ERROR_BREAK(console, Reset()); 117 117 } 118 else if (!strcmp(a->argv[1], "unplugcpu")) 119 { 120 if (a->argc <= 1 + 1) 121 { 122 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]); 123 rc = E_FAIL; 124 break; 125 } 126 127 unsigned n = parseNum(a->argv[2], 32, "CPU"); 128 129 CHECK_ERROR_BREAK(sessionMachine, HotUnplugCPU(n)); 130 } 131 else if (!strcmp(a->argv[1], "plugcpu")) 132 { 133 if (a->argc <= 1 + 1) 134 { 135 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]); 136 rc = E_FAIL; 137 break; 138 } 139 140 unsigned n = parseNum(a->argv[2], 32, "CPU"); 141 142 CHECK_ERROR_BREAK(sessionMachine, HotPlugCPU(n)); 143 } 118 144 else if (!strcmp(a->argv[1], "poweroff")) 119 145 { -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
r25819 r25901 71 71 MODIFYVM_VTXVPID, 72 72 MODIFYVM_CPUS, 73 MODIFYVM_CPUHOTPLUG, 74 MODIFYVM_PLUGCPU, 75 MODIFYVM_UNPLUGCPU, 73 76 MODIFYVM_SETCPUID, 74 77 MODIFYVM_DELCPUID, … … 153 156 { "--cpuidremoveall", MODIFYVM_DELALLCPUID, RTGETOPT_REQ_NOTHING}, 154 157 { "--cpus", MODIFYVM_CPUS, RTGETOPT_REQ_UINT32 }, 158 { "--cpuhotplug", MODIFYVM_CPUHOTPLUG, RTGETOPT_REQ_BOOL_ONOFF }, 159 { "--plugcpu", MODIFYVM_PLUGCPU, RTGETOPT_REQ_UINT32 }, 160 { "--unplugcpu", MODIFYVM_UNPLUGCPU, RTGETOPT_REQ_UINT32 }, 155 161 { "--rtcuseutc", MODIFYVM_RTCUSEUTC, RTGETOPT_REQ_BOOL_ONOFF }, 156 162 { "--monitorcount", MODIFYVM_MONITORCOUNT, RTGETOPT_REQ_UINT32 }, … … 423 429 } 424 430 431 case MODIFYVM_CPUHOTPLUG: 432 { 433 CHECK_ERROR(machine, COMSETTER(CPUHotPlugEnabled)(ValueUnion.f)); 434 break; 435 } 436 437 case MODIFYVM_PLUGCPU: 438 { 439 CHECK_ERROR(machine, HotPlugCPU(ValueUnion.u32)); 440 break; 441 } 442 443 case MODIFYVM_UNPLUGCPU: 444 { 445 CHECK_ERROR(machine, HotUnplugCPU(ValueUnion.u32)); 446 break; 447 } 448 425 449 case MODIFYVM_MONITORCOUNT: 426 450 { -
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r25026 r25901 542 542 543 543 STDMETHOD(OnMediumChange)(IMediumAttachment * /*aMediumAttachment*/) 544 { 545 return S_OK; 546 } 547 548 STDMETHOD(OnCPUChange)(ULONG /*aCPU*/, BOOL /* aRemove */) 544 549 { 545 550 return S_OK; -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxConsoleView.cpp
r25583 r25901 536 536 break; 537 537 } 538 return S_OK; 539 } 540 541 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove) 542 { 543 NOREF(aCPU); 544 NOREF(aRemove); 538 545 return S_OK; 539 546 } -
trunk/src/VBox/Main/ConsoleImpl.cpp
r25893 r25901 1730 1730 } 1731 1731 1732 DECLCALLBACK(int) Console::unplugCpu(Console *pThis, unsigned uCpu) 1733 { 1734 LogFlowFunc(("pThis=%p uCpu=%u\n", pThis, uCpu)); 1735 1736 AssertReturn(pThis, VERR_INVALID_PARAMETER); 1737 1738 int vrc = PDMR3DeviceDetach(pThis->mpVM, "acpi", 0, uCpu, 0); 1739 Log(("UnplugCpu: rc=%Rrc\n", vrc)); 1740 1741 return vrc; 1742 } 1743 1744 STDMETHODIMP Console::doCPURemove(ULONG aCpu) 1745 { 1746 HRESULT rc = S_OK; 1747 1748 LogFlowThisFuncEnter(); 1749 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 1750 1751 AutoCaller autoCaller(this); 1752 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1753 1754 AutoWriteLock alock(this); 1755 1756 if ( mMachineState != MachineState_Running 1757 && mMachineState != MachineState_Teleporting 1758 && mMachineState != MachineState_LiveSnapshotting 1759 ) 1760 return setError(VBOX_E_INVALID_VM_STATE, 1761 tr("Invalid machine state: %s"), 1762 Global::stringifyMachineState(mMachineState)); 1763 1764 /* protect mpVM */ 1765 AutoVMCaller autoVMCaller(this); 1766 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 1767 1768 /* Check if the CPU is present */ 1769 BOOL fCpuAttached; 1770 rc = mMachine->GetCPUStatus(aCpu, &fCpuAttached); 1771 if (FAILED(rc)) return rc; 1772 1773 if (!fCpuAttached) 1774 return setError(E_FAIL, 1775 tr("CPU %d is not attached"), aCpu); 1776 1777 /* Check if the CPU is unlocked */ 1778 PPDMIBASE pBase; 1779 int vrc = PDMR3QueryDeviceLun(mpVM, "acpi", 0, aCpu, &pBase); 1780 bool fLocked = true; 1781 if (RT_SUCCESS(vrc)) 1782 { 1783 uint32_t idCpuCore, idCpuPackage; 1784 1785 /* Notify the guest if possible. */ 1786 vrc = VMR3GetCpuCoreAndPackageIdFromCpuId(mpVM, aCpu, &idCpuCore, &idCpuPackage); 1787 AssertRC(vrc); 1788 1789 Assert(pBase); 1790 1791 PPDMIACPIPORT pPort = 1792 (PPDMIACPIPORT) pBase->pfnQueryInterface(pBase, PDMINTERFACE_ACPI_PORT); 1793 1794 vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotUnplug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage); 1795 if (RT_SUCCESS(vrc)) 1796 { 1797 unsigned cTries = 10; 1798 1799 do 1800 { 1801 /* It will take some time until the event is processed in the guest. Wait */ 1802 vrc = pPort ? pPort->pfnGetCpuStatus(pPort, aCpu, &fLocked) : VERR_INVALID_POINTER; 1803 1804 if (RT_SUCCESS(vrc) && !fLocked) 1805 break; 1806 1807 /* Sleep a bit */ 1808 RTThreadSleep(100); 1809 } while (cTries-- > 0); 1810 } 1811 else if (vrc == VERR_CPU_HOTPLUG_NOT_MONITORED_BY_GUEST) 1812 { 1813 /* Query one time. It is possible that the user ejected the CPU. */ 1814 vrc = pPort ? pPort->pfnGetCpuStatus(pPort, aCpu, &fLocked) : VERR_INVALID_POINTER; 1815 } 1816 } 1817 1818 /* If the CPU was unlocked we can detach it now. */ 1819 if (RT_SUCCESS(vrc) && !fLocked) 1820 { 1821 /* 1822 * Call worker in EMT, that's faster and safer than doing everything 1823 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 1824 * here to make requests from under the lock in order to serialize them. 1825 */ 1826 PVMREQ pReq; 1827 vrc = VMR3ReqCall(mpVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 1828 (PFNRT)Console::unplugCpu, 2, 1829 this, aCpu); 1830 1831 /* leave the lock before a VMR3* call (EMT will call us back)! */ 1832 alock.leave(); 1833 1834 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 1835 { 1836 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 1837 AssertRC(vrc); 1838 if (RT_SUCCESS(vrc)) 1839 vrc = pReq->iStatus; 1840 } 1841 VMR3ReqFree(pReq); 1842 1843 if (RT_SUCCESS(vrc)) 1844 { 1845 /* Detach it from the VM */ 1846 vrc = VMR3HotUnplugCpu(mpVM, aCpu); 1847 AssertRC(vrc); 1848 } 1849 else 1850 rc = setError(VBOX_E_VM_ERROR, 1851 tr("Hot-Remove failed (rc=%Rrc)"), vrc); 1852 } 1853 else 1854 rc = setError(VBOX_E_VM_ERROR, 1855 tr("Hot-Remove was aborted because the CPU may still be used by the guest"), VERR_RESOURCE_BUSY); 1856 1857 LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc)); 1858 LogFlowThisFuncLeave(); 1859 return rc; 1860 } 1861 1862 DECLCALLBACK(int) Console::plugCpu(Console *pThis, unsigned uCpu) 1863 { 1864 LogFlowFunc(("pThis=%p uCpu=%u\n", pThis, uCpu)); 1865 1866 AssertReturn(pThis, VERR_INVALID_PARAMETER); 1867 1868 int rc = VMR3HotPlugCpu(pThis->mpVM, uCpu); 1869 AssertRC(rc); 1870 1871 PCFGMNODE pInst = CFGMR3GetChild(CFGMR3GetRoot(pThis->mpVM), "Devices/acpi/0/"); 1872 AssertRelease(pInst); 1873 /* nuke anything which might have been left behind. */ 1874 CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%d", uCpu)); 1875 1876 #define RC_CHECK() do { if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; } } while (0) 1877 1878 PCFGMNODE pLunL0; 1879 PCFGMNODE pCfg; 1880 rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%d", uCpu); RC_CHECK(); 1881 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPICpu"); RC_CHECK(); 1882 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1883 1884 /* 1885 * Attach the driver. 1886 */ 1887 PPDMIBASE pBase; 1888 rc = PDMR3DeviceAttach(pThis->mpVM, "acpi", 0, uCpu, 0, &pBase); RC_CHECK(); 1889 1890 Log(("PlugCpu: rc=%Rrc\n", rc)); 1891 1892 CFGMR3Dump(pInst); 1893 1894 return VINF_SUCCESS; 1895 } 1896 1897 STDMETHODIMP Console::doCPUAdd(ULONG aCpu) 1898 { 1899 HRESULT rc = S_OK; 1900 1901 LogFlowThisFuncEnter(); 1902 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 1903 1904 AutoCaller autoCaller(this); 1905 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1906 1907 AutoWriteLock alock(this); 1908 1909 if ( mMachineState != MachineState_Running 1910 && mMachineState != MachineState_Teleporting 1911 && mMachineState != MachineState_LiveSnapshotting 1912 /** @todo r=bird: This should be allowed on paused VMs as well. Later. */ 1913 ) 1914 return setError(VBOX_E_INVALID_VM_STATE, 1915 tr("Invalid machine state: %s"), 1916 Global::stringifyMachineState(mMachineState)); 1917 1918 /* protect mpVM */ 1919 AutoVMCaller autoVMCaller(this); 1920 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 1921 1922 /* Check if the CPU is present */ 1923 BOOL fCpuAttached; 1924 rc = mMachine->GetCPUStatus(aCpu, &fCpuAttached); 1925 if (FAILED(rc)) return rc; 1926 1927 if (fCpuAttached) 1928 return setError(E_FAIL, 1929 tr("CPU %d is already attached"), aCpu); 1930 1931 /* 1932 * Call worker in EMT, that's faster and safer than doing everything 1933 * using VMR3ReqCall. Note that we separate VMR3ReqCall from VMR3ReqWait 1934 * here to make requests from under the lock in order to serialize them. 1935 */ 1936 PVMREQ pReq; 1937 int vrc = VMR3ReqCall(mpVM, 0, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS, 1938 (PFNRT)Console::plugCpu, 2, 1939 this, aCpu); 1940 1941 /* leave the lock before a VMR3* call (EMT will call us back)! */ 1942 alock.leave(); 1943 1944 if (vrc == VERR_TIMEOUT || RT_SUCCESS(vrc)) 1945 { 1946 vrc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT); 1947 AssertRC(vrc); 1948 if (RT_SUCCESS(vrc)) 1949 vrc = pReq->iStatus; 1950 } 1951 VMR3ReqFree(pReq); 1952 1953 rc = RT_SUCCESS(vrc) ? S_OK : 1954 setError(VBOX_E_VM_ERROR, 1955 tr("Could not add CPU to the machine (%Rrc)"), 1956 vrc); 1957 1958 if (RT_SUCCESS(vrc)) 1959 { 1960 uint32_t idCpuCore, idCpuPackage; 1961 1962 /* Notify the guest if possible. */ 1963 vrc = VMR3GetCpuCoreAndPackageIdFromCpuId(mpVM, aCpu, &idCpuCore, &idCpuPackage); 1964 AssertRC(vrc); 1965 1966 vrc = getVMMDev()->getVMMDevPort()->pfnCpuHotPlug(getVMMDev()->getVMMDevPort(), idCpuCore, idCpuPackage); 1967 /** @todo warning if the guest doesn't support it */ 1968 } 1969 1970 LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc)); 1971 LogFlowThisFuncLeave(); 1972 return rc; 1973 } 1974 1732 1975 STDMETHODIMP Console::Pause() 1733 1976 { … … 3730 3973 while (it != mCallbacks.end()) 3731 3974 (*it++)->OnMediumChange(aMediumAttachment); 3975 } 3976 3977 LogFlowThisFunc(("Leaving rc=%#x\n", rc)); 3978 return rc; 3979 } 3980 3981 /** 3982 * Called by IInternalSessionControl::OnCPUChange(). 3983 * 3984 * @note Locks this object for writing. 3985 */ 3986 HRESULT Console::onCPUChange(ULONG aCPU, BOOL aRemove) 3987 { 3988 LogFlowThisFunc(("\n")); 3989 3990 AutoCaller autoCaller(this); 3991 AssertComRCReturnRC(autoCaller.rc()); 3992 3993 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3994 3995 /* Don't do anything if the VM isn't running */ 3996 if (!mpVM) 3997 return S_OK; 3998 3999 HRESULT rc = S_OK; 4000 4001 /* protect mpVM */ 4002 AutoVMCaller autoVMCaller(this); 4003 if (FAILED(autoVMCaller.rc())) return autoVMCaller.rc(); 4004 4005 if (aRemove) 4006 rc = doCPURemove(aCPU); 4007 else 4008 rc = doCPUAdd(aCPU); 4009 4010 /* notify console callbacks on success */ 4011 if (SUCCEEDED(rc)) 4012 { 4013 CallbackList::iterator it = mCallbacks.begin(); 4014 while (it != mCallbacks.end()) 4015 (*it++)->OnCPUChange(aCPU, aRemove); 3732 4016 } 3733 4017 -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r25867 r25901 1851 1851 if (fACPI) 1852 1852 { 1853 BOOL fCpuHotPlug = false; 1853 1854 BOOL fShowCpu = fExtProfile; 1854 1855 /* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled. … … 1856 1857 * intelppm driver refuses to register an idle state handler. 1857 1858 */ 1858 if ((cCpus > 1) || 1859 if ((cCpus > 1) || fIOAPIC) 1859 1860 fShowCpu = true; 1861 1862 hrc = pMachine->COMGETTER(CPUHotPlugEnabled)(&fCpuHotPlug); H(); 1860 1863 1861 1864 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK(); … … 1878 1881 1879 1882 rc = CFGMR3InsertInteger(pCfg, "ShowCpu", fShowCpu); RC_CHECK(); 1883 rc = CFGMR3InsertInteger(pCfg, "CpuHotPlug", fCpuHotPlug); RC_CHECK(); 1880 1884 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK(); 1881 1885 Assert(!afPciDeviceNo[7]); … … 1886 1890 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK(); 1887 1891 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1892 1893 /* Attach the dummy CPU drivers */ 1894 for (ULONG iCpuCurr = 1; iCpuCurr < cCpus; iCpuCurr++) 1895 { 1896 BOOL fCpuAttached = true; 1897 1898 if (fCpuHotPlug) 1899 { 1900 hrc = pMachine->GetCPUStatus(iCpuCurr, &fCpuAttached); H(); 1901 } 1902 1903 if (fCpuAttached) 1904 { 1905 rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%u", iCpuCurr); RC_CHECK(); 1906 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPICpu"); RC_CHECK(); 1907 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1908 } 1909 } 1888 1910 } 1889 1911 -
trunk/src/VBox/Main/ConsoleVRDPServer.cpp
r25860 r25901 119 119 120 120 STDMETHOD(OnMediumChange)(IMediumAttachment *aAttachment) 121 { 122 return S_OK; 123 } 124 125 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove) 121 126 { 122 127 return S_OK; -
trunk/src/VBox/Main/MachineImpl.cpp
r25880 r25901 156 156 mMemorySize = 128; 157 157 mCPUCount = 1; 158 mCPUHotPlugEnabled = false; 158 159 mMemoryBalloonSize = 0; 159 160 mStatisticsUpdateInterval = 0; … … 189 190 190 191 mFirmwareType = FirmwareType_BIOS; 192 193 for (size_t i = 0; i < RT_ELEMENTS(mCPUAttached); i++) 194 mCPUAttached[i] = false; 191 195 } 192 196 … … 217 221 mSyntheticCpu != that.mSyntheticCpu || 218 222 mCPUCount != that.mCPUCount || 223 mCPUHotPlugEnabled != that.mCPUHotPlugEnabled || 219 224 mClipboardMode != that.mClipboardMode) 220 225 return false; … … 223 228 if (mBootOrder [i] != that.mBootOrder [i]) 224 229 return false; 230 231 232 for (size_t i = 0; i < RT_ELEMENTS(mCPUAttached); i++) 233 { 234 if (mCPUAttached[i] != that.mCPUAttached[i]) 235 return false; 236 } 225 237 226 238 if (mSharedFolders.size() != that.mSharedFolders.size()) … … 1075 1087 STDMETHODIMP Machine::COMSETTER(CPUCount) (ULONG CPUCount) 1076 1088 { 1077 /* check RAMlimits */1089 /* check CPU limits */ 1078 1090 if ( CPUCount < SchemaDefs::MinCPUCount 1079 1091 || CPUCount > SchemaDefs::MaxCPUCount … … 1088 1100 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1089 1101 1102 /* We cant go below the current number of CPUs if hotplug is enabled*/ 1103 if (mHWData->mCPUHotPlugEnabled) 1104 { 1105 for (unsigned idx = CPUCount; idx < SchemaDefs::MaxCPUCount; idx++) 1106 { 1107 if (mHWData->mCPUAttached[idx]) 1108 return setError(E_INVALIDARG, 1109 tr(": %lu (must be higher than or equal to %lu)"), 1110 CPUCount, idx+1); 1111 } 1112 } 1113 1090 1114 HRESULT rc = checkStateDependency(MutableStateDep); 1091 1115 if (FAILED(rc)) return rc; … … 1095 1119 1096 1120 return S_OK; 1121 } 1122 1123 STDMETHODIMP Machine::COMGETTER(CPUHotPlugEnabled) (BOOL *enabled) 1124 { 1125 if (!enabled) 1126 return E_POINTER; 1127 1128 AutoCaller autoCaller(this); 1129 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1130 1131 AutoReadLock alock(this); 1132 1133 *enabled = mHWData->mCPUHotPlugEnabled; 1134 1135 return S_OK; 1136 } 1137 1138 STDMETHODIMP Machine::COMSETTER(CPUHotPlugEnabled) (BOOL enabled) 1139 { 1140 HRESULT rc = S_OK; 1141 1142 AutoCaller autoCaller(this); 1143 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1144 1145 AutoWriteLock alock(this); 1146 1147 rc = checkStateDependency(MutableStateDep); 1148 if (FAILED(rc)) return rc; 1149 1150 if (mHWData->mCPUHotPlugEnabled != enabled) 1151 { 1152 if (enabled) 1153 { 1154 mHWData.backup(); 1155 1156 /* Add the amount of CPUs currently attached */ 1157 for (unsigned i = 0; i < mHWData->mCPUCount; i++) 1158 { 1159 mHWData->mCPUAttached[i] = true; 1160 } 1161 } 1162 else 1163 { 1164 /* 1165 * We can disable hotplug only if the amount of maximum CPUs is equal 1166 * to the amount of attached CPUs 1167 */ 1168 unsigned cCpusAttached = 0; 1169 unsigned iHighestId = 0; 1170 1171 for (unsigned i = 0; i < SchemaDefs::MaxCPUCount; i++) 1172 { 1173 if (mHWData->mCPUAttached[i]) 1174 { 1175 cCpusAttached++; 1176 iHighestId = i; 1177 } 1178 } 1179 1180 if ( (cCpusAttached != mHWData->mCPUCount) 1181 || (iHighestId >= mHWData->mCPUCount)) 1182 return setError(E_INVALIDARG, 1183 tr("CPU hotplugging can't be disabled because the maximum number of CPUs is not equal to the amount of CPUs attached\n")); 1184 1185 mHWData.backup(); 1186 } 1187 } 1188 1189 mHWData->mCPUHotPlugEnabled = enabled; 1190 1191 return rc; 1097 1192 } 1098 1193 … … 4257 4352 } 4258 4353 4354 STDMETHODIMP Machine::HotPlugCPU(ULONG aCpu) 4355 { 4356 HRESULT rc = S_OK; 4357 LogFlowThisFunc(("\n")); 4358 4359 AutoCaller autoCaller(this); 4360 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 4361 4362 AutoWriteLock alock(this); 4363 4364 if (!mHWData->mCPUHotPlugEnabled) 4365 return setError(E_INVALIDARG, tr("CPU hotplug is not enabled")); 4366 4367 if (aCpu >= mHWData->mCPUCount) 4368 return setError(E_INVALIDARG, tr("CPU id exceeds number of possible CPUs [0:%lu]"), mHWData->mCPUCount-1); 4369 4370 if (mHWData->mCPUAttached[aCpu]) 4371 return setError(VBOX_E_OBJECT_IN_USE, tr("CPU %lu is already attached"), aCpu); 4372 4373 alock.leave(); 4374 rc = onCPUChange(aCpu, false); 4375 alock.enter(); 4376 if (FAILED(rc)) return rc; 4377 4378 mHWData.backup(); 4379 mHWData->mCPUAttached[aCpu] = true; 4380 4381 /* Save settings if online */ 4382 if (Global::IsOnline(mData->mMachineState)) 4383 SaveSettings(); 4384 4385 return S_OK; 4386 } 4387 4388 STDMETHODIMP Machine::HotUnplugCPU(ULONG aCpu) 4389 { 4390 HRESULT rc = S_OK; 4391 LogFlowThisFunc(("\n")); 4392 4393 AutoCaller autoCaller(this); 4394 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 4395 4396 AutoWriteLock alock(this); 4397 4398 if (!mHWData->mCPUHotPlugEnabled) 4399 return setError(E_INVALIDARG, tr("CPU hotplug is not enabled")); 4400 4401 if (aCpu >= SchemaDefs::MaxCPUCount) 4402 return setError(E_INVALIDARG, 4403 tr("CPU index exceeds maximum CPU count (must be in range [0:%lu])"), 4404 SchemaDefs::MaxCPUCount); 4405 4406 if (!mHWData->mCPUAttached[aCpu]) 4407 return setError(VBOX_E_OBJECT_NOT_FOUND, tr("CPU %lu is not attached"), aCpu); 4408 4409 /* CPU 0 can't be detached */ 4410 if (aCpu == 0) 4411 return setError(E_INVALIDARG, tr("It is not possible to detach CPU 0")); 4412 4413 alock.leave(); 4414 rc = onCPUChange(aCpu, true); 4415 alock.enter(); 4416 if (FAILED(rc)) return rc; 4417 4418 mHWData.backup(); 4419 mHWData->mCPUAttached[aCpu] = false; 4420 4421 /* Save settings if online */ 4422 if (Global::IsOnline(mData->mMachineState)) 4423 SaveSettings(); 4424 4425 return S_OK; 4426 } 4427 4428 STDMETHODIMP Machine::GetCPUStatus(ULONG aCpu, BOOL *aCpuAttached) 4429 { 4430 LogFlowThisFunc(("\n")); 4431 4432 CheckComArgNotNull(aCpuAttached); 4433 4434 *aCpuAttached = false; 4435 4436 AutoCaller autoCaller(this); 4437 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 4438 4439 AutoReadLock alock(this); 4440 4441 /* If hotplug is enabled the CPU is always enabled. */ 4442 if (!mHWData->mCPUHotPlugEnabled) 4443 { 4444 if (aCpu < mHWData->mCPUCount) 4445 *aCpuAttached = true; 4446 } 4447 else 4448 { 4449 if (aCpu < SchemaDefs::MaxCPUCount) 4450 *aCpuAttached = mHWData->mCPUAttached[aCpu]; 4451 } 4452 4453 return S_OK; 4454 } 4455 4259 4456 // public methods for internal purposes 4260 4457 ///////////////////////////////////////////////////////////////////////////// … … 5960 6157 mHWData->mSyntheticCpu = data.fSyntheticCpu; 5961 6158 5962 mHWData->mCPUCount = data.cCPUs; 6159 mHWData->mCPUCount = data.cCPUs; 6160 mHWData->mCPUHotPlugEnabled = data.fCpuHotPlug; 6161 6162 // cpu 6163 if (mHWData->mCPUHotPlugEnabled) 6164 { 6165 for (settings::CpuList::const_iterator it = data.llCpus.begin(); 6166 it != data.llCpus.end(); 6167 ++it) 6168 { 6169 const settings::Cpu &cpu = *it; 6170 6171 mHWData->mCPUAttached[cpu.ulId] = true; 6172 } 6173 } 5963 6174 5964 6175 // cpuid leafs … … 6983 7194 } 6984 7195 6985 data.cCPUs = mHWData->mCPUCount; 7196 data.cCPUs = mHWData->mCPUCount; 7197 data.fCpuHotPlug = mHWData->mCPUHotPlugEnabled; 7198 7199 data.llCpus.clear(); 7200 if (data.fCpuHotPlug) 7201 { 7202 for (unsigned idx = 0; idx < data.cCPUs; idx++) 7203 { 7204 if (mHWData->mCPUAttached[idx]) 7205 { 7206 settings::Cpu cpu; 7207 cpu.ulId = idx; 7208 data.llCpus.push_back(cpu); 7209 } 7210 } 7211 } 6986 7212 6987 7213 // memory … … 9659 9885 * @note Locks this object for reading. 9660 9886 */ 9887 HRESULT SessionMachine::onCPUChange(ULONG aCPU, BOOL aRemove) 9888 { 9889 LogFlowThisFunc(("\n")); 9890 9891 AutoCaller autoCaller(this); 9892 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 9893 9894 ComPtr<IInternalSessionControl> directControl; 9895 { 9896 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 9897 directControl = mData->mSession.mDirectControl; 9898 } 9899 9900 /* ignore notifications sent after #OnSessionEnd() is called */ 9901 if (!directControl) 9902 return S_OK; 9903 9904 return directControl->OnCPUChange(aCPU, aRemove); 9905 } 9906 9907 /** 9908 * @note Locks this object for reading. 9909 */ 9661 9910 HRESULT SessionMachine::onVRDPServerChange() 9662 9911 { -
trunk/src/VBox/Main/SessionImpl.cpp
r25860 r25901 571 571 572 572 return mConsole->onMediumChange(aMediumAttachment, aForce); 573 } 574 575 STDMETHODIMP Session::OnCPUChange(ULONG aCPU, BOOL aRemove) 576 { 577 LogFlowThisFunc(("\n")); 578 579 AutoCaller autoCaller(this); 580 AssertComRCReturn (autoCaller.rc(), autoCaller.rc()); 581 582 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 583 AssertReturn(mState == SessionState_Open, VBOX_E_INVALID_VM_STATE); 584 AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE); 585 586 return mConsole->onCPUChange(aCPU, aRemove); 573 587 } 574 588 -
trunk/src/VBox/Main/VirtualBoxCallbackImpl.cpp
r25310 r25901 289 289 } 290 290 291 STDMETHODIMP CallbackWrapper::OnCPUChange(ULONG aCPU, BOOL aRemove) 292 { 293 if (mConsoleCallback.isNull()) 294 return S_OK; 295 296 return mConsoleCallback->OnCPUChange(aCPU, aRemove); 297 } 298 291 299 STDMETHODIMP CallbackWrapper::OnRuntimeError(BOOL fFatal, IN_BSTR id, IN_BSTR message) 292 300 { -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r25672 r25901 459 459 --> 460 460 </const> 461 <const name="Future" value="13"> 462 <desc>Settings version greater than "1.10", written by a future VirtualBox version.</desc> 461 <const name="v1_11" value="13"> 462 <desc>Settings version "1.10", written by VirtualBox 3.2.x.</desc> 463 <!-- CPU hot-plug support 464 --> 465 </const> 466 <const name="Future" value="14"> 467 <desc>Settings version greater than "1.11", written by a future VirtualBox version.</desc> 463 468 </const> 464 469 </enum> … … 4356 4361 </attribute> 4357 4362 4363 <attribute name="CPUHotPlugEnabled" type="boolean"> 4364 <desc> 4365 This setting determines whether VirtualBox allows CPU 4366 hotplugging for this machine.</desc> 4367 </attribute> 4368 4358 4369 <attribute name="memorySize" type="unsigned long"> 4359 4370 <desc>System memory size in megabytes.</desc> … … 5932 5943 </param> 5933 5944 </method> 5945 5946 <method name="HotPlugCPU"> 5947 <desc> 5948 Plugs a CPU into the machine. 5949 </desc> 5950 <param name="cpu" type="unsigned long" dir="in"> 5951 <desc> 5952 The CPU id to insert. 5953 </desc> 5954 </param> 5955 </method> 5956 5957 <method name="HotUnplugCPU"> 5958 <desc> 5959 Removes a CPU from the machine. 5960 </desc> 5961 <param name="cpu" type="unsigned long" dir="in"> 5962 <desc> 5963 The CPU id to remove. 5964 </desc> 5965 </param> 5966 </method> 5967 5968 <method name="GetCPUStatus"> 5969 <desc> 5970 Plugs a CPU into the machine. 5971 </desc> 5972 <param name="cpu" type="unsigned long" dir="in"> 5973 <desc> 5974 The CPU id to check for. 5975 </desc> 5976 </param> 5977 <param name="attached" type="boolean" dir="return"> 5978 <desc> 5979 Status of the CPU. 5980 </desc> 5981 </param> 5982 </method> 5934 5983 </interface> 5935 5984 … … 6116 6165 <param name="mediumAttachment" type="IMediumAttachment" dir="in"> 6117 6166 <desc>Medium attachment that is subject to change.</desc> 6167 </param> 6168 </method> 6169 6170 <method name="onCPUChange"> 6171 <desc> 6172 Notification when a CPU changes. 6173 </desc> 6174 <param name="cpu" type="unsigned long" dir="in"> 6175 <desc>The CPU which changed</desc> 6176 </param> 6177 <param name="add" type="boolean" dir="in"> 6178 <desc>Flag whether the CPU was added or removed</desc> 6118 6179 </param> 6119 6180 </method> … … 12706 12767 <param name="mediumAttachment" type="IMediumAttachment" dir="in"/> 12707 12768 <param name="force" type="boolean" dir="in"/> 12769 </method> 12770 12771 <method name="onCPUChange"> 12772 <desc> 12773 Notification when a CPU changes. 12774 </desc> 12775 <param name="cpu" type="unsigned long" dir="in"> 12776 <desc>The CPU which changed</desc> 12777 </param> 12778 <param name="add" type="boolean" dir="in"> 12779 <desc>Flag whether the CPU was added or removed</desc> 12780 </param> 12708 12781 </method> 12709 12782 -
trunk/src/VBox/Main/include/ConsoleImpl.h
r25859 r25901 179 179 HRESULT onStorageControllerChange (); 180 180 HRESULT onMediumChange(IMediumAttachment *aMediumAttachment, BOOL aForce); 181 HRESULT onCPUChange(ULONG aCPU, BOOL aRemove); 181 182 HRESULT onVRDPServerChange(); 182 183 HRESULT onUSBControllerChange(); … … 448 449 const char *pszFormat, bool fPassthrough, 449 450 bool fForce); 451 static DECLCALLBACK(int) unplugCpu (Console *pThis, unsigned uCpu); 452 static DECLCALLBACK(int) plugCpu (Console *pThis, unsigned uCpu); 450 453 HRESULT doMediumChange(IMediumAttachment *aMediumAttachment, bool fForce); 454 HRESULT doCPURemove(ULONG aCpu); 455 HRESULT doCPUAdd(ULONG aCpu); 451 456 452 457 #ifdef VBOX_DYNAMIC_NET_ATTACH -
trunk/src/VBox/Main/include/DisplayImpl.h
r25069 r25901 194 194 } 195 195 196 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove) 197 { 198 return S_OK; 199 } 200 196 201 STDMETHOD(OnVRDPServerChange)() 197 202 { -
trunk/src/VBox/Main/include/MachineImpl.h
r25859 r25901 296 296 BOOL mSyntheticCpu; 297 297 ULONG mCPUCount; 298 BOOL mCPUHotPlugEnabled; 298 299 BOOL mAccelerate3DEnabled; 300 301 BOOL mCPUAttached[SchemaDefs::MaxCPUCount]; 299 302 300 303 settings::CpuIdLeaf mCpuIdStdLeafs[10]; … … 531 534 STDMETHOD(COMGETTER(CPUCount))(ULONG *cpuCount); 532 535 STDMETHOD(COMSETTER(CPUCount))(ULONG cpuCount); 536 STDMETHOD(COMGETTER(CPUHotPlugEnabled))(BOOL *enabled); 537 STDMETHOD(COMSETTER(CPUHotPlugEnabled))(BOOL enabled); 533 538 STDMETHOD(COMGETTER(MemoryBalloonSize))(ULONG *memoryBalloonSize); 534 539 STDMETHOD(COMSETTER(MemoryBalloonSize))(ULONG memoryBalloonSize); … … 634 639 STDMETHOD(QuerySavedScreenshotPNGSize)(ULONG *aSize, ULONG *aWidth, ULONG *aHeight); 635 640 STDMETHOD(ReadSavedScreenshotPNGToArray)(ULONG *aWidth, ULONG *aHeight, ComSafeArrayOut(BYTE, aData)); 641 STDMETHOD(HotPlugCPU(ULONG aCpu)); 642 STDMETHOD(HotUnplugCPU(ULONG aCpu)); 643 STDMETHOD(GetCPUStatus(ULONG aCpu, BOOL *aCpuAttached)); 636 644 637 645 // public methods only for internal purposes … … 717 725 virtual HRESULT onUSBControllerChange() { return S_OK; } 718 726 virtual HRESULT onStorageControllerChange() { return S_OK; } 727 virtual HRESULT onCPUChange(ULONG /* aCPU */, BOOL /* aRemove */) { return S_OK; } 719 728 virtual HRESULT onMediumChange(IMediumAttachment * /* mediumAttachment */, BOOL /* force */) { return S_OK; } 720 729 virtual HRESULT onSharedFolderChange() { return S_OK; } … … 1036 1045 HRESULT onSerialPortChange(ISerialPort *serialPort); 1037 1046 HRESULT onParallelPortChange(IParallelPort *parallelPort); 1047 HRESULT onCPUChange(ULONG aCPU, BOOL aRemove); 1038 1048 HRESULT onVRDPServerChange(); 1039 1049 HRESULT onUSBControllerChange(); -
trunk/src/VBox/Main/include/SessionImpl.h
r25642 r25901 96 96 STDMETHOD(OnStorageControllerChange)(); 97 97 STDMETHOD(OnMediumChange)(IMediumAttachment *aMediumAttachment, BOOL aForce); 98 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove); 98 99 STDMETHOD(OnVRDPServerChange)(); 99 100 STDMETHOD(OnUSBControllerChange)(); -
trunk/src/VBox/Main/include/VirtualBoxCallbackImpl.h
r23643 r25901 94 94 STDMETHOD(OnStorageControllerChange) (); 95 95 STDMETHOD(OnMediumChange)(IMediumAttachment *iMediumAttachment); 96 STDMETHOD(OnCPUChange)(ULONG aCPU, BOOL aRemove); 96 97 STDMETHOD(OnRuntimeError)(BOOL fFatal, IN_BSTR id, IN_BSTR message); 97 98 STDMETHOD(OnCanShowWindow)(BOOL *canShow); -
trunk/src/VBox/Main/xml/Settings.cpp
r25892 r25901 30 30 * 3) In the settings writer method, write the setting _only_ if the current settings 31 31 * version (stored in m->sv) is high enough. That is, for VirtualBox 3.2, write it 32 * only if (m->sv >= SettingsVersion_v1_1 0).32 * only if (m->sv >= SettingsVersion_v1_11). 33 33 * 34 34 * 4) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has … … 82 82 83 83 /** VirtualBox XML settings version number substring ("x.y") */ 84 #define VBOX_XML_VERSION "1. 9"84 #define VBOX_XML_VERSION "1.11" 85 85 86 86 /** VirtualBox XML settings version platform substring */ … … 282 282 else if (ulMinor == 10) 283 283 m->sv = SettingsVersion_v1_10; 284 else if (ulMinor > 10) 284 else if (ulMinor == 11) 285 m->sv = SettingsVersion_v1_11; 286 else if (ulMinor > 11) 285 287 m->sv = SettingsVersion_Future; 286 288 } … … 302 304 // creating new settings file: 303 305 m->strSettingsVersionFull = VBOX_XML_VERSION_FULL; 304 m->sv = SettingsVersion_v1_1 0;306 m->sv = SettingsVersion_v1_11; 305 307 } 306 308 } … … 556 558 557 559 case SettingsVersion_v1_10: 560 pcszVersion = "1.10"; 561 m->sv = SettingsVersion_v1_10; 562 break; 563 564 case SettingsVersion_v1_11: 558 565 case SettingsVersion_Future: // can be set if this code runs on XML files that were created by a future version of VBox; 559 566 // in that case, downgrade to current version when writing since we can't write future versions... 560 pcszVersion = "1.1 0";561 m->sv = SettingsVersion_v1_1 0;567 pcszVersion = "1.11"; 568 m->sv = SettingsVersion_v1_11; 562 569 break; 563 570 … … 1263 1270 fPAE(false), 1264 1271 cCPUs(1), 1272 fCpuHotPlug(false), 1265 1273 ulMemorySizeMB((uint32_t)-1), 1266 1274 ulVRAMSizeMB(8), … … 1284 1292 fPAE = true; 1285 1293 #endif 1294 } 1295 1296 /** 1297 * Called from MachineConfigFile::readHardware() to read cpu information. 1298 * @param elmCpuid 1299 * @param ll 1300 */ 1301 void MachineConfigFile::readCpuTree(const xml::ElementNode &elmCpu, 1302 CpuList &ll) 1303 { 1304 xml::NodesLoop nl1(elmCpu, "Cpu"); 1305 const xml::ElementNode *pelmCpu; 1306 while ((pelmCpu = nl1.forAllNodes())) 1307 { 1308 Cpu cpu; 1309 1310 if (!pelmCpu->getAttributeValue("id", cpu.ulId)) 1311 throw ConfigFileError(this, pelmCpu, N_("Required Cpu/@id attribute is missing")); 1312 1313 ll.push_back(cpu); 1314 } 1286 1315 } 1287 1316 … … 1560 1589 } 1561 1590 1591 pelmHwChild->getAttributeValue("hotplug", hw.fCpuHotPlug); 1592 1562 1593 const xml::ElementNode *pelmCPUChild; 1594 if (hw.fCpuHotPlug) 1595 { 1596 if ((pelmCPUChild = pelmHwChild->findChildElement("CpuTree"))) 1597 readCpuTree(*pelmCPUChild, hw.llCpus); 1598 } 1599 1563 1600 if ((pelmCPUChild = pelmHwChild->findChildElement("HardwareVirtEx"))) 1564 1601 { … … 2468 2505 pelmCPU->createChild("SyntheticCpu")->setAttribute("enabled", hw.fSyntheticCpu); 2469 2506 pelmCPU->setAttribute("count", hw.cCPUs); 2507 2508 if (m->sv >= SettingsVersion_v1_11) 2509 { 2510 pelmCPU->setAttribute("hotplug", hw.fCpuHotPlug); 2511 2512 xml::ElementNode *pelmCpuTree = NULL; 2513 for (CpuList::const_iterator it = hw.llCpus.begin(); 2514 it != hw.llCpus.end(); 2515 ++it) 2516 { 2517 const Cpu &cpu = *it; 2518 2519 if (pelmCpuTree == NULL) 2520 pelmCpuTree = pelmCPU->createChild("CpuTree"); 2521 2522 xml::ElementNode *pelmCpu = pelmCpuTree->createChild("Cpu"); 2523 pelmCpu->setAttribute("id", cpu.ulId); 2524 } 2525 } 2526 2470 2527 xml::ElementNode *pelmCpuIdTree = NULL; 2471 2528 for (CpuIdLeafsList::const_iterator it = hw.llCpuIdLeafs.begin(); … … 3081 3138 ) 3082 3139 m->sv = SettingsVersion_v1_10; 3140 3141 // Version 1.11 is required for CPU hotplugging 3142 if ( (m->sv < SettingsVersion_v1_11) 3143 && (hardwareMachine.fCpuHotPlug) 3144 ) 3145 m->sv = SettingsVersion_v1_11; 3083 3146 } 3084 3147
Note:
See TracChangeset
for help on using the changeset viewer.