machine.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
  4. * Copyright (c) 1993,1994 The University of Utah and
  5. * the Computer Systems Laboratory (CSL).
  6. * All rights reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
  15. * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
  16. * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
  17. * THIS SOFTWARE.
  18. *
  19. * Carnegie Mellon requests users of this software to return to
  20. *
  21. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  22. * School of Computer Science
  23. * Carnegie Mellon University
  24. * Pittsburgh PA 15213-3890
  25. *
  26. * any improvements or extensions that they make and grant Carnegie Mellon
  27. * the rights to redistribute these changes.
  28. */
  29. /*
  30. * File: kern/machine.c
  31. * Author: Avadis Tevanian, Jr.
  32. * Date: 1987
  33. *
  34. * Support for machine independent machine abstraction.
  35. */
  36. #include <string.h>
  37. #include <mach/boolean.h>
  38. #include <mach/kern_return.h>
  39. #include <mach/mach_types.h>
  40. #include <mach/machine.h>
  41. #include <mach/host_info.h>
  42. #include <kern/counters.h>
  43. #include <kern/debug.h>
  44. #include <kern/ipc_host.h>
  45. #include <kern/host.h>
  46. #include <kern/lock.h>
  47. #include <kern/processor.h>
  48. #include <kern/queue.h>
  49. #include <kern/sched.h>
  50. #include <kern/task.h>
  51. #include <kern/thread.h>
  52. #include <machine/machspl.h> /* for splsched */
  53. #include <machine/model_dep.h>
  54. #include <sys/reboot.h>
  55. /*
  56. * Exported variables:
  57. */
  58. struct machine_info machine_info;
  59. struct machine_slot machine_slot[NCPUS];
  60. queue_head_t action_queue; /* assign/shutdown queue */
  61. decl_simple_lock_data(,action_lock);
  62. /*
  63. * cpu_up:
  64. *
  65. * Flag specified cpu as up and running. Called when a processor comes
  66. * online.
  67. */
  68. void cpu_up(int cpu)
  69. {
  70. struct machine_slot *ms;
  71. processor_t processor;
  72. spl_t s;
  73. processor = cpu_to_processor(cpu);
  74. pset_lock(&default_pset);
  75. s = splsched();
  76. processor_lock(processor);
  77. #if NCPUS > 1
  78. init_ast_check(processor);
  79. #endif /* NCPUS > 1 */
  80. ms = &machine_slot[cpu];
  81. ms->running = TRUE;
  82. machine_info.avail_cpus++;
  83. pset_add_processor(&default_pset, processor);
  84. processor->state = PROCESSOR_RUNNING;
  85. processor_unlock(processor);
  86. splx(s);
  87. pset_unlock(&default_pset);
  88. }
  89. /*
  90. * cpu_down:
  91. *
  92. * Flag specified cpu as down. Called when a processor is about to
  93. * go offline.
  94. */
  95. void cpu_down(int cpu)
  96. {
  97. struct machine_slot *ms;
  98. processor_t processor;
  99. spl_t s;
  100. s = splsched();
  101. processor = cpu_to_processor(cpu);
  102. processor_lock(processor);
  103. ms = &machine_slot[cpu];
  104. ms->running = FALSE;
  105. machine_info.avail_cpus--;
  106. /*
  107. * processor has already been removed from pset.
  108. */
  109. processor->processor_set_next = PROCESSOR_SET_NULL;
  110. processor->state = PROCESSOR_OFF_LINE;
  111. processor_unlock(processor);
  112. splx(s);
  113. }
  114. kern_return_t
  115. host_reboot(host, options)
  116. const host_t host;
  117. int options;
  118. {
  119. if (host == HOST_NULL)
  120. return (KERN_INVALID_HOST);
  121. if (options & RB_DEBUGGER) {
  122. Debugger("Debugger");
  123. } else {
  124. #ifdef parisc
  125. /* XXX this could be made common */
  126. halt_all_cpus(options);
  127. #else
  128. halt_all_cpus(!(options & RB_HALT));
  129. #endif
  130. }
  131. return (KERN_SUCCESS);
  132. }
  133. #if NCPUS > 1
  134. /*
  135. * processor_request_action - common internals of processor_assign
  136. * and processor_shutdown. If new_pset is null, this is
  137. * a shutdown, else it's an assign and caller must donate
  138. * a reference.
  139. */
  140. void
  141. processor_request_action(
  142. processor_t processor,
  143. processor_set_t new_pset)
  144. {
  145. processor_set_t pset;
  146. /*
  147. * Processor must be in a processor set. Must lock its idle lock to
  148. * get at processor state.
  149. */
  150. pset = processor->processor_set;
  151. simple_lock(&pset->idle_lock);
  152. /*
  153. * If the processor is dispatching, let it finish - it will set its
  154. * state to running very soon.
  155. */
  156. while (*(volatile int *)&processor->state == PROCESSOR_DISPATCHING)
  157. continue;
  158. /*
  159. * Now lock the action queue and do the dirty work.
  160. */
  161. simple_lock(&action_lock);
  162. switch (processor->state) {
  163. case PROCESSOR_IDLE:
  164. /*
  165. * Remove from idle queue.
  166. */
  167. queue_remove(&pset->idle_queue, processor, processor_t,
  168. processor_queue);
  169. pset->idle_count--;
  170. /* fall through ... */
  171. case PROCESSOR_RUNNING:
  172. /*
  173. * Put it on the action queue.
  174. */
  175. queue_enter(&action_queue, processor, processor_t,
  176. processor_queue);
  177. /* fall through ... */
  178. case PROCESSOR_ASSIGN:
  179. /*
  180. * And ask the action_thread to do the work.
  181. */
  182. if (new_pset == PROCESSOR_SET_NULL) {
  183. processor->state = PROCESSOR_SHUTDOWN;
  184. }
  185. else {
  186. assert(processor->state != PROCESSOR_ASSIGN);
  187. processor->state = PROCESSOR_ASSIGN;
  188. processor->processor_set_next = new_pset;
  189. }
  190. break;
  191. default:
  192. printf("state: %d\n", processor->state);
  193. panic("processor_request_action: bad state");
  194. }
  195. simple_unlock(&action_lock);
  196. simple_unlock(&pset->idle_lock);
  197. thread_wakeup((event_t)&action_queue);
  198. }
  199. #if MACH_HOST
  200. /*
  201. * processor_assign() changes the processor set that a processor is
  202. * assigned to. Any previous assignment in progress is overridden.
  203. * Synchronizes with assignment completion if wait is TRUE.
  204. */
  205. kern_return_t
  206. processor_assign(
  207. processor_t processor,
  208. processor_set_t new_pset,
  209. boolean_t wait)
  210. {
  211. spl_t s;
  212. /*
  213. * Check for null arguments.
  214. * XXX Can't assign master processor.
  215. */
  216. if (processor == PROCESSOR_NULL || new_pset == PROCESSOR_SET_NULL ||
  217. processor == master_processor) {
  218. return(KERN_INVALID_ARGUMENT);
  219. }
  220. /*
  221. * Get pset reference to donate to processor_request_action.
  222. */
  223. pset_reference(new_pset);
  224. /*
  225. * Check processor status.
  226. * If shutdown or being shutdown, can`t reassign.
  227. * If being assigned, wait for assignment to finish.
  228. */
  229. Retry:
  230. s = splsched();
  231. processor_lock(processor);
  232. if(processor->state == PROCESSOR_OFF_LINE ||
  233. processor->state == PROCESSOR_SHUTDOWN) {
  234. /*
  235. * Already shutdown or being shutdown -- Can't reassign.
  236. */
  237. processor_unlock(processor);
  238. (void) splx(s);
  239. pset_deallocate(new_pset);
  240. return(KERN_FAILURE);
  241. }
  242. if (processor->state == PROCESSOR_ASSIGN) {
  243. assert_wait((event_t) processor, TRUE);
  244. processor_unlock(processor);
  245. splx(s);
  246. thread_block(thread_no_continuation);
  247. goto Retry;
  248. }
  249. /*
  250. * Avoid work if processor is already in this processor set.
  251. */
  252. if (processor->processor_set == new_pset) {
  253. processor_unlock(processor);
  254. (void) splx(s);
  255. /* clean up dangling ref */
  256. pset_deallocate(new_pset);
  257. return(KERN_SUCCESS);
  258. }
  259. /*
  260. * OK to start processor assignment.
  261. */
  262. processor_request_action(processor, new_pset);
  263. /*
  264. * Synchronization with completion.
  265. */
  266. if (wait) {
  267. while (processor->state == PROCESSOR_ASSIGN ||
  268. processor->state == PROCESSOR_SHUTDOWN) {
  269. assert_wait((event_t)processor, TRUE);
  270. processor_unlock(processor);
  271. splx(s);
  272. thread_block(thread_no_continuation);
  273. s = splsched();
  274. processor_lock(processor);
  275. }
  276. }
  277. processor_unlock(processor);
  278. splx(s);
  279. return(KERN_SUCCESS);
  280. }
  281. #else /* MACH_HOST */
  282. kern_return_t
  283. processor_assign(
  284. processor_t processor,
  285. processor_set_t new_pset,
  286. boolean_t wait)
  287. {
  288. return KERN_FAILURE;
  289. }
  290. #endif /* MACH_HOST */
  291. /*
  292. * processor_shutdown() queues a processor up for shutdown.
  293. * Any assignment in progress is overriden. It does not synchronize
  294. * with the shutdown (can be called from interrupt level).
  295. */
  296. kern_return_t
  297. processor_shutdown(processor_t processor)
  298. {
  299. spl_t s;
  300. if (processor == PROCESSOR_NULL)
  301. return KERN_INVALID_ARGUMENT;
  302. s = splsched();
  303. processor_lock(processor);
  304. if(processor->state == PROCESSOR_OFF_LINE ||
  305. processor->state == PROCESSOR_SHUTDOWN) {
  306. /*
  307. * Already shutdown or being shutdown -- nothing to do.
  308. */
  309. processor_unlock(processor);
  310. splx(s);
  311. return(KERN_SUCCESS);
  312. }
  313. processor_request_action(processor, PROCESSOR_SET_NULL);
  314. processor_unlock(processor);
  315. splx(s);
  316. return(KERN_SUCCESS);
  317. }
  318. /*
  319. * action_thread() shuts down processors or changes their assignment.
  320. */
  321. void action_thread_continue(void)
  322. {
  323. processor_t processor;
  324. spl_t s;
  325. while (TRUE) {
  326. s = splsched();
  327. simple_lock(&action_lock);
  328. while ( !queue_empty(&action_queue)) {
  329. processor = (processor_t) queue_first(&action_queue);
  330. queue_remove(&action_queue, processor, processor_t,
  331. processor_queue);
  332. simple_unlock(&action_lock);
  333. (void) splx(s);
  334. processor_doaction(processor);
  335. s = splsched();
  336. simple_lock(&action_lock);
  337. }
  338. assert_wait((event_t) &action_queue, FALSE);
  339. simple_unlock(&action_lock);
  340. (void) splx(s);
  341. counter(c_action_thread_block++);
  342. thread_block(action_thread_continue);
  343. }
  344. }
  345. void __attribute__((noreturn)) action_thread(void)
  346. {
  347. action_thread_continue();
  348. /*NOTREACHED*/
  349. }
  350. /*
  351. * processor_doaction actually does the shutdown. The trick here
  352. * is to schedule ourselves onto a cpu and then save our
  353. * context back into the runqs before taking out the cpu.
  354. */
  355. void processor_doaction(processor_t processor)
  356. {
  357. thread_t this_thread;
  358. spl_t s;
  359. processor_set_t pset;
  360. #if MACH_HOST
  361. processor_set_t new_pset;
  362. thread_t thread;
  363. thread_t prev_thread = THREAD_NULL;
  364. boolean_t have_pset_ref = FALSE;
  365. #endif /* MACH_HOST */
  366. /*
  367. * Get onto the processor to shutdown
  368. */
  369. this_thread = current_thread();
  370. thread_bind(this_thread, processor);
  371. thread_block(thread_no_continuation);
  372. pset = processor->processor_set;
  373. #if MACH_HOST
  374. /*
  375. * If this is the last processor in the processor_set,
  376. * stop all the threads first.
  377. */
  378. pset_lock(pset);
  379. if (pset->processor_count == 1) {
  380. /*
  381. * First suspend all of them.
  382. */
  383. queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
  384. thread_hold(thread);
  385. }
  386. pset->empty = TRUE;
  387. /*
  388. * Now actually stop them. Need a pset reference.
  389. */
  390. pset->ref_count++;
  391. have_pset_ref = TRUE;
  392. Restart_thread:
  393. prev_thread = THREAD_NULL;
  394. queue_iterate(&pset->threads, thread, thread_t, pset_threads) {
  395. thread_reference(thread);
  396. pset_unlock(pset);
  397. if (prev_thread != THREAD_NULL)
  398. thread_deallocate(prev_thread);
  399. /*
  400. * Only wait for threads still in the pset.
  401. */
  402. thread_freeze(thread);
  403. if (thread->processor_set != pset) {
  404. /*
  405. * It got away - start over.
  406. */
  407. thread_unfreeze(thread);
  408. thread_deallocate(thread);
  409. pset_lock(pset);
  410. goto Restart_thread;
  411. }
  412. (void) thread_dowait(thread, TRUE);
  413. prev_thread = thread;
  414. pset_lock(pset);
  415. thread_unfreeze(prev_thread);
  416. }
  417. }
  418. pset_unlock(pset);
  419. /*
  420. * At this point, it is ok to remove the processor from the pset.
  421. * We can use processor->processor_set_next without locking the
  422. * processor, since it cannot change while processor->state is
  423. * PROCESSOR_ASSIGN or PROCESSOR_SHUTDOWN.
  424. */
  425. new_pset = processor->processor_set_next;
  426. Restart_pset:
  427. if (new_pset) {
  428. /*
  429. * Reassigning processor.
  430. */
  431. if ((integer_t) pset < (integer_t) new_pset) {
  432. pset_lock(pset);
  433. pset_lock(new_pset);
  434. }
  435. else {
  436. pset_lock(new_pset);
  437. pset_lock(pset);
  438. }
  439. if (!(new_pset->active)) {
  440. pset_unlock(new_pset);
  441. pset_unlock(pset);
  442. pset_deallocate(new_pset);
  443. new_pset = &default_pset;
  444. pset_reference(new_pset);
  445. goto Restart_pset;
  446. }
  447. /*
  448. * Handle remove last / assign first race.
  449. * Only happens if there is more than one action thread.
  450. */
  451. while (new_pset->empty && new_pset->processor_count > 0) {
  452. pset_unlock(new_pset);
  453. pset_unlock(pset);
  454. while (*(volatile boolean_t *)&new_pset->empty &&
  455. *(volatile int *)&new_pset->processor_count > 0)
  456. /* spin */;
  457. goto Restart_pset;
  458. }
  459. /*
  460. * Lock the processor. new_pset should not have changed.
  461. */
  462. s = splsched();
  463. processor_lock(processor);
  464. assert(processor->processor_set_next == new_pset);
  465. /*
  466. * Shutdown may have been requested while this assignment
  467. * was in progress.
  468. */
  469. if (processor->state == PROCESSOR_SHUTDOWN) {
  470. processor->processor_set_next = PROCESSOR_SET_NULL;
  471. pset_unlock(new_pset);
  472. goto shutdown; /* releases pset reference */
  473. }
  474. /*
  475. * Do assignment, then wakeup anyone waiting for it.
  476. */
  477. pset_remove_processor(pset, processor);
  478. pset_unlock(pset);
  479. pset_add_processor(new_pset, processor);
  480. if (new_pset->empty) {
  481. /*
  482. * Set all the threads loose.
  483. *
  484. * NOTE: this appears to violate the locking
  485. * order, since the processor lock should
  486. * be taken AFTER a thread lock. However,
  487. * thread_setrun (called by thread_release)
  488. * only takes the processor lock if the
  489. * processor is idle. The processor is
  490. * not idle here.
  491. */
  492. queue_iterate(&new_pset->threads, thread, thread_t,
  493. pset_threads) {
  494. thread_release(thread);
  495. }
  496. new_pset->empty = FALSE;
  497. }
  498. processor->processor_set_next = PROCESSOR_SET_NULL;
  499. processor->state = PROCESSOR_RUNNING;
  500. thread_wakeup((event_t)processor);
  501. processor_unlock(processor);
  502. splx(s);
  503. pset_unlock(new_pset);
  504. /*
  505. * Clean up dangling references, and release our binding.
  506. */
  507. pset_deallocate(new_pset);
  508. if (have_pset_ref)
  509. pset_deallocate(pset);
  510. if (prev_thread != THREAD_NULL)
  511. thread_deallocate(prev_thread);
  512. thread_bind(this_thread, PROCESSOR_NULL);
  513. thread_block(thread_no_continuation);
  514. return;
  515. }
  516. #endif /* MACH_HOST */
  517. /*
  518. * Do shutdown, make sure we live when processor dies.
  519. */
  520. if (processor->state != PROCESSOR_SHUTDOWN) {
  521. printf("state: %d\n", processor->state);
  522. panic("action_thread -- bad processor state");
  523. }
  524. s = splsched();
  525. processor_lock(processor);
  526. shutdown:
  527. pset_remove_processor(pset, processor);
  528. processor_unlock(processor);
  529. pset_unlock(pset);
  530. splx(s);
  531. /*
  532. * Clean up dangling references, and release our binding.
  533. */
  534. #if MACH_HOST
  535. if (new_pset != PROCESSOR_SET_NULL)
  536. pset_deallocate(new_pset);
  537. if (have_pset_ref)
  538. pset_deallocate(pset);
  539. if (prev_thread != THREAD_NULL)
  540. thread_deallocate(prev_thread);
  541. #endif /* MACH_HOST */
  542. thread_bind(this_thread, PROCESSOR_NULL);
  543. switch_to_shutdown_context(this_thread,
  544. processor_doshutdown,
  545. processor);
  546. }
  547. /*
  548. * Actually do the processor shutdown. This is called at splsched,
  549. * running on the processor's shutdown stack.
  550. */
  551. void processor_doshutdown(processor)
  552. processor_t processor;
  553. {
  554. int cpu = processor->slot_num;
  555. timer_switch(&kernel_timer[cpu]);
  556. /*
  557. * Ok, now exit this cpu.
  558. */
  559. PMAP_DEACTIVATE_KERNEL(cpu);
  560. #ifndef MIGRATING_THREADS
  561. active_threads[cpu] = THREAD_NULL;
  562. #endif
  563. cpu_down(cpu);
  564. thread_wakeup((event_t)processor);
  565. halt_cpu();
  566. /*
  567. * The action thread returns to life after the call to
  568. * switch_to_shutdown_context above, on some other cpu.
  569. */
  570. /*NOTREACHED*/
  571. }
  572. #else /* NCPUS > 1 */
  573. kern_return_t
  574. processor_assign(
  575. processor_t processor,
  576. processor_set_t new_pset,
  577. boolean_t wait)
  578. {
  579. return(KERN_FAILURE);
  580. }
  581. #endif /* NCPUS > 1 */
  582. kern_return_t
  583. host_get_boot_info(
  584. host_t priv_host,
  585. kernel_boot_info_t boot_info)
  586. {
  587. char *src = "";
  588. if (priv_host == HOST_NULL) {
  589. return KERN_INVALID_HOST;
  590. }
  591. (void) strncpy(boot_info, src, KERNEL_BOOT_INFO_MAX);
  592. return KERN_SUCCESS;
  593. }