genapic_cluster.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * Copyright 2004 James Cleverdon, IBM.
  3. * Subject to the GNU Public License, v.2
  4. *
  5. * Clustered APIC subarch code. Up to 255 CPUs, physical delivery.
  6. * (A more realistic maximum is around 230 CPUs.)
  7. *
  8. * Hacked for x86-64 by James Cleverdon from i386 architecture code by
  9. * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
  10. * James Cleverdon.
  11. */
  12. #include <linux/threads.h>
  13. #include <linux/cpumask.h>
  14. #include <linux/string.h>
  15. #include <linux/kernel.h>
  16. #include <linux/ctype.h>
  17. #include <linux/init.h>
  18. #include <asm/smp.h>
  19. #include <asm/ipi.h>
  20. /*
  21. * Set up the logical destination ID.
  22. *
  23. * Intel recommends to set DFR, LDR and TPR before enabling
  24. * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
  25. * document number 292116). So here it goes...
  26. */
  27. static void cluster_init_apic_ldr(void)
  28. {
  29. unsigned long val, id;
  30. long i, count;
  31. u8 lid;
  32. u8 my_id = hard_smp_processor_id();
  33. u8 my_cluster = APIC_CLUSTER(my_id);
  34. /* Create logical APIC IDs by counting CPUs already in cluster. */
  35. for (count = 0, i = NR_CPUS; --i >= 0; ) {
  36. lid = x86_cpu_to_log_apicid[i];
  37. if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
  38. ++count;
  39. }
  40. /*
  41. * We only have a 4 wide bitmap in cluster mode. There's no way
  42. * to get above 60 CPUs and still give each one it's own bit.
  43. * But, we're using physical IRQ delivery, so we don't care.
  44. * Use bit 3 for the 4th through Nth CPU in each cluster.
  45. */
  46. if (count >= XAPIC_DEST_CPUS_SHIFT)
  47. count = 3;
  48. id = my_cluster | (1UL << count);
  49. x86_cpu_to_log_apicid[smp_processor_id()] = id;
  50. apic_write(APIC_DFR, APIC_DFR_CLUSTER);
  51. val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
  52. val |= SET_APIC_LOGICAL_ID(id);
  53. apic_write(APIC_LDR, val);
  54. }
  55. /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
  56. static cpumask_t cluster_target_cpus(void)
  57. {
  58. return cpumask_of_cpu(0);
  59. }
  60. static void cluster_send_IPI_mask(cpumask_t mask, int vector)
  61. {
  62. send_IPI_mask_sequence(mask, vector);
  63. }
  64. static void cluster_send_IPI_allbutself(int vector)
  65. {
  66. cpumask_t mask = cpu_online_map;
  67. cpu_clear(smp_processor_id(), mask);
  68. if (!cpus_empty(mask))
  69. cluster_send_IPI_mask(mask, vector);
  70. }
  71. static void cluster_send_IPI_all(int vector)
  72. {
  73. cluster_send_IPI_mask(cpu_online_map, vector);
  74. }
  75. static int cluster_apic_id_registered(void)
  76. {
  77. return 1;
  78. }
  79. static unsigned int cluster_cpu_mask_to_apicid(cpumask_t cpumask)
  80. {
  81. int cpu;
  82. /*
  83. * We're using fixed IRQ delivery, can only return one phys APIC ID.
  84. * May as well be the first.
  85. */
  86. cpu = first_cpu(cpumask);
  87. if ((unsigned)cpu < NR_CPUS)
  88. return x86_cpu_to_apicid[cpu];
  89. else
  90. return BAD_APICID;
  91. }
  92. /* cpuid returns the value latched in the HW at reset, not the APIC ID
  93. * register's value. For any box whose BIOS changes APIC IDs, like
  94. * clustered APIC systems, we must use hard_smp_processor_id.
  95. *
  96. * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
  97. */
  98. static unsigned int phys_pkg_id(int index_msb)
  99. {
  100. return hard_smp_processor_id() >> index_msb;
  101. }
  102. struct genapic apic_cluster = {
  103. .name = "clustered",
  104. .int_delivery_mode = dest_Fixed,
  105. .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
  106. .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
  107. .target_cpus = cluster_target_cpus,
  108. .apic_id_registered = cluster_apic_id_registered,
  109. .init_apic_ldr = cluster_init_apic_ldr,
  110. .send_IPI_all = cluster_send_IPI_all,
  111. .send_IPI_allbutself = cluster_send_IPI_allbutself,
  112. .send_IPI_mask = cluster_send_IPI_mask,
  113. .cpu_mask_to_apicid = cluster_cpu_mask_to_apicid,
  114. .phys_pkg_id = phys_pkg_id,
  115. };