smp.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /*
  2. * linux/arch/m32r/kernel/smp.c
  3. *
  4. * M32R SMP support routines.
  5. *
  6. * Copyright (c) 2001, 2002 Hitoshi Yamamoto
  7. *
  8. * Taken from i386 version.
  9. * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
  10. * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
  11. *
  12. * This code is released under the GNU General Public License version 2 or
  13. * later.
  14. */
  15. #undef DEBUG_SMP
  16. #include <linux/irq.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/sched.h>
  19. #include <linux/spinlock.h>
  20. #include <linux/mm.h>
  21. #include <linux/smp.h>
  22. #include <linux/profile.h>
  23. #include <linux/cpu.h>
  24. #include <asm/cacheflush.h>
  25. #include <asm/pgalloc.h>
  26. #include <asm/atomic.h>
  27. #include <asm/io.h>
  28. #include <asm/mmu_context.h>
  29. #include <asm/m32r.h>
  30. #include <asm/tlbflush.h>
  31. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  32. /* Data structures and variables */
  33. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  34. /*
  35. * For flush_cache_all()
  36. */
  37. static DEFINE_SPINLOCK(flushcache_lock);
  38. static volatile unsigned long flushcache_cpumask = 0;
  39. /*
  40. * For flush_tlb_others()
  41. */
  42. static volatile cpumask_t flush_cpumask;
  43. static struct mm_struct *flush_mm;
  44. static struct vm_area_struct *flush_vma;
  45. static volatile unsigned long flush_va;
  46. static DEFINE_SPINLOCK(tlbstate_lock);
  47. #define FLUSH_ALL 0xffffffff
  48. DECLARE_PER_CPU(int, prof_multiplier);
  49. DECLARE_PER_CPU(int, prof_old_multiplier);
  50. DECLARE_PER_CPU(int, prof_counter);
  51. extern spinlock_t ipi_lock[];
  52. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  53. /* Function Prototypes */
  54. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  55. void smp_reschedule_interrupt(void);
  56. void smp_flush_cache_all_interrupt(void);
  57. static void flush_tlb_all_ipi(void *);
  58. static void flush_tlb_others(cpumask_t, struct mm_struct *,
  59. struct vm_area_struct *, unsigned long);
  60. void smp_invalidate_interrupt(void);
  61. static void stop_this_cpu(void *);
  62. void smp_ipi_timer_interrupt(struct pt_regs *);
  63. void smp_local_timer_interrupt(void);
  64. static void send_IPI_allbutself(int, int);
  65. static void send_IPI_mask(const struct cpumask *, int, int);
  66. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  67. /* Rescheduling request Routines */
  68. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  69. /*==========================================================================*
  70. * Name: smp_send_reschedule
  71. *
  72. * Description: This routine requests other CPU to execute rescheduling.
  73. * 1.Send 'RESCHEDULE_IPI' to other CPU.
  74. * Request other CPU to execute 'smp_reschedule_interrupt()'.
  75. *
  76. * Born on Date: 2002.02.05
  77. *
  78. * Arguments: cpu_id - Target CPU ID
  79. *
  80. * Returns: void (cannot fail)
  81. *
  82. * Modification log:
  83. * Date Who Description
  84. * ---------- --- --------------------------------------------------------
  85. *
  86. *==========================================================================*/
  87. void smp_send_reschedule(int cpu_id)
  88. {
  89. WARN_ON(cpu_is_offline(cpu_id));
  90. send_IPI_mask(cpumask_of(cpu_id), RESCHEDULE_IPI, 1);
  91. }
  92. /*==========================================================================*
  93. * Name: smp_reschedule_interrupt
  94. *
  95. * Description: This routine executes on CPU which received
  96. * 'RESCHEDULE_IPI'.
  97. *
  98. * Born on Date: 2002.02.05
  99. *
  100. * Arguments: NONE
  101. *
  102. * Returns: void (cannot fail)
  103. *
  104. * Modification log:
  105. * Date Who Description
  106. * ---------- --- --------------------------------------------------------
  107. *
  108. *==========================================================================*/
  109. void smp_reschedule_interrupt(void)
  110. {
  111. scheduler_ipi();
  112. }
  113. /*==========================================================================*
  114. * Name: smp_flush_cache_all
  115. *
  116. * Description: This routine sends a 'INVALIDATE_CACHE_IPI' to all other
  117. * CPUs in the system.
  118. *
  119. * Born on Date: 2003-05-28
  120. *
  121. * Arguments: NONE
  122. *
  123. * Returns: void (cannot fail)
  124. *
  125. * Modification log:
  126. * Date Who Description
  127. * ---------- --- --------------------------------------------------------
  128. *
  129. *==========================================================================*/
  130. void smp_flush_cache_all(void)
  131. {
  132. cpumask_t cpumask;
  133. unsigned long *mask;
  134. preempt_disable();
  135. cpumask_copy(&cpumask, cpu_online_mask);
  136. cpumask_clear_cpu(smp_processor_id(), &cpumask);
  137. spin_lock(&flushcache_lock);
  138. mask=cpumask_bits(&cpumask);
  139. atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
  140. send_IPI_mask(&cpumask, INVALIDATE_CACHE_IPI, 0);
  141. _flush_cache_copyback_all();
  142. while (flushcache_cpumask)
  143. mb();
  144. spin_unlock(&flushcache_lock);
  145. preempt_enable();
  146. }
  147. void smp_flush_cache_all_interrupt(void)
  148. {
  149. _flush_cache_copyback_all();
  150. clear_bit(smp_processor_id(), &flushcache_cpumask);
  151. }
  152. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  153. /* TLB flush request Routines */
  154. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  155. /*==========================================================================*
  156. * Name: smp_flush_tlb_all
  157. *
  158. * Description: This routine flushes all processes TLBs.
  159. * 1.Request other CPU to execute 'flush_tlb_all_ipi()'.
  160. * 2.Execute 'do_flush_tlb_all_local()'.
  161. *
  162. * Born on Date: 2002.02.05
  163. *
  164. * Arguments: NONE
  165. *
  166. * Returns: void (cannot fail)
  167. *
  168. * Modification log:
  169. * Date Who Description
  170. * ---------- --- --------------------------------------------------------
  171. *
  172. *==========================================================================*/
  173. void smp_flush_tlb_all(void)
  174. {
  175. unsigned long flags;
  176. preempt_disable();
  177. local_irq_save(flags);
  178. __flush_tlb_all();
  179. local_irq_restore(flags);
  180. smp_call_function(flush_tlb_all_ipi, NULL, 1);
  181. preempt_enable();
  182. }
  183. /*==========================================================================*
  184. * Name: flush_tlb_all_ipi
  185. *
  186. * Description: This routine flushes all local TLBs.
  187. * 1.Execute 'do_flush_tlb_all_local()'.
  188. *
  189. * Born on Date: 2002.02.05
  190. *
  191. * Arguments: *info - not used
  192. *
  193. * Returns: void (cannot fail)
  194. *
  195. * Modification log:
  196. * Date Who Description
  197. * ---------- --- --------------------------------------------------------
  198. *
  199. *==========================================================================*/
  200. static void flush_tlb_all_ipi(void *info)
  201. {
  202. __flush_tlb_all();
  203. }
  204. /*==========================================================================*
  205. * Name: smp_flush_tlb_mm
  206. *
  207. * Description: This routine flushes the specified mm context TLB's.
  208. *
  209. * Born on Date: 2002.02.05
  210. *
  211. * Arguments: *mm - a pointer to the mm struct for flush TLB
  212. *
  213. * Returns: void (cannot fail)
  214. *
  215. * Modification log:
  216. * Date Who Description
  217. * ---------- --- --------------------------------------------------------
  218. *
  219. *==========================================================================*/
  220. void smp_flush_tlb_mm(struct mm_struct *mm)
  221. {
  222. int cpu_id;
  223. cpumask_t cpu_mask;
  224. unsigned long *mmc;
  225. unsigned long flags;
  226. preempt_disable();
  227. cpu_id = smp_processor_id();
  228. mmc = &mm->context[cpu_id];
  229. cpumask_copy(&cpu_mask, mm_cpumask(mm));
  230. cpumask_clear_cpu(cpu_id, &cpu_mask);
  231. if (*mmc != NO_CONTEXT) {
  232. local_irq_save(flags);
  233. *mmc = NO_CONTEXT;
  234. if (mm == current->mm)
  235. activate_context(mm);
  236. else
  237. cpumask_clear_cpu(cpu_id, mm_cpumask(mm));
  238. local_irq_restore(flags);
  239. }
  240. if (!cpumask_empty(&cpu_mask))
  241. flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL);
  242. preempt_enable();
  243. }
  244. /*==========================================================================*
  245. * Name: smp_flush_tlb_range
  246. *
  247. * Description: This routine flushes a range of pages.
  248. *
  249. * Born on Date: 2002.02.05
  250. *
  251. * Arguments: *mm - a pointer to the mm struct for flush TLB
  252. * start - not used
  253. * end - not used
  254. *
  255. * Returns: void (cannot fail)
  256. *
  257. * Modification log:
  258. * Date Who Description
  259. * ---------- --- --------------------------------------------------------
  260. *
  261. *==========================================================================*/
  262. void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
  263. unsigned long end)
  264. {
  265. smp_flush_tlb_mm(vma->vm_mm);
  266. }
  267. /*==========================================================================*
  268. * Name: smp_flush_tlb_page
  269. *
  270. * Description: This routine flushes one page.
  271. *
  272. * Born on Date: 2002.02.05
  273. *
  274. * Arguments: *vma - a pointer to the vma struct include va
  275. * va - virtual address for flush TLB
  276. *
  277. * Returns: void (cannot fail)
  278. *
  279. * Modification log:
  280. * Date Who Description
  281. * ---------- --- --------------------------------------------------------
  282. *
  283. *==========================================================================*/
  284. void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
  285. {
  286. struct mm_struct *mm = vma->vm_mm;
  287. int cpu_id;
  288. cpumask_t cpu_mask;
  289. unsigned long *mmc;
  290. unsigned long flags;
  291. preempt_disable();
  292. cpu_id = smp_processor_id();
  293. mmc = &mm->context[cpu_id];
  294. cpumask_copy(&cpu_mask, mm_cpumask(mm));
  295. cpumask_clear_cpu(cpu_id, &cpu_mask);
  296. #ifdef DEBUG_SMP
  297. if (!mm)
  298. BUG();
  299. #endif
  300. if (*mmc != NO_CONTEXT) {
  301. local_irq_save(flags);
  302. va &= PAGE_MASK;
  303. va |= (*mmc & MMU_CONTEXT_ASID_MASK);
  304. __flush_tlb_page(va);
  305. local_irq_restore(flags);
  306. }
  307. if (!cpumask_empty(&cpu_mask))
  308. flush_tlb_others(cpu_mask, mm, vma, va);
  309. preempt_enable();
  310. }
  311. /*==========================================================================*
  312. * Name: flush_tlb_others
  313. *
  314. * Description: This routine requests other CPU to execute flush TLB.
  315. * 1.Setup parameters.
  316. * 2.Send 'INVALIDATE_TLB_IPI' to other CPU.
  317. * Request other CPU to execute 'smp_invalidate_interrupt()'.
  318. * 3.Wait for other CPUs operation finished.
  319. *
  320. * Born on Date: 2002.02.05
  321. *
  322. * Arguments: cpumask - bitmap of target CPUs
  323. * *mm - a pointer to the mm struct for flush TLB
  324. * *vma - a pointer to the vma struct include va
  325. * va - virtual address for flush TLB
  326. *
  327. * Returns: void (cannot fail)
  328. *
  329. * Modification log:
  330. * Date Who Description
  331. * ---------- --- --------------------------------------------------------
  332. *
  333. *==========================================================================*/
  334. static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
  335. struct vm_area_struct *vma, unsigned long va)
  336. {
  337. unsigned long *mask;
  338. #ifdef DEBUG_SMP
  339. unsigned long flags;
  340. __save_flags(flags);
  341. if (!(flags & 0x0040)) /* Interrupt Disable NONONO */
  342. BUG();
  343. #endif /* DEBUG_SMP */
  344. /*
  345. * A couple of (to be removed) sanity checks:
  346. *
  347. * - we do not send IPIs to not-yet booted CPUs.
  348. * - current CPU must not be in mask
  349. * - mask must exist :)
  350. */
  351. BUG_ON(cpumask_empty(&cpumask));
  352. BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask));
  353. BUG_ON(!mm);
  354. /* If a CPU which we ran on has gone down, OK. */
  355. cpumask_and(&cpumask, &cpumask, cpu_online_mask);
  356. if (cpumask_empty(&cpumask))
  357. return;
  358. /*
  359. * i'm not happy about this global shared spinlock in the
  360. * MM hot path, but we'll see how contended it is.
  361. * Temporarily this turns IRQs off, so that lockups are
  362. * detected by the NMI watchdog.
  363. */
  364. spin_lock(&tlbstate_lock);
  365. flush_mm = mm;
  366. flush_vma = vma;
  367. flush_va = va;
  368. mask=cpumask_bits(&cpumask);
  369. atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
  370. /*
  371. * We have to send the IPI only to
  372. * CPUs affected.
  373. */
  374. send_IPI_mask(&cpumask, INVALIDATE_TLB_IPI, 0);
  375. while (!cpumask_empty((cpumask_t*)&flush_cpumask)) {
  376. /* nothing. lockup detection does not belong here */
  377. mb();
  378. }
  379. flush_mm = NULL;
  380. flush_vma = NULL;
  381. flush_va = 0;
  382. spin_unlock(&tlbstate_lock);
  383. }
  384. /*==========================================================================*
  385. * Name: smp_invalidate_interrupt
  386. *
  387. * Description: This routine executes on CPU which received
  388. * 'INVALIDATE_TLB_IPI'.
  389. * 1.Flush local TLB.
  390. * 2.Report flush TLB process was finished.
  391. *
  392. * Born on Date: 2002.02.05
  393. *
  394. * Arguments: NONE
  395. *
  396. * Returns: void (cannot fail)
  397. *
  398. * Modification log:
  399. * Date Who Description
  400. * ---------- --- --------------------------------------------------------
  401. *
  402. *==========================================================================*/
  403. void smp_invalidate_interrupt(void)
  404. {
  405. int cpu_id = smp_processor_id();
  406. unsigned long *mmc = &flush_mm->context[cpu_id];
  407. if (!cpumask_test_cpu(cpu_id, &flush_cpumask))
  408. return;
  409. if (flush_va == FLUSH_ALL) {
  410. *mmc = NO_CONTEXT;
  411. if (flush_mm == current->active_mm)
  412. activate_context(flush_mm);
  413. else
  414. cpumask_clear_cpu(cpu_id, mm_cpumask(flush_mm));
  415. } else {
  416. unsigned long va = flush_va;
  417. if (*mmc != NO_CONTEXT) {
  418. va &= PAGE_MASK;
  419. va |= (*mmc & MMU_CONTEXT_ASID_MASK);
  420. __flush_tlb_page(va);
  421. }
  422. }
  423. cpumask_clear_cpu(cpu_id, (cpumask_t*)&flush_cpumask);
  424. }
  425. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  426. /* Stop CPU request Routines */
  427. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  428. /*==========================================================================*
  429. * Name: smp_send_stop
  430. *
  431. * Description: This routine requests stop all CPUs.
  432. * 1.Request other CPU to execute 'stop_this_cpu()'.
  433. *
  434. * Born on Date: 2002.02.05
  435. *
  436. * Arguments: NONE
  437. *
  438. * Returns: void (cannot fail)
  439. *
  440. * Modification log:
  441. * Date Who Description
  442. * ---------- --- --------------------------------------------------------
  443. *
  444. *==========================================================================*/
  445. void smp_send_stop(void)
  446. {
  447. smp_call_function(stop_this_cpu, NULL, 0);
  448. }
  449. /*==========================================================================*
  450. * Name: stop_this_cpu
  451. *
  452. * Description: This routine halt CPU.
  453. *
  454. * Born on Date: 2002.02.05
  455. *
  456. * Arguments: NONE
  457. *
  458. * Returns: void (cannot fail)
  459. *
  460. * Modification log:
  461. * Date Who Description
  462. * ---------- --- --------------------------------------------------------
  463. *
  464. *==========================================================================*/
  465. static void stop_this_cpu(void *dummy)
  466. {
  467. int cpu_id = smp_processor_id();
  468. /*
  469. * Remove this CPU:
  470. */
  471. set_cpu_online(cpu_id, false);
  472. /*
  473. * PSW IE = 1;
  474. * IMASK = 0;
  475. * goto SLEEP
  476. */
  477. local_irq_disable();
  478. outl(0, M32R_ICU_IMASK_PORTL);
  479. inl(M32R_ICU_IMASK_PORTL); /* dummy read */
  480. local_irq_enable();
  481. for ( ; ; );
  482. }
  483. void arch_send_call_function_ipi_mask(const struct cpumask *mask)
  484. {
  485. send_IPI_mask(mask, CALL_FUNCTION_IPI, 0);
  486. }
  487. void arch_send_call_function_single_ipi(int cpu)
  488. {
  489. send_IPI_mask(cpumask_of(cpu), CALL_FUNC_SINGLE_IPI, 0);
  490. }
  491. /*==========================================================================*
  492. * Name: smp_call_function_interrupt
  493. *
  494. * Description: This routine executes on CPU which received
  495. * 'CALL_FUNCTION_IPI'.
  496. *
  497. * Born on Date: 2002.02.05
  498. *
  499. * Arguments: NONE
  500. *
  501. * Returns: void (cannot fail)
  502. *
  503. * Modification log:
  504. * Date Who Description
  505. * ---------- --- --------------------------------------------------------
  506. *
  507. *==========================================================================*/
  508. void smp_call_function_interrupt(void)
  509. {
  510. irq_enter();
  511. generic_smp_call_function_interrupt();
  512. irq_exit();
  513. }
  514. void smp_call_function_single_interrupt(void)
  515. {
  516. irq_enter();
  517. generic_smp_call_function_single_interrupt();
  518. irq_exit();
  519. }
  520. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  521. /* Timer Routines */
  522. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  523. /*==========================================================================*
  524. * Name: smp_send_timer
  525. *
  526. * Description: This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs
  527. * in the system.
  528. *
  529. * Born on Date: 2002.02.05
  530. *
  531. * Arguments: NONE
  532. *
  533. * Returns: void (cannot fail)
  534. *
  535. * Modification log:
  536. * Date Who Description
  537. * ---------- --- --------------------------------------------------------
  538. *
  539. *==========================================================================*/
  540. void smp_send_timer(void)
  541. {
  542. send_IPI_allbutself(LOCAL_TIMER_IPI, 1);
  543. }
  544. /*==========================================================================*
  545. * Name: smp_send_timer
  546. *
  547. * Description: This routine executes on CPU which received
  548. * 'LOCAL_TIMER_IPI'.
  549. *
  550. * Born on Date: 2002.02.05
  551. *
  552. * Arguments: *regs - a pointer to the saved regster info
  553. *
  554. * Returns: void (cannot fail)
  555. *
  556. * Modification log:
  557. * Date Who Description
  558. * ---------- --- --------------------------------------------------------
  559. *
  560. *==========================================================================*/
  561. void smp_ipi_timer_interrupt(struct pt_regs *regs)
  562. {
  563. struct pt_regs *old_regs;
  564. old_regs = set_irq_regs(regs);
  565. irq_enter();
  566. smp_local_timer_interrupt();
  567. irq_exit();
  568. set_irq_regs(old_regs);
  569. }
  570. /*==========================================================================*
  571. * Name: smp_local_timer_interrupt
  572. *
  573. * Description: Local timer interrupt handler. It does both profiling and
  574. * process statistics/rescheduling.
  575. * We do profiling in every local tick, statistics/rescheduling
  576. * happen only every 'profiling multiplier' ticks. The default
  577. * multiplier is 1 and it can be changed by writing the new
  578. * multiplier value into /proc/profile.
  579. *
  580. * Born on Date: 2002.02.05
  581. *
  582. * Arguments: *regs - a pointer to the saved regster info
  583. *
  584. * Returns: void (cannot fail)
  585. *
  586. * Original: arch/i386/kernel/apic.c
  587. *
  588. * Modification log:
  589. * Date Who Description
  590. * ---------- --- --------------------------------------------------------
  591. * 2003-06-24 hy use per_cpu structure.
  592. *==========================================================================*/
  593. void smp_local_timer_interrupt(void)
  594. {
  595. int user = user_mode(get_irq_regs());
  596. int cpu_id = smp_processor_id();
  597. /*
  598. * The profiling function is SMP safe. (nothing can mess
  599. * around with "current", and the profiling counters are
  600. * updated with atomic operations). This is especially
  601. * useful with a profiling multiplier != 1
  602. */
  603. profile_tick(CPU_PROFILING);
  604. if (--per_cpu(prof_counter, cpu_id) <= 0) {
  605. /*
  606. * The multiplier may have changed since the last time we got
  607. * to this point as a result of the user writing to
  608. * /proc/profile. In this case we need to adjust the APIC
  609. * timer accordingly.
  610. *
  611. * Interrupts are already masked off at this point.
  612. */
  613. per_cpu(prof_counter, cpu_id)
  614. = per_cpu(prof_multiplier, cpu_id);
  615. if (per_cpu(prof_counter, cpu_id)
  616. != per_cpu(prof_old_multiplier, cpu_id))
  617. {
  618. per_cpu(prof_old_multiplier, cpu_id)
  619. = per_cpu(prof_counter, cpu_id);
  620. }
  621. update_process_times(user);
  622. }
  623. }
  624. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  625. /* Send IPI Routines */
  626. /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
  627. /*==========================================================================*
  628. * Name: send_IPI_allbutself
  629. *
  630. * Description: This routine sends a IPI to all other CPUs in the system.
  631. *
  632. * Born on Date: 2002.02.05
  633. *
  634. * Arguments: ipi_num - Number of IPI
  635. * try - 0 : Send IPI certainly.
  636. * !0 : The following IPI is not sent when Target CPU
  637. * has not received the before IPI.
  638. *
  639. * Returns: void (cannot fail)
  640. *
  641. * Modification log:
  642. * Date Who Description
  643. * ---------- --- --------------------------------------------------------
  644. *
  645. *==========================================================================*/
  646. static void send_IPI_allbutself(int ipi_num, int try)
  647. {
  648. cpumask_t cpumask;
  649. cpumask_copy(&cpumask, cpu_online_mask);
  650. cpumask_clear_cpu(smp_processor_id(), &cpumask);
  651. send_IPI_mask(&cpumask, ipi_num, try);
  652. }
  653. /*==========================================================================*
  654. * Name: send_IPI_mask
  655. *
  656. * Description: This routine sends a IPI to CPUs in the system.
  657. *
  658. * Born on Date: 2002.02.05
  659. *
  660. * Arguments: cpu_mask - Bitmap of target CPUs logical ID
  661. * ipi_num - Number of IPI
  662. * try - 0 : Send IPI certainly.
  663. * !0 : The following IPI is not sent when Target CPU
  664. * has not received the before IPI.
  665. *
  666. * Returns: void (cannot fail)
  667. *
  668. * Modification log:
  669. * Date Who Description
  670. * ---------- --- --------------------------------------------------------
  671. *
  672. *==========================================================================*/
  673. static void send_IPI_mask(const struct cpumask *cpumask, int ipi_num, int try)
  674. {
  675. cpumask_t physid_mask, tmp;
  676. int cpu_id, phys_id;
  677. int num_cpus = num_online_cpus();
  678. if (num_cpus <= 1) /* NO MP */
  679. return;
  680. cpumask_and(&tmp, cpumask, cpu_online_mask);
  681. BUG_ON(!cpumask_equal(cpumask, &tmp));
  682. cpumask_clear(&physid_mask);
  683. for_each_cpu(cpu_id, cpumask) {
  684. if ((phys_id = cpu_to_physid(cpu_id)) != -1)
  685. cpumask_set_cpu(phys_id, &physid_mask);
  686. }
  687. send_IPI_mask_phys(&physid_mask, ipi_num, try);
  688. }
  689. /*==========================================================================*
  690. * Name: send_IPI_mask_phys
  691. *
  692. * Description: This routine sends a IPI to other CPUs in the system.
  693. *
  694. * Born on Date: 2002.02.05
  695. *
  696. * Arguments: cpu_mask - Bitmap of target CPUs physical ID
  697. * ipi_num - Number of IPI
  698. * try - 0 : Send IPI certainly.
  699. * !0 : The following IPI is not sent when Target CPU
  700. * has not received the before IPI.
  701. *
  702. * Returns: IPICRi regster value.
  703. *
  704. * Modification log:
  705. * Date Who Description
  706. * ---------- --- --------------------------------------------------------
  707. *
  708. *==========================================================================*/
  709. unsigned long send_IPI_mask_phys(const cpumask_t *physid_mask, int ipi_num,
  710. int try)
  711. {
  712. spinlock_t *ipilock;
  713. volatile unsigned long *ipicr_addr;
  714. unsigned long ipicr_val;
  715. unsigned long my_physid_mask;
  716. unsigned long mask = cpumask_bits(physid_mask)[0];
  717. if (mask & ~physids_coerce(phys_cpu_present_map))
  718. BUG();
  719. if (ipi_num >= NR_IPIS || ipi_num < 0)
  720. BUG();
  721. mask <<= IPI_SHIFT;
  722. ipilock = &ipi_lock[ipi_num];
  723. ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR
  724. + (ipi_num << 2));
  725. my_physid_mask = ~(1 << smp_processor_id());
  726. /*
  727. * lock ipi_lock[i]
  728. * check IPICRi == 0
  729. * write IPICRi (send IPIi)
  730. * unlock ipi_lock[i]
  731. */
  732. spin_lock(ipilock);
  733. __asm__ __volatile__ (
  734. ";; CHECK IPICRi == 0 \n\t"
  735. ".fillinsn \n"
  736. "1: \n\t"
  737. "ld %0, @%1 \n\t"
  738. "and %0, %4 \n\t"
  739. "beqz %0, 2f \n\t"
  740. "bnez %3, 3f \n\t"
  741. "bra 1b \n\t"
  742. ";; WRITE IPICRi (send IPIi) \n\t"
  743. ".fillinsn \n"
  744. "2: \n\t"
  745. "st %2, @%1 \n\t"
  746. ".fillinsn \n"
  747. "3: \n\t"
  748. : "=&r"(ipicr_val)
  749. : "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask)
  750. : "memory"
  751. );
  752. spin_unlock(ipilock);
  753. return ipicr_val;
  754. }