cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

of_numa.c (3990B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * OF NUMA Parsing support.
      4 *
      5 * Copyright (C) 2015 - 2016 Cavium Inc.
      6 */
      7
      8#define pr_fmt(fmt) "OF: NUMA: " fmt
      9
     10#include <linux/of.h>
     11#include <linux/of_address.h>
     12#include <linux/nodemask.h>
     13
     14#include <asm/numa.h>
     15
     16/* define default numa node to 0 */
     17#define DEFAULT_NODE 0
     18
     19/*
     20 * Even though we connect cpus to numa domains later in SMP
     21 * init, we need to know the node ids now for all cpus.
     22*/
     23static void __init of_numa_parse_cpu_nodes(void)
     24{
     25	u32 nid;
     26	int r;
     27	struct device_node *np;
     28
     29	for_each_of_cpu_node(np) {
     30		r = of_property_read_u32(np, "numa-node-id", &nid);
     31		if (r)
     32			continue;
     33
     34		pr_debug("CPU on %u\n", nid);
     35		if (nid >= MAX_NUMNODES)
     36			pr_warn("Node id %u exceeds maximum value\n", nid);
     37		else
     38			node_set(nid, numa_nodes_parsed);
     39	}
     40}
     41
     42static int __init of_numa_parse_memory_nodes(void)
     43{
     44	struct device_node *np = NULL;
     45	struct resource rsrc;
     46	u32 nid;
     47	int i, r;
     48
     49	for_each_node_by_type(np, "memory") {
     50		r = of_property_read_u32(np, "numa-node-id", &nid);
     51		if (r == -EINVAL)
     52			/*
     53			 * property doesn't exist if -EINVAL, continue
     54			 * looking for more memory nodes with
     55			 * "numa-node-id" property
     56			 */
     57			continue;
     58
     59		if (nid >= MAX_NUMNODES) {
     60			pr_warn("Node id %u exceeds maximum value\n", nid);
     61			r = -EINVAL;
     62		}
     63
     64		for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++)
     65			r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);
     66
     67		if (!i || r) {
     68			of_node_put(np);
     69			pr_err("bad property in memory node\n");
     70			return r ? : -EINVAL;
     71		}
     72	}
     73
     74	return 0;
     75}
     76
     77static int __init of_numa_parse_distance_map_v1(struct device_node *map)
     78{
     79	const __be32 *matrix;
     80	int entry_count;
     81	int i;
     82
     83	pr_info("parsing numa-distance-map-v1\n");
     84
     85	matrix = of_get_property(map, "distance-matrix", NULL);
     86	if (!matrix) {
     87		pr_err("No distance-matrix property in distance-map\n");
     88		return -EINVAL;
     89	}
     90
     91	entry_count = of_property_count_u32_elems(map, "distance-matrix");
     92	if (entry_count <= 0) {
     93		pr_err("Invalid distance-matrix\n");
     94		return -EINVAL;
     95	}
     96
     97	for (i = 0; i + 2 < entry_count; i += 3) {
     98		u32 nodea, nodeb, distance;
     99
    100		nodea = of_read_number(matrix, 1);
    101		matrix++;
    102		nodeb = of_read_number(matrix, 1);
    103		matrix++;
    104		distance = of_read_number(matrix, 1);
    105		matrix++;
    106
    107		if ((nodea == nodeb && distance != LOCAL_DISTANCE) ||
    108		    (nodea != nodeb && distance <= LOCAL_DISTANCE)) {
    109			pr_err("Invalid distance[node%d -> node%d] = %d\n",
    110			       nodea, nodeb, distance);
    111			return -EINVAL;
    112		}
    113
    114		node_set(nodea, numa_nodes_parsed);
    115
    116		numa_set_distance(nodea, nodeb, distance);
    117
    118		/* Set default distance of node B->A same as A->B */
    119		if (nodeb > nodea)
    120			numa_set_distance(nodeb, nodea, distance);
    121	}
    122
    123	return 0;
    124}
    125
    126static int __init of_numa_parse_distance_map(void)
    127{
    128	int ret = 0;
    129	struct device_node *np;
    130
    131	np = of_find_compatible_node(NULL, NULL,
    132				     "numa-distance-map-v1");
    133	if (np)
    134		ret = of_numa_parse_distance_map_v1(np);
    135
    136	of_node_put(np);
    137	return ret;
    138}
    139
    140int of_node_to_nid(struct device_node *device)
    141{
    142	struct device_node *np;
    143	u32 nid;
    144	int r = -ENODATA;
    145
    146	np = of_node_get(device);
    147
    148	while (np) {
    149		r = of_property_read_u32(np, "numa-node-id", &nid);
    150		/*
    151		 * -EINVAL indicates the property was not found, and
    152		 *  we walk up the tree trying to find a parent with a
    153		 *  "numa-node-id".  Any other type of error indicates
    154		 *  a bad device tree and we give up.
    155		 */
    156		if (r != -EINVAL)
    157			break;
    158
    159		np = of_get_next_parent(np);
    160	}
    161	if (np && r)
    162		pr_warn("Invalid \"numa-node-id\" property in node %pOFn\n",
    163			np);
    164	of_node_put(np);
    165
    166	/*
    167	 * If numa=off passed on command line, or with a defective
    168	 * device tree, the nid may not be in the set of possible
    169	 * nodes.  Check for this case and return NUMA_NO_NODE.
    170	 */
    171	if (!r && nid < MAX_NUMNODES && node_possible(nid))
    172		return nid;
    173
    174	return NUMA_NO_NODE;
    175}
    176
    177int __init of_numa_init(void)
    178{
    179	int r;
    180
    181	of_numa_parse_cpu_nodes();
    182	r = of_numa_parse_memory_nodes();
    183	if (r)
    184		return r;
    185	return of_numa_parse_distance_map();
    186}