#include <string.h>
#include <mach/mach_types.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/machine.h>
#include <mach/host_info.h>
#include <mach/host_reboot.h>
#include <mach/host_priv_server.h>
#include <mach/processor_server.h>
#include <kern/kern_types.h>
#include <kern/counters.h>
#include <kern/cpu_data.h>
#include <kern/ipc_host.h>
#include <kern/host.h>
#include <kern/machine.h>
#include <kern/misc_protos.h>
#include <kern/processor.h>
#include <kern/queue.h>
#include <kern/sched.h>
#include <kern/task.h>
#include <kern/thread.h>
#include <machine/commpage.h>
#if HIBERNATION
#include <IOKit/IOHibernatePrivate.h>
#endif
#include <IOKit/IOPlatformExpert.h>
#if CONFIG_DTRACE
extern void (*dtrace_cpu_state_changed_hook)(int, boolean_t);
#endif
struct machine_info machine_info;
void processor_doshutdown(
processor_t processor);
void
processor_up(
processor_t processor)
{
processor_set_t pset;
spl_t s;
s = splsched();
init_ast_check(processor);
pset = processor->processor_set;
pset_lock(pset);
++pset->online_processor_count;
enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
processor->state = PROCESSOR_RUNNING;
(void)hw_atomic_add(&processor_avail_count, 1);
commpage_update_active_cpus();
pset_unlock(pset);
ml_cpu_up();
splx(s);
#if CONFIG_DTRACE
if (dtrace_cpu_state_changed_hook)
(*dtrace_cpu_state_changed_hook)(processor->cpu_id, TRUE);
#endif
}
#include <atm/atm_internal.h>
kern_return_t
host_reboot(
host_priv_t host_priv,
int options)
{
if (host_priv == HOST_PRIV_NULL)
return (KERN_INVALID_HOST);
assert(host_priv == &realhost);
if (options & HOST_REBOOT_DEBUGGER) {
Debugger("Debugger");
return (KERN_SUCCESS);
}
if (options & HOST_REBOOT_UPSDELAY) {
PEHaltRestart( kPEUPSDelayHaltCPU );
} else {
halt_all_cpus(!(options & HOST_REBOOT_HALT));
}
return (KERN_SUCCESS);
}
kern_return_t
processor_assign(
__unused processor_t processor,
__unused processor_set_t new_pset,
__unused boolean_t wait)
{
return (KERN_FAILURE);
}
kern_return_t
processor_shutdown(
processor_t processor)
{
processor_set_t pset;
spl_t s;
s = splsched();
pset = processor->processor_set;
pset_lock(pset);
if (processor->state == PROCESSOR_OFF_LINE) {
pset_unlock(pset);
splx(s);
return (KERN_SUCCESS);
}
if (processor->state == PROCESSOR_START) {
pset_unlock(pset);
splx(s);
return (KERN_FAILURE);
}
while (processor->state == PROCESSOR_DISPATCHING) {
pset_unlock(pset);
splx(s);
delay(1);
s = splsched();
pset_lock(pset);
}
if (processor->state == PROCESSOR_SHUTDOWN) {
pset_unlock(pset);
splx(s);
return (KERN_SUCCESS);
}
if (processor->state == PROCESSOR_IDLE)
remqueue((queue_entry_t)processor);
else
if (processor->state == PROCESSOR_RUNNING)
remqueue((queue_entry_t)processor);
processor->state = PROCESSOR_SHUTDOWN;
pset_unlock(pset);
processor_doshutdown(processor);
splx(s);
cpu_exit_wait(processor->cpu_id);
return (KERN_SUCCESS);
}
void
processor_doshutdown(
processor_t processor)
{
thread_t old_thread, self = current_thread();
processor_t prev;
processor_set_t pset;
prev = thread_bind(processor);
thread_block(THREAD_CONTINUE_NULL);
assert(processor->state == PROCESSOR_SHUTDOWN);
#if CONFIG_DTRACE
if (dtrace_cpu_state_changed_hook)
(*dtrace_cpu_state_changed_hook)(processor->cpu_id, FALSE);
#endif
ml_cpu_down();
#if HIBERNATION
if (processor_avail_count < 2) {
hibernate_vm_lock();
hibernate_vm_unlock();
}
#endif
pset = processor->processor_set;
pset_lock(pset);
processor->state = PROCESSOR_OFF_LINE;
--pset->online_processor_count;
(void)hw_atomic_sub(&processor_avail_count, 1);
commpage_update_active_cpus();
SCHED(processor_queue_shutdown)(processor);
thread_bind(prev);
old_thread = machine_processor_shutdown(self, processor_offline, processor);
thread_dispatch(old_thread, self);
}
void
processor_offline(
processor_t processor)
{
thread_t new_thread, old_thread = processor->active_thread;
new_thread = processor->idle_thread;
processor->active_thread = new_thread;
processor->current_pri = IDLEPRI;
processor->current_thmode = TH_MODE_NONE;
processor->deadline = UINT64_MAX;
new_thread->last_processor = processor;
processor->last_dispatch = mach_absolute_time();
timer_stop(PROCESSOR_DATA(processor, thread_timer), processor->last_dispatch);
machine_set_current_thread(new_thread);
thread_dispatch(old_thread, new_thread);
PMAP_DEACTIVATE_KERNEL(processor->cpu_id);
cpu_sleep();
panic("zombie processor");
}
kern_return_t
host_get_boot_info(
host_priv_t host_priv,
kernel_boot_info_t boot_info)
{
const char *src = "";
if (host_priv == HOST_PRIV_NULL)
return (KERN_INVALID_HOST);
assert(host_priv == &realhost);
src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX);
if (src != boot_info)
(void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
return (KERN_SUCCESS);
}