Skip to content

Commit ed7b60d

Browse files
thomastaioraclegregkh
authored andcommitted
sparc64: Fix find_node warning if numa node cannot be found
[ Upstream commit 74a5ed5c4f692df2ff0a2313ea71e81243525519 ] When booting up LDOM, find_node() warns that a physical address doesn't match a NUMA node. WARNING: CPU: 0 PID: 0 at arch/sparc/mm/init_64.c:835 find_node+0xf4/0x120 find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.0-rc3 #4 Call Trace: [0000000000468ba0] __warn+0xc0/0xe0 [0000000000468c74] warn_slowpath_fmt+0x34/0x60 [00000000004592f4] find_node+0xf4/0x120 [0000000000dd0774] add_node_ranges+0x38/0xe4 [0000000000dd0b1c] numa_parse_mdesc+0x268/0x2e4 [0000000000dd0e9c] bootmem_init+0xb8/0x160 [0000000000dd174c] paging_init+0x808/0x8fc [0000000000dcb0d0] setup_arch+0x2c8/0x2f0 [0000000000dc68a0] start_kernel+0x48/0x424 [0000000000dcb374] start_early_boot+0x27c/0x28c [0000000000a32c08] tlb_fixup_done+0x4c/0x64 [0000000000027f08] 0x27f08 It is because linux use an internal structure node_masks[] to keep the best memory latency node only. However, LDOM mdesc can contain single latency-group with multiple memory latency nodes. If the address doesn't match the best latency node within node_masks[], it should check for an alternative via mdesc. The warning message should only be printed if the address doesn't match any node_masks[] nor within mdesc. To minimize the impact of searching mdesc every time, the last matched mask and index is stored in a variable. Signed-off-by: Thomas Tai <thomas.tai@oracle.com> Reviewed-by: Chris Hyser <chris.hyser@oracle.com> Reviewed-by: Liam Merwick <liam.merwick@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 438e91d commit ed7b60d

1 file changed

Lines changed: 61 additions & 4 deletions

File tree

arch/sparc/mm/init_64.c

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,8 @@ struct mdesc_mblock {
800800
};
801801
static struct mdesc_mblock *mblocks;
802802
static int num_mblocks;
803+
static int find_numa_node_for_addr(unsigned long pa,
804+
struct node_mem_mask *pnode_mask);
803805

804806
static unsigned long ra_to_pa(unsigned long addr)
805807
{
@@ -819,6 +821,9 @@ static unsigned long ra_to_pa(unsigned long addr)
819821

820822
static int find_node(unsigned long addr)
821823
{
824+
static bool search_mdesc = true;
825+
static struct node_mem_mask last_mem_mask = { ~0UL, ~0UL };
826+
static int last_index;
822827
int i;
823828

824829
addr = ra_to_pa(addr);
@@ -828,10 +833,27 @@ static int find_node(unsigned long addr)
828833
if ((addr & p->mask) == p->val)
829834
return i;
830835
}
831-
/* The following condition has been observed on LDOM guests.*/
832-
WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node"
833-
" rule. Some physical memory will be owned by node 0.");
834-
return 0;
836+
/* The following condition has been observed on LDOM guests because
837+
* node_masks only contains the best latency mask and value.
838+
* LDOM guest's mdesc can contain a single latency group to
839+
* cover multiple address range. Print warning message only if the
840+
* address cannot be found in node_masks nor mdesc.
841+
*/
842+
if ((search_mdesc) &&
843+
((addr & last_mem_mask.mask) != last_mem_mask.val)) {
844+
/* find the available node in the mdesc */
845+
last_index = find_numa_node_for_addr(addr, &last_mem_mask);
846+
numadbg("find_node: latency group for address 0x%lx is %d\n",
847+
addr, last_index);
848+
if ((last_index < 0) || (last_index >= num_node_masks)) {
849+
/* WARN_ONCE() and use default group 0 */
850+
WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.");
851+
search_mdesc = false;
852+
last_index = 0;
853+
}
854+
}
855+
856+
return last_index;
835857
}
836858

837859
static u64 memblock_nid_range(u64 start, u64 end, int *nid)
@@ -1158,6 +1180,41 @@ int __node_distance(int from, int to)
11581180
return numa_latency[from][to];
11591181
}
11601182

1183+
static int find_numa_node_for_addr(unsigned long pa,
1184+
struct node_mem_mask *pnode_mask)
1185+
{
1186+
struct mdesc_handle *md = mdesc_grab();
1187+
u64 node, arc;
1188+
int i = 0;
1189+
1190+
node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
1191+
if (node == MDESC_NODE_NULL)
1192+
goto out;
1193+
1194+
mdesc_for_each_node_by_name(md, node, "group") {
1195+
mdesc_for_each_arc(arc, md, node, MDESC_ARC_TYPE_FWD) {
1196+
u64 target = mdesc_arc_target(md, arc);
1197+
struct mdesc_mlgroup *m = find_mlgroup(target);
1198+
1199+
if (!m)
1200+
continue;
1201+
if ((pa & m->mask) == m->match) {
1202+
if (pnode_mask) {
1203+
pnode_mask->mask = m->mask;
1204+
pnode_mask->val = m->match;
1205+
}
1206+
mdesc_release(md);
1207+
return i;
1208+
}
1209+
}
1210+
i++;
1211+
}
1212+
1213+
out:
1214+
mdesc_release(md);
1215+
return -1;
1216+
}
1217+
11611218
static int find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
11621219
{
11631220
int i;

0 commit comments

Comments
 (0)