darwin-xnu/osfmk/kern/machine.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/*
  23 * @OSF_COPYRIGHT@
  24 */
  25/* 
  26 * Mach Operating System
  27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
  28 * All Rights Reserved.
  29 * 
  30 * Permission to use, copy, modify and distribute this software and its
  31 * documentation is hereby granted, provided that both the copyright
  32 * notice and this permission notice appear in all copies of the
  33 * software, derivative works or modified versions, and any portions
  34 * thereof, and that both notices appear in supporting documentation.
  35 * 
  36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  37 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  39 * 
  40 * Carnegie Mellon requests users of this software to return to
  41 * 
  42 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  43 *  School of Computer Science
  44 *  Carnegie Mellon University
  45 *  Pittsburgh PA 15213-3890
  46 * 
  47 * any improvements or extensions that they make and grant Carnegie Mellon
  48 * the rights to redistribute these changes.
  49 */
  50/*
  51 */
  52/*
  53 *      File:   kern/machine.c
  54 *      Author: Avadis Tevanian, Jr.
  55 *      Date:   1987
  56 *
  57 *      Support for machine independent machine abstraction.
  58 */
  59
  60#include <string.h>
  61
  62#include <mach/mach_types.h>
  63#include <mach/boolean.h>
  64#include <mach/kern_return.h>
  65#include <mach/machine.h>
  66#include <mach/host_info.h>
  67#include <mach/host_reboot.h>
  68#include <mach/host_priv_server.h>
  69#include <mach/processor_server.h>
  70
  71#include <kern/kern_types.h>
  72#include <kern/counters.h>
  73#include <kern/cpu_data.h>
  74#include <kern/ipc_host.h>
  75#include <kern/host.h>
  76#include <kern/lock.h>
  77#include <kern/machine.h>
  78#include <kern/misc_protos.h>
  79#include <kern/processor.h>
  80#include <kern/queue.h>
  81#include <kern/sched.h>
  82#include <kern/task.h>
  83#include <kern/thread.h>
  84
  85#include <IOKit/IOHibernatePrivate.h>
  86
  87/*
  88 *      Exported variables:
  89 */
  90
  91struct machine_info     machine_info;
  92
  93/* Forwards */
  94void                    processor_doshutdown(
  95                                        processor_t                     processor);
  96
  97/*
  98 *      processor_up:
  99 *
 100 *      Flag processor as up and running, and available
 101 *      for scheduling.
 102 */
 103void
 104processor_up(
 105        processor_t             processor)
 106{
 107        processor_set_t         pset = &default_pset;
 108        spl_t                           s;
 109
 110        s = splsched();
 111        processor_lock(processor);
 112        init_ast_check(processor);
 113        simple_lock(&pset->sched_lock);
 114        pset_add_processor(pset, processor);
 115        enqueue_tail(&pset->active_queue, (queue_entry_t)processor);
 116        processor->state = PROCESSOR_RUNNING;
 117        simple_unlock(&pset->sched_lock);
 118        hw_atomic_add(&machine_info.avail_cpus, 1);
 119        ml_cpu_up();
 120        processor_unlock(processor);
 121        splx(s);
 122}
 123
 124kern_return_t
 125host_reboot(
 126        host_priv_t             host_priv,
 127        int                             options)
 128{
 129        if (host_priv == HOST_PRIV_NULL)
 130                return (KERN_INVALID_HOST);
 131
 132        assert(host_priv == &realhost);
 133
 134        if (options & HOST_REBOOT_DEBUGGER) {
 135                Debugger("Debugger");
 136                return (KERN_SUCCESS);
 137        }
 138
 139        halt_all_cpus(!(options & HOST_REBOOT_HALT));
 140
 141        return (KERN_SUCCESS);
 142}
 143
 144kern_return_t
 145processor_assign(
 146        __unused processor_t            processor,
 147        __unused processor_set_t        new_pset,
 148        __unused boolean_t              wait)
 149{
 150        return (KERN_FAILURE);
 151}
 152
 153kern_return_t
 154processor_shutdown(
 155        processor_t                     processor)
 156{
 157        processor_set_t         pset;
 158        spl_t                           s;
 159
 160        s = splsched();
 161        processor_lock(processor);
 162        if (processor->state == PROCESSOR_OFF_LINE) {
 163                /*
 164                 * Success if already shutdown.
 165                 */
 166                processor_unlock(processor);
 167                splx(s);
 168
 169                return (KERN_SUCCESS);
 170        }
 171
 172        if (processor->state == PROCESSOR_START) {
 173                /*
 174                 * Failure if currently being started.
 175                 */
 176                processor_unlock(processor);
 177                splx(s);
 178
 179                return (KERN_FAILURE);
 180        }
 181
 182        /*
 183         * Must lock the scheduling lock
 184         * to get at the processor state.
 185         */
 186        pset = processor->processor_set;
 187        if (pset != PROCESSOR_SET_NULL) {
 188                simple_lock(&pset->sched_lock);
 189
 190                /*
 191                 * If the processor is dispatching, let it finish.
 192                 */
 193                while (processor->state == PROCESSOR_DISPATCHING) {
 194                        simple_unlock(&pset->sched_lock);
 195                        delay(1);
 196                        simple_lock(&pset->sched_lock);
 197                }
 198
 199                /*
 200                 * Success if already being shutdown.
 201                 */
 202                if (processor->state == PROCESSOR_SHUTDOWN) {
 203                        simple_unlock(&pset->sched_lock);
 204                        processor_unlock(processor);
 205                        splx(s);
 206
 207                        return (KERN_SUCCESS);
 208                }
 209        }
 210        else {
 211                /*
 212                 * Success, already being shutdown.
 213                 */
 214                processor_unlock(processor);
 215                splx(s);
 216
 217                return (KERN_SUCCESS);
 218        }
 219
 220        if (processor->state == PROCESSOR_IDLE) {
 221                remqueue(&pset->idle_queue, (queue_entry_t)processor);
 222                pset->idle_count--;
 223        }
 224        else
 225        if (processor->state == PROCESSOR_RUNNING)
 226                remqueue(&pset->active_queue, (queue_entry_t)processor);
 227        else
 228                panic("processor_shutdown");
 229
 230        processor->state = PROCESSOR_SHUTDOWN;
 231
 232        simple_unlock(&pset->sched_lock);
 233
 234        processor_unlock(processor);
 235
 236        processor_doshutdown(processor);
 237        splx(s);
 238
 239        cpu_exit_wait(PROCESSOR_DATA(processor, slot_num));
 240
 241        return (KERN_SUCCESS);
 242}
 243
 244/*
 245 * Called at splsched.
 246 */
 247void
 248processor_doshutdown(
 249        processor_t                     processor)
 250{
 251        thread_t                        old_thread, self = current_thread();
 252        processor_set_t         pset;
 253        processor_t                     prev;
 254        int                                     pcount;
 255
 256        /*
 257         *      Get onto the processor to shutdown
 258         */
 259        prev = thread_bind(self, processor);
 260        thread_block(THREAD_CONTINUE_NULL);
 261
 262        processor_lock(processor);
 263        pset = processor->processor_set;
 264        simple_lock(&pset->sched_lock);
 265
 266        if ((pcount = pset->processor_count) == 1) {
 267                simple_unlock(&pset->sched_lock);
 268                processor_unlock(processor);
 269
 270                hibernate_vm_lock();
 271
 272                processor_lock(processor);
 273                simple_lock(&pset->sched_lock);
 274        }
 275
 276        assert(processor->state == PROCESSOR_SHUTDOWN);
 277
 278        pset_remove_processor(pset, processor);
 279        simple_unlock(&pset->sched_lock);
 280        processor_unlock(processor);
 281
 282        if (pcount == 1)
 283                hibernate_vm_unlock();
 284
 285        /*
 286         *      Continue processor shutdown in shutdown context.
 287         */
 288        thread_bind(self, prev);
 289        old_thread = machine_processor_shutdown(self, processor_offline, processor);
 290
 291        thread_begin(self, self->last_processor);
 292
 293        thread_dispatch(old_thread);
 294
 295        /*
 296         * If we just shutdown another processor, move the
 297         * timer call outs to the current processor.
 298         */
 299        if (processor != current_processor()) {
 300                processor_lock(processor);
 301                if (    processor->state == PROCESSOR_OFF_LINE  ||
 302                                processor->state == PROCESSOR_SHUTDOWN  )
 303                        timer_call_shutdown(processor);
 304                processor_unlock(processor);
 305        }
 306}
 307
 308/*
 309 *      Complete the shutdown and place the processor offline.
 310 *
 311 *      Called at splsched in the shutdown context.
 312 */
 313void
 314processor_offline(
 315        processor_t             processor)
 316{
 317        thread_t                thread, old_thread = processor->active_thread;
 318
 319        thread = processor->idle_thread;
 320        processor->active_thread = thread;
 321        processor->current_pri = IDLEPRI;
 322
 323        processor->last_dispatch = mach_absolute_time();
 324        timer_switch((uint32_t)processor->last_dispatch,
 325                                                        &PROCESSOR_DATA(processor, offline_timer));
 326
 327        thread_done(old_thread, thread, processor);
 328
 329        machine_set_current_thread(thread);
 330
 331        thread_begin(thread, processor);
 332
 333        thread_dispatch(old_thread);
 334
 335        PMAP_DEACTIVATE_KERNEL(PROCESSOR_DATA(processor, slot_num));
 336
 337        processor_lock(processor);
 338        processor->state = PROCESSOR_OFF_LINE;
 339        hw_atomic_sub(&machine_info.avail_cpus, 1);
 340        ml_cpu_down();
 341        processor_unlock(processor);
 342
 343        cpu_sleep();
 344        panic("zombie processor");
 345        /*NOTREACHED*/
 346}
 347
 348kern_return_t
 349host_get_boot_info(
 350        host_priv_t         host_priv,
 351        kernel_boot_info_t  boot_info)
 352{
 353        const char *src = "";
 354        if (host_priv == HOST_PRIV_NULL)
 355                return (KERN_INVALID_HOST);
 356
 357        assert(host_priv == &realhost);
 358
 359        /*
 360         * Copy first operator string terminated by '\0' followed by
 361         *      standardized strings generated from boot string.
 362         */
 363        src = machine_boot_info(boot_info, KERNEL_BOOT_INFO_MAX);
 364        if (src != boot_info)
 365                (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
 366
 367        return (KERN_SUCCESS);
 368}
 369
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.