home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / x86 / include / asm / ipi.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  3.0 KB  |  139 lines

  1. #ifndef _ASM_X86_IPI_H
  2. #define _ASM_X86_IPI_H
  3.  
  4. /*
  5.  * Copyright 2004 James Cleverdon, IBM.
  6.  * Subject to the GNU Public License, v.2
  7.  *
  8.  * Generic APIC InterProcessor Interrupt code.
  9.  *
  10.  * Moved to include file by James Cleverdon from
  11.  * arch/x86-64/kernel/smp.c
  12.  *
  13.  * Copyrights from kernel/smp.c:
  14.  *
  15.  * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
  16.  * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
  17.  * (c) 2002,2003 Andi Kleen, SuSE Labs.
  18.  * Subject to the GNU Public License, v.2
  19.  */
  20.  
  21. #include <asm/hw_irq.h>
  22. #include <asm/apic.h>
  23. #include <asm/smp.h>
  24.  
  25. /*
  26.  * the following functions deal with sending IPIs between CPUs.
  27.  *
  28.  * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
  29.  */
  30.  
  31. static inline unsigned int __prepare_ICR(unsigned int shortcut, int vector,
  32.                      unsigned int dest)
  33. {
  34.     unsigned int icr = shortcut | dest;
  35.  
  36.     switch (vector) {
  37.     default:
  38.         icr |= APIC_DM_FIXED | vector;
  39.         break;
  40.     case NMI_VECTOR:
  41.         icr |= APIC_DM_NMI;
  42.         break;
  43.     }
  44.     return icr;
  45. }
  46.  
  47. static inline int __prepare_ICR2(unsigned int mask)
  48. {
  49.     return SET_APIC_DEST_FIELD(mask);
  50. }
  51.  
  52. static inline void __xapic_wait_icr_idle(void)
  53. {
  54.     while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
  55.         cpu_relax();
  56. }
  57.  
  58. static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
  59.                        unsigned int dest)
  60. {
  61.     /*
  62.      * Subtle. In the case of the 'never do double writes' workaround
  63.      * we have to lock out interrupts to be safe.  As we don't care
  64.      * of the value read we use an atomic rmw access to avoid costly
  65.      * cli/sti.  Otherwise we use an even cheaper single atomic write
  66.      * to the APIC.
  67.      */
  68.     unsigned int cfg;
  69.  
  70.     /*
  71.      * Wait for idle.
  72.      */
  73.     __xapic_wait_icr_idle();
  74.  
  75.     /*
  76.      * No need to touch the target chip field
  77.      */
  78.     cfg = __prepare_ICR(shortcut, vector, dest);
  79.  
  80.     /*
  81.      * Send the IPI. The write to APIC_ICR fires this off.
  82.      */
  83.     native_apic_mem_write(APIC_ICR, cfg);
  84. }
  85.  
  86. /*
  87.  * This is used to send an IPI with no shorthand notation (the destination is
  88.  * specified in bits 56 to 63 of the ICR).
  89.  */
  90. static inline void __send_IPI_dest_field(unsigned int mask, int vector,
  91.                      unsigned int dest)
  92. {
  93.     unsigned long cfg;
  94.  
  95.     /*
  96.      * Wait for idle.
  97.      */
  98.     if (unlikely(vector == NMI_VECTOR))
  99.         safe_apic_wait_icr_idle();
  100.     else
  101.         __xapic_wait_icr_idle();
  102.  
  103.     /*
  104.      * prepare target chip field
  105.      */
  106.     cfg = __prepare_ICR2(mask);
  107.     native_apic_mem_write(APIC_ICR2, cfg);
  108.  
  109.     /*
  110.      * program the ICR
  111.      */
  112.     cfg = __prepare_ICR(0, vector, dest);
  113.  
  114.     /*
  115.      * Send the IPI. The write to APIC_ICR fires this off.
  116.      */
  117.     native_apic_mem_write(APIC_ICR, cfg);
  118. }
  119.  
  120. static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
  121. {
  122.     unsigned long flags;
  123.     unsigned long query_cpu;
  124.  
  125.     /*
  126.      * Hack. The clustered APIC addressing mode doesn't allow us to send
  127.      * to an arbitrary mask, so I do a unicast to each CPU instead.
  128.      * - mbligh
  129.      */
  130.     local_irq_save(flags);
  131.     for_each_cpu_mask_nr(query_cpu, mask) {
  132.         __send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu),
  133.                       vector, APIC_DEST_PHYSICAL);
  134.     }
  135.     local_irq_restore(flags);
  136. }
  137.  
  138. #endif /* _ASM_X86_IPI_H */
  139.