genapic_64.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Copyright 2004 James Cleverdon, IBM.
  3. * Subject to the GNU Public License, v.2
  4. *
  5. * Generic APIC sub-arch probe layer.
  6. *
  7. * Hacked for x86-64 by James Cleverdon from i386 architecture code by
  8. * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
  9. * James Cleverdon.
  10. */
  11. #include <linux/threads.h>
  12. #include <linux/cpumask.h>
  13. #include <linux/string.h>
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/ctype.h>
  17. #include <linux/init.h>
  18. #include <linux/hardirq.h>
  19. #include <asm/smp.h>
  20. #include <asm/ipi.h>
  21. #include <asm/genapic.h>
  22. #ifdef CONFIG_ACPI
  23. #include <acpi/acpi_bus.h>
  24. #endif
  25. /* which logical CPU number maps to which CPU (physical APIC ID) */
  26. #ifdef CONFIG_SMP
  27. u16 x86_cpu_to_apicid_init[NR_CPUS] __initdata
  28. = { [0 ... NR_CPUS-1] = BAD_APICID };
  29. void *x86_cpu_to_apicid_early_ptr;
  30. #endif
  31. DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
  32. EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
  33. DEFINE_PER_CPU(int, x2apic_extra_bits);
  34. struct genapic __read_mostly *genapic = &apic_flat;
  35. static enum uv_system_type uv_system_type;
  36. /*
  37. * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  38. */
  39. void __init setup_apic_routing(void)
  40. {
  41. if (uv_system_type == UV_NON_UNIQUE_APIC)
  42. genapic = &apic_x2apic_uv_x;
  43. else
  44. #ifdef CONFIG_ACPI
  45. /*
  46. * Quirk: some x86_64 machines can only use physical APIC mode
  47. * regardless of how many processors are present (x86_64 ES7000
  48. * is an example).
  49. */
  50. if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
  51. (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
  52. genapic = &apic_physflat;
  53. else
  54. #endif
  55. if (cpus_weight(cpu_possible_map) <= 8)
  56. genapic = &apic_flat;
  57. else
  58. genapic = &apic_physflat;
  59. printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
  60. }
  61. /* Same for both flat and physical. */
  62. void send_IPI_self(int vector)
  63. {
  64. __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
  65. }
  66. int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  67. {
  68. if (!strcmp(oem_id, "SGI")) {
  69. if (!strcmp(oem_table_id, "UVL"))
  70. uv_system_type = UV_LEGACY_APIC;
  71. else if (!strcmp(oem_table_id, "UVX"))
  72. uv_system_type = UV_X2APIC;
  73. else if (!strcmp(oem_table_id, "UVH"))
  74. uv_system_type = UV_NON_UNIQUE_APIC;
  75. }
  76. return 0;
  77. }
  78. unsigned int read_apic_id(void)
  79. {
  80. unsigned int id;
  81. WARN_ON(preemptible());
  82. id = apic_read(APIC_ID);
  83. if (uv_system_type >= UV_X2APIC)
  84. id |= __get_cpu_var(x2apic_extra_bits);
  85. return id;
  86. }
  87. enum uv_system_type get_uv_system_type(void)
  88. {
  89. return uv_system_type;
  90. }
  91. int is_uv_system(void)
  92. {
  93. return uv_system_type != UV_NONE;
  94. }