chrp_smp.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  * Smp support for CHRP machines.
  6.  *
  7.  * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
  8.  * deal of code from the sparc and intel versions.
  9.  *
  10.  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
  11.  *
  12.  */
  13. #include <linux/config.h>
  14. #include <linux/kernel.h>
  15. #include <linux/sched.h>
  16. #include <linux/smp.h>
  17. #include <linux/smp_lock.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/kernel_stat.h>
  20. #include <linux/delay.h>
  21. #define __KERNEL_SYSCALLS__
  22. #include <linux/unistd.h>
  23. #include <linux/init.h>
  24. #include <linux/spinlock.h>
  25. #include <asm/ptrace.h>
  26. #include <asm/atomic.h>
  27. #include <asm/irq.h>
  28. #include <asm/page.h>
  29. #include <asm/pgtable.h>
  30. #include <asm/hardirq.h>
  31. #include <asm/softirq.h>
  32. #include <asm/sections.h>
  33. #include <asm/io.h>
  34. #include <asm/prom.h>
  35. #include <asm/smp.h>
  36. #include <asm/residual.h>
  37. #include <asm/time.h>
  38. #include <asm/open_pic.h>
  39. extern unsigned long smp_chrp_cpu_nr;
  40. /*
  41.  * The CHRP RTAS note on multiprocessor systems:
  42.  * "In a multiprocessor system, each processor should
  43.  * call event-scan periodically, not always the same
  44.  * one.  The event-scan function needs to be called a
  45.  * total of rtas-event-scan-rate times a minute"
  46.  * 
  47.  * We must call on each cpu in on a regular basis
  48.  * so that firmware can watch for cpu unique errors.
  49.  */
  50. static void spread_heartbeat(void)
  51. {
  52. unsigned count = heartbeat_count(0);
  53. unsigned offset = count;
  54. int i;
  55. if (!count || smp_chrp_cpu_nr < 2)
  56. return;
  57. count *=  smp_chrp_cpu_nr;
  58. for (i = 0; i < smp_chrp_cpu_nr ; i++)
  59. {
  60. heartbeat_reset(i) = count;
  61. heartbeat_count(i) = i * offset;
  62. }
  63. printk("RTAS Event Scan now every %u jiffes on each cpun", count);
  64. }
  65. static int __init
  66. smp_chrp_probe(void)
  67. {
  68. if (smp_chrp_cpu_nr > 1)
  69. openpic_request_IPIs();
  70. return smp_chrp_cpu_nr;
  71. }
  72. static void __init
  73. smp_chrp_kick_cpu(int nr)
  74. {
  75. *(unsigned long *)KERNELBASE = nr;
  76. asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
  77. }
  78. static void __init
  79. smp_chrp_setup_cpu(int cpu_nr)
  80. {
  81. static atomic_t ready = ATOMIC_INIT(1);
  82. static volatile int frozen = 0;
  83. if (cpu_nr == 0) {
  84. /* wait for all the others */
  85. while (atomic_read(&ready) < smp_num_cpus)
  86. barrier();
  87. atomic_set(&ready, 1);
  88. /* freeze the timebase */
  89. call_rtas("freeze-time-base", 0, 1, NULL);
  90. mb();
  91. frozen = 1;
  92. /* XXX assumes this is not a 601 */
  93. set_tb(0, 0);
  94. last_jiffy_stamp(0) = 0;
  95. while (atomic_read(&ready) < smp_num_cpus)
  96. barrier();
  97. /* thaw the timebase again */
  98. call_rtas("thaw-time-base", 0, 1, NULL);
  99. mb();
  100. frozen = 0;
  101. smp_tb_synchronized = 1;
  102. } else {
  103. atomic_inc(&ready);
  104. while (!frozen)
  105. barrier();
  106. set_tb(0, 0);
  107. last_jiffy_stamp(0) = 0;
  108. mb();
  109. atomic_inc(&ready);
  110. while (frozen)
  111. barrier();
  112. }
  113. if (OpenPIC_Addr)
  114. do_openpic_setup_cpu();
  115. }
  116. #ifdef CONFIG_POWER4
  117. static void __chrp
  118. smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
  119. {
  120. /* for now, only do reschedule messages
  121.    since we only have one IPI */
  122. if (msg != PPC_MSG_RESCHEDULE)
  123. return;
  124. for (i = 0; i < smp_num_cpus; ++i) {
  125. if (target == MSG_ALL || target == i
  126.     || (target == MSG_ALL_BUT_SELF
  127. && i != smp_processor_id()))
  128. xics_cause_IPI(i);
  129. }
  130. }
  131. static int __chrp
  132. smp_xics_probe(void)
  133. {
  134. return smp_chrp_cpu_nr;
  135. }
  136. static void __chrp
  137. smp_xics_setup_cpu(int cpu_nr)
  138. {
  139. if (cpu_nr > 0)
  140. xics_setup_cpu();
  141. }
  142. #endif /* CONFIG_POWER4 */
  143. /* CHRP with openpic */
  144. struct smp_ops_t chrp_smp_ops __chrpdata = {
  145. smp_openpic_message_pass,
  146. smp_chrp_probe,
  147. smp_chrp_kick_cpu,
  148. smp_chrp_setup_cpu,
  149. };
  150. #ifdef CONFIG_POWER4
  151. /* CHRP with new XICS interrupt controller */
  152. struct smp_ops_t xics_smp_ops __chrpdata = {
  153. smp_xics_message_pass,
  154. smp_xics_probe,
  155. smp_chrp_kick_cpu,
  156. smp_xics_setup_cpu,
  157. };
  158. #endif /* CONFIG_POWER4 */