apic_numachip.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Numascale NumaConnect-Specific APIC Code
  7. *
  8. * Copyright (C) 2011 Numascale AS. All rights reserved.
  9. *
  10. * Send feedback to <support@numascale.com>
  11. *
  12. */
  13. #include <linux/types.h>
  14. #include <linux/init.h>
  15. #include <linux/pgtable.h>
  16. #include <asm/numachip/numachip.h>
  17. #include <asm/numachip/numachip_csr.h>
  18. #include "local.h"
  19. u8 numachip_system __read_mostly;
  20. static const struct apic apic_numachip1;
  21. static const struct apic apic_numachip2;
  22. static void (*numachip_apic_icr_write)(int apicid, unsigned int val) __read_mostly;
  23. static u32 numachip1_get_apic_id(u32 x)
  24. {
  25. unsigned long value;
  26. unsigned int id = (x >> 24) & 0xff;
  27. if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
  28. rdmsrl(MSR_FAM10H_NODE_ID, value);
  29. id |= (value << 2) & 0xff00;
  30. }
  31. return id;
  32. }
  33. static u32 numachip2_get_apic_id(u32 x)
  34. {
  35. u64 mcfg;
  36. rdmsrl(MSR_FAM10H_MMIO_CONF_BASE, mcfg);
  37. return ((mcfg >> (28 - 8)) & 0xfff00) | (x >> 24);
  38. }
  39. static void numachip1_apic_icr_write(int apicid, unsigned int val)
  40. {
  41. write_lcsr(CSR_G3_EXT_IRQ_GEN, (apicid << 16) | val);
  42. }
  43. static void numachip2_apic_icr_write(int apicid, unsigned int val)
  44. {
  45. numachip2_write32_lcsr(NUMACHIP2_APIC_ICR, (apicid << 12) | val);
  46. }
  47. static int numachip_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
  48. {
  49. numachip_apic_icr_write(phys_apicid, APIC_DM_INIT);
  50. numachip_apic_icr_write(phys_apicid, APIC_DM_STARTUP |
  51. (start_rip >> 12));
  52. return 0;
  53. }
  54. static void numachip_send_IPI_one(int cpu, int vector)
  55. {
  56. int local_apicid, apicid = per_cpu(x86_cpu_to_apicid, cpu);
  57. unsigned int dmode;
  58. preempt_disable();
  59. local_apicid = __this_cpu_read(x86_cpu_to_apicid);
  60. /* Send via local APIC where non-local part matches */
  61. if (!((apicid ^ local_apicid) >> NUMACHIP_LAPIC_BITS)) {
  62. unsigned long flags;
  63. local_irq_save(flags);
  64. __default_send_IPI_dest_field(apicid, vector,
  65. APIC_DEST_PHYSICAL);
  66. local_irq_restore(flags);
  67. preempt_enable();
  68. return;
  69. }
  70. preempt_enable();
  71. dmode = (vector == NMI_VECTOR) ? APIC_DM_NMI : APIC_DM_FIXED;
  72. numachip_apic_icr_write(apicid, dmode | vector);
  73. }
  74. static void numachip_send_IPI_mask(const struct cpumask *mask, int vector)
  75. {
  76. unsigned int cpu;
  77. for_each_cpu(cpu, mask)
  78. numachip_send_IPI_one(cpu, vector);
  79. }
  80. static void numachip_send_IPI_mask_allbutself(const struct cpumask *mask,
  81. int vector)
  82. {
  83. unsigned int this_cpu = smp_processor_id();
  84. unsigned int cpu;
  85. for_each_cpu(cpu, mask) {
  86. if (cpu != this_cpu)
  87. numachip_send_IPI_one(cpu, vector);
  88. }
  89. }
  90. static void numachip_send_IPI_allbutself(int vector)
  91. {
  92. unsigned int this_cpu = smp_processor_id();
  93. unsigned int cpu;
  94. for_each_online_cpu(cpu) {
  95. if (cpu != this_cpu)
  96. numachip_send_IPI_one(cpu, vector);
  97. }
  98. }
  99. static void numachip_send_IPI_all(int vector)
  100. {
  101. numachip_send_IPI_mask(cpu_online_mask, vector);
  102. }
  103. static void numachip_send_IPI_self(int vector)
  104. {
  105. apic_write(APIC_SELF_IPI, vector);
  106. }
  107. static int __init numachip1_probe(void)
  108. {
  109. return apic == &apic_numachip1;
  110. }
  111. static int __init numachip2_probe(void)
  112. {
  113. return apic == &apic_numachip2;
  114. }
  115. static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
  116. {
  117. u64 val;
  118. u32 nodes = 1;
  119. c->topo.llc_id = node;
  120. /* Account for nodes per socket in multi-core-module processors */
  121. if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
  122. rdmsrl(MSR_FAM10H_NODE_ID, val);
  123. nodes = ((val >> 3) & 7) + 1;
  124. }
  125. c->topo.pkg_id = node / nodes;
  126. }
  127. static int __init numachip_system_init(void)
  128. {
  129. /* Map the LCSR area and set up the apic_icr_write function */
  130. switch (numachip_system) {
  131. case 1:
  132. init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE);
  133. numachip_apic_icr_write = numachip1_apic_icr_write;
  134. break;
  135. case 2:
  136. init_extra_mapping_uc(NUMACHIP2_LCSR_BASE, NUMACHIP2_LCSR_SIZE);
  137. numachip_apic_icr_write = numachip2_apic_icr_write;
  138. break;
  139. default:
  140. return 0;
  141. }
  142. x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
  143. x86_init.pci.arch_init = pci_numachip_init;
  144. return 0;
  145. }
  146. early_initcall(numachip_system_init);
  147. static int numachip1_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  148. {
  149. if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
  150. (strncmp(oem_table_id, "NCONNECT", 8) != 0))
  151. return 0;
  152. numachip_system = 1;
  153. return 1;
  154. }
  155. static int numachip2_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
  156. {
  157. if ((strncmp(oem_id, "NUMASC", 6) != 0) ||
  158. (strncmp(oem_table_id, "NCONECT2", 8) != 0))
  159. return 0;
  160. numachip_system = 2;
  161. return 1;
  162. }
  163. static const struct apic apic_numachip1 __refconst = {
  164. .name = "NumaConnect system",
  165. .probe = numachip1_probe,
  166. .acpi_madt_oem_check = numachip1_acpi_madt_oem_check,
  167. .dest_mode_logical = false,
  168. .disable_esr = 0,
  169. .cpu_present_to_apicid = default_cpu_present_to_apicid,
  170. .max_apic_id = UINT_MAX,
  171. .get_apic_id = numachip1_get_apic_id,
  172. .calc_dest_apicid = apic_default_calc_apicid,
  173. .send_IPI = numachip_send_IPI_one,
  174. .send_IPI_mask = numachip_send_IPI_mask,
  175. .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
  176. .send_IPI_allbutself = numachip_send_IPI_allbutself,
  177. .send_IPI_all = numachip_send_IPI_all,
  178. .send_IPI_self = numachip_send_IPI_self,
  179. .wakeup_secondary_cpu = numachip_wakeup_secondary,
  180. .read = native_apic_mem_read,
  181. .write = native_apic_mem_write,
  182. .eoi = native_apic_mem_eoi,
  183. .icr_read = native_apic_icr_read,
  184. .icr_write = native_apic_icr_write,
  185. };
  186. apic_driver(apic_numachip1);
  187. static const struct apic apic_numachip2 __refconst = {
  188. .name = "NumaConnect2 system",
  189. .probe = numachip2_probe,
  190. .acpi_madt_oem_check = numachip2_acpi_madt_oem_check,
  191. .dest_mode_logical = false,
  192. .disable_esr = 0,
  193. .cpu_present_to_apicid = default_cpu_present_to_apicid,
  194. .max_apic_id = UINT_MAX,
  195. .get_apic_id = numachip2_get_apic_id,
  196. .calc_dest_apicid = apic_default_calc_apicid,
  197. .send_IPI = numachip_send_IPI_one,
  198. .send_IPI_mask = numachip_send_IPI_mask,
  199. .send_IPI_mask_allbutself = numachip_send_IPI_mask_allbutself,
  200. .send_IPI_allbutself = numachip_send_IPI_allbutself,
  201. .send_IPI_all = numachip_send_IPI_all,
  202. .send_IPI_self = numachip_send_IPI_self,
  203. .wakeup_secondary_cpu = numachip_wakeup_secondary,
  204. .read = native_apic_mem_read,
  205. .write = native_apic_mem_write,
  206. .eoi = native_apic_mem_eoi,
  207. .icr_read = native_apic_icr_read,
  208. .icr_write = native_apic_icr_write,
  209. };
  210. apic_driver(apic_numachip2);