Loading...
iokit/Kernel/IOCPU.cpp xnu-12377.101.15 xnu-201
--- xnu/xnu-12377.101.15/iokit/Kernel/IOCPU.cpp
+++ xnu/xnu-201/iokit/Kernel/IOCPU.cpp
@@ -1,240 +1,81 @@
 /*
- * Copyright (c) 1999-2016 Apple Inc.  All rights reserved.
+ * Copyright (c) 1999-2000 Apple Computer, Inc.  All rights reserved.
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1999-2000 Apple Computer, Inc.  All rights reserved.
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ *  DRI: Josh de Cesare
+ *
  */
 
-#define IOKIT_ENABLE_SHARED_PTR
-
 extern "C" {
+#include <machine/machine_routines.h>
 #include <pexpert/pexpert.h>
-#include <kern/cpu_number.h>
-extern void kperf_kernel_configure(char *);
-}
-
-#include <machine/machine_routines.h>
+}
+
 #include <IOKit/IOLib.h>
 #include <IOKit/IOPlatformExpert.h>
-#include <IOKit/pwr_mgt/RootDomain.h>
-#include <IOKit/pwr_mgt/IOPMPrivate.h>
-#include <libkern/c++/OSSharedPtr.h>
 #include <IOKit/IOUserClient.h>
-#include <IOKit/IOKitKeysPrivate.h>
 #include <IOKit/IOCPU.h>
-#include "IOKitKernelInternal.h"
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#include <kern/queue.h>
-#include <kern/sched_prim.h>
-#include <kern/processor.h>
-
-extern "C" void console_suspend();
-extern "C" void console_resume();
-extern "C" void sched_override_available_cores_for_sleep(void);
-extern "C" void sched_restore_available_cores_after_sleep(void);
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-static IOLock *gIOCPUsLock;
-static OSSharedPtr<OSArray> gIOCPUs;
-static OSSharedPtr<const OSSymbol> gIOCPUStateKey;
-static OSSharedPtr<OSString> gIOCPUStateNames[kIOCPUStateCount];
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#if !USE_APPLEARMSMP
-
-void
-IOCPUInitialize(void)
-{
-	gIOCPUsLock = IOLockAlloc();
-	gIOCPUs     = OSArray::withCapacity(1);
-
-	gIOCPUStateKey = OSSymbol::withCStringNoCopy("IOCPUState");
-
-	gIOCPUStateNames[kIOCPUStateUnregistered] =
-	    OSString::withCStringNoCopy("Unregistered");
-	gIOCPUStateNames[kIOCPUStateUninitalized] =
-	    OSString::withCStringNoCopy("Uninitalized");
-	gIOCPUStateNames[kIOCPUStateStopped] =
-	    OSString::withCStringNoCopy("Stopped");
-	gIOCPUStateNames[kIOCPUStateRunning] =
-	    OSString::withCStringNoCopy("Running");
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * This is IOKit KPI, but not used by anyone today.
- */
-kern_return_t __abortlike
-PE_cpu_start_from_kext(cpu_id_t target,
-    __unused vm_offset_t start_paddr, __unused vm_offset_t arg_paddr)
-{
-	panic("PE_cpu_start_from_kext unimplemented");
-}
-
-void
-PE_cpu_start_internal(cpu_id_t target,
-    vm_offset_t start_paddr, vm_offset_t arg_paddr)
-{
-	IOCPU *targetCPU = (IOCPU *)target;
-
-	targetCPU->startCPU(start_paddr, arg_paddr);
-}
-
-/*
- * This is IOKit public KPI, though nothing uses it.
- */
-void __abortlike
-PE_cpu_halt(cpu_id_t target)
-{
-	panic("PE_cpu_halt unimplemented");
-}
-
-void
-PE_cpu_signal(cpu_id_t source, cpu_id_t target)
-{
-	IOCPU *sourceCPU = (IOCPU *)source;
-	IOCPU *targetCPU = (IOCPU *)target;
-
-	sourceCPU->signalCPU(targetCPU);
-}
-
-void
-PE_cpu_signal_deferred(cpu_id_t source, cpu_id_t target)
-{
-	IOCPU *sourceCPU = (IOCPU *)source;
-	IOCPU *targetCPU = (IOCPU *)target;
-
-	sourceCPU->signalCPUDeferred(targetCPU);
-}
-
-void
-PE_cpu_signal_cancel(cpu_id_t source, cpu_id_t target)
-{
-	IOCPU *sourceCPU = (IOCPU *)source;
-	IOCPU *targetCPU = (IOCPU *)target;
-
-	sourceCPU->signalCPUCancel(targetCPU);
-}
-
-void
-PE_cpu_machine_init(cpu_id_t target, boolean_t bootb)
-{
-	IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
-
-	if (targetCPU == NULL) {
-		panic("%s: invalid target CPU %p", __func__, target);
-	}
-
-#if defined(__arm64__)
-	assert_ml_cpu_signal_is_enabled(false);
-#endif /* defined(__arm64__) */
-
-	targetCPU->initCPU(bootb);
-
-#if defined(__arm64__)
-	if (!bootb && (targetCPU->getCPUNumber() == (UInt32)boot_cpu_id)) {
-		assert(ml_is_quiescing());
-	}
-
-	if (ml_get_interrupts_enabled()) {
-		assert(bootb);
-		assert3u(targetCPU->getCPUNumber(), ==, (UInt32)boot_cpu_id);
-		/*
-		 * We want to assert that the AIC self-IPI actually arrives
-		 * here, but after much trials and tribulations, I found that
-		 * registering that interrupt handler is deeply entangled with
-		 * and asynchronous to the CPU booting, so it can only be a
-		 * 'hopefully it'll happen later' thing.  We will still check
-		 * that it did happen before we next enter S2R.
-		 *
-		 * We'll publish that the boot processor can have timers
-		 * migrated to it a little earlier than it is truly ready,
-		 * but fortunately that only happens on next S2R, by which time
-		 * setup should have completed.
-		 */
-		bool intr = ml_set_interrupts_enabled(FALSE);
-
-		ml_cpu_up();
-
-		ml_set_interrupts_enabled(intr);
-	}
-#endif /* defined(__arm64__) */
-}
-
-void
-PE_cpu_machine_quiesce(cpu_id_t target)
-{
-	IOCPU *targetCPU = (IOCPU*)target;
-#if defined(__arm64__)
-	if (targetCPU->getCPUNumber() == (UInt32)boot_cpu_id) {
-		assert(ml_is_quiescing());
-	}
-#endif /* defined(__arm64__) */
-	targetCPU->quiesceCPU();
-}
-
-#if defined(__arm64__)
-static perfmon_interrupt_handler_func pmi_handler = NULL;
-
-kern_return_t
-PE_cpu_perfmon_interrupt_install_handler(perfmon_interrupt_handler_func handler)
-{
-	pmi_handler = handler;
-
-	return KERN_SUCCESS;
-}
-
-void
-PE_cpu_perfmon_interrupt_enable(cpu_id_t target, boolean_t enable)
-{
-	IOCPU *targetCPU = (IOCPU*)target;
-
-	if (targetCPU == nullptr) {
-		return;
-	}
-
-	if (enable) {
-		targetCPU->getProvider()->registerInterrupt(1, targetCPU, (IOInterruptAction)(void (*)(void))pmi_handler, NULL);
-		targetCPU->getProvider()->enableInterrupt(1);
-	} else {
-		targetCPU->getProvider()->disableInterrupt(1);
-	}
-}
-#endif
-
-bool
-PE_cpu_power_check_kdp(int cpu_id)
-{
-	return true;
-}
-
-#endif /* !USE_APPLEARMSMP */
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t PE_cpu_start(cpu_id_t target,
+			   vm_offset_t start_paddr, vm_offset_t arg_paddr)
+{
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+  
+  if (targetCPU == 0) return KERN_FAILURE;
+  return targetCPU->startCPU(start_paddr, arg_paddr);
+}
+
+void PE_cpu_halt(cpu_id_t target)
+{
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+  
+  if (targetCPU) targetCPU->haltCPU();
+}
+
+void PE_cpu_signal(cpu_id_t source, cpu_id_t target)
+{
+  IOCPU *sourceCPU = OSDynamicCast(IOCPU, (OSObject *)source);
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+  
+  if (sourceCPU && targetCPU) sourceCPU->signalCPU(targetCPU);
+}
+
+void PE_cpu_machine_init(cpu_id_t target, boolean_t boot)
+{
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+  
+  if (targetCPU) targetCPU->initCPU(boot);
+}
+
+void PE_cpu_machine_quiesce(cpu_id_t target)
+{
+  IOCPU *targetCPU = OSDynamicCast(IOCPU, (OSObject *)target);
+  
+  if (targetCPU) targetCPU->quiesceCPU();
+}
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -252,329 +93,164 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-#if !USE_APPLEARMSMP
-void
-IOCPUSleepKernel(void)
-{
-#if defined(__x86_64__)
-	extern IOCPU *currentShutdownTarget;
-#endif
-	unsigned int cnt, numCPUs;
-	IOCPU *target;
-	IOCPU *bootCPU = NULL;
-	IOPMrootDomain  *rootDomain = IOService::getPMRootDomain();
-
-	printf("IOCPUSleepKernel enter\n");
-	sched_override_available_cores_for_sleep();
-
-	rootDomain->tracePoint( kIOPMTracePointSleepPlatformActions );
-	IOPlatformActionsPreSleep();
-	rootDomain->tracePoint( kIOPMTracePointSleepCPUs );
-
-	numCPUs = gIOCPUs->getCount();
-#if defined(__x86_64__)
-	currentShutdownTarget = NULL;
-#endif
-
-	integer_t old_pri;
-	thread_t self = current_thread();
-
-	/*
-	 * We need to boost this thread's priority to the maximum kernel priority to
-	 * ensure we can urgently preempt ANY thread currently executing on the
-	 * target CPU.  Note that realtime threads have their own mechanism to eventually
-	 * demote their priority below MAXPRI_KERNEL if they hog the CPU for too long.
-	 */
-	old_pri = thread_kern_get_pri(self);
-	thread_kern_set_pri(self, thread_kern_get_kernel_maxpri());
-
-	// Sleep the CPUs.
-	ml_set_is_quiescing(true);
-	cnt = numCPUs;
-	while (cnt--) {
-		target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt));
-
-		// We make certain that the bootCPU is the last to sleep
-		// We'll skip it for now, and halt it after finishing the
-		// non-boot CPU's.
-		if (target->getCPUNumber() == (UInt32)boot_cpu_id) {
-			bootCPU = target;
-		} else if (target->getCPUState() == kIOCPUStateRunning) {
-#if defined(__x86_64__)
-			currentShutdownTarget = target;
-#endif
-			target->haltCPU();
-			processor_sleep(target->getMachProcessor());
-		}
-	}
-
-	assert(bootCPU != NULL);
-	assert(cpu_number() == boot_cpu_id);
-
-	console_suspend();
-
-	rootDomain->tracePoint( kIOPMTracePointSleepPlatformDriver );
-	rootDomain->stop_watchdog_timer();
-
-	/*
-	 * Now sleep the boot CPU, including calling the kQueueQuiesce actions.
-	 * On Intel, the system sleeps here, and it does not actually sleep
-	 * the boot processor.
-	 */
-
-	bootCPU->haltCPU();
-#if __arm64__
-	/*
-	 * On ARM, we sleep the boot procesor, transitioning to the idle thread
-	 * and its interrupt stack drives the rest of sleep.
-	 */
-	processor_sleep(bootCPU->getMachProcessor());
-#endif /* __arm64__ */
-	ml_set_is_quiescing(false);
-
-	/*
-	 * The system is now coming back from sleep on the boot CPU.
-	 * The kQueueActive actions have already been called.
-	 */
-
-	rootDomain->start_watchdog_timer();
-
-	console_resume();
-
-	rootDomain->tracePoint( kIOPMTracePointWakeCPUs );
-
-	// Wake the other CPUs.
-	for (cnt = 0; cnt < numCPUs; cnt++) {
-		target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt));
-
-		// Skip the already-woken boot CPU.
-		if (target->getCPUNumber() != (UInt32)boot_cpu_id) {
-			if (target->getCPUState() == kIOCPUStateRunning) {
-				panic("Spurious wakeup of cpu %u", (unsigned int)(target->getCPUNumber()));
-			}
-
-			if (target->getCPUState() == kIOCPUStateStopped) {
-				processor_wake(target->getMachProcessor());
-			}
-		}
-	}
-
-	rootDomain->tracePoint( kIOPMTracePointWakePlatformActions );
-	IOPlatformActionsPostResume();
-
-	sched_restore_available_cores_after_sleep();
-
-	thread_kern_set_pri(self, old_pri);
-	printf("IOCPUSleepKernel exit\n");
-}
-
-static bool
-is_IOCPU_disabled(void)
-{
-	return false;
-}
-#else /* !USE_APPLEARMSMP */
-static bool
-is_IOCPU_disabled(void)
-{
-	return true;
-}
-#endif /* !USE_APPLEARMSMP */
-
-bool
-IOCPU::start(IOService *provider)
-{
-	if (is_IOCPU_disabled()) {
-		return false;
-	}
-
-	if (!super::start(provider)) {
-		return false;
-	}
-
-	_cpuGroup = gIOCPUs;
-	cpuNub = provider;
-
-	IOLockLock(gIOCPUsLock);
-	gIOCPUs->setObject(this);
-	IOLockUnlock(gIOCPUsLock);
-
-	// Correct the bus, cpu and timebase frequencies in the device tree.
-	if (gPEClockFrequencyInfo.bus_frequency_hz < 0x100000000ULL) {
-		OSSharedPtr<OSData> busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
-		provider->setProperty("bus-frequency", busFrequency.get());
-	} else {
-		OSSharedPtr<OSData> busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_frequency_hz, 8);
-		provider->setProperty("bus-frequency", busFrequency.get());
-	}
-
-	if (gPEClockFrequencyInfo.cpu_frequency_hz < 0x100000000ULL) {
-		OSSharedPtr<OSData> cpuFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.cpu_clock_rate_hz, 4);
-		provider->setProperty("clock-frequency", cpuFrequency.get());
-	} else {
-		OSSharedPtr<OSData> cpuFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.cpu_frequency_hz, 8);
-		provider->setProperty("clock-frequency", cpuFrequency.get());
-	}
-
-	OSSharedPtr<OSData> timebaseFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.timebase_frequency_hz, 4);
-	provider->setProperty("timebase-frequency", timebaseFrequency.get());
-
-	super::setProperty("IOCPUID", getRegistryEntryID(), sizeof(uint64_t) * 8);
-
-	setCPUNumber(0);
-	setCPUState(kIOCPUStateUnregistered);
-
-	return true;
-}
-
-void
-IOCPU::detach(IOService *provider)
-{
-	if (is_IOCPU_disabled()) {
-		return;
-	}
-
-	super::detach(provider);
-	IOLockLock(gIOCPUsLock);
-	unsigned int index = gIOCPUs->getNextIndexOfObject(this, 0);
-	if (index != (unsigned int)-1) {
-		gIOCPUs->removeObject(index);
-	}
-	IOLockUnlock(gIOCPUsLock);
-}
-
-OSObject *
-IOCPU::getProperty(const OSSymbol *aKey) const
-{
-	if (aKey == gIOCPUStateKey) {
-		return gIOCPUStateNames[_cpuState].get();
-	}
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-	return super::getProperty(aKey);
-#pragma clang diagnostic pop
-}
-
-bool
-IOCPU::setProperty(const OSSymbol *aKey, OSObject *anObject)
-{
-	if (aKey == gIOCPUStateKey) {
-		return false;
-	}
-
-	return super::setProperty(aKey, anObject);
-}
-
-bool
-IOCPU::serializeProperties(OSSerialize *serialize) const
-{
-	bool result;
-	OSSharedPtr<OSDictionary> dict = dictionaryWithProperties();
-	if (!dict) {
-		return false;
-	}
-	dict->setObject(gIOCPUStateKey.get(), gIOCPUStateNames[_cpuState].get());
-	result = dict->serialize(serialize);
-	return result;
-}
-
-IOReturn
-IOCPU::setProperties(OSObject *properties)
-{
-	OSDictionary *dict = OSDynamicCast(OSDictionary, properties);
-	OSString     *stateStr;
-	IOReturn     result;
-
-	if (dict == NULL) {
-		return kIOReturnUnsupported;
-	}
-
-	stateStr = OSDynamicCast(OSString, dict->getObject(gIOCPUStateKey.get()));
-	if (stateStr != NULL) {
-		result = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
-		if (result != kIOReturnSuccess) {
-			return result;
-		}
-
-		if (setProperty(gIOCPUStateKey.get(), stateStr)) {
-			return kIOReturnSuccess;
-		}
-
-		return kIOReturnUnsupported;
-	}
-
+static OSArray *gIOCPUs;
+static const OSSymbol *gIOCPUStateKey;
+static OSString *gIOCPUStateNames[kIOCPUStateCount];
+
+void IOCPUSleepKernel(void)
+{
+  long cnt, numCPUs;
+  IOCPU *target;
+  
+  numCPUs = gIOCPUs->getCount();
+  
+  // Sleep the CPUs.
+  cnt = numCPUs;
+  while (cnt--) {
+    target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt));
+    if (target->getCPUState() == kIOCPUStateRunning) {
+      target->haltCPU();
+    }
+  }
+  
+  // Wake the other CPUs.
+  for (cnt = 1; cnt < numCPUs; cnt++) {
+    target = OSDynamicCast(IOCPU, gIOCPUs->getObject(cnt));
+    if (target->getCPUState() == kIOCPUStateStopped) {
+      processor_start(target->getMachProcessor());
+    }
+  }
+}
+
+void IOCPU::initCPUs(void)
+{
+  if (gIOCPUs == 0) {
+    gIOCPUs = OSArray::withCapacity(1);
+    
+    gIOCPUStateKey = OSSymbol::withCStringNoCopy("IOCPUState");
+    
+    gIOCPUStateNames[kIOCPUStateUnregistered] =
+      OSString::withCStringNoCopy("Unregistered");
+    gIOCPUStateNames[kIOCPUStateUninitalized] =
+      OSString::withCStringNoCopy("Uninitalized");
+    gIOCPUStateNames[kIOCPUStateStopped] =
+      OSString::withCStringNoCopy("Stopped");
+    gIOCPUStateNames[kIOCPUStateRunning] =
+      OSString::withCStringNoCopy("Running");
+  }
+}
+
+bool IOCPU::start(IOService *provider)
+{
+  OSData *busFrequency, *cpuFrequency, *decFrequency;
+  
+  if (!super::start(provider)) return false;
+  
+  initCPUs();
+  
+  _cpuGroup = gIOCPUs;
+  cpuNub = provider;
+  
+  gIOCPUs->setObject(this);
+  
+  // Correct the bus, cpu and dec frequencies in the device tree.
+  busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
+  cpuFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.cpu_clock_rate_hz, 4);
+  decFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.dec_clock_rate_hz, 4);
+  provider->setProperty("bus-frequency", busFrequency);
+  provider->setProperty("clock-frequency", cpuFrequency);
+  provider->setProperty("timebase-frequency", decFrequency);
+  busFrequency->release();
+  cpuFrequency->release();
+  decFrequency->release();
+  
+  setProperty("IOCPUID", (UInt32)this, 32);
+  
+  setCPUNumber(0);
+  setCPUState(kIOCPUStateUnregistered);
+  
+  return true;
+}
+
+IOReturn IOCPU::setProperties(OSObject *properties)
+{
+  OSDictionary *dict = OSDynamicCast(OSDictionary, properties);
+  OSString     *stateStr;
+  
+  if (dict == 0) return kIOReturnUnsupported;
+  
+  stateStr = OSDynamicCast(OSString, dict->getObject(gIOCPUStateKey));
+  if (stateStr != 0) {
+    if (!IOUserClient::clientHasPrivilege(current_task(), "root"))
+      return kIOReturnNotPrivileged;
+    
+    if (_cpuNumber == 0) return kIOReturnUnsupported;
+    
+    if (stateStr->isEqualTo("running")) {
+      if (_cpuState == kIOCPUStateStopped) {
+	processor_start(machProcessor);
+      } else if (_cpuState != kIOCPUStateRunning) {
 	return kIOReturnUnsupported;
-}
-
-void
-IOCPU::signalCPU(IOCPU */*target*/)
-{
-}
-
-void
-IOCPU::signalCPUDeferred(IOCPU *target)
-{
-	// Our CPU may not support deferred IPIs,
-	// so send a regular IPI by default
-	signalCPU(target);
-}
-
-void
-IOCPU::signalCPUCancel(IOCPU */*target*/)
-{
-	// Meant to cancel signals sent by
-	// signalCPUDeferred; unsupported
-	// by default
-}
-
-void
-IOCPU::enableCPUTimeBase(bool /*enable*/)
-{
-}
-
-UInt32
-IOCPU::getCPUNumber(void)
-{
-	return _cpuNumber;
-}
-
-void
-IOCPU::setCPUNumber(UInt32 cpuNumber)
-{
-	_cpuNumber = cpuNumber;
-	super::setProperty("IOCPUNumber", _cpuNumber, 32);
-}
-
-UInt32
-IOCPU::getCPUState(void)
-{
-	return _cpuState;
-}
-
-void
-IOCPU::setCPUState(UInt32 cpuState)
-{
-	if (cpuState < kIOCPUStateCount) {
-		_cpuState = cpuState;
-	}
-}
-
-OSArray *
-IOCPU::getCPUGroup(void)
-{
-	return _cpuGroup.get();
-}
-
-UInt32
-IOCPU::getCPUGroupSize(void)
-{
-	return _cpuGroup->getCount();
-}
-
-processor_t
-IOCPU::getMachProcessor(void)
-{
-	return machProcessor;
+      }
+    } else if (stateStr->isEqualTo("stopped")) {
+      if (_cpuState == kIOCPUStateRunning) {
+        haltCPU();
+      } else if (_cpuState != kIOCPUStateStopped) {
+        return kIOReturnUnsupported;
+      }
+    } else return kIOReturnUnsupported;
+    
+    return kIOReturnSuccess;
+  }
+  
+  return kIOReturnUnsupported;
+}
+
+void IOCPU::signalCPU(IOCPU */*target*/)
+{
+}
+
+void IOCPU::enableCPUTimeBase(bool /*enable*/)
+{
+}
+
+UInt32 IOCPU::getCPUNumber(void)
+{
+  return _cpuNumber;
+}
+
+void IOCPU::setCPUNumber(UInt32 cpuNumber)
+{
+  _cpuNumber = cpuNumber;
+  setProperty("IOCPUNumber", _cpuNumber, 32);
+}
+
+UInt32 IOCPU::getCPUState(void)
+{
+  return _cpuState;
+}
+
+void IOCPU::setCPUState(UInt32 cpuState)
+{
+  if ((cpuState >= 0) && (cpuState < kIOCPUStateCount)) {
+    _cpuState = cpuState;
+    setProperty(gIOCPUStateKey, gIOCPUStateNames[cpuState]);
+  }
+}
+
+OSArray *IOCPU::getCPUGroup(void)
+{
+  return _cpuGroup;
+}
+
+UInt32 IOCPU::getCPUGroupSize(void)
+{
+  return _cpuGroup->getCount();
+}
+
+processor_t IOCPU::getMachProcessor(void)
+{
+  return machProcessor;
 }
 
 
@@ -585,6 +261,7 @@
 
 OSDefineMetaClassAndStructors(IOCPUInterruptController, IOInterruptController);
 
+OSMetaClassDefineReservedUnused(IOCPUInterruptController, 0);
 OSMetaClassDefineReservedUnused(IOCPUInterruptController, 1);
 OSMetaClassDefineReservedUnused(IOCPUInterruptController, 2);
 OSMetaClassDefineReservedUnused(IOCPUInterruptController, 3);
@@ -595,214 +272,175 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-IOReturn
-IOCPUInterruptController::initCPUInterruptController(int sources)
-{
-	return initCPUInterruptController(sources, sources);
-}
-
-IOReturn
-IOCPUInterruptController::initCPUInterruptController(int sources, int cpus)
-{
-	int cnt;
-
-	if (!super::init()) {
-		return kIOReturnInvalid;
-	}
-
-	numSources = sources;
-	numCPUs = cpus;
-
-	vectors = (IOInterruptVector *)zalloc_permanent(numSources *
-	    sizeof(IOInterruptVector), ZALIGN(IOInterruptVector));
-
-	// Allocate a lock for each vector
-	for (cnt = 0; cnt < numSources; cnt++) {
-		vectors[cnt].interruptLock = IOLockAlloc();
-		if (vectors[cnt].interruptLock == NULL) {
-			for (cnt = 0; cnt < numSources; cnt++) {
-				if (vectors[cnt].interruptLock != NULL) {
-					IOLockFree(vectors[cnt].interruptLock);
-				}
-			}
-			return kIOReturnNoResources;
-		}
-	}
-
-	ml_set_max_cpus(numSources);
-	return kIOReturnSuccess;
-}
-
-void
-IOCPUInterruptController::registerCPUInterruptController(void)
-{
-	setProperty(gPlatformInterruptControllerName, kOSBooleanTrue);
-	registerService();
-
-	getPlatform()->registerInterruptController(gPlatformInterruptControllerName,
-	    this);
-}
-
-void
-IOCPUInterruptController::setCPUInterruptProperties(IOService *service)
-{
-	int          cnt;
-	OSSharedPtr<OSArray> specifier;
-	OSSharedPtr<OSArray> controller;
-	long         tmpLong;
-
-	if ((service->propertyExists(gIOInterruptControllersKey)) &&
-	    (service->propertyExists(gIOInterruptSpecifiersKey))) {
-		return;
-	}
-
-	// Create the interrupt specifer array.
-	specifier = OSArray::withCapacity(numSources);
-	for (cnt = 0; cnt < numSources; cnt++) {
-		tmpLong = cnt;
-		OSSharedPtr<OSData> tmpData = OSData::withValue(tmpLong);
-		specifier->setObject(tmpData.get());
-	}
-
-	// Create the interrupt controller array.
-	controller = OSArray::withCapacity(numSources);
-	for (cnt = 0; cnt < numSources; cnt++) {
-		controller->setObject(gPlatformInterruptControllerName);
-	}
-
-	// Put the two arrays into the property table.
-	service->setProperty(gIOInterruptControllersKey, controller.get());
-	service->setProperty(gIOInterruptSpecifiersKey, specifier.get());
-}
-
-void
-IOCPUInterruptController::enableCPUInterrupt(IOCPU *cpu)
-{
-	IOInterruptHandler handler = OSMemberFunctionCast(
-		IOInterruptHandler, this, &IOCPUInterruptController::handleInterrupt);
-
-	assert(numCPUs > 0);
-
-	ml_install_interrupt_handler(cpu, cpu->getCPUNumber(), this, handler, NULL);
-
-	IOTakeLock(vectors[0].interruptLock);
-	++enabledCPUs;
-
-	if (enabledCPUs == numCPUs) {
-		IOService::cpusRunning();
-		thread_wakeup(this);
-	}
-	IOUnlock(vectors[0].interruptLock);
-}
-
-IOReturn
-IOCPUInterruptController::registerInterrupt(IOService *nub,
-    int source,
-    void *target,
-    IOInterruptHandler handler,
-    void *refCon)
-{
-	IOInterruptVector *vector;
-
-	// Interrupts must be enabled, as this can allocate memory.
-	assert(ml_get_interrupts_enabled() == TRUE);
-
-	if (source >= numSources) {
-		return kIOReturnNoResources;
-	}
-
-	vector = &vectors[source];
-
-	// Get the lock for this vector.
-	IOTakeLock(vector->interruptLock);
-
-	// Make sure the vector is not in use.
-	if (vector->interruptRegistered) {
-		IOUnlock(vector->interruptLock);
-		return kIOReturnNoResources;
-	}
-
-	// Fill in vector with the client's info.
-	vector->handler = handler;
-	vector->nub     = nub;
-	vector->source  = source;
-	vector->target  = target;
-	vector->refCon  = refCon;
-
-	// Get the vector ready.  It starts hard disabled.
-	vector->interruptDisabledHard = 1;
-	vector->interruptDisabledSoft = 1;
-	vector->interruptRegistered   = 1;
-
-	IOUnlock(vector->interruptLock);
-
-	IOTakeLock(vectors[0].interruptLock);
-	if (enabledCPUs != numCPUs) {
-		assert_wait(this, THREAD_UNINT);
-		IOUnlock(vectors[0].interruptLock);
-		thread_block(THREAD_CONTINUE_NULL);
-	} else {
-		IOUnlock(vectors[0].interruptLock);
-	}
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOCPUInterruptController::getInterruptType(IOService */*nub*/,
-    int /*source*/,
-    int *interruptType)
-{
-	if (interruptType == NULL) {
-		return kIOReturnBadArgument;
-	}
-
-	*interruptType = kIOInterruptTypeLevel;
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOCPUInterruptController::enableInterrupt(IOService */*nub*/,
-    int /*source*/)
+
+IOReturn IOCPUInterruptController::initCPUInterruptController(int sources)
+{
+  int cnt;
+  
+  if (!super::init()) return kIOReturnInvalid;
+  
+  numCPUs = sources;
+  
+  cpus = (IOCPU **)IOMalloc(numCPUs * sizeof(IOCPU *));
+  if (cpus == 0) return kIOReturnNoMemory;
+  bzero(cpus, numCPUs * sizeof(IOCPU *));
+  
+  vectors = (IOInterruptVector *)IOMalloc(numCPUs * sizeof(IOInterruptVector));
+  if (vectors == 0) return kIOReturnNoMemory;
+  bzero(vectors, numCPUs * sizeof(IOInterruptVector));
+  
+  // Allocate locks for the
+  for (cnt = 0; cnt < numCPUs; cnt++) {
+    vectors[cnt].interruptLock = IOLockAlloc();
+    if (vectors[cnt].interruptLock == NULL) {
+      for (cnt = 0; cnt < numCPUs; cnt++) {
+	if (vectors[cnt].interruptLock != NULL)
+	  IOLockFree(vectors[cnt].interruptLock);
+      }
+      return kIOReturnNoResources;
+    }
+  }
+  
+  return kIOReturnSuccess;
+}
+
+void IOCPUInterruptController::registerCPUInterruptController(void)
+{
+  registerService();
+  
+  getPlatform()->registerInterruptController(gPlatformInterruptControllerName,
+					     this);
+}
+
+void IOCPUInterruptController::setCPUInterruptProperties(IOService *service)
+{
+  int          cnt;
+  OSArray      *controller;
+  OSArray      *specifier;
+  OSData       *tmpData;
+  long         tmpLong;
+  
+  // Create the interrupt specifer array.
+  specifier = OSArray::withCapacity(numCPUs);
+  for (cnt = 0; cnt < numCPUs; cnt++) {
+    tmpLong = cnt;
+    tmpData = OSData::withBytes(&tmpLong, sizeof(tmpLong));
+    specifier->setObject(tmpData);
+    tmpData->release();
+  };
+  
+  // Create the interrupt controller array.
+  controller = OSArray::withCapacity(numCPUs);
+  for (cnt = 0; cnt < numCPUs; cnt++) {
+    controller->setObject(gPlatformInterruptControllerName);
+  }
+  
+  // Put the two arrays into the property table.
+  service->setProperty(gIOInterruptControllersKey, controller);
+  service->setProperty(gIOInterruptSpecifiersKey, specifier);
+  controller->release();
+  specifier->release();
+}
+
+void IOCPUInterruptController::enableCPUInterrupt(IOCPU *cpu)
+{
+  ml_install_interrupt_handler(cpu, cpu->getCPUNumber(), this,
+                               (IOInterruptHandler)&IOCPUInterruptController::handleInterrupt, 0);
+  
+  enabledCPUs++;
+  
+  if (enabledCPUs == numCPUs) thread_wakeup(this);
+}
+
+IOReturn IOCPUInterruptController::registerInterrupt(IOService *nub,
+						     int source,
+						     void *target,
+						     IOInterruptHandler handler,
+						     void *refCon)
+{
+  IOInterruptVector *vector;
+  
+  if (source >= numCPUs) return kIOReturnNoResources;
+  
+  vector = &vectors[source];
+  
+  // Get the lock for this vector.
+  IOTakeLock(vector->interruptLock);
+  
+  // Make sure the vector is not in use.
+  if (vector->interruptRegistered) {
+    IOUnlock(vector->interruptLock);
+    return kIOReturnNoResources;
+  }
+  
+  // Fill in vector with the client's info.
+  vector->handler = handler;
+  vector->nub     = nub;
+  vector->source  = source;
+  vector->target  = target;
+  vector->refCon  = refCon;
+  
+  // Get the vector ready.  It starts hard disabled.
+  vector->interruptDisabledHard = 1;
+  vector->interruptDisabledSoft = 1;
+  vector->interruptRegistered   = 1;
+  
+  IOUnlock(vector->interruptLock);
+  
+  if (enabledCPUs != numCPUs) {
+    assert_wait(this, THREAD_UNINT);
+    thread_block(0);
+  }
+  
+  return kIOReturnSuccess;
+}
+
+IOReturn IOCPUInterruptController::getInterruptType(IOService */*nub*/,
+						    int /*source*/,
+						    int *interruptType)
+{
+  if (interruptType == 0) return kIOReturnBadArgument;
+  
+  *interruptType = kIOInterruptTypeLevel;
+  
+  return kIOReturnSuccess;
+}
+
+IOReturn IOCPUInterruptController::enableInterrupt(IOService */*nub*/,
+						   int /*source*/)
 {
 //  ml_set_interrupts_enabled(true);
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOCPUInterruptController::disableInterrupt(IOService */*nub*/,
-    int /*source*/)
+  return kIOReturnSuccess;
+}
+
+IOReturn IOCPUInterruptController::disableInterrupt(IOService */*nub*/,
+						    int /*source*/)
 {
 //  ml_set_interrupts_enabled(false);
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOCPUInterruptController::causeInterrupt(IOService */*nub*/,
-    int /*source*/)
-{
-	ml_cause_interrupt();
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOCPUInterruptController::handleInterrupt(void */*refCon*/,
-    IOService */*nub*/,
-    int source)
-{
-	IOInterruptVector *vector;
-
-	vector = &vectors[source];
-
-	if (!vector->interruptRegistered) {
-		return kIOReturnInvalid;
-	}
-
-	vector->handler(vector->target, vector->refCon,
-	    vector->nub, vector->source);
-
-	return kIOReturnSuccess;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+  return kIOReturnSuccess;
+}
+
+IOReturn IOCPUInterruptController::causeInterrupt(IOService */*nub*/,
+						  int /*source*/)
+{
+  ml_cause_interrupt();
+  return kIOReturnSuccess;
+}
+
+IOReturn IOCPUInterruptController::handleInterrupt(void */*refCon*/,
+						   IOService */*nub*/,
+						   int source)
+{
+  IOInterruptVector *vector;
+  
+  vector = &vectors[source];
+  
+  if (!vector->interruptRegistered) return kIOReturnInvalid;
+  
+  vector->handler(vector->target, vector->refCon,
+		  vector->nub, vector->source);
+  
+  return kIOReturnSuccess;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */