genapic_cluster.c 3.5 KB

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