hmat.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019, Intel Corporation.
  4. *
  5. * Heterogeneous Memory Attributes Table (HMAT) representation
  6. *
  7. * This program parses and reports the platform's HMAT tables, and registers
  8. * the applicable attributes with the node's interfaces.
  9. */
  10. #define pr_fmt(fmt) "acpi/hmat: " fmt
  11. #include <linux/acpi.h>
  12. #include <linux/bitops.h>
  13. #include <linux/device.h>
  14. #include <linux/init.h>
  15. #include <linux/list.h>
  16. #include <linux/mm.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/list_sort.h>
  19. #include <linux/memregion.h>
  20. #include <linux/memory.h>
  21. #include <linux/mutex.h>
  22. #include <linux/node.h>
  23. #include <linux/sysfs.h>
  24. #include <linux/dax.h>
  25. static u8 hmat_revision;
  26. static int hmat_disable __initdata;
  27. void __init disable_hmat(void)
  28. {
  29. hmat_disable = 1;
  30. }
  31. static LIST_HEAD(targets);
  32. static LIST_HEAD(initiators);
  33. static LIST_HEAD(localities);
  34. static DEFINE_MUTEX(target_lock);
  35. /*
  36. * The defined enum order is used to prioritize attributes to break ties when
  37. * selecting the best performing node.
  38. */
  39. enum locality_types {
  40. WRITE_LATENCY,
  41. READ_LATENCY,
  42. WRITE_BANDWIDTH,
  43. READ_BANDWIDTH,
  44. };
  45. static struct memory_locality *localities_types[4];
  46. struct target_cache {
  47. struct list_head node;
  48. struct node_cache_attrs cache_attrs;
  49. };
  50. struct memory_target {
  51. struct list_head node;
  52. unsigned int memory_pxm;
  53. unsigned int processor_pxm;
  54. struct resource memregions;
  55. struct node_hmem_attrs hmem_attrs[2];
  56. struct list_head caches;
  57. struct node_cache_attrs cache_attrs;
  58. bool registered;
  59. };
  60. struct memory_initiator {
  61. struct list_head node;
  62. unsigned int processor_pxm;
  63. bool has_cpu;
  64. };
  65. struct memory_locality {
  66. struct list_head node;
  67. struct acpi_hmat_locality *hmat_loc;
  68. };
  69. static struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
  70. {
  71. struct memory_initiator *initiator;
  72. list_for_each_entry(initiator, &initiators, node)
  73. if (initiator->processor_pxm == cpu_pxm)
  74. return initiator;
  75. return NULL;
  76. }
  77. static struct memory_target *find_mem_target(unsigned int mem_pxm)
  78. {
  79. struct memory_target *target;
  80. list_for_each_entry(target, &targets, node)
  81. if (target->memory_pxm == mem_pxm)
  82. return target;
  83. return NULL;
  84. }
  85. static __init void alloc_memory_initiator(unsigned int cpu_pxm)
  86. {
  87. struct memory_initiator *initiator;
  88. if (pxm_to_node(cpu_pxm) == NUMA_NO_NODE)
  89. return;
  90. initiator = find_mem_initiator(cpu_pxm);
  91. if (initiator)
  92. return;
  93. initiator = kzalloc(sizeof(*initiator), GFP_KERNEL);
  94. if (!initiator)
  95. return;
  96. initiator->processor_pxm = cpu_pxm;
  97. initiator->has_cpu = node_state(pxm_to_node(cpu_pxm), N_CPU);
  98. list_add_tail(&initiator->node, &initiators);
  99. }
  100. static __init void alloc_memory_target(unsigned int mem_pxm,
  101. resource_size_t start, resource_size_t len)
  102. {
  103. struct memory_target *target;
  104. target = find_mem_target(mem_pxm);
  105. if (!target) {
  106. target = kzalloc(sizeof(*target), GFP_KERNEL);
  107. if (!target)
  108. return;
  109. target->memory_pxm = mem_pxm;
  110. target->processor_pxm = PXM_INVAL;
  111. target->memregions = (struct resource) {
  112. .name = "ACPI mem",
  113. .start = 0,
  114. .end = -1,
  115. .flags = IORESOURCE_MEM,
  116. };
  117. list_add_tail(&target->node, &targets);
  118. INIT_LIST_HEAD(&target->caches);
  119. }
  120. /*
  121. * There are potentially multiple ranges per PXM, so record each
  122. * in the per-target memregions resource tree.
  123. */
  124. if (!__request_region(&target->memregions, start, len, "memory target",
  125. IORESOURCE_MEM))
  126. pr_warn("failed to reserve %#llx - %#llx in pxm: %d\n",
  127. start, start + len, mem_pxm);
  128. }
  129. static __init const char *hmat_data_type(u8 type)
  130. {
  131. switch (type) {
  132. case ACPI_HMAT_ACCESS_LATENCY:
  133. return "Access Latency";
  134. case ACPI_HMAT_READ_LATENCY:
  135. return "Read Latency";
  136. case ACPI_HMAT_WRITE_LATENCY:
  137. return "Write Latency";
  138. case ACPI_HMAT_ACCESS_BANDWIDTH:
  139. return "Access Bandwidth";
  140. case ACPI_HMAT_READ_BANDWIDTH:
  141. return "Read Bandwidth";
  142. case ACPI_HMAT_WRITE_BANDWIDTH:
  143. return "Write Bandwidth";
  144. default:
  145. return "Reserved";
  146. }
  147. }
  148. static __init const char *hmat_data_type_suffix(u8 type)
  149. {
  150. switch (type) {
  151. case ACPI_HMAT_ACCESS_LATENCY:
  152. case ACPI_HMAT_READ_LATENCY:
  153. case ACPI_HMAT_WRITE_LATENCY:
  154. return " nsec";
  155. case ACPI_HMAT_ACCESS_BANDWIDTH:
  156. case ACPI_HMAT_READ_BANDWIDTH:
  157. case ACPI_HMAT_WRITE_BANDWIDTH:
  158. return " MB/s";
  159. default:
  160. return "";
  161. }
  162. }
  163. static u32 hmat_normalize(u16 entry, u64 base, u8 type)
  164. {
  165. u32 value;
  166. /*
  167. * Check for invalid and overflow values
  168. */
  169. if (entry == 0xffff || !entry)
  170. return 0;
  171. else if (base > (UINT_MAX / (entry)))
  172. return 0;
  173. /*
  174. * Divide by the base unit for version 1, convert latency from
  175. * picosenonds to nanoseconds if revision 2.
  176. */
  177. value = entry * base;
  178. if (hmat_revision == 1) {
  179. if (value < 10)
  180. return 0;
  181. value = DIV_ROUND_UP(value, 10);
  182. } else if (hmat_revision == 2) {
  183. switch (type) {
  184. case ACPI_HMAT_ACCESS_LATENCY:
  185. case ACPI_HMAT_READ_LATENCY:
  186. case ACPI_HMAT_WRITE_LATENCY:
  187. value = DIV_ROUND_UP(value, 1000);
  188. break;
  189. default:
  190. break;
  191. }
  192. }
  193. return value;
  194. }
  195. static void hmat_update_target_access(struct memory_target *target,
  196. u8 type, u32 value, int access)
  197. {
  198. switch (type) {
  199. case ACPI_HMAT_ACCESS_LATENCY:
  200. target->hmem_attrs[access].read_latency = value;
  201. target->hmem_attrs[access].write_latency = value;
  202. break;
  203. case ACPI_HMAT_READ_LATENCY:
  204. target->hmem_attrs[access].read_latency = value;
  205. break;
  206. case ACPI_HMAT_WRITE_LATENCY:
  207. target->hmem_attrs[access].write_latency = value;
  208. break;
  209. case ACPI_HMAT_ACCESS_BANDWIDTH:
  210. target->hmem_attrs[access].read_bandwidth = value;
  211. target->hmem_attrs[access].write_bandwidth = value;
  212. break;
  213. case ACPI_HMAT_READ_BANDWIDTH:
  214. target->hmem_attrs[access].read_bandwidth = value;
  215. break;
  216. case ACPI_HMAT_WRITE_BANDWIDTH:
  217. target->hmem_attrs[access].write_bandwidth = value;
  218. break;
  219. default:
  220. break;
  221. }
  222. }
  223. static __init void hmat_add_locality(struct acpi_hmat_locality *hmat_loc)
  224. {
  225. struct memory_locality *loc;
  226. loc = kzalloc(sizeof(*loc), GFP_KERNEL);
  227. if (!loc) {
  228. pr_notice_once("Failed to allocate HMAT locality\n");
  229. return;
  230. }
  231. loc->hmat_loc = hmat_loc;
  232. list_add_tail(&loc->node, &localities);
  233. switch (hmat_loc->data_type) {
  234. case ACPI_HMAT_ACCESS_LATENCY:
  235. localities_types[READ_LATENCY] = loc;
  236. localities_types[WRITE_LATENCY] = loc;
  237. break;
  238. case ACPI_HMAT_READ_LATENCY:
  239. localities_types[READ_LATENCY] = loc;
  240. break;
  241. case ACPI_HMAT_WRITE_LATENCY:
  242. localities_types[WRITE_LATENCY] = loc;
  243. break;
  244. case ACPI_HMAT_ACCESS_BANDWIDTH:
  245. localities_types[READ_BANDWIDTH] = loc;
  246. localities_types[WRITE_BANDWIDTH] = loc;
  247. break;
  248. case ACPI_HMAT_READ_BANDWIDTH:
  249. localities_types[READ_BANDWIDTH] = loc;
  250. break;
  251. case ACPI_HMAT_WRITE_BANDWIDTH:
  252. localities_types[WRITE_BANDWIDTH] = loc;
  253. break;
  254. default:
  255. break;
  256. }
  257. }
  258. static __init int hmat_parse_locality(union acpi_subtable_headers *header,
  259. const unsigned long end)
  260. {
  261. struct acpi_hmat_locality *hmat_loc = (void *)header;
  262. struct memory_target *target;
  263. unsigned int init, targ, total_size, ipds, tpds;
  264. u32 *inits, *targs, value;
  265. u16 *entries;
  266. u8 type, mem_hier;
  267. if (hmat_loc->header.length < sizeof(*hmat_loc)) {
  268. pr_notice("Unexpected locality header length: %u\n",
  269. hmat_loc->header.length);
  270. return -EINVAL;
  271. }
  272. type = hmat_loc->data_type;
  273. mem_hier = hmat_loc->flags & ACPI_HMAT_MEMORY_HIERARCHY;
  274. ipds = hmat_loc->number_of_initiator_Pds;
  275. tpds = hmat_loc->number_of_target_Pds;
  276. total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
  277. sizeof(*inits) * ipds + sizeof(*targs) * tpds;
  278. if (hmat_loc->header.length < total_size) {
  279. pr_notice("Unexpected locality header length:%u, minimum required:%u\n",
  280. hmat_loc->header.length, total_size);
  281. return -EINVAL;
  282. }
  283. pr_info("Locality: Flags:%02x Type:%s Initiator Domains:%u Target Domains:%u Base:%lld\n",
  284. hmat_loc->flags, hmat_data_type(type), ipds, tpds,
  285. hmat_loc->entry_base_unit);
  286. inits = (u32 *)(hmat_loc + 1);
  287. targs = inits + ipds;
  288. entries = (u16 *)(targs + tpds);
  289. for (init = 0; init < ipds; init++) {
  290. alloc_memory_initiator(inits[init]);
  291. for (targ = 0; targ < tpds; targ++) {
  292. value = hmat_normalize(entries[init * tpds + targ],
  293. hmat_loc->entry_base_unit,
  294. type);
  295. pr_info(" Initiator-Target[%u-%u]:%u%s\n",
  296. inits[init], targs[targ], value,
  297. hmat_data_type_suffix(type));
  298. if (mem_hier == ACPI_HMAT_MEMORY) {
  299. target = find_mem_target(targs[targ]);
  300. if (target && target->processor_pxm == inits[init]) {
  301. hmat_update_target_access(target, type, value, 0);
  302. /* If the node has a CPU, update access 1 */
  303. if (node_state(pxm_to_node(inits[init]), N_CPU))
  304. hmat_update_target_access(target, type, value, 1);
  305. }
  306. }
  307. }
  308. }
  309. if (mem_hier == ACPI_HMAT_MEMORY)
  310. hmat_add_locality(hmat_loc);
  311. return 0;
  312. }
  313. static __init int hmat_parse_cache(union acpi_subtable_headers *header,
  314. const unsigned long end)
  315. {
  316. struct acpi_hmat_cache *cache = (void *)header;
  317. struct memory_target *target;
  318. struct target_cache *tcache;
  319. u32 attrs;
  320. if (cache->header.length < sizeof(*cache)) {
  321. pr_notice("Unexpected cache header length: %u\n",
  322. cache->header.length);
  323. return -EINVAL;
  324. }
  325. attrs = cache->cache_attributes;
  326. pr_info("Cache: Domain:%u Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
  327. cache->memory_PD, cache->cache_size, attrs,
  328. cache->number_of_SMBIOShandles);
  329. target = find_mem_target(cache->memory_PD);
  330. if (!target)
  331. return 0;
  332. tcache = kzalloc(sizeof(*tcache), GFP_KERNEL);
  333. if (!tcache) {
  334. pr_notice_once("Failed to allocate HMAT cache info\n");
  335. return 0;
  336. }
  337. tcache->cache_attrs.size = cache->cache_size;
  338. tcache->cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4;
  339. tcache->cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16;
  340. switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) {
  341. case ACPI_HMAT_CA_DIRECT_MAPPED:
  342. tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
  343. break;
  344. case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING:
  345. tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;
  346. break;
  347. case ACPI_HMAT_CA_NONE:
  348. default:
  349. tcache->cache_attrs.indexing = NODE_CACHE_OTHER;
  350. break;
  351. }
  352. switch ((attrs & ACPI_HMAT_WRITE_POLICY) >> 12) {
  353. case ACPI_HMAT_CP_WB:
  354. tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_BACK;
  355. break;
  356. case ACPI_HMAT_CP_WT:
  357. tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH;
  358. break;
  359. case ACPI_HMAT_CP_NONE:
  360. default:
  361. tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER;
  362. break;
  363. }
  364. list_add_tail(&tcache->node, &target->caches);
  365. return 0;
  366. }
  367. static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *header,
  368. const unsigned long end)
  369. {
  370. struct acpi_hmat_proximity_domain *p = (void *)header;
  371. struct memory_target *target = NULL;
  372. if (p->header.length != sizeof(*p)) {
  373. pr_notice("Unexpected address range header length: %u\n",
  374. p->header.length);
  375. return -EINVAL;
  376. }
  377. if (hmat_revision == 1)
  378. pr_info("Memory (%#llx length %#llx) Flags:%04x Processor Domain:%u Memory Domain:%u\n",
  379. p->reserved3, p->reserved4, p->flags, p->processor_PD,
  380. p->memory_PD);
  381. else
  382. pr_info("Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n",
  383. p->flags, p->processor_PD, p->memory_PD);
  384. if ((hmat_revision == 1 && p->flags & ACPI_HMAT_MEMORY_PD_VALID) ||
  385. hmat_revision > 1) {
  386. target = find_mem_target(p->memory_PD);
  387. if (!target) {
  388. pr_debug("Memory Domain missing from SRAT\n");
  389. return -EINVAL;
  390. }
  391. }
  392. if (target && p->flags & ACPI_HMAT_PROCESSOR_PD_VALID) {
  393. int p_node = pxm_to_node(p->processor_PD);
  394. if (p_node == NUMA_NO_NODE) {
  395. pr_debug("Invalid Processor Domain\n");
  396. return -EINVAL;
  397. }
  398. target->processor_pxm = p->processor_PD;
  399. }
  400. return 0;
  401. }
  402. static int __init hmat_parse_subtable(union acpi_subtable_headers *header,
  403. const unsigned long end)
  404. {
  405. struct acpi_hmat_structure *hdr = (void *)header;
  406. if (!hdr)
  407. return -EINVAL;
  408. switch (hdr->type) {
  409. case ACPI_HMAT_TYPE_PROXIMITY:
  410. return hmat_parse_proximity_domain(header, end);
  411. case ACPI_HMAT_TYPE_LOCALITY:
  412. return hmat_parse_locality(header, end);
  413. case ACPI_HMAT_TYPE_CACHE:
  414. return hmat_parse_cache(header, end);
  415. default:
  416. return -EINVAL;
  417. }
  418. }
  419. static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header,
  420. const unsigned long end)
  421. {
  422. struct acpi_srat_mem_affinity *ma = (void *)header;
  423. if (!ma)
  424. return -EINVAL;
  425. if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
  426. return 0;
  427. alloc_memory_target(ma->proximity_domain, ma->base_address, ma->length);
  428. return 0;
  429. }
  430. static u32 hmat_initiator_perf(struct memory_target *target,
  431. struct memory_initiator *initiator,
  432. struct acpi_hmat_locality *hmat_loc)
  433. {
  434. unsigned int ipds, tpds, i, idx = 0, tdx = 0;
  435. u32 *inits, *targs;
  436. u16 *entries;
  437. ipds = hmat_loc->number_of_initiator_Pds;
  438. tpds = hmat_loc->number_of_target_Pds;
  439. inits = (u32 *)(hmat_loc + 1);
  440. targs = inits + ipds;
  441. entries = (u16 *)(targs + tpds);
  442. for (i = 0; i < ipds; i++) {
  443. if (inits[i] == initiator->processor_pxm) {
  444. idx = i;
  445. break;
  446. }
  447. }
  448. if (i == ipds)
  449. return 0;
  450. for (i = 0; i < tpds; i++) {
  451. if (targs[i] == target->memory_pxm) {
  452. tdx = i;
  453. break;
  454. }
  455. }
  456. if (i == tpds)
  457. return 0;
  458. return hmat_normalize(entries[idx * tpds + tdx],
  459. hmat_loc->entry_base_unit,
  460. hmat_loc->data_type);
  461. }
  462. static bool hmat_update_best(u8 type, u32 value, u32 *best)
  463. {
  464. bool updated = false;
  465. if (!value)
  466. return false;
  467. switch (type) {
  468. case ACPI_HMAT_ACCESS_LATENCY:
  469. case ACPI_HMAT_READ_LATENCY:
  470. case ACPI_HMAT_WRITE_LATENCY:
  471. if (!*best || *best > value) {
  472. *best = value;
  473. updated = true;
  474. }
  475. break;
  476. case ACPI_HMAT_ACCESS_BANDWIDTH:
  477. case ACPI_HMAT_READ_BANDWIDTH:
  478. case ACPI_HMAT_WRITE_BANDWIDTH:
  479. if (!*best || *best < value) {
  480. *best = value;
  481. updated = true;
  482. }
  483. break;
  484. }
  485. return updated;
  486. }
  487. static int initiator_cmp(void *priv, const struct list_head *a,
  488. const struct list_head *b)
  489. {
  490. struct memory_initiator *ia;
  491. struct memory_initiator *ib;
  492. ia = list_entry(a, struct memory_initiator, node);
  493. ib = list_entry(b, struct memory_initiator, node);
  494. return ia->processor_pxm - ib->processor_pxm;
  495. }
  496. static int initiators_to_nodemask(unsigned long *p_nodes)
  497. {
  498. struct memory_initiator *initiator;
  499. if (list_empty(&initiators))
  500. return -ENXIO;
  501. list_for_each_entry(initiator, &initiators, node)
  502. set_bit(initiator->processor_pxm, p_nodes);
  503. return 0;
  504. }
  505. static void hmat_register_target_initiators(struct memory_target *target)
  506. {
  507. static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
  508. struct memory_initiator *initiator;
  509. unsigned int mem_nid, cpu_nid;
  510. struct memory_locality *loc = NULL;
  511. u32 best = 0;
  512. bool access0done = false;
  513. int i;
  514. mem_nid = pxm_to_node(target->memory_pxm);
  515. /*
  516. * If the Address Range Structure provides a local processor pxm, link
  517. * only that one. Otherwise, find the best performance attributes and
  518. * register all initiators that match.
  519. */
  520. if (target->processor_pxm != PXM_INVAL) {
  521. cpu_nid = pxm_to_node(target->processor_pxm);
  522. register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
  523. access0done = true;
  524. if (node_state(cpu_nid, N_CPU)) {
  525. register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
  526. return;
  527. }
  528. }
  529. if (list_empty(&localities))
  530. return;
  531. /*
  532. * We need the initiator list sorted so we can use bitmap_clear for
  533. * previously set initiators when we find a better memory accessor.
  534. * We'll also use the sorting to prime the candidate nodes with known
  535. * initiators.
  536. */
  537. bitmap_zero(p_nodes, MAX_NUMNODES);
  538. list_sort(NULL, &initiators, initiator_cmp);
  539. if (initiators_to_nodemask(p_nodes) < 0)
  540. return;
  541. if (!access0done) {
  542. for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
  543. loc = localities_types[i];
  544. if (!loc)
  545. continue;
  546. best = 0;
  547. list_for_each_entry(initiator, &initiators, node) {
  548. u32 value;
  549. if (!test_bit(initiator->processor_pxm, p_nodes))
  550. continue;
  551. value = hmat_initiator_perf(target, initiator,
  552. loc->hmat_loc);
  553. if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
  554. bitmap_clear(p_nodes, 0, initiator->processor_pxm);
  555. if (value != best)
  556. clear_bit(initiator->processor_pxm, p_nodes);
  557. }
  558. if (best)
  559. hmat_update_target_access(target, loc->hmat_loc->data_type,
  560. best, 0);
  561. }
  562. for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
  563. cpu_nid = pxm_to_node(i);
  564. register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
  565. }
  566. }
  567. /* Access 1 ignores Generic Initiators */
  568. bitmap_zero(p_nodes, MAX_NUMNODES);
  569. if (initiators_to_nodemask(p_nodes) < 0)
  570. return;
  571. for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
  572. loc = localities_types[i];
  573. if (!loc)
  574. continue;
  575. best = 0;
  576. list_for_each_entry(initiator, &initiators, node) {
  577. u32 value;
  578. if (!initiator->has_cpu) {
  579. clear_bit(initiator->processor_pxm, p_nodes);
  580. continue;
  581. }
  582. if (!test_bit(initiator->processor_pxm, p_nodes))
  583. continue;
  584. value = hmat_initiator_perf(target, initiator, loc->hmat_loc);
  585. if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
  586. bitmap_clear(p_nodes, 0, initiator->processor_pxm);
  587. if (value != best)
  588. clear_bit(initiator->processor_pxm, p_nodes);
  589. }
  590. if (best)
  591. hmat_update_target_access(target, loc->hmat_loc->data_type, best, 1);
  592. }
  593. for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
  594. cpu_nid = pxm_to_node(i);
  595. register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
  596. }
  597. }
  598. static void hmat_register_target_cache(struct memory_target *target)
  599. {
  600. unsigned mem_nid = pxm_to_node(target->memory_pxm);
  601. struct target_cache *tcache;
  602. list_for_each_entry(tcache, &target->caches, node)
  603. node_add_cache(mem_nid, &tcache->cache_attrs);
  604. }
  605. static void hmat_register_target_perf(struct memory_target *target, int access)
  606. {
  607. unsigned mem_nid = pxm_to_node(target->memory_pxm);
  608. node_set_perf_attrs(mem_nid, &target->hmem_attrs[access], access);
  609. }
  610. static void hmat_register_target_devices(struct memory_target *target)
  611. {
  612. struct resource *res;
  613. /*
  614. * Do not bother creating devices if no driver is available to
  615. * consume them.
  616. */
  617. if (!IS_ENABLED(CONFIG_DEV_DAX_HMEM))
  618. return;
  619. for (res = target->memregions.child; res; res = res->sibling) {
  620. int target_nid = pxm_to_node(target->memory_pxm);
  621. hmem_register_device(target_nid, res);
  622. }
  623. }
  624. static void hmat_register_target(struct memory_target *target)
  625. {
  626. int nid = pxm_to_node(target->memory_pxm);
  627. /*
  628. * Devices may belong to either an offline or online
  629. * node, so unconditionally add them.
  630. */
  631. hmat_register_target_devices(target);
  632. /*
  633. * Skip offline nodes. This can happen when memory
  634. * marked EFI_MEMORY_SP, "specific purpose", is applied
  635. * to all the memory in a proximity domain leading to
  636. * the node being marked offline / unplugged, or if
  637. * memory-only "hotplug" node is offline.
  638. */
  639. if (nid == NUMA_NO_NODE || !node_online(nid))
  640. return;
  641. mutex_lock(&target_lock);
  642. if (!target->registered) {
  643. hmat_register_target_initiators(target);
  644. hmat_register_target_cache(target);
  645. hmat_register_target_perf(target, 0);
  646. hmat_register_target_perf(target, 1);
  647. target->registered = true;
  648. }
  649. mutex_unlock(&target_lock);
  650. }
  651. static void hmat_register_targets(void)
  652. {
  653. struct memory_target *target;
  654. list_for_each_entry(target, &targets, node)
  655. hmat_register_target(target);
  656. }
  657. static int hmat_callback(struct notifier_block *self,
  658. unsigned long action, void *arg)
  659. {
  660. struct memory_target *target;
  661. struct memory_notify *mnb = arg;
  662. int pxm, nid = mnb->status_change_nid;
  663. if (nid == NUMA_NO_NODE || action != MEM_ONLINE)
  664. return NOTIFY_OK;
  665. pxm = node_to_pxm(nid);
  666. target = find_mem_target(pxm);
  667. if (!target)
  668. return NOTIFY_OK;
  669. hmat_register_target(target);
  670. return NOTIFY_OK;
  671. }
  672. static struct notifier_block hmat_callback_nb = {
  673. .notifier_call = hmat_callback,
  674. .priority = 2,
  675. };
  676. static __init void hmat_free_structures(void)
  677. {
  678. struct memory_target *target, *tnext;
  679. struct memory_locality *loc, *lnext;
  680. struct memory_initiator *initiator, *inext;
  681. struct target_cache *tcache, *cnext;
  682. list_for_each_entry_safe(target, tnext, &targets, node) {
  683. struct resource *res, *res_next;
  684. list_for_each_entry_safe(tcache, cnext, &target->caches, node) {
  685. list_del(&tcache->node);
  686. kfree(tcache);
  687. }
  688. list_del(&target->node);
  689. res = target->memregions.child;
  690. while (res) {
  691. res_next = res->sibling;
  692. __release_region(&target->memregions, res->start,
  693. resource_size(res));
  694. res = res_next;
  695. }
  696. kfree(target);
  697. }
  698. list_for_each_entry_safe(initiator, inext, &initiators, node) {
  699. list_del(&initiator->node);
  700. kfree(initiator);
  701. }
  702. list_for_each_entry_safe(loc, lnext, &localities, node) {
  703. list_del(&loc->node);
  704. kfree(loc);
  705. }
  706. }
  707. static __init int hmat_init(void)
  708. {
  709. struct acpi_table_header *tbl;
  710. enum acpi_hmat_type i;
  711. acpi_status status;
  712. if (srat_disabled() || hmat_disable)
  713. return 0;
  714. status = acpi_get_table(ACPI_SIG_SRAT, 0, &tbl);
  715. if (ACPI_FAILURE(status))
  716. return 0;
  717. if (acpi_table_parse_entries(ACPI_SIG_SRAT,
  718. sizeof(struct acpi_table_srat),
  719. ACPI_SRAT_TYPE_MEMORY_AFFINITY,
  720. srat_parse_mem_affinity, 0) < 0)
  721. goto out_put;
  722. acpi_put_table(tbl);
  723. status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
  724. if (ACPI_FAILURE(status))
  725. goto out_put;
  726. hmat_revision = tbl->revision;
  727. switch (hmat_revision) {
  728. case 1:
  729. case 2:
  730. break;
  731. default:
  732. pr_notice("Ignoring: Unknown revision:%d\n", hmat_revision);
  733. goto out_put;
  734. }
  735. for (i = ACPI_HMAT_TYPE_PROXIMITY; i < ACPI_HMAT_TYPE_RESERVED; i++) {
  736. if (acpi_table_parse_entries(ACPI_SIG_HMAT,
  737. sizeof(struct acpi_table_hmat), i,
  738. hmat_parse_subtable, 0) < 0) {
  739. pr_notice("Ignoring: Invalid table");
  740. goto out_put;
  741. }
  742. }
  743. hmat_register_targets();
  744. /* Keep the table and structures if the notifier may use them */
  745. if (!register_hotmemory_notifier(&hmat_callback_nb))
  746. return 0;
  747. out_put:
  748. hmat_free_structures();
  749. acpi_put_table(tbl);
  750. return 0;
  751. }
  752. device_initcall(hmat_init);