Skip to content

Commit 6f6b0c3

Browse files
authored
[DM/feature] Simple NUMA (Non-Uniform Memory Access) (#9000)
For some CPU memory access devices, that the drivers will find memory and CPU affinity to config device. Signed-off-by: GuEe-GUI <[email protected]>
1 parent 952f2c4 commit 6f6b0c3

File tree

4 files changed

+198
-1
lines changed

4 files changed

+198
-1
lines changed

components/drivers/core/SConscript

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if GetDepend(['RT_USING_DEV_BUS']) or GetDepend(['RT_USING_DM']):
88
src = src + ['bus.c']
99

1010
if GetDepend(['RT_USING_DM']):
11-
src = src + ['dm.c', 'driver.c', 'platform.c']
11+
src = src + ['dm.c', 'driver.c', 'numa.c', 'platform.c']
1212

1313
if GetDepend(['RT_USING_DFS']):
1414
src += ['mnt.c'];

components/drivers/core/numa.c

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright (c) 2006-2023, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-09-24 GuEe-GUI the first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
14+
#define DBG_TAG "rtdm.numa"
15+
#define DBG_LVL DBG_INFO
16+
#include <rtdbg.h>
17+
18+
#include <drivers/pic.h>
19+
20+
struct numa_memory
21+
{
22+
rt_list_t list;
23+
24+
int nid;
25+
rt_uint64_t start;
26+
rt_uint64_t end;
27+
28+
union
29+
{
30+
void *ofw_node;
31+
};
32+
};
33+
34+
static rt_bool_t numa_enabled = RT_FALSE;
35+
static int cpu_numa_map[RT_CPUS_NR] rt_section(".bss.noclean.numa");
36+
static rt_list_t numa_memory_nodes rt_section(".bss.noclean.numa");
37+
38+
int rt_numa_cpu_id(int cpuid)
39+
{
40+
if (!numa_enabled)
41+
{
42+
return -RT_ENOSYS;
43+
}
44+
45+
return cpuid < RT_ARRAY_SIZE(cpu_numa_map) ? cpu_numa_map[cpuid] : -RT_EINVAL;
46+
}
47+
48+
int rt_numa_device_id(struct rt_device *dev)
49+
{
50+
rt_uint32_t nid = (rt_uint32_t)-RT_ENOSYS;
51+
52+
if (!numa_enabled)
53+
{
54+
return nid;
55+
}
56+
57+
return rt_dm_dev_prop_read_u32(dev, "numa-node-id", &nid) ? : (int)nid;
58+
}
59+
60+
rt_err_t rt_numa_memory_affinity(rt_uint64_t phy_addr, rt_bitmap_t *out_affinity)
61+
{
62+
struct numa_memory *nm;
63+
64+
if (!out_affinity)
65+
{
66+
return -RT_EINVAL;
67+
}
68+
69+
if (!numa_enabled)
70+
{
71+
/* Default to CPU#0 */
72+
RT_IRQ_AFFINITY_SET(out_affinity, 0);
73+
74+
return RT_EOK;
75+
}
76+
77+
rt_memset(out_affinity, 0, sizeof(*out_affinity) * RT_BITMAP_LEN(RT_CPUS_NR));
78+
79+
rt_list_for_each_entry(nm, &numa_memory_nodes, list)
80+
{
81+
if (phy_addr >= nm->start && phy_addr < nm->end)
82+
{
83+
for (int i = 0; i < RT_ARRAY_SIZE(cpu_numa_map); ++i)
84+
{
85+
if (cpu_numa_map[i] == nm->nid)
86+
{
87+
RT_IRQ_AFFINITY_SET(out_affinity, i);
88+
}
89+
}
90+
91+
return RT_EOK;
92+
}
93+
}
94+
95+
return -RT_EEMPTY;
96+
}
97+
98+
#ifdef RT_USING_OFW
99+
static int numa_ofw_init(void)
100+
{
101+
int i = 0;
102+
rt_uint32_t nid;
103+
const char *numa_conf;
104+
struct rt_ofw_node *np = RT_NULL;
105+
106+
numa_conf = rt_ofw_bootargs_select("numa=", 0);
107+
108+
if (!numa_conf || rt_strcmp(numa_conf, "on"))
109+
{
110+
return (int)RT_EOK;
111+
}
112+
113+
numa_enabled = RT_TRUE;
114+
115+
for (int i = 0; i < RT_ARRAY_SIZE(cpu_numa_map); ++i)
116+
{
117+
cpu_numa_map[i] = -RT_ENOSYS;
118+
}
119+
120+
rt_list_init(&numa_memory_nodes);
121+
122+
rt_ofw_foreach_cpu_node(np)
123+
{
124+
rt_ofw_prop_read_u32(np, "numa-node-id", (rt_uint32_t *)&cpu_numa_map[i]);
125+
126+
if (++i >= RT_CPUS_NR)
127+
{
128+
break;
129+
}
130+
}
131+
132+
rt_ofw_foreach_node_by_type(np, "memory")
133+
{
134+
if (!rt_ofw_prop_read_u32(np, "numa-node-id", &nid))
135+
{
136+
int mem_nr = rt_ofw_get_address_count(np);
137+
138+
for (i = 0; i < mem_nr; ++i)
139+
{
140+
rt_uint64_t addr, size;
141+
struct numa_memory *nm;
142+
143+
if (rt_ofw_get_address(np, i, &addr, &size))
144+
{
145+
continue;
146+
}
147+
148+
nm = rt_malloc(sizeof(*nm));
149+
150+
if (!nm)
151+
{
152+
LOG_E("No memory to record NUMA[%d] memory[%p, %p] info",
153+
nid, addr, addr + size);
154+
155+
return (int)-RT_ENOMEM;
156+
}
157+
158+
nm->start = addr;
159+
nm->end = addr + size;
160+
nm->ofw_node = np;
161+
162+
rt_list_init(&nm->list);
163+
rt_list_insert_before(&numa_memory_nodes, &nm->list);
164+
}
165+
}
166+
}
167+
168+
return 0;
169+
}
170+
INIT_CORE_EXPORT(numa_ofw_init);
171+
#endif /* RT_USING_OFW */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2006-2023, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-09-24 GuEe-GUI the first version
9+
*/
10+
11+
#ifndef __RT_DM_NUMA_H__
12+
#define __RT_DM_NUMA_H__
13+
14+
#include <rthw.h>
15+
#include <rtthread.h>
16+
17+
#include <bitmap.h>
18+
19+
/* NUMA: Non-Uniform Memory Access */
20+
21+
int rt_numa_cpu_id(int cpuid);
22+
int rt_numa_device_id(struct rt_device *dev);
23+
rt_err_t rt_numa_memory_affinity(rt_uint64_t phy_addr, rt_bitmap_t *out_affinity);
24+
25+
#endif /* __RT_DM_NUMA_H__ */

components/drivers/include/rtdevice.h

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern "C" {
4141

4242
#ifdef RT_USING_DM
4343
#include "drivers/core/dm.h"
44+
#include "drivers/core/numa.h"
4445
#include "drivers/platform.h"
4546

4647
#ifdef RT_USING_OFW

0 commit comments

Comments
 (0)