#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/lock.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>
struct machine_info machine_info;
void processor_doshutdown(
processor_t processor);
void
processor_up(
processor_t processor)
{
processor_set_t pset = &default_pset;
spl_t s;
s = splsched();
processor_lock(processor);
init_ast_check(processor);
simple_lock(&pset->sched_lock);
pset_add_processor(pset, processor);
enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
processor->state = PROCESSOR_RUNNING;
simple_unlock(&pset->sched_lock);
hw_atomic_add(&machine_info.avail_cpus, 1);
ml_cpu_up();
processor_unlock(processor);
splx(s);
}
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);
}
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();
processor_lock(processor);
if (processor->state == PROCESSOR_OFF_LINE) {
processor_unlock(processor);
splx(s);
return (KERN_SUCCESS);
}
if (processor->state == PROCESSOR_START) {
processor_unlock(processor);
splx(s);
return (KERN_FAILURE);
}
pset = processor->processor_set;
if (pset != PROCESSOR_SET_NULL) {
simple_lock(&pset->sched_lock);
while (processor->state == PROCESSOR_DISPATCHING) {
simple_unlock(&pset->sched_lock);
delay(1);
simple_lock(&pset->sched_lock);
}
if (processor->state == PROCESSOR_SHUTDOWN) {
simple_unlock(&pset->sched_lock);
processor_unlock(processor);
splx(s);
return (KERN_SUCCESS);
}
}
else {
processor_unlock(processor);
splx(s);
return (KERN_SUCCESS);
}
if (processor->state == PROCESSOR_IDLE) {
remqueue(&pset->idle_queue, (queue_entry_t)processor);
pset->idle_count--;
}
else
if (processor->state == PROCESSOR_RUNNING)
remqueue(&pset->active_queue, (queue_entry_t)processor);
else
panic("processor_shutdown");
processor->state = PROCESSOR_SHUTDOWN;
simple_unlock(&pset->sched_lock);
processor_unlock(processor);
processor_doshutdown(processor);
splx(s);
cpu_exit_wait(PROCESSOR_DATA(processor, slot_num));
return (KERN_SUCCESS);
}
void
processor_doshutdown(
processor_t processor)
{
thread_t old_thread, self = current_thread();
processor_set_t pset;
processor_t prev;
int pcount;
prev = thread_bind(self, processor);
thread_block(THREAD_CONTINUE_NULL);
processor_lock(processor);
pset = processor->processor_set;
simple_lock(&pset->sched_lock);
if ((pcount = pset->processor_count) == 1) {
simple_unlock(&pset->sched_lock);
processor_unlock(processor);
processor_lock(processor);
simple_lock(&pset->sched_lock);
}
assert(processor->state == PROCESSOR_SHUTDOWN);
pset_remove_processor(pset, processor);
simple_unlock(&pset->sched_lock);
processor_unlock(processor);
thread_bind(self, prev);
old_thread = machine_processor_shutdown(self, processor_offline, processor);
thread_begin(self, self->last_processor);
thread_dispatch(old_thread);
if (processor != current_processor()) {
processor_lock(processor);
if ( processor->state == PROCESSOR_OFF_LINE ||
processor->state == PROCESSOR_SHUTDOWN )
timer_call_shutdown(processor);
processor_unlock(processor);
}
}
void
processor_offline(
processor_t processor)
{
thread_t thread, old_thread = processor->active_thread;
thread = processor->idle_thread;
processor->active_thread = thread;
processor->current_pri = IDLEPRI;
processor->last_dispatch = mach_absolute_time();
timer_switch((uint32_t)processor->last_dispatch,
&PROCESSOR_DATA(processor, offline_timer));
thread_done(old_thread, thread, processor);
machine_set_current_thread(thread);
thread_begin(thread, processor);
thread_dispatch(old_thread);
PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
processor_lock(processor);
processor->state = PROCESSOR_OFF_LINE;
hw_atomic_sub(&machine_info.avail_cpus, 1);
ml_cpu_down();
processor_unlock(processor);
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);
}