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 16#undef DEBUG_SMP 17 18#include <linux/irq.h> 19#include <linux/interrupt.h> 20#include <linux/spinlock.h> 21#include <linux/mm.h> 22#include <linux/smp.h> 23#include <linux/profile.h> 24#include <linux/cpu.h> 25 26#include <asm/cacheflush.h> 27#include <asm/pgalloc.h> 28#include <asm/atomic.h> 29#include <asm/io.h> 30#include <asm/mmu_context.h> 31#include <asm/m32r.h> 32 33/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 34/* Data structures and variables */ 35/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 36 37/* 38 * Structure and data for smp_call_function(). This is designed to minimise 39 * static memory requirements. It also looks cleaner. 40 */ 41static DEFINE_SPINLOCK(call_lock); 42 43struct call_data_struct { 44 void (*func) (void *info); 45 void *info; 46 atomic_t started; 47 atomic_t finished; 48 int wait; 49} __attribute__ ((__aligned__(SMP_CACHE_BYTES))); 50 51static struct call_data_struct *call_data; 52 53/* 54 * For flush_cache_all() 55 */ 56static DEFINE_SPINLOCK(flushcache_lock); 57static volatile unsigned long flushcache_cpumask = 0; 58 59/* 60 * For flush_tlb_others() 61 */ 62static volatile cpumask_t flush_cpumask; 63static struct mm_struct *flush_mm; 64static struct vm_area_struct *flush_vma; 65static volatile unsigned long flush_va; 66static DEFINE_SPINLOCK(tlbstate_lock); 67#define FLUSH_ALL 0xffffffff 68 69DECLARE_PER_CPU(int, prof_multiplier); 70DECLARE_PER_CPU(int, prof_old_multiplier); 71DECLARE_PER_CPU(int, prof_counter); 72 73extern spinlock_t ipi_lock[]; 74 75/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 76/* Function Prototypes */ 77/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 78 79void smp_send_reschedule(int); 80void smp_reschedule_interrupt(void); 81 82void smp_flush_cache_all(void); 83void smp_flush_cache_all_interrupt(void); 84 85void smp_flush_tlb_all(void); 86static void flush_tlb_all_ipi(void *); 87 88void smp_flush_tlb_mm(struct mm_struct *); 89void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \ 90 unsigned long); 91void smp_flush_tlb_page(struct vm_area_struct *, unsigned long); 92static void flush_tlb_others(cpumask_t, struct mm_struct *, 93 struct vm_area_struct *, unsigned long); 94void smp_invalidate_interrupt(void); 95 96void smp_send_stop(void); 97static void stop_this_cpu(void *); 98 99int smp_call_function(void (*) (void *), void *, int, int); 100void smp_call_function_interrupt(void); 101 102void smp_send_timer(void); 103void smp_ipi_timer_interrupt(struct pt_regs *); 104void smp_local_timer_interrupt(void); 105 106void send_IPI_allbutself(int, int); 107static void send_IPI_mask(cpumask_t, int, int); 108unsigned long send_IPI_mask_phys(cpumask_t, int, int); 109 110/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 111/* Rescheduling request Routines */ 112/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 113 114/*==========================================================================* 115 * Name: smp_send_reschedule 116 * 117 * Description: This routine requests other CPU to execute rescheduling. 118 * 1.Send 'RESCHEDULE_IPI' to other CPU. 119 * Request other CPU to execute 'smp_reschedule_interrupt()'. 120 * 121 * Born on Date: 2002.02.05 122 * 123 * Arguments: cpu_id - Target CPU ID 124 * 125 * Returns: void (cannot fail) 126 * 127 * Modification log: 128 * Date Who Description 129 * ---------- --- -------------------------------------------------------- 130 * 131 *==========================================================================*/ 132void smp_send_reschedule(int cpu_id) 133{ 134 WARN_ON(cpu_is_offline(cpu_id)); 135 send_IPI_mask(cpumask_of_cpu(cpu_id), RESCHEDULE_IPI, 1); 136} 137 138/*==========================================================================* 139 * Name: smp_reschedule_interrupt 140 * 141 * Description: This routine executes on CPU which received 142 * 'RESCHEDULE_IPI'. 143 * Rescheduling is processed at the exit of interrupt 144 * operation. 145 * 146 * Born on Date: 2002.02.05 147 * 148 * Arguments: NONE 149 * 150 * Returns: void (cannot fail) 151 * 152 * Modification log: 153 * Date Who Description 154 * ---------- --- -------------------------------------------------------- 155 * 156 *==========================================================================*/ 157void smp_reschedule_interrupt(void) 158{ 159 /* nothing to do */ 160} 161 162/*==========================================================================* 163 * Name: smp_flush_cache_all 164 * 165 * Description: This routine sends a 'INVALIDATE_CACHE_IPI' to all other 166 * CPUs in the system. 167 * 168 * Born on Date: 2003-05-28 169 * 170 * Arguments: NONE 171 * 172 * Returns: void (cannot fail) 173 * 174 * Modification log: 175 * Date Who Description 176 * ---------- --- -------------------------------------------------------- 177 * 178 *==========================================================================*/ 179void smp_flush_cache_all(void) 180{ 181 cpumask_t cpumask; 182 unsigned long *mask; 183 184 preempt_disable(); 185 cpumask = cpu_online_map; 186 cpu_clear(smp_processor_id(), cpumask); 187 spin_lock(&flushcache_lock); 188 mask=cpus_addr(cpumask); 189 atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask); 190 send_IPI_mask(cpumask, INVALIDATE_CACHE_IPI, 0); 191 _flush_cache_copyback_all(); 192 while (flushcache_cpumask) 193 mb(); 194 spin_unlock(&flushcache_lock); 195 preempt_enable(); 196} 197 198void smp_flush_cache_all_interrupt(void) 199{ 200 _flush_cache_copyback_all(); 201 clear_bit(smp_processor_id(), &flushcache_cpumask); 202} 203 204/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 205/* TLB flush request Routins */ 206/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 207 208/*==========================================================================* 209 * Name: smp_flush_tlb_all 210 * 211 * Description: This routine flushes all processes TLBs. 212 * 1.Request other CPU to execute 'flush_tlb_all_ipi()'. 213 * 2.Execute 'do_flush_tlb_all_local()'. 214 * 215 * Born on Date: 2002.02.05 216 * 217 * Arguments: NONE 218 * 219 * Returns: void (cannot fail) 220 * 221 * Modification log: 222 * Date Who Description 223 * ---------- --- -------------------------------------------------------- 224 * 225 *==========================================================================*/ 226void smp_flush_tlb_all(void) 227{ 228 unsigned long flags; 229 230 preempt_disable(); 231 local_irq_save(flags); 232 __flush_tlb_all(); 233 local_irq_restore(flags); 234 smp_call_function(flush_tlb_all_ipi, NULL, 1, 1); 235 preempt_enable(); 236} 237 238/*==========================================================================* 239 * Name: flush_tlb_all_ipi 240 * 241 * Description: This routine flushes all local TLBs. 242 * 1.Execute 'do_flush_tlb_all_local()'. 243 * 244 * Born on Date: 2002.02.05 245 * 246 * Arguments: *info - not used 247 * 248 * Returns: void (cannot fail) 249 * 250 * Modification log: 251 * Date Who Description 252 * ---------- --- -------------------------------------------------------- 253 * 254 *==========================================================================*/ 255static void flush_tlb_all_ipi(void *info) 256{ 257 __flush_tlb_all(); 258} 259 260/*==========================================================================* 261 * Name: smp_flush_tlb_mm 262 * 263 * Description: This routine flushes the specified mm context TLB's. 264 * 265 * Born on Date: 2002.02.05 266 * 267 * Arguments: *mm - a pointer to the mm struct for flush TLB 268 * 269 * Returns: void (cannot fail) 270 * 271 * Modification log: 272 * Date Who Description 273 * ---------- --- -------------------------------------------------------- 274 * 275 *==========================================================================*/ 276void smp_flush_tlb_mm(struct mm_struct *mm) 277{ 278 int cpu_id; 279 cpumask_t cpu_mask; 280 unsigned long *mmc; 281 unsigned long flags; 282 283 preempt_disable(); 284 cpu_id = smp_processor_id(); 285 mmc = &mm->context[cpu_id]; 286 cpu_mask = mm->cpu_vm_mask; 287 cpu_clear(cpu_id, cpu_mask); 288 289 if (*mmc != NO_CONTEXT) { 290 local_irq_save(flags); 291 *mmc = NO_CONTEXT; 292 if (mm == current->mm) 293 activate_context(mm); 294 else 295 cpu_clear(cpu_id, mm->cpu_vm_mask); 296 local_irq_restore(flags); 297 } 298 if (!cpus_empty(cpu_mask)) 299 flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL); 300 301 preempt_enable(); 302} 303 304/*==========================================================================* 305 * Name: smp_flush_tlb_range 306 * 307 * Description: This routine flushes a range of pages. 308 * 309 * Born on Date: 2002.02.05 310 * 311 * Arguments: *mm - a pointer to the mm struct for flush TLB 312 * start - not used 313 * end - not used 314 * 315 * Returns: void (cannot fail) 316 * 317 * Modification log: 318 * Date Who Description 319 * ---------- --- -------------------------------------------------------- 320 * 321 *==========================================================================*/ 322void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 323 unsigned long end) 324{ 325 smp_flush_tlb_mm(vma->vm_mm); 326} 327 328/*==========================================================================* 329 * Name: smp_flush_tlb_page 330 * 331 * Description: This routine flushes one page. 332 * 333 * Born on Date: 2002.02.05 334 * 335 * Arguments: *vma - a pointer to the vma struct include va 336 * va - virtual address for flush TLB 337 * 338 * Returns: void (cannot fail) 339 * 340 * Modification log: 341 * Date Who Description 342 * ---------- --- -------------------------------------------------------- 343 * 344 *==========================================================================*/ 345void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va) 346{ 347 struct mm_struct *mm = vma->vm_mm; 348 int cpu_id; 349 cpumask_t cpu_mask; 350 unsigned long *mmc; 351 unsigned long flags; 352 353 preempt_disable(); 354 cpu_id = smp_processor_id(); 355 mmc = &mm->context[cpu_id]; 356 cpu_mask = mm->cpu_vm_mask; 357 cpu_clear(cpu_id, cpu_mask); 358 359#ifdef DEBUG_SMP 360 if (!mm) 361 BUG(); 362#endif 363 364 if (*mmc != NO_CONTEXT) { 365 local_irq_save(flags); 366 va &= PAGE_MASK; 367 va |= (*mmc & MMU_CONTEXT_ASID_MASK); 368 __flush_tlb_page(va); 369 local_irq_restore(flags); 370 } 371 if (!cpus_empty(cpu_mask)) 372 flush_tlb_others(cpu_mask, mm, vma, va); 373 374 preempt_enable(); 375} 376 377/*==========================================================================* 378 * Name: flush_tlb_others 379 * 380 * Description: This routine requests other CPU to execute flush TLB. 381 * 1.Setup parmeters. 382 * 2.Send 'INVALIDATE_TLB_IPI' to other CPU. 383 * Request other CPU to execute 'smp_invalidate_interrupt()'. 384 * 3.Wait for other CPUs operation finished. 385 * 386 * Born on Date: 2002.02.05 387 * 388 * Arguments: cpumask - bitmap of target CPUs 389 * *mm - a pointer to the mm struct for flush TLB 390 * *vma - a pointer to the vma struct include va 391 * va - virtual address for flush TLB 392 * 393 * Returns: void (cannot fail) 394 * 395 * Modification log: 396 * Date Who Description 397 * ---------- --- -------------------------------------------------------- 398 * 399 *==========================================================================*/ 400static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, 401 struct vm_area_struct *vma, unsigned long va) 402{ 403 unsigned long *mask; 404#ifdef DEBUG_SMP 405 unsigned long flags; 406 __save_flags(flags); 407 if (!(flags & 0x0040)) /* Interrupt Disable NONONO */ 408 BUG(); 409#endif /* DEBUG_SMP */ 410 411 /* 412 * A couple of (to be removed) sanity checks: 413 * 414 * - we do not send IPIs to not-yet booted CPUs. 415 * - current CPU must not be in mask 416 * - mask must exist :) 417 */ 418 BUG_ON(cpus_empty(cpumask)); 419 420 BUG_ON(cpu_isset(smp_processor_id(), cpumask)); 421 BUG_ON(!mm); 422 423 /* If a CPU which we ran on has gone down, OK. */ 424 cpus_and(cpumask, cpumask, cpu_online_map); 425 if (cpus_empty(cpumask)) 426 return; 427 428 /* 429 * i'm not happy about this global shared spinlock in the 430 * MM hot path, but we'll see how contended it is. 431 * Temporarily this turns IRQs off, so that lockups are 432 * detected by the NMI watchdog. 433 */ 434 spin_lock(&tlbstate_lock); 435 436 flush_mm = mm; 437 flush_vma = vma; 438 flush_va = va; 439 mask=cpus_addr(cpumask); 440 atomic_set_mask(*mask, (atomic_t *)&flush_cpumask); 441 442 /* 443 * We have to send the IPI only to 444 * CPUs affected. 445 */ 446 send_IPI_mask(cpumask, INVALIDATE_TLB_IPI, 0); 447 448 while (!cpus_empty(flush_cpumask)) { 449 /* nothing. lockup detection does not belong here */ 450 mb(); 451 } 452 453 flush_mm = NULL; 454 flush_vma = NULL; 455 flush_va = 0; 456 spin_unlock(&tlbstate_lock); 457} 458 459/*==========================================================================* 460 * Name: smp_invalidate_interrupt 461 * 462 * Description: This routine executes on CPU which received 463 * 'INVALIDATE_TLB_IPI'. 464 * 1.Flush local TLB. 465 * 2.Report flush TLB process was finished. 466 * 467 * Born on Date: 2002.02.05 468 * 469 * Arguments: NONE 470 * 471 * Returns: void (cannot fail) 472 * 473 * Modification log: 474 * Date Who Description 475 * ---------- --- -------------------------------------------------------- 476 * 477 *==========================================================================*/ 478void smp_invalidate_interrupt(void) 479{ 480 int cpu_id = smp_processor_id(); 481 unsigned long *mmc = &flush_mm->context[cpu_id]; 482 483 if (!cpu_isset(cpu_id, flush_cpumask)) 484 return; 485 486 if (flush_va == FLUSH_ALL) { 487 *mmc = NO_CONTEXT; 488 if (flush_mm == current->active_mm) 489 activate_context(flush_mm); 490 else 491 cpu_clear(cpu_id, flush_mm->cpu_vm_mask); 492 } else { 493 unsigned long va = flush_va; 494 495 if (*mmc != NO_CONTEXT) { 496 va &= PAGE_MASK; 497 va |= (*mmc & MMU_CONTEXT_ASID_MASK); 498 __flush_tlb_page(va); 499 } 500 } 501 cpu_clear(cpu_id, flush_cpumask); 502} 503 504/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 505/* Stop CPU request Routins */ 506/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 507 508/*==========================================================================* 509 * Name: smp_send_stop 510 * 511 * Description: This routine requests stop all CPUs. 512 * 1.Request other CPU to execute 'stop_this_cpu()'. 513 * 514 * Born on Date: 2002.02.05 515 * 516 * Arguments: NONE 517 * 518 * Returns: void (cannot fail) 519 * 520 * Modification log: 521 * Date Who Description 522 * ---------- --- -------------------------------------------------------- 523 * 524 *==========================================================================*/ 525void smp_send_stop(void) 526{ 527 smp_call_function(stop_this_cpu, NULL, 1, 0); 528} 529 530/*==========================================================================* 531 * Name: stop_this_cpu 532 * 533 * Description: This routine halt CPU. 534 * 535 * Born on Date: 2002.02.05 536 * 537 * Arguments: NONE 538 * 539 * Returns: void (cannot fail) 540 * 541 * Modification log: 542 * Date Who Description 543 * ---------- --- -------------------------------------------------------- 544 * 545 *==========================================================================*/ 546static void stop_this_cpu(void *dummy) 547{ 548 int cpu_id = smp_processor_id(); 549 550 /* 551 * Remove this CPU: 552 */ 553 cpu_clear(cpu_id, cpu_online_map); 554 555 /* 556 * PSW IE = 1; 557 * IMASK = 0; 558 * goto SLEEP 559 */ 560 local_irq_disable(); 561 outl(0, M32R_ICU_IMASK_PORTL); 562 inl(M32R_ICU_IMASK_PORTL); /* dummy read */ 563 local_irq_enable(); 564 565 for ( ; ; ); 566} 567 568/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 569/* Call function Routins */ 570/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 571 572/*==========================================================================* 573 * Name: smp_call_function 574 * 575 * Description: This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs 576 * in the system. 577 * 578 * Born on Date: 2002.02.05 579 * 580 * Arguments: *func - The function to run. This must be fast and 581 * non-blocking. 582 * *info - An arbitrary pointer to pass to the function. 583 * nonatomic - currently unused. 584 * wait - If true, wait (atomically) until function has 585 * completed on other CPUs. 586 * 587 * Returns: 0 on success, else a negative status code. Does not return 588 * until remote CPUs are nearly ready to execute <<func>> or 589 * are or have executed. 590 * 591 * Cautions: You must not call this function with disabled interrupts or 592 * from a hardware interrupt handler, you may call it from a 593 * bottom half handler. 594 * 595 * Modification log: 596 * Date Who Description 597 * ---------- --- -------------------------------------------------------- 598 * 599 *==========================================================================*/ 600int smp_call_function(void (*func) (void *info), void *info, int nonatomic, 601 int wait) 602{ 603 struct call_data_struct data; 604 int cpus; 605 606#ifdef DEBUG_SMP 607 unsigned long flags; 608 __save_flags(flags); 609 if (!(flags & 0x0040)) /* Interrupt Disable NONONO */ 610 BUG(); 611#endif /* DEBUG_SMP */ 612 613 /* Holding any lock stops cpus from going down. */ 614 spin_lock(&call_lock); 615 cpus = num_online_cpus() - 1; 616 617 if (!cpus) { 618 spin_unlock(&call_lock); 619 return 0; 620 } 621 622 /* Can deadlock when called with interrupts disabled */ 623 WARN_ON(irqs_disabled()); 624 625 data.func = func; 626 data.info = info; 627 atomic_set(&data.started, 0); 628 data.wait = wait; 629 if (wait) 630 atomic_set(&data.finished, 0); 631 632 call_data = &data; 633 mb(); 634 635 /* Send a message to all other CPUs and wait for them to respond */ 636 send_IPI_allbutself(CALL_FUNCTION_IPI, 0); 637 638 /* Wait for response */ 639 while (atomic_read(&data.started) != cpus) 640 barrier(); 641 642 if (wait) 643 while (atomic_read(&data.finished) != cpus) 644 barrier(); 645 spin_unlock(&call_lock); 646 647 return 0; 648} 649 650/*==========================================================================* 651 * Name: smp_call_function_interrupt 652 * 653 * Description: This routine executes on CPU which received 654 * 'CALL_FUNCTION_IPI'. 655 * 656 * Born on Date: 2002.02.05 657 * 658 * Arguments: NONE 659 * 660 * Returns: void (cannot fail) 661 * 662 * Modification log: 663 * Date Who Description 664 * ---------- --- -------------------------------------------------------- 665 * 666 *==========================================================================*/ 667void smp_call_function_interrupt(void) 668{ 669 void (*func) (void *info) = call_data->func; 670 void *info = call_data->info; 671 int wait = call_data->wait; 672 673 /* 674 * Notify initiating CPU that I've grabbed the data and am 675 * about to execute the function 676 */ 677 mb(); 678 atomic_inc(&call_data->started); 679 /* 680 * At this point the info structure may be out of scope unless wait==1 681 */ 682 irq_enter(); 683 (*func)(info); 684 irq_exit(); 685 686 if (wait) { 687 mb(); 688 atomic_inc(&call_data->finished); 689 } 690} 691 692/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 693/* Timer Routins */ 694/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 695 696/*==========================================================================* 697 * Name: smp_send_timer 698 * 699 * Description: This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs 700 * in the system. 701 * 702 * Born on Date: 2002.02.05 703 * 704 * Arguments: NONE 705 * 706 * Returns: void (cannot fail) 707 * 708 * Modification log: 709 * Date Who Description 710 * ---------- --- -------------------------------------------------------- 711 * 712 *==========================================================================*/ 713void smp_send_timer(void) 714{ 715 send_IPI_allbutself(LOCAL_TIMER_IPI, 1); 716} 717 718/*==========================================================================* 719 * Name: smp_send_timer 720 * 721 * Description: This routine executes on CPU which received 722 * 'LOCAL_TIMER_IPI'. 723 * 724 * Born on Date: 2002.02.05 725 * 726 * Arguments: *regs - a pointer to the saved regster info 727 * 728 * Returns: void (cannot fail) 729 * 730 * Modification log: 731 * Date Who Description 732 * ---------- --- -------------------------------------------------------- 733 * 734 *==========================================================================*/ 735void smp_ipi_timer_interrupt(struct pt_regs *regs) 736{ 737 struct pt_regs *old_regs; 738 old_regs = set_irq_regs(regs); 739 irq_enter(); 740 smp_local_timer_interrupt(); 741 irq_exit(); 742 set_irq_regs(old_regs); 743} 744 745/*==========================================================================* 746 * Name: smp_local_timer_interrupt 747 * 748 * Description: Local timer interrupt handler. It does both profiling and 749 * process statistics/rescheduling. 750 * We do profiling in every local tick, statistics/rescheduling 751 * happen only every 'profiling multiplier' ticks. The default 752 * multiplier is 1 and it can be changed by writing the new 753 * multiplier value into /proc/profile. 754 * 755 * Born on Date: 2002.02.05 756 * 757 * Arguments: *regs - a pointer to the saved regster info 758 * 759 * Returns: void (cannot fail) 760 * 761 * Original: arch/i386/kernel/apic.c 762 * 763 * Modification log: 764 * Date Who Description 765 * ---------- --- -------------------------------------------------------- 766 * 2003-06-24 hy use per_cpu structure. 767 *==========================================================================*/ 768void smp_local_timer_interrupt(void) 769{ 770 int user = user_mode(get_irq_regs()); 771 int cpu_id = smp_processor_id(); 772 773 /* 774 * The profiling function is SMP safe. (nothing can mess 775 * around with "current", and the profiling counters are 776 * updated with atomic operations). This is especially 777 * useful with a profiling multiplier != 1 778 */ 779 780 profile_tick(CPU_PROFILING); 781 782 if (--per_cpu(prof_counter, cpu_id) <= 0) { 783 /* 784 * The multiplier may have changed since the last time we got 785 * to this point as a result of the user writing to 786 * /proc/profile. In this case we need to adjust the APIC 787 * timer accordingly. 788 * 789 * Interrupts are already masked off at this point. 790 */ 791 per_cpu(prof_counter, cpu_id) 792 = per_cpu(prof_multiplier, cpu_id); 793 if (per_cpu(prof_counter, cpu_id) 794 != per_cpu(prof_old_multiplier, cpu_id)) 795 { 796 per_cpu(prof_old_multiplier, cpu_id) 797 = per_cpu(prof_counter, cpu_id); 798 } 799 800 update_process_times(user); 801 } 802} 803 804/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 805/* Send IPI Routins */ 806/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ 807 808/*==========================================================================* 809 * Name: send_IPI_allbutself 810 * 811 * Description: This routine sends a IPI to all other CPUs in the system. 812 * 813 * Born on Date: 2002.02.05 814 * 815 * Arguments: ipi_num - Number of IPI 816 * try - 0 : Send IPI certainly. 817 * !0 : The following IPI is not sended when Target CPU 818 * has not received the before IPI. 819 * 820 * Returns: void (cannot fail) 821 * 822 * Modification log: 823 * Date Who Description 824 * ---------- --- -------------------------------------------------------- 825 * 826 *==========================================================================*/ 827void send_IPI_allbutself(int ipi_num, int try) 828{ 829 cpumask_t cpumask; 830 831 cpumask = cpu_online_map; 832 cpu_clear(smp_processor_id(), cpumask); 833 834 send_IPI_mask(cpumask, ipi_num, try); 835} 836 837/*==========================================================================* 838 * Name: send_IPI_mask 839 * 840 * Description: This routine sends a IPI to CPUs in the system. 841 * 842 * Born on Date: 2002.02.05 843 * 844 * Arguments: cpu_mask - Bitmap of target CPUs logical ID 845 * ipi_num - Number of IPI 846 * try - 0 : Send IPI certainly. 847 * !0 : The following IPI is not sended when Target CPU 848 * has not received the before IPI. 849 * 850 * Returns: void (cannot fail) 851 * 852 * Modification log: 853 * Date Who Description 854 * ---------- --- -------------------------------------------------------- 855 * 856 *==========================================================================*/ 857static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try) 858{ 859 cpumask_t physid_mask, tmp; 860 int cpu_id, phys_id; 861 int num_cpus = num_online_cpus(); 862 863 if (num_cpus <= 1) /* NO MP */ 864 return; 865 866 cpus_and(tmp, cpumask, cpu_online_map); 867 BUG_ON(!cpus_equal(cpumask, tmp)); 868 869 physid_mask = CPU_MASK_NONE; 870 for_each_cpu_mask(cpu_id, cpumask){ 871 if ((phys_id = cpu_to_physid(cpu_id)) != -1) 872 cpu_set(phys_id, physid_mask); 873 } 874 875 send_IPI_mask_phys(physid_mask, ipi_num, try); 876} 877 878/*==========================================================================* 879 * Name: send_IPI_mask_phys 880 * 881 * Description: This routine sends a IPI to other CPUs in the system. 882 * 883 * Born on Date: 2002.02.05 884 * 885 * Arguments: cpu_mask - Bitmap of target CPUs physical ID 886 * ipi_num - Number of IPI 887 * try - 0 : Send IPI certainly. 888 * !0 : The following IPI is not sended when Target CPU 889 * has not received the before IPI. 890 * 891 * Returns: IPICRi regster value. 892 * 893 * Modification log: 894 * Date Who Description 895 * ---------- --- -------------------------------------------------------- 896 * 897 *==========================================================================*/ 898unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num, 899 int try) 900{ 901 spinlock_t *ipilock; 902 volatile unsigned long *ipicr_addr; 903 unsigned long ipicr_val; 904 unsigned long my_physid_mask; 905 unsigned long mask = cpus_addr(physid_mask)[0]; 906 907 908 if (mask & ~physids_coerce(phys_cpu_present_map)) 909 BUG(); 910 if (ipi_num >= NR_IPIS) 911 BUG(); 912 913 mask <<= IPI_SHIFT; 914 ipilock = &ipi_lock[ipi_num]; 915 ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR 916 + (ipi_num << 2)); 917 my_physid_mask = ~(1 << smp_processor_id()); 918 919 /* 920 * lock ipi_lock[i] 921 * check IPICRi == 0 922 * write IPICRi (send IPIi) 923 * unlock ipi_lock[i] 924 */ 925 spin_lock(ipilock); 926 __asm__ __volatile__ ( 927 ";; CHECK IPICRi == 0 \n\t" 928 ".fillinsn \n" 929 "1: \n\t" 930 "ld %0, @%1 \n\t" 931 "and %0, %4 \n\t" 932 "beqz %0, 2f \n\t" 933 "bnez %3, 3f \n\t" 934 "bra 1b \n\t" 935 ";; WRITE IPICRi (send IPIi) \n\t" 936 ".fillinsn \n" 937 "2: \n\t" 938 "st %2, @%1 \n\t" 939 ".fillinsn \n" 940 "3: \n\t" 941 : "=&r"(ipicr_val) 942 : "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask) 943 : "memory" 944 ); 945 spin_unlock(ipilock); 946 947 return ipicr_val; 948} 949